Skip to content

Improve Claude stream completion handling - #1030

Merged
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:improve-claude-stream-completion-handling
Jul 30, 2026
Merged

Improve Claude stream completion handling#1030
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:improve-claude-stream-completion-handling

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Jul 27, 2026

Copy link
Copy Markdown
Member

Follow-up to #1026.

What changed

  • Detect Anthropic max_tokens and refusal stop reasons instead of treating them as successful completions.
  • Require message_stop before accepting a Claude response as complete.
  • Preserve explicit abort behavior and avoid duplicate terminal messages.
  • Report localized errors across supported locales.
  • Add regression coverage for incomplete responses, transport failures, callback errors, and aborts.

Why

Claude Opus 5 can consume the configured response token limit while producing little or no visible text. The previous SSE handling treated these responses as successful and could also emit a duplicate completion message.

Validation

  • npm run pretty
  • npm run lint
  • npm test (949/949 passing)
  • npm run build and expected build artifacts
  • Chromium extension smoke test with Playwright and Xvfb
  • Firefox extension smoke test with web-ext and Xvfb
  • git diff --check

Live Anthropic API smoke testing was not run because API credentials were unavailable.

Summary by CodeRabbit

  • New Features
    • Added localized UI messages for Claude-specific failure/limit states across supported languages, including response token limits, model context limits, request refusals, and early/unfinished response streams.
  • Bug Fixes
    • Improved streamed answer handling to more accurately classify successful completion versus refusals, limit conditions, and streaming/reader failures.
    • Refined when final “done” status is emitted, preventing incorrect or partial updates during interruptions, early ends, or abnormal stop scenarios.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Claude SSE handling now distinguishes completion, refusal, token-limit, abort, and stream-failure outcomes. Successful answers are finalized explicitly, incomplete responses are rejected, cleanup is enforced, tests cover termination scenarios, and localized messages were added in 13 locales.

Changes

Claude stream completion

Layer / File(s) Summary
Stream completion decision flow
src/services/apis/claude-api.mjs
Claude stream processing records stop reasons, finalizes successful responses, handles aborts and stream errors, and posts completion only after successful message_stop handling.
Stream termination validation
tests/unit/services/apis/claude-api.test.mjs
Tests cover successful completion, incomplete responses, refusals, post-completion failures, clean EOF, cleanup errors, read failures, and aborted streams.
Localized Claude status messages
src/_locales/*/main.json
Thirteen locales add messages for token limits, context limits, refusals, and incomplete response streams.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClaudeAPI
  participant SSEStream
  participant ConversationStorage
  participant Port
  SSEStream->>ClaudeAPI: Send message_delta and message_stop events
  ClaudeAPI->>ClaudeAPI: Classify stop reason and stream state
  ClaudeAPI->>ConversationStorage: Persist successful response
  ClaudeAPI->>Port: Post completed response
  SSEStream->>ClaudeAPI: Report stream end or error
  ClaudeAPI->>ClaudeAPI: Abort or propagate incomplete stream failure
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: improving Claude stream completion handling.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Fix Claude SSE completion detection and surface token-limit/refusal errors

🐞 Bug fix 🧪 Tests ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Treat Claude max_tokens/refusal stop reasons as errors, not successful completions.
• Require message_stop to finalize responses and avoid duplicate terminal messages.
• Add localized error strings and regression tests for stream/abort edge cases.
Diagram

graph TD
  UI["Extension UI / Port"] --> Claude["claude-api.mjs"] --> SSE["fetch-sse.mjs"] --> Anthropic{{"Anthropic Messages SSE"}}
  Claude --> I18n["Locales (main.json)"]
  Tests["claude-api.test.mjs"] --> Claude

  subgraph Legend
    direction LR
    _svc["Module/Service"] ~~~ _file["File/Resource"] ~~~ _ext{{"External API"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Adopt official Anthropic SDK streaming
  • ➕ Offloads SSE parsing and stop-reason semantics to a maintained client
  • ➕ Potentially reduces bespoke edge-case handling over time
  • ➖ Adds dependency/footprint and may not align with extension runtime constraints
  • ➖ Migration risk and different streaming abstractions than current fetchSSE
2. Finalize on stop_reason alone (without requiring message_stop)
  • ➕ Can terminate earlier if stop_reason is received before message_stop
  • ➕ Slightly simpler completion gating
  • ➖ Risks false positives if stop_reason is emitted but stream is incomplete
  • ➖ Harder to reason about correctness across stream interruptions

Recommendation: The PR’s approach (require message_stop, interpret stop_reason, then decide success/error) is the safest correctness boundary for streamed responses and cleanly separates: (1) semantic completion from Claude and (2) transport/stream failures from fetchSSE. An SDK switch could be revisited later if dependency constraints allow, but for now this targeted fix plus regression tests is the best tradeoff.

Files changed (15) +307 / -15

Bug fix (1) +35 / -7
claude-api.mjsGate completion on message_stop and stop_reason; preserve abort semantics +35/-7

Gate completion on message_stop and stop_reason; preserve abort semantics

• Tracks 'stop_reason' from 'message_delta' and only marks completion on 'message_stop'. Converts 'max_tokens' and 'refusal' into explicit errors, avoids emitting an extra terminal '{done:true}' on non-abort paths, and handles stream failures differently depending on whether completion already occurred.

src/services/apis/claude-api.mjs

Tests (1) +233 / -8
claude-api.test.mjsAdd regression tests for Claude streaming completion, failures, and aborts +233/-8

Add regression tests for Claude streaming completion, failures, and aborts

• Introduces a shared setup helper and adds coverage for token-limit/refusal stop reasons, clean EOF before completion, response-stream failures, callback cleanup errors, and abort suppression of completion errors. Tightens assertions around posted messages, record persistence, and listener cleanup.

tests/unit/services/apis/claude-api.test.mjs

Documentation (13) +39 / -0
main.jsonAdd German strings for new Claude completion/stream errors +3/-0

Add German strings for new Claude completion/stream errors

• Adds localized messages for token-limit, refusal, and premature stream termination errors emitted by the Claude SSE handler.

src/_locales/de/main.json

main.jsonAdd English strings for new Claude completion/stream errors +3/-0

Add English strings for new Claude completion/stream errors

• Introduces user-facing error messages for Claude token-limit exhaustion, refusal stop reason, and incomplete stream termination.

src/_locales/en/main.json

main.jsonAdd Spanish strings for new Claude completion/stream errors +3/-0

Add Spanish strings for new Claude completion/stream errors

• Adds Spanish translations for the new Claude stop-reason and incomplete-stream error conditions.

src/_locales/es/main.json

main.jsonAdd French strings for new Claude completion/stream errors +3/-0

Add French strings for new Claude completion/stream errors

• Adds French translations for token-limit, refusal, and stream-ended-before-completion errors.

src/_locales/fr/main.json

main.jsonAdd Indonesian strings for new Claude completion/stream errors +3/-0

Add Indonesian strings for new Claude completion/stream errors

• Adds Indonesian translations for Claude token-limit, refusal, and premature stream termination errors.

src/_locales/in/main.json

main.jsonAdd Italian strings for new Claude completion/stream errors +3/-0

Add Italian strings for new Claude completion/stream errors

• Adds Italian translations for Claude stop-reason failures and incomplete stream completion messaging.

src/_locales/it/main.json

main.jsonAdd Japanese strings for new Claude completion/stream errors +3/-0

Add Japanese strings for new Claude completion/stream errors

• Adds Japanese translations for token-limit reached, refusal, and stream ended before completion errors.

src/_locales/ja/main.json

main.jsonAdd Korean strings for new Claude completion/stream errors +3/-0

Add Korean strings for new Claude completion/stream errors

• Adds Korean translations for the newly reported Claude streaming stop-reason/incomplete-response errors.

src/_locales/ko/main.json

main.jsonAdd Portuguese strings for new Claude completion/stream errors +3/-0

Add Portuguese strings for new Claude completion/stream errors

• Adds Portuguese translations for Claude token-limit, refusal, and incomplete stream errors.

src/_locales/pt/main.json

main.jsonAdd Russian strings for new Claude completion/stream errors +3/-0

Add Russian strings for new Claude completion/stream errors

• Adds Russian translations for Claude stop_reason error reporting and premature stream termination.

src/_locales/ru/main.json

main.jsonAdd Turkish strings for new Claude completion/stream errors +3/-0

Add Turkish strings for new Claude completion/stream errors

• Adds Turkish translations for Claude token-limit, refusal, and incomplete response stream errors.

src/_locales/tr/main.json

main.jsonAdd Simplified Chinese strings for new Claude completion/stream errors +3/-0

Add Simplified Chinese strings for new Claude completion/stream errors

• Adds Simplified Chinese translations for token-limit reached, refusal stop reason, and stream ended early errors.

src/_locales/zh-hans/main.json

main.jsonAdd Traditional Chinese strings for new Claude completion/stream errors +3/-0

Add Traditional Chinese strings for new Claude completion/stream errors

• Adds Traditional Chinese translations for Claude token-limit, refusal, and incomplete stream termination errors.

src/_locales/zh-hant/main.json

Copilot AI 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.

Pull request overview

This PR improves Anthropic Claude API streaming completion handling so the extension can reliably distinguish successful completions from token-limit truncations, refusals, transport interruptions, and early EOFs—avoiding false “success” states (and duplicate terminal messages) seen with Claude Opus 5.

Changes:

  • Track stop_reason (message_delta) and require message_stop before treating a stream as completed; surface max_tokens and refusal as explicit errors.
  • Preserve “abort” behavior and ignore late response-stream interruptions after a confirmed successful completion.
  • Add regression tests for incomplete responses, stream/transport failures, callback cleanup failures, and abort flows; add i18n keys for the new Claude-specific errors.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/services/apis/claude-api.mjs Implements stop-reason tracking, message_stop-gated completion, and refined error/abort handling for Claude SSE streams.
tests/unit/services/apis/claude-api.test.mjs Adds targeted regression coverage for the new completion/error behaviors (max_tokens/refusal, EOF, stream failure, callback errors, abort).
src/_locales/en/main.json Adds new Claude error strings as i18n keys.
src/_locales/de/main.json Adds translations for the new Claude error strings.
src/_locales/es/main.json Adds translations for the new Claude error strings.
src/_locales/fr/main.json Adds translations for the new Claude error strings.
src/_locales/in/main.json Adds translations for the new Claude error strings.
src/_locales/it/main.json Adds translations for the new Claude error strings.
src/_locales/ja/main.json Adds translations for the new Claude error strings.
src/_locales/ko/main.json Adds translations for the new Claude error strings.
src/_locales/pt/main.json Adds translations for the new Claude error strings.
src/_locales/ru/main.json Adds translations for the new Claude error strings.
src/_locales/tr/main.json Adds translations for the new Claude error strings.
src/_locales/zh-hans/main.json Adds translations for the new Claude error strings.
src/_locales/zh-hant/main.json Adds translations for the new Claude error strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@qodo-code-review

qodo-code-review Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 6 rules

Grey Divider


Informational

1. Claude strings exceed 100 columns 📘 Rule violation ⚙ Maintainability ⭐ New
Description
The new Claude error string and SSE fixtures contain physical lines longer than 100 characters.
These additions violate the source line-length limit.
Code

src/services/apis/claude-api.mjs[83]

+            'Claude reached the response token limit. Increase Max Response Token Length and try again.',
Evidence
PR Compliance ID 2261946 requires every non-comment physical source line to be at most 100
characters. The error literal at line 83 and SSE fixture literals at lines 234, 243, and 253 exceed
that limit.

Rule 2261946: Limit source line length to 100 characters
src/services/apis/claude-api.mjs[83-83]
tests/unit/services/apis/claude-api.test.mjs[234-253]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New Claude error and test fixture strings exceed the 100-character physical line limit.

## Issue Context
Preserve the exact runtime string values by wrapping them with concatenation or another formatting approach that does not introduce whitespace.

## Fix Focus Areas
- src/services/apis/claude-api.mjs[83-83]
- tests/unit/services/apis/claude-api.test.mjs[234-253]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Locale JSON lines exceed 100 📘 Rule violation ⚙ Maintainability
Description
New localization entries add very long single-line JSON mappings that exceed the 100-character
line-length limit. This reduces readability and violates the project’s max line length requirement.
Code

src/_locales/en/main.json[R97-99]

+  "Claude reached the response token limit. Increase Max Response Token Length and try again.": "Claude reached the response token limit. Increase Max Response Token Length and try again.",
+  "Claude declined to respond to this request.": "Claude declined to respond to this request.",
+  "Claude response stream ended before completion.": "Claude response stream ended before completion.",
Evidence
PR Compliance ID 2261946 requires all non-comment lines to be <= 100 characters. The newly added
locale mappings include full-sentence keys and values on the same line, which necessarily pushes the
physical line length well beyond 100 characters.

Rule 2261946: Limit source line length to 100 characters
src/_locales/en/main.json[97-99]
src/_locales/de/main.json[90-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New locale entries are written as single-line JSON key/value pairs whose physical line length exceeds 100 characters.

## Issue Context
These keys/values are full sentences (often duplicated as key and value), which makes each JSON line very long in multiple `src/_locales/*/main.json` files.

## Fix Focus Areas
- src/_locales/en/main.json[97-99]
- src/_locales/de/main.json[90-92]

Potential approaches:
- Reformat JSON entries so the key and value are on separate lines (only helps if each individual string stays <= 100 chars).
- Shorten the user-facing strings (and keep them consistent with any code that matches on these messages).
- If long translations are expected, add an explicit repo-wide exemption for `src/_locales/**/main.json` in the relevant line-length/linting configuration.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Previous review results

Review updated until commit 46786e0

Results up to commit d015a29 ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Informational
1. Locale JSON lines exceed 100 📘 Rule violation ⚙ Maintainability
Description
New localization entries add very long single-line JSON mappings that exceed the 100-character
line-length limit. This reduces readability and violates the project’s max line length requirement.
Code

src/_locales/en/main.json[R97-99]

+  "Claude reached the response token limit. Increase Max Response Token Length and try again.": "Claude reached the response token limit. Increase Max Response Token Length and try again.",
+  "Claude declined to respond to this request.": "Claude declined to respond to this request.",
+  "Claude response stream ended before completion.": "Claude response stream ended before completion.",
Evidence
PR Compliance ID 2261946 requires all non-comment lines to be <= 100 characters. The newly added
locale mappings include full-sentence keys and values on the same line, which necessarily pushes the
physical line length well beyond 100 characters.

Rule 2261946: Limit source line length to 100 characters
src/_locales/en/main.json[97-99]
src/_locales/de/main.json[90-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New locale entries are written as single-line JSON key/value pairs whose physical line length exceeds 100 characters.

## Issue Context
These keys/values are full sentences (often duplicated as key and value), which makes each JSON line very long in multiple `src/_locales/*/main.json` files.

## Fix Focus Areas
- src/_locales/en/main.json[97-99]
- src/_locales/de/main.json[90-92]

Potential approaches:
- Reformat JSON entries so the key and value are on separate lines (only helps if each individual string stays <= 100 chars).
- Shorten the user-facing strings (and keep them consistent with any code that matches on these messages).
- If long translations are expected, add an explicit repo-wide exemption for `src/_locales/**/main.json` in the relevant line-length/linting configuration.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread src/_locales/en/main.json
Comment on lines +97 to +99
"Claude reached the response token limit. Increase Max Response Token Length and try again.": "Claude reached the response token limit. Increase Max Response Token Length and try again.",
"Claude declined to respond to this request.": "Claude declined to respond to this request.",
"Claude response stream ended before completion.": "Claude response stream ended before completion.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Informational

1. Locale json lines exceed 100 📘 Rule violation ⚙ Maintainability

New localization entries add very long single-line JSON mappings that exceed the 100-character
line-length limit. This reduces readability and violates the project’s max line length requirement.
Agent Prompt
## Issue description
New locale entries are written as single-line JSON key/value pairs whose physical line length exceeds 100 characters.

## Issue Context
These keys/values are full sentences (often duplicated as key and value), which makes each JSON line very long in multiple `src/_locales/*/main.json` files.

## Fix Focus Areas
- src/_locales/en/main.json[97-99]
- src/_locales/de/main.json[90-92]

Potential approaches:
- Reformat JSON entries so the key and value are on separate lines (only helps if each individual string stays <= 100 chars).
- Shorten the user-facing strings (and keep them consistent with any code that matches on these messages).
- If long translations are expected, add an explicit repo-wide exemption for `src/_locales/**/main.json` in the relevant line-length/linting configuration.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/services/apis/claude-api.mjs`:
- Around line 91-95: In the successful completion path, set
completedSuccessfully to true before calling pushRecord and before
port.postMessage. Keep the existing persistence and notification behavior
unchanged so the completion flag remains true if either side effect fails after
the response has been recorded.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a65031d-7675-4dc9-bcab-b0d7d7534bda

📥 Commits

Reviewing files that changed from the base of the PR and between eaa9d4b and d015a29.

📒 Files selected for processing (15)
  • src/_locales/de/main.json
  • src/_locales/en/main.json
  • src/_locales/es/main.json
  • src/_locales/fr/main.json
  • src/_locales/in/main.json
  • src/_locales/it/main.json
  • src/_locales/ja/main.json
  • src/_locales/ko/main.json
  • src/_locales/pt/main.json
  • src/_locales/ru/main.json
  • src/_locales/tr/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/zh-hant/main.json
  • src/services/apis/claude-api.mjs
  • tests/unit/services/apis/claude-api.test.mjs

Comment thread src/services/apis/claude-api.mjs
@PeterDaveHello
PeterDaveHello force-pushed the improve-claude-stream-completion-handling branch from d015a29 to 02d0533 Compare July 28, 2026 14:47
@PeterDaveHello
PeterDaveHello requested a review from Copilot July 28, 2026 14:49

Copilot AI 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.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tests/unit/services/apis/claude-api.test.mjs:19

  • The new setupCompletionTest() helper seeds config using legacy storage keys (customClaudeApiUrl, claudeApiKey). These tests are about Claude API streaming behavior, so tying them to config-migration behavior makes them more brittle (they’ll start failing if/when the migration cleanup is removed). Prefer setting the current config keys directly.
const setupCompletionTest = (modelName = 'claudeOpus5Api') => {
  setStorage({
    customClaudeApiUrl: 'https://api.anthropic.com',
    claudeApiKey: 'sk-ant-test',
    maxConversationContextLength: 3,
    maxResponseTokenLength: 100,
    temperature: 0.5,
  })

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02d0533a8a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +135 to +136
if (!completedSuccessfully) {
throw new Error('Claude response stream ended before completion.')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve Anthropic SSE error details

When Anthropic accepts the request but later emits an SSE error event, such as overloaded_error, onMessage ignores that event and this fallback reports only “Claude response stream ended before completion.” This masks the provider's actionable error type/message during overloads and other mid-stream failures; capture data.error and surface it before applying the generic EOF fallback.

Useful? React with 👍 / 👎.

Comment on lines +93 to +96
if (stopReason === 'refusal') {
completionError = new Error('Claude declined to respond to this request.')
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject nonterminal Claude stop reasons

When Anthropic returns another non-final stop reason such as pause_turn, this blacklist falls through at message_stop, saves the partial answer, and reports success. A paused turn must be continued rather than committed as a completed response, so success should be limited to terminal reasons such as end_turn and stop_sequence, with pause_turn handled explicitly.

Useful? React with 👍 / 👎.

@PeterDaveHello

Copy link
Copy Markdown
Member Author

/agentic_review

if (data?.type === 'message_stop') {
if (stopReason === 'max_tokens') {
completionError = new Error(
'Claude reached the response token limit. Increase Max Response Token Length and try again.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Informational

1. Claude strings exceed 100 columns 📘 Rule violation ⚙ Maintainability

The new Claude error string and SSE fixtures contain physical lines longer than 100 characters.
These additions violate the source line-length limit.
Agent Prompt
## Issue description
New Claude error and test fixture strings exceed the 100-character physical line limit.

## Issue Context
Preserve the exact runtime string values by wrapping them with concatenation or another formatting approach that does not introduce whitespace.

## Fix Focus Areas
- src/services/apis/claude-api.mjs[83-83]
- tests/unit/services/apis/claude-api.test.mjs[234-253]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 02d0533

@PeterDaveHello
PeterDaveHello force-pushed the improve-claude-stream-completion-handling branch from 02d0533 to a33cc9d Compare July 30, 2026 18:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/unit/services/apis/claude-api.test.mjs (1)

499-514: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the finally cleanup actually ran.

This is the only test covering the new try/finally in onEnd, but it stops at the rejection. Add an assertion that onDisconnect was still removed so a regression that drops the finally would fail here.

♻️ Proposed addition
   await assert.rejects(generateAnswersWithClaudeApi(port, 'Q', session), /listener cleanup failed/)
+  assert.equal(port.listenerCounts().onDisconnect, 0)
+  assert.deepEqual(session.conversationRecords, [{ question: 'Q', answer: 'Answer' }])
 })
🤖 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 `@tests/unit/services/apis/claude-api.test.mjs` around lines 499 - 514, Extend
the test for generateAnswersWithClaudeApi to assert that the onDisconnect
listener was removed after the callback cleanup error. Keep the existing
rejection assertion and verify the cleanup state after it, so the test fails if
the onEnd finally block does not execute.
🤖 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.

Nitpick comments:
In `@tests/unit/services/apis/claude-api.test.mjs`:
- Around line 499-514: Extend the test for generateAnswersWithClaudeApi to
assert that the onDisconnect listener was removed after the callback cleanup
error. Keep the existing rejection assertion and verify the cleanup state after
it, so the test fails if the onEnd finally block does not execute.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a7141905-0d65-4694-931a-766dc0669e72

📥 Commits

Reviewing files that changed from the base of the PR and between 02d0533 and a33cc9d.

📒 Files selected for processing (15)
  • src/_locales/de/main.json
  • src/_locales/en/main.json
  • src/_locales/es/main.json
  • src/_locales/fr/main.json
  • src/_locales/in/main.json
  • src/_locales/it/main.json
  • src/_locales/ja/main.json
  • src/_locales/ko/main.json
  • src/_locales/pt/main.json
  • src/_locales/ru/main.json
  • src/_locales/tr/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/zh-hant/main.json
  • src/services/apis/claude-api.mjs
  • tests/unit/services/apis/claude-api.test.mjs
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/_locales/en/main.json
  • src/_locales/fr/main.json
  • src/_locales/ko/main.json
  • src/_locales/ja/main.json
  • src/_locales/ru/main.json
  • src/_locales/pt/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/zh-hant/main.json
  • src/_locales/it/main.json
  • src/_locales/de/main.json
  • src/_locales/in/main.json

Copilot AI 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.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit a33cc9d

Reject token, context, refusal, and nonterminal stop conditions instead
of treating incomplete Claude responses as successful completions. Stop
processing once a response completes and surface streamed API errors
without undoing completed responses.

Add localized completion errors and regression coverage for stop
reasons, provider errors, transport failures, callbacks, and aborts.

Follow-up to ChatGPTBox-dev#1026.
@PeterDaveHello
PeterDaveHello force-pushed the improve-claude-stream-completion-handling branch from a33cc9d to 46786e0 Compare July 30, 2026 19:10
@PeterDaveHello
PeterDaveHello requested a review from Copilot July 30, 2026 19:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/services/apis/claude-api.mjs (1)

137-148: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Ordering nuance worth documenting: wasAborted short-circuits before completionError.

Today this is safe because a completionError always throws synchronously out of onMessage, so fetchSSE rejects via onError without ever invoking onEnd(true) (tests at tests/unit/services/apis/claude-api.test.mjs Lines 542-581 pin readCount === 1). But if that throw path is ever softened (e.g. onError swallowing instead of rethrowing), the controller.abort() on Line 105 would surface as onEnd(true) and this early return would silently discard the token-limit/refusal error. A short comment here recording that invariant would protect the ordering against future refactors.

🤖 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/services/apis/claude-api.mjs` around lines 137 - 148, Document the
ordering invariant at the early wasAborted return in the stream completion
handling: it must remain before completionError because completionError
currently rejects synchronously through onMessage/onError, preventing
onEnd(true) from masking it. Add a concise comment near wasAborted that warns
future changes must preserve this behavior.
🤖 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.

Nitpick comments:
In `@src/services/apis/claude-api.mjs`:
- Around line 137-148: Document the ordering invariant at the early wasAborted
return in the stream completion handling: it must remain before completionError
because completionError currently rejects synchronously through
onMessage/onError, preventing onEnd(true) from masking it. Add a concise comment
near wasAborted that warns future changes must preserve this behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d5b24a81-ffb0-457e-9c96-4eeb1e4e1769

📥 Commits

Reviewing files that changed from the base of the PR and between a33cc9d and 46786e0.

📒 Files selected for processing (15)
  • src/_locales/de/main.json
  • src/_locales/en/main.json
  • src/_locales/es/main.json
  • src/_locales/fr/main.json
  • src/_locales/in/main.json
  • src/_locales/it/main.json
  • src/_locales/ja/main.json
  • src/_locales/ko/main.json
  • src/_locales/pt/main.json
  • src/_locales/ru/main.json
  • src/_locales/tr/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/zh-hant/main.json
  • src/services/apis/claude-api.mjs
  • tests/unit/services/apis/claude-api.test.mjs
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/_locales/ko/main.json
  • src/_locales/fr/main.json
  • src/_locales/zh-hant/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/ru/main.json
  • src/_locales/de/main.json
  • src/_locales/in/main.json
  • src/_locales/it/main.json
  • src/_locales/es/main.json
  • src/_locales/en/main.json
  • src/_locales/pt/main.json

Copilot AI 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.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 46786e0

@PeterDaveHello
PeterDaveHello merged commit c05d505 into ChatGPTBox-dev:master Jul 30, 2026
4 checks passed
@PeterDaveHello
PeterDaveHello deleted the improve-claude-stream-completion-handling branch July 30, 2026 19:28
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.

2 participants