Skip to content

fix(cursor): bound invocation argument restoration - #5458

Draft
luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:fix/556-cursor-invocation-bound
Draft

luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:fix/556-cursor-invocation-bound

Conversation

@luvs01

@luvs01 luvs01 commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Motivation

  • The refund pass that restores clipped invocation arguments re-serialized a call's arguments and allocated an input-sized buffer before it could tell whether the raw byte growth could even fit the spare envelope budget.

Description

  • truncateUtf8 now uses encodeInto into a bound-sized buffer instead of encoding the whole input first.
  • A new boundedUtf8ByteLength returns the UTF-8 length only when it fits the bound, without allocating an input-sized buffer.
  • serializedToolCallArgumentsText reuses the single serialization the refund pass already produced, and the pass rejects an impossible restoration with a bounded scan before building the widened string.
  • structure/providers/cursor.md documents the bounded scan and serialization reuse.
  • Regression coverage in tests/providers/cursor/cursor-tool-result-invocation.test.ts asserts an impossible restoration serializes its arguments only once.

Testing

  • bun test tests/providers/cursor/cursor-tool-result-invocation.test.ts: 36 tests pass.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 21, 2026
@github-actions

github-actions Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

Automatic ready-for-review conversion failed; please mark the pull request ready manually if it is still a draft.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers notified: @lidge-jun @Ingwannu

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 24 / 80

이 PR은 Cursor에 다시 보여줄 도구 호출 인자를, 너무 길어서 잘라 둔 뒤 봉투에 남은 바이트로 되돌릴 때 메모리를 크게 쓰지 않게 고칩니다.

도구 결과가 다시 재생되면, 그 결과를 만든 호출의 인자가 한 줄로 붙습니다. 인자가 한도를 넘으면 뒤를 …[arguments truncated]로 자릅니다. 히스토리 봉투에 자리가 남으면, 나중 패스가 잘린 인자를 원래 글로 다시 넓힙니다. 인자가 봉투보다 크면 넓힐 수 없습니다. 예전 코드는 그걸 알기 전에 인자를 한 번 더 JSON으로 만들고, 그 글 크기만큼 버퍼를 잡았습니다.

truncateUtf8는 글 전체를 먼저 인코딩하지 않습니다. 예산만큼만 가진 버퍼에 encodeInto로 들어가는 글자만 넣습니다. 글자가 바이트 중간에서 잘리지 않습니다. boundedUtf8ByteLength는 글자를 하나씩 보며 UTF-8 바이트를 더하다가, 한도를 넘는 순간 길이를 포기하고 돌아옵니다. 환불 패스는 인자를 JSON으로 한 번만 만들고, 그 문자열을 잘라 보여주는 쪽과 같이 씁니다. 잘린 글의 바이트와 남은 예산을 더한 값보다 원문이 길면, 넓힌 문자열을 만들기 전에 그 호출을 건너뜁니다. structure/providers/cursor.md에 이 검사와 직렬화 재사용을 적어 두었습니다.

베이스는 dev입니다. types.ts/config.ts를 나누는 변경이 아니고, 같은 주제로 열린 다른 PR은 없습니다.

라인 src/adapters/cursor/protobuf-request.ts 1077 - fullBytes - clippedBytes > spare는 실행되지 않습니다. 바로 위의 boundedUtf8ByteLength(full, clippedBytes + spare)가 원문이 그 합보다 길면 이미 undefined를 돌려줍니다. 숫자가 나온 경우는 늘 fullBytesclippedBytes + spare 이하입니다. 남겨도 결과는 같고, 나중에는 진짜 검사처럼 보입니다.

라인 tests/providers/cursor/cursor-tool-result-invocation.test.ts 618 - toJSON이 4번 불리는지만 봅니다. 앞의 세 번은 반복 횟수를 세는 곳과, 결과를 글로 그리는 곳 두 번입니다. 환불 패스가 인자를 두 번 JSON으로 만드는 회귀는 잡힙니다. encoder.encode(full)로 원문 크기 버퍼를 다시 잡아도 이 숫자는 4로 남습니다. 이 PR이 없애려 한 큰 버퍼는 테스트가 지키지 않습니다.

메인테이너의 판단이 필요한 지점

초안 체크리스트 네 칸이 아직 비어 있습니다. PR 설명은 네 칸이 채워지기 전에는 초안으로 둔다고 적습니다. 코드와 별개로, 초안을 벗길 시점만 정하면 됩니다. 1077의 두 번째 조건은 지워도 동작이 같습니다.

너의 추천

합쳐도 됩니다. 잘린 인자를 되돌리기 전에, 원문 바이트가 남은 예산에 드는지 먼저 보는 쪽이 맞습니다. 넘치면 넓힌 글을 만들지 않고 다음 결과로 넘어갑니다. 나중에 실제 비용이 예산을 넘으면 거절하는 기존 검사도 그대로입니다. 두 번째 조건은 지워도 됩니다. 큰 버퍼를 테스트로 잠그려면 toJSON 횟수와는 다른 증거가 필요합니다. 초안 네 칸을 채운 뒤에 초안을 벗기면 됩니다.

이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants