Skip to content

fix(providers): bound transit response buffering - #224

Closed
hyrious wants to merge 1 commit into
mainfrom
provider-transit-bounds-20260729
Closed

fix(providers): bound transit response buffering#224
hyrious wants to merge 1 commit into
mainfrom
provider-transit-bounds-20260729

Conversation

@hyrious

@hyrious hyrious commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

概要

批次 provider 自审发现,多个文件输出 action 会先无界读取完整 provider 响应,再由 transitFiles.create 检查大小。超大图片、音频、视频或导出文件因此可能在限制生效前放大进程内存。

本 PR 将 16 个 provider 的 response → transit 路径改为复用现有 readBoundedResponseBytes,以 transitFiles.maxBytes 在读取阶段早停并返回 413:

  • Agenty、Docsend2pdf、ElevenLabs、Feishu App Bot、Foxit、Gemini、Gladia、Google Drive
  • Klangio、Kraken.io、remove.bg、ScreenshotOne、Stability AI、TinyPNG、Vimeo、YouTube

remove.bg 与 ElevenLabs 的 JSON/base64 文件分支按 base64 膨胀量限制 JSON 响应,并在解码后再次检查实际文件大小。仅返回 inline base64、读取本地 transit file 或已有独立 bounded reader 的路径保持不变。

边界

  • 不修改共享 helper;沿用 src/core/request.ts 已有 bounded reader
  • 保留各 provider 的认证、请求、输出和非超限错误语义
  • 不混入审计发现的低优先级旧 JSON helper 清理

验证

  • npm run fix-check
  • npm run build
  • npx vitest run src/core/request.test.ts src/providers/provider-runtime.test.ts(2 files / 36 tests)
  • git diff --check origin/main..HEAD

未运行全量测试;本 PR 未改共享 helper,涉及 provider 没有对应的 OSS provider-local tests。

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • Bug Fixes
    • Added maximum-size enforcement for downloaded files, images, audio, video, captions, and PDFs across multiple providers.
    • Oversized outputs now fail with a clear HTTP 413 error instead of being fully loaded into memory.
    • Improved handling of invalid or oversized response data during media and file processing.
    • Audio-returning actions now require file storage support when applicable.

Walkthrough

Provider file and media download paths now use readBoundedResponseBytes with context.transitFiles.maxBytes instead of unbounded response.arrayBuffer() reads. Oversized responses generally produce ProviderRequestError status 413 before transit-file creation. Docsend and Remove.bg add conditional or encoded-response handling, while ElevenLabs also bounds JSON responses, requires transit storage for audio actions, and validates decoded audio size.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required type(scope): subject format and accurately reflects the bounded transit buffering change.
Description check ✅ Passed The description is clearly related to the provider buffering changes and validation work in this pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch provider-transit-bounds-20260729

Comment @coderabbitai help to get the list of available commands.

@hyrious

hyrious commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

按维护者安排,改为本地合并整理,关闭此独立加固 PR。

@hyrious hyrious closed this Jul 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/providers/elevenlabs/executors.ts (1)

544-552: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an interface for this object contract.

ElevenlabsRequestInput is object-shaped rather than a union or mapped composition.

Proposed fix
-type ElevenlabsRequestInput = {
+interface ElevenlabsRequestInput {
   method?: "DELETE" | "GET" | "POST";
   baseUrl?: string;
   path: string;
   query?: Record<string, string | string[] | undefined>;
   body?: Record<string, unknown>;
   mode?: "validate" | "execute";
   maxResponseBytes?: number;
-};
+}

As per coding guidelines, “Prefer interface for object-shaped contracts; use type for unions and mapped or utility compositions.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/elevenlabs/executors.ts` around lines 544 - 552, Change
ElevenlabsRequestInput from a type alias to an interface while preserving all
existing optional properties and their types.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/providers/agenty/runtime.ts`:
- Around line 585-590: Update the oversized-response handling in
src/core/request.ts around lines 83-91 to cancel response.body before throwing
the early Content-Length 413 error, and add a regression test covering this
path. The affected response consumers at src/providers/agenty/runtime.ts lines
585-590, src/providers/feishu_app_bot/executors.ts lines 1145-1151,
src/providers/fuxin/executors.ts lines 357-369, src/providers/gemini/runtime.ts
lines 674-678, src/providers/gladia/runtime.ts lines 180-185,
src/providers/googledrive/executors.ts lines 511-516, and
src/providers/klangio/runtime.ts lines 222-235 require no direct changes; they
are corrected by the shared request-layer fix.

In `@src/providers/elevenlabs/executors.ts`:
- Around line 345-347: Move the context.transitFiles precondition checks before
the corresponding context.fetcher calls in the text_to_speech,
create_sound_effect, and history-audio execution paths. Update all three sites
in src/providers/elevenlabs/executors.ts:345-347, :433-435, and :466-468,
placing each check before the TTS POST, sound-effect POST, and history-audio GET
respectively while preserving the existing ProviderRequestError behavior.

---

Nitpick comments:
In `@src/providers/elevenlabs/executors.ts`:
- Around line 544-552: Change ElevenlabsRequestInput from a type alias to an
interface while preserving all existing optional properties and their types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2fd662a3-4e9c-477b-b23c-4de3c5106aed

📥 Commits

Reviewing files that changed from the base of the PR and between 962d735 and b50d09a.

📒 Files selected for processing (16)
  • src/providers/agenty/runtime.ts
  • src/providers/docsend_2_pdf/executors.ts
  • src/providers/elevenlabs/executors.ts
  • src/providers/feishu_app_bot/executors.ts
  • src/providers/fuxin/executors.ts
  • src/providers/gemini/runtime.ts
  • src/providers/gladia/runtime.ts
  • src/providers/googledrive/executors.ts
  • src/providers/klangio/runtime.ts
  • src/providers/kraken_io/executors.ts
  • src/providers/remove_bg/executors.ts
  • src/providers/screenshotone/runtime.ts
  • src/providers/stabilityai/executors.ts
  • src/providers/tinypng/runtime.ts
  • src/providers/vimeo/runtime.ts
  • src/providers/youtube/runtime.ts

Comment on lines +585 to +590
const bytes = await readBoundedResponseBytes(response, {
maxBytes: context.transitFiles.maxBytes,
fieldName: "Agenty file output",
createError: (message) => new ProviderRequestError(413, message),
});
const upload = await context.transitFiles.create(new File([Uint8Array.from(bytes)], name, { type: mimeType }));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== locate helper and call sites ==\n'
rg -n "readBoundedResponseBytes|assertMaxBytes|response.body\\?\\.cancel|Content-Length|maxBytes" src/providers src -g'*.ts'

printf '\n== helper definition context ==\n'
helper_file=$(rg -l "function readBoundedResponseBytes|const readBoundedResponseBytes|async function readBoundedResponseBytes" src -g'*.ts' | head -n 1)
echo "helper_file=$helper_file"
if [ -n "${helper_file:-}" ]; then
  nl -ba "$helper_file" | sed -n '1,260p'
fi

printf '\n== tests referencing bounded bytes helper ==\n'
rg -n "readBoundedResponseBytes|Content-Length|413|cancel\\(" src test tests -g'*.ts' -g'*.tsx'

Repository: oomol-lab/open-connector

Length of output: 49634


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== direct helper file search ==\n'
fd -a "readBoundedResponseBytes" src -t f

Repository: oomol-lab/open-connector

Length of output: 195


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

path = Path("src/core/request.ts")
lines = path.read_text().splitlines()
for start, end in [(60, 130), (470, 520)]:
    print(f"\n== {path} lines {start}-{end} ==")
    for i in range(start, min(end, len(lines)) + 1):
        print(f"{i:4d}: {lines[i-1]}")
PY

printf '\n== tests mentioning readBoundedResponseBytes or Content-Length ==\n'
python3 - <<'PY'
from pathlib import Path
import re

for path in Path("src").rglob("*.test.ts"):
    text = path.read_text(errors="ignore")
    if "readBoundedResponseBytes" in text or "Content-Length" in text or "content-length" in text:
        print(path)
PY

Repository: oomol-lab/open-connector

Length of output: 4119


Cancel the body before the early Content-Length 413

src/core/request.ts#L83-L91 rejects oversized responses before touching response.body, so the underlying request can stay open. Cancel the body before throwing and add a regression test for this path.

📍 Affects 7 files
  • src/providers/agenty/runtime.ts#L585-L590 (this comment)
  • src/providers/feishu_app_bot/executors.ts#L1145-L1151
  • src/providers/fuxin/executors.ts#L357-L369
  • src/providers/gemini/runtime.ts#L674-L678
  • src/providers/gladia/runtime.ts#L180-L185
  • src/providers/googledrive/executors.ts#L511-L516
  • src/providers/klangio/runtime.ts#L222-L235
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/agenty/runtime.ts` around lines 585 - 590, Update the
oversized-response handling in src/core/request.ts around lines 83-91 to cancel
response.body before throwing the early Content-Length 413 error, and add a
regression test covering this path. The affected response consumers at
src/providers/agenty/runtime.ts lines 585-590,
src/providers/feishu_app_bot/executors.ts lines 1145-1151,
src/providers/fuxin/executors.ts lines 357-369, src/providers/gemini/runtime.ts
lines 674-678, src/providers/gladia/runtime.ts lines 180-185,
src/providers/googledrive/executors.ts lines 511-516, and
src/providers/klangio/runtime.ts lines 222-235 require no direct changes; they
are corrected by the shared request-layer fix.

Comment on lines +345 to +347
if (!context.transitFiles) {
throw new ProviderRequestError(500, "text_to_speech requires transit file storage");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate transit storage before making the upstream request.

The check is too late: text_to_speech and create_sound_effect can consume ElevenLabs credits before inevitably failing with a local 500. Move each precondition ahead of its context.fetcher call; this also avoids an unnecessary history-audio request.

  • src/providers/elevenlabs/executors.ts#L345-L347: move the check before the TTS POST at Line 328.
  • src/providers/elevenlabs/executors.ts#L433-L435: move the check before the sound-effect POST at Line 417.
  • src/providers/elevenlabs/executors.ts#L466-L468: move the check before the history-audio GET at Line 456.
📍 Affects 1 file
  • src/providers/elevenlabs/executors.ts#L345-L347 (this comment)
  • src/providers/elevenlabs/executors.ts#L433-L435
  • src/providers/elevenlabs/executors.ts#L466-L468
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/elevenlabs/executors.ts` around lines 345 - 347, Move the
context.transitFiles precondition checks before the corresponding
context.fetcher calls in the text_to_speech, create_sound_effect, and
history-audio execution paths. Update all three sites in
src/providers/elevenlabs/executors.ts:345-347, :433-435, and :466-468, placing
each check before the TTS POST, sound-effect POST, and history-audio GET
respectively while preserving the existing ProviderRequestError behavior.

@hyrious
hyrious deleted the provider-transit-bounds-20260729 branch July 29, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant