Skip to content

fix: tolerate anthropic relays that omit text deltas - #3207

Open
rootkiller6788 wants to merge 1 commit into
MoonshotAI:mainfrom
rootkiller6788:fix-anthropic-missing-text-delta
Open

fix: tolerate anthropic relays that omit text deltas#3207
rootkiller6788 wants to merge 1 commit into
MoonshotAI:mainfrom
rootkiller6788:fix-anthropic-missing-text-delta

Conversation

@rootkiller6788

Copy link
Copy Markdown

Closes #2924

Problem

Some Anthropic-compatible relays stream content_block_start (text) and text_delta events without the text field. The stream converter then yields { type: 'text', text: undefined }, the v2 loop forwards part.text verbatim as the delta, and JSON serialization drops the delta key; the TUI renderer crashes with Cannot read properties of undefined (reading 'trim').

Verified against the current source:

  • packages/agent-core-v2/src/kosong/provider/bases/anthropic/anthropic.ts yields text: block.text / text: delta.text unguarded (while thinking already falls back to ?? '').
  • packages/agent-core-v2/src/agent/loop/loopService.ts forwards part.text verbatim as the delta.
  • apps/kimi-code/src/tui/controllers/session-event-handler.ts calls event.delta.trim() on both thinking.delta and assistant.delta.

Fix

  • Coerce missing text to '' in both the v2 and packages/kosong Anthropic stream converters, matching the existing thinking ?? '' pattern.
  • Defensively coerce a non-string delta to '' in the TUI handlers so a malformed wire record can never crash the renderer.

Test

Regression test in packages/kosong/test/anthropic.test.ts feeds content_block_start / text_delta events that omit text; it fails on the old code (yields text: undefined) and passes after the fix. Full packages/kosong suite: 49 files / 1366 tests green.

Some Anthropic-compatible relays stream text blocks and text_delta events
without a text field. The stream converter then yields a text part with
undefined text, which the v2 loop publishes as an assistant.delta event
without a delta field, crashing the TUI renderer with a trim() on
undefined.

Coerce missing text to an empty string in both the v2 and kosong Anthropic
stream converters (matching the existing thinking ?? '' pattern), and
defensively coerce a non-string delta in the TUI session event handlers.
@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a0fdafe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@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: a0fdafe1e0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

{ type: 'message_stop' },
]);

(provider as any)._client.messages.create = vi.fn().mockResolvedValue(stream) as never;

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 Stub the relay through the public client factory

This regression test reaches into the private _client field, so a refactor of the provider's client storage or initialization would break the test even if streaming behavior remains correct. Construct the provider with the supported clientFactory boundary instead; the existing collectAnthropicStreamParts helper already does this and can exercise the same malformed relay events through generate() without depending on private implementation details.

Useful? React with 👍 / 👎.

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.

[Bug] TUI crashes on assistant.delta events with missing delta payload (Cannot read properties of undefined (reading 'trim'))

1 participant