Skip to content

Commit f1170fb

Browse files
committed
fix: restructure existing agent patterns and fix bugs
1 parent 4bb6dc7 commit f1170fb

File tree

30 files changed

+521
-600
lines changed

30 files changed

+521
-600
lines changed

frontend/package-lock.json

Lines changed: 58 additions & 57 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/src/lib/agentcore-client/parsers/langgraph.ts

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@ import type { ChunkParser } from "../types"
66
/**
77
* Parses SSE chunks from LangGraph agents (stream_mode="messages").
88
*
9-
* Each SSE line is a model_dump() of either AIMessageChunk or ToolMessage.
9+
* Uses LangChain's normalized message fields — works with any ChatModel backend.
1010
*
11-
* AIMessageChunk shapes:
12-
* - text: content: [{type:"text", text:"...", index:N}]
13-
* - tool start: content: [{type:"tool_use", id, name, input:{}, index:N}] + tool_calls[]
14-
* - tool delta: content: [{type:"tool_use", partial_json:"...", index:N}] + tool_call_chunks[]
15-
* - stop: response_metadata: {stop_reason:"end_turn"|"tool_use"}
16-
* - last: chunk_position: "last"
17-
*
18-
* ToolMessage shape:
19-
* - type: "tool", content: "result", name: "tool_name", tool_call_id: "id"
11+
* Stream format:
12+
* AIMessageChunk:
13+
* - text: content (string)
14+
* - tool start: tool_call_chunks[{id, name, args}] — first chunk has id + name
15+
* - tool delta: tool_call_chunks[{args}] — subsequent chunks have args only
16+
* - stop: response_metadata.stop_reason
17+
* ToolMessage:
18+
* - type: "tool", content: string, tool_call_id: string
2019
*/
2120

22-
// Track current tool_use_id across chunks (deltas don't carry the id)
21+
// Track current tool_use_id — streaming deltas may omit the id
2322
let currentToolUseId = ""
2423

2524
export const parseLanggraphChunk: ChunkParser = (line, callback) => {
@@ -43,39 +42,29 @@ export const parseLanggraphChunk: ChunkParser = (line, callback) => {
4342

4443
// AIMessageChunk
4544
if (json.type === "AIMessageChunk") {
46-
// Content as plain string (when model responds without tool use)
45+
// Text token — content can be a string or array of text blocks
4746
if (typeof json.content === "string" && json.content) {
4847
callback({ type: "text", content: json.content })
49-
}
50-
51-
// Content as array of blocks (when model uses tools)
52-
if (Array.isArray(json.content)) {
48+
} else if (Array.isArray(json.content)) {
5349
for (const block of json.content) {
54-
// Text token
5550
if (block.type === "text" && block.text) {
5651
callback({ type: "text", content: block.text })
5752
}
53+
}
54+
}
5855

59-
// Tool use start — has id and name
60-
if (block.type === "tool_use" && block.id && block.name) {
61-
currentToolUseId = block.id
62-
callback({
63-
type: "tool_use_start",
64-
toolUseId: block.id,
65-
name: block.name,
66-
})
56+
// Tool calls — streamed via tool_call_chunks (LangChain's standard streaming field)
57+
if (Array.isArray(json.tool_call_chunks)) {
58+
for (const chunk of json.tool_call_chunks) {
59+
if (chunk.id && chunk.name) {
60+
currentToolUseId = chunk.id
61+
callback({ type: "tool_use_start", toolUseId: chunk.id, name: chunk.name })
6762
}
68-
69-
// Tool input streaming — has partial_json
70-
if (
71-
block.type === "tool_use" &&
72-
typeof block.partial_json === "string" &&
73-
block.partial_json
74-
) {
63+
if (typeof chunk.args === "string" && chunk.args) {
7564
callback({
7665
type: "tool_use_delta",
77-
toolUseId: currentToolUseId,
78-
input: block.partial_json,
66+
toolUseId: chunk.id || currentToolUseId,
67+
input: chunk.args,
7968
})
8069
}
8170
}

0 commit comments

Comments
 (0)