Skip to content

main => prod#370

Merged
dariusz-did merged 11 commits intoprodfrom
main
Apr 28, 2026
Merged

main => prod#370
dariusz-did merged 11 commits intoprodfrom
main

Conversation

@dariusz-did
Copy link
Copy Markdown
Contributor

Pull Request Type

🔮 Feature
🐛 BugFix
⚒️ Refactor
🧹 Chore
🔥 HotFix
🚀 Release

Description

Reference Links

dor-eitan and others added 10 commits April 15, 2026 15:45
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.
@dariusz-did dariusz-did marked this pull request as ready for review April 28, 2026 10:14
@dariusz-did dariusz-did merged commit abc3d20 into prod Apr 28, 2026
17 checks passed
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