main => prod#368
Merged
dariusz-did merged 9 commits intoprodfrom Apr 28, 2026
Merged
Conversation
chore: upgrade Node.js from 20 to 22
The first assistant turn of a session (an unsolicited greeting) was being dropped because processChatEvent's message-creation branch only fired when the last message was a transcribed user turn. With an empty message list, every partial and answer hit the fallback early return and the greeting never appeared in the UI. Broaden the creation branch to also fire when there is no last message. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: add message.parts — structured content representation Add MessagePart type and optional parts field to Message interface. Create content-parser utility that parses markdown content (images, videos, links, HTML anchors) into typed MessagePart arrays. Integrate parser into all message construction paths: - Streaming pipeline (processChatEvent partials + answers) - Audio transcription (handleAudioTranscribedMessage) - REST chat (user message + assistant response) - Speak (assistant message) Export parseMessageParts utility and MessagePart type from SDK public API for consumer use. * fix: harden regexes against ReDoS (CodeQL polynomial backtracking) Restrict character classes to prevent catastrophic backtracking: - Alt text: [^\]* → [^\[\]]* (disallow nested brackets) - URLs: [^)]+ → [^)\s]+ (disallow whitespace in URLs) - HTML attrs: [^>]* → [^>]*? (lazy quantifier) * style: fix prettier formatting * refactor: use parseMessagePartsMemo consistently across internal SDK code Unify message parsing calls inside the SDK on the memoized variant. The non-memo parseMessageParts remains the public API export for consumers.
Change Message.parts from optional to required so consumers can rely on it without defensive fallbacks. This closes a narrow contract gap where the SDK briefly pushes a Message into items.messages before the first content chunk arrives, leaving parts undefined. Initialize parts: [] in the only construction site that lacked it (streaming assistant message in message-queue.ts). All other paths already populated parts via parseMessagePartsMemo. This is a type-level tightening matching the actual runtime contract.
* fix: preserve multiple assistant messages within the same turn When a backend emits more than one `chat/answer` event for a single user turn (e.g. after a client tool call, or when the agent sends several messages in a row), the previous assistant message was being overwritten because `processChatEvent` reused the last assistant message in the list without comparing ids. Detect the case via `data.id !== lastMessage.id` on `ChatProgress.Answer` and push a new message, clearing the streaming buffer so its content does not leak into the new one. Same id or missing id keeps the existing overwrite behaviour for backward compatibility. Asana: https://app.asana.com/1/856614567666442/project/1213882276505882/task/1214081847771983 * style: apply prettier formatting * fix: detect new assistant message on partial events too New assistant messages typically start streaming with Partial events before the final Answer, so the id-change discriminator must fire on both event types — otherwise the first Partial of the new message overwrites the previous one.
* fix: dispatch new tool-call/* data channel events Backend migrated tool execution notifications from tool/calling + tool/result to tool-call/started + tool-call/done + tool-call/error. Add the new subjects to the dispatch table and route tool-call/started through handleToolEvents so the SDK emits AgentActivityState.ToolActive again. Full onToolEvent payload rewire is tracked in a follow-up task. * chore: remove unused ToolCalling/ToolResult events Backend no longer emits tool/calling or tool/result — the new tool-call/* subjects replaced them. This removes the dead enum values, payload types, dispatch entries, and the onToolEvent callback whose signature was pinned to the legacy payloads. The public onToolEvent callback will be reintroduced with the new payload shapes as part of the deferred full-support task. Addresses review feedback on #366. * feat: wire onToolEvent to new tool-call/* payloads Adds ToolCallStartedPayload, ToolCallDonePayload and ToolCallErrorPayload type definitions matching the backend wire format (call_id, name, input, output, timestamp; plus duration_ms and extra on done/error). Restores the public onToolEvent callback with an overloaded signature discriminated by the event argument, and invokes it from handleToolEvents for all three tool-call events. tool-call/started still drives the ToolActive activity state transition; tool-call/done and tool-call/error only forward the payload and leave state transitions to the existing stream-video/done path.
dor-eitan
approved these changes
Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Type
🔮 Feature
🐛 BugFix
⚒️ Refactor
🧹 Chore
🔥 HotFix
🚀 Release
Description
Reference Links