@langchain/langgraph-sdk 1.9.5 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/client/stream/handles/subagents.cjs +3 -1
  2. package/dist/client/stream/handles/subagents.cjs.map +1 -1
  3. package/dist/client/stream/handles/subagents.d.cts.map +1 -1
  4. package/dist/client/stream/handles/subagents.d.ts.map +1 -1
  5. package/dist/client/stream/handles/subagents.js +4 -2
  6. package/dist/client/stream/handles/subagents.js.map +1 -1
  7. package/dist/client/stream/handles/tools.cjs +75 -10
  8. package/dist/client/stream/handles/tools.cjs.map +1 -1
  9. package/dist/client/stream/handles/tools.d.cts +6 -5
  10. package/dist/client/stream/handles/tools.d.cts.map +1 -1
  11. package/dist/client/stream/handles/tools.d.ts +6 -5
  12. package/dist/client/stream/handles/tools.d.ts.map +1 -1
  13. package/dist/client/stream/handles/tools.js +75 -11
  14. package/dist/client/stream/handles/tools.js.map +1 -1
  15. package/dist/client/stream/index.cjs +11 -3
  16. package/dist/client/stream/index.cjs.map +1 -1
  17. package/dist/client/stream/index.d.cts.map +1 -1
  18. package/dist/client/stream/index.d.ts.map +1 -1
  19. package/dist/client/stream/index.js +11 -3
  20. package/dist/client/stream/index.js.map +1 -1
  21. package/dist/headless-tools.cjs +128 -4
  22. package/dist/headless-tools.cjs.map +1 -1
  23. package/dist/headless-tools.d.cts +9 -1
  24. package/dist/headless-tools.d.cts.map +1 -1
  25. package/dist/headless-tools.d.ts +9 -1
  26. package/dist/headless-tools.d.ts.map +1 -1
  27. package/dist/headless-tools.js +126 -5
  28. package/dist/headless-tools.js.map +1 -1
  29. package/dist/index.cjs +1 -0
  30. package/dist/index.d.cts +2 -2
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +2 -2
  33. package/dist/react/stream.lgp.cjs +15 -1
  34. package/dist/react/stream.lgp.cjs.map +1 -1
  35. package/dist/react/stream.lgp.js +15 -1
  36. package/dist/react/stream.lgp.js.map +1 -1
  37. package/dist/stream/controller.cjs +26 -15
  38. package/dist/stream/controller.cjs.map +1 -1
  39. package/dist/stream/controller.d.cts +3 -1
  40. package/dist/stream/controller.d.cts.map +1 -1
  41. package/dist/stream/controller.d.ts +3 -1
  42. package/dist/stream/controller.d.ts.map +1 -1
  43. package/dist/stream/controller.js +27 -16
  44. package/dist/stream/controller.js.map +1 -1
  45. package/dist/stream/discovery/subagents.cjs +13 -0
  46. package/dist/stream/discovery/subagents.cjs.map +1 -1
  47. package/dist/stream/discovery/subagents.d.cts +5 -0
  48. package/dist/stream/discovery/subagents.d.cts.map +1 -1
  49. package/dist/stream/discovery/subagents.d.ts +5 -0
  50. package/dist/stream/discovery/subagents.d.ts.map +1 -1
  51. package/dist/stream/discovery/subagents.js +13 -0
  52. package/dist/stream/discovery/subagents.js.map +1 -1
  53. package/dist/stream/discovery/subgraphs.cjs +13 -0
  54. package/dist/stream/discovery/subgraphs.cjs.map +1 -1
  55. package/dist/stream/discovery/subgraphs.d.cts +5 -0
  56. package/dist/stream/discovery/subgraphs.d.cts.map +1 -1
  57. package/dist/stream/discovery/subgraphs.d.ts +5 -0
  58. package/dist/stream/discovery/subgraphs.d.ts.map +1 -1
  59. package/dist/stream/discovery/subgraphs.js +13 -0
  60. package/dist/stream/discovery/subgraphs.js.map +1 -1
  61. package/dist/stream/projections/tool-calls.cjs +1 -2
  62. package/dist/stream/projections/tool-calls.cjs.map +1 -1
  63. package/dist/stream/projections/tool-calls.d.cts.map +1 -1
  64. package/dist/stream/projections/tool-calls.d.ts.map +1 -1
  65. package/dist/stream/projections/tool-calls.js +2 -3
  66. package/dist/stream/projections/tool-calls.js.map +1 -1
  67. package/dist/stream/submit-coordinator.cjs +10 -12
  68. package/dist/stream/submit-coordinator.cjs.map +1 -1
  69. package/dist/stream/submit-coordinator.d.cts.map +1 -1
  70. package/dist/stream/submit-coordinator.d.ts.map +1 -1
  71. package/dist/stream/submit-coordinator.js +10 -12
  72. package/dist/stream/submit-coordinator.js.map +1 -1
  73. package/dist/stream/tool-calls.cjs +39 -2
  74. package/dist/stream/tool-calls.cjs.map +1 -1
  75. package/dist/stream/tool-calls.js +38 -3
  76. package/dist/stream/tool-calls.js.map +1 -1
  77. package/dist/stream/types.d.cts +2 -2
  78. package/dist/stream/types.d.ts +2 -2
  79. package/package.json +1 -1
@@ -57,7 +57,9 @@ var SubagentHandle = class {
57
57
  const assembler = new require_tools.ToolCallAssembler();
58
58
  this.#startProjection(["tools"], (event) => {
59
59
  if (event.method !== "tools") return;
60
- const tc = assembler.consume(event);
60
+ const toolsEvent = event;
61
+ if (require_tools.shouldIgnoreScopedTaskToolEvent(this.namespace, toolsEvent)) return;
62
+ const tc = assembler.consume(toolsEvent);
61
63
  if (tc) buffer.push(require_tools.toClientAssembledToolCall(tc));
62
64
  }, () => buffer.close());
63
65
  return buffer;
@@ -1 +1 @@
1
- {"version":3,"file":"subagents.cjs","names":["#session","#messagesIterable","MultiCursorBuffer","StreamingMessageAssembler","#startProjection","#toolCallsIterable","ToolCallAssembler","toClientAssembledToolCall","#ensureMediaDispatcher","#audioBuffer","#imagesBuffer","#videoBuffer","#filesBuffer","#mediaDispatcherStarted","MediaAssembler","#subgraphsIterable","SubgraphDiscoveryHandle","#source","#queue","#waiters","#pending","#sourcePump","#processEvent","#closed","#start"],"sources":["../../../../src/client/stream/handles/subagents.ts"],"sourcesContent":["import type {\n Channel,\n Event,\n MessagesEvent,\n SubscribeParams,\n ToolsEvent,\n} from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../index.js\";\nimport { MultiCursorBuffer } from \"../multi-cursor-buffer.js\";\nimport { StreamingMessageAssembler } from \"../messages.js\";\nimport type { StreamingMessage, StreamingMessageHandle } from \"../messages.js\";\nimport { ToolCallAssembler, toClientAssembledToolCall } from \"./tools.js\";\nimport type { ClientAssembledToolCall } from \"./tools.js\";\nimport { MediaAssembler } from \"../media.js\";\nimport type {\n AudioMedia,\n FileMedia,\n ImageMedia,\n VideoMedia,\n} from \"../media.js\";\nimport type {\n EventForChannel,\n EventForChannels,\n SubscribeOptions,\n YieldForChannel,\n YieldForChannels,\n} from \"../types.js\";\nimport {\n type Subscribable,\n type SubgraphHandle,\n SubgraphDiscoveryHandle,\n} from \"./subgraphs.js\";\n\n/**\n * Discovered subagent within a streaming session. Mirrors the\n * in-process `SubagentRunStream` from DeepAgent.\n *\n * Each subagent is discovered when a `tool-started` event with\n * `tool_name === \"task\"` is observed. The `taskInput` and `output`\n * promises resolve from the task tool's lifecycle events.\n *\n * Use lazy getters (`sub.messages`, `sub.toolCalls`, etc.) for\n * namespace-scoped projections.\n */\nexport class SubagentHandle {\n readonly name: string;\n readonly callId: string;\n readonly taskInput: Promise<string>;\n readonly output: Promise<unknown>;\n readonly namespace: string[];\n readonly #session: Subscribable;\n\n #messagesIterable?: AsyncIterable<StreamingMessage>;\n #toolCallsIterable?: AsyncIterable<ClientAssembledToolCall>;\n #subgraphsIterable?: AsyncIterable<SubgraphHandle>;\n\n #mediaDispatcherStarted = false;\n #audioBuffer?: MultiCursorBuffer<AudioMedia>;\n #imagesBuffer?: MultiCursorBuffer<ImageMedia>;\n #videoBuffer?: MultiCursorBuffer<VideoMedia>;\n #filesBuffer?: MultiCursorBuffer<FileMedia>;\n\n constructor(\n name: string,\n callId: string,\n namespace: string[],\n taskInput: Promise<string>,\n output: Promise<unknown>,\n session: Subscribable\n ) {\n this.name = name;\n this.callId = callId;\n this.namespace = namespace;\n this.taskInput = taskInput;\n this.output = output;\n this.#session = session;\n }\n\n get messages(): AsyncIterable<StreamingMessageHandle> {\n if (this.#messagesIterable) return this.#messagesIterable;\n const buffer = new MultiCursorBuffer<StreamingMessage>();\n this.#messagesIterable = buffer;\n const assembler = new StreamingMessageAssembler();\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n const msg = assembler.consume(event as MessagesEvent);\n if (msg) buffer.push(msg);\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get toolCalls(): AsyncIterable<ClientAssembledToolCall> {\n if (this.#toolCallsIterable) return this.#toolCallsIterable;\n const buffer = new MultiCursorBuffer<ClientAssembledToolCall>();\n this.#toolCallsIterable = buffer;\n const assembler = new ToolCallAssembler();\n void this.#startProjection(\n [\"tools\"],\n (event) => {\n if (event.method !== \"tools\") return;\n const tc = assembler.consume(event as ToolsEvent);\n if (tc) buffer.push(toClientAssembledToolCall(tc));\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get audio(): AsyncIterable<AudioMedia> {\n this.#ensureMediaDispatcher();\n return this.#audioBuffer!;\n }\n\n get images(): AsyncIterable<ImageMedia> {\n this.#ensureMediaDispatcher();\n return this.#imagesBuffer!;\n }\n\n get video(): AsyncIterable<VideoMedia> {\n this.#ensureMediaDispatcher();\n return this.#videoBuffer!;\n }\n\n get files(): AsyncIterable<FileMedia> {\n this.#ensureMediaDispatcher();\n return this.#filesBuffer!;\n }\n\n #ensureMediaDispatcher(): void {\n if (this.#mediaDispatcherStarted) return;\n this.#mediaDispatcherStarted = true;\n const audio = new MultiCursorBuffer<AudioMedia>();\n const images = new MultiCursorBuffer<ImageMedia>();\n const video = new MultiCursorBuffer<VideoMedia>();\n const files = new MultiCursorBuffer<FileMedia>();\n this.#audioBuffer = audio;\n this.#imagesBuffer = images;\n this.#videoBuffer = video;\n this.#filesBuffer = files;\n const assembler = new MediaAssembler({\n onAudio: (m: AudioMedia) => audio.push(m),\n onImage: (m: ImageMedia) => images.push(m),\n onVideo: (m: VideoMedia) => video.push(m),\n onFile: (m: FileMedia) => files.push(m),\n });\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n assembler.consume(event as MessagesEvent);\n },\n () => {\n assembler.close();\n audio.close();\n images.close();\n video.close();\n files.close();\n }\n );\n }\n\n get subgraphs(): AsyncIterable<SubgraphHandle> {\n if (this.#subgraphsIterable) return this.#subgraphsIterable;\n const buffer = new MultiCursorBuffer<SubgraphHandle>();\n this.#subgraphsIterable = buffer;\n void (async () => {\n const rawHandle = await this.#session.subscribe({\n channels: [\"lifecycle\"],\n namespaces: [this.namespace],\n });\n const discovery = new SubgraphDiscoveryHandle(\n rawHandle,\n this.#session,\n this.namespace\n );\n for await (const sub of discovery) {\n buffer.push(sub);\n }\n buffer.close();\n })();\n return buffer;\n }\n\n /**\n * Create a raw channel subscription scoped to this subagent's namespace.\n */\n subscribe<TChannel extends Channel>(\n channel: TChannel,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannel<TChannel>, YieldForChannel<TChannel>>\n >;\n subscribe<const TChannels extends readonly Channel[]>(\n channels: TChannels,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannels<TChannels>, YieldForChannels<TChannels>>\n >;\n subscribe(params: SubscribeParams): Promise<SubscriptionHandle<Event>>;\n subscribe(\n paramsOrChannels: SubscribeParams | Channel | string | readonly Channel[],\n options: SubscribeOptions = {}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n if (\n typeof paramsOrChannels === \"object\" &&\n !Array.isArray(paramsOrChannels) &&\n \"channels\" in paramsOrChannels\n ) {\n return this.#session.subscribe({\n ...paramsOrChannels,\n namespaces: paramsOrChannels.namespaces ?? [this.namespace],\n });\n }\n\n return this.#session.subscribe(paramsOrChannels as Channel, {\n ...options,\n namespaces: options.namespaces ?? [this.namespace],\n });\n }\n\n async #startProjection(\n channels: Channel[],\n onEvent: (event: Event) => void,\n onDone: () => void\n ): Promise<void> {\n try {\n const rawHandle = await this.#session.subscribe({\n channels,\n namespaces: [this.namespace],\n });\n for await (const event of rawHandle) {\n onEvent(event);\n }\n } finally {\n onDone();\n }\n }\n}\n\n/**\n * Async iterable that yields {@link SubagentHandle} instances as task\n * tool calls are discovered from the `tools` channel.\n *\n * Mirrors the in-process `createSubagentTransformer` from DeepAgent:\n * watches for `tool_name === \"task\"` with `tool-started`, extracts\n * `subagent_type` and `description` from the input, and resolves\n * `output` on `tool-finished`.\n */\nexport class SubagentDiscoveryHandle implements AsyncIterable<SubagentHandle> {\n readonly #source: SubscriptionHandle<Event>;\n readonly #session: Subscribable;\n readonly #queue: SubagentHandle[] = [];\n readonly #waiters: Array<(value: IteratorResult<SubagentHandle>) => void> =\n [];\n readonly #pending = new Map<\n string,\n {\n resolveOutput: (v: unknown) => void;\n rejectOutput: (e: unknown) => void;\n }\n >();\n #sourcePump?: Promise<void>;\n #closed = false;\n\n constructor(source: SubscriptionHandle<Event>, session: Subscribable) {\n this.#source = source;\n this.#session = session;\n }\n\n #processEvent(event: Event): SubagentHandle | undefined {\n if (event.method !== \"tools\") return undefined;\n const tools = event as ToolsEvent;\n const data = tools.params.data;\n const toolCallId = (data as Record<string, unknown>).tool_call_id as string;\n const toolName = (data as Record<string, unknown>).tool_name as string;\n\n if (toolName === \"task\" && data.event === \"tool-started\") {\n const rawInput = (data as Record<string, unknown>).input;\n const input: { description?: string; subagent_type?: string } =\n typeof rawInput === \"string\"\n ? JSON.parse(rawInput)\n : ((rawInput as Record<string, unknown>) ?? {});\n\n const name = input.subagent_type ?? \"unknown\";\n const description = input.description ?? \"\";\n\n let resolveTaskInput!: (v: string) => void;\n let resolveOutput!: (v: unknown) => void;\n let rejectOutput!: (e: unknown) => void;\n\n const taskInput = new Promise<string>((r) => {\n resolveTaskInput = r;\n });\n const output = new Promise<unknown>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n resolveTaskInput(description);\n this.#pending.set(toolCallId, { resolveOutput, rejectOutput });\n\n const namespace = [...tools.params.namespace];\n\n return new SubagentHandle(\n name,\n toolCallId,\n namespace,\n taskInput,\n output,\n this.#session\n );\n }\n\n if (toolCallId) {\n const pending = this.#pending.get(toolCallId);\n if (pending) {\n if (data.event === \"tool-finished\") {\n pending.resolveOutput((data as Record<string, unknown>).output);\n this.#pending.delete(toolCallId);\n } else if (data.event === \"tool-error\") {\n const message =\n ((data as Record<string, unknown>).message as string) ??\n \"unknown error\";\n pending.rejectOutput(new Error(message));\n this.#pending.delete(toolCallId);\n }\n }\n }\n\n return undefined;\n }\n\n #start(): void {\n if (this.#sourcePump) return;\n this.#sourcePump = (async () => {\n for await (const event of this.#source) {\n const handle = this.#processEvent(event);\n if (!handle) continue;\n\n const waiter = this.#waiters.shift();\n if (waiter) {\n waiter({ done: false, value: handle });\n } else {\n this.#queue.push(handle);\n }\n }\n this.#closed = true;\n for (const pending of this.#pending.values()) {\n pending.resolveOutput(undefined);\n }\n this.#pending.clear();\n while (this.#waiters.length > 0) {\n this.#waiters.shift()?.({ done: true, value: undefined });\n }\n })();\n }\n\n async close(): Promise<void> {\n this.#closed = true;\n await this.#source.unsubscribe();\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SubagentHandle> {\n this.#start();\n return {\n next: async () => {\n if (this.#queue.length > 0) {\n return { done: false, value: this.#queue.shift()! };\n }\n if (this.#closed) {\n return { done: true, value: undefined };\n }\n return await new Promise<IteratorResult<SubagentHandle>>((resolve) => {\n this.#waiters.push(resolve);\n });\n },\n return: async () => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"subagents.cjs","names":["#session","#messagesIterable","MultiCursorBuffer","StreamingMessageAssembler","#startProjection","#toolCallsIterable","ToolCallAssembler","shouldIgnoreScopedTaskToolEvent","toClientAssembledToolCall","#ensureMediaDispatcher","#audioBuffer","#imagesBuffer","#videoBuffer","#filesBuffer","#mediaDispatcherStarted","MediaAssembler","#subgraphsIterable","SubgraphDiscoveryHandle","#source","#queue","#waiters","#pending","#sourcePump","#processEvent","#closed","#start"],"sources":["../../../../src/client/stream/handles/subagents.ts"],"sourcesContent":["import type {\n Channel,\n Event,\n MessagesEvent,\n SubscribeParams,\n ToolsEvent,\n} from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../index.js\";\nimport { MultiCursorBuffer } from \"../multi-cursor-buffer.js\";\nimport { StreamingMessageAssembler } from \"../messages.js\";\nimport type { StreamingMessage, StreamingMessageHandle } from \"../messages.js\";\nimport {\n shouldIgnoreScopedTaskToolEvent,\n ToolCallAssembler,\n toClientAssembledToolCall,\n} from \"./tools.js\";\nimport type { ClientAssembledToolCall } from \"./tools.js\";\nimport { MediaAssembler } from \"../media.js\";\nimport type {\n AudioMedia,\n FileMedia,\n ImageMedia,\n VideoMedia,\n} from \"../media.js\";\nimport type {\n EventForChannel,\n EventForChannels,\n SubscribeOptions,\n YieldForChannel,\n YieldForChannels,\n} from \"../types.js\";\nimport {\n type Subscribable,\n type SubgraphHandle,\n SubgraphDiscoveryHandle,\n} from \"./subgraphs.js\";\n\n/**\n * Discovered subagent within a streaming session. Mirrors the\n * in-process `SubagentRunStream` from DeepAgent.\n *\n * Each subagent is discovered when a `tool-started` event with\n * `tool_name === \"task\"` is observed. The `taskInput` and `output`\n * promises resolve from the task tool's lifecycle events.\n *\n * Use lazy getters (`sub.messages`, `sub.toolCalls`, etc.) for\n * namespace-scoped projections.\n */\nexport class SubagentHandle {\n readonly name: string;\n readonly callId: string;\n readonly taskInput: Promise<string>;\n readonly output: Promise<unknown>;\n readonly namespace: string[];\n readonly #session: Subscribable;\n\n #messagesIterable?: AsyncIterable<StreamingMessage>;\n #toolCallsIterable?: AsyncIterable<ClientAssembledToolCall>;\n #subgraphsIterable?: AsyncIterable<SubgraphHandle>;\n\n #mediaDispatcherStarted = false;\n #audioBuffer?: MultiCursorBuffer<AudioMedia>;\n #imagesBuffer?: MultiCursorBuffer<ImageMedia>;\n #videoBuffer?: MultiCursorBuffer<VideoMedia>;\n #filesBuffer?: MultiCursorBuffer<FileMedia>;\n\n constructor(\n name: string,\n callId: string,\n namespace: string[],\n taskInput: Promise<string>,\n output: Promise<unknown>,\n session: Subscribable\n ) {\n this.name = name;\n this.callId = callId;\n this.namespace = namespace;\n this.taskInput = taskInput;\n this.output = output;\n this.#session = session;\n }\n\n get messages(): AsyncIterable<StreamingMessageHandle> {\n if (this.#messagesIterable) return this.#messagesIterable;\n const buffer = new MultiCursorBuffer<StreamingMessage>();\n this.#messagesIterable = buffer;\n const assembler = new StreamingMessageAssembler();\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n const msg = assembler.consume(event as MessagesEvent);\n if (msg) buffer.push(msg);\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get toolCalls(): AsyncIterable<ClientAssembledToolCall> {\n if (this.#toolCallsIterable) return this.#toolCallsIterable;\n const buffer = new MultiCursorBuffer<ClientAssembledToolCall>();\n this.#toolCallsIterable = buffer;\n const assembler = new ToolCallAssembler();\n void this.#startProjection(\n [\"tools\"],\n (event) => {\n if (event.method !== \"tools\") return;\n const toolsEvent = event as ToolsEvent;\n if (shouldIgnoreScopedTaskToolEvent(this.namespace, toolsEvent)) return;\n const tc = assembler.consume(toolsEvent);\n if (tc) buffer.push(toClientAssembledToolCall(tc));\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get audio(): AsyncIterable<AudioMedia> {\n this.#ensureMediaDispatcher();\n return this.#audioBuffer!;\n }\n\n get images(): AsyncIterable<ImageMedia> {\n this.#ensureMediaDispatcher();\n return this.#imagesBuffer!;\n }\n\n get video(): AsyncIterable<VideoMedia> {\n this.#ensureMediaDispatcher();\n return this.#videoBuffer!;\n }\n\n get files(): AsyncIterable<FileMedia> {\n this.#ensureMediaDispatcher();\n return this.#filesBuffer!;\n }\n\n #ensureMediaDispatcher(): void {\n if (this.#mediaDispatcherStarted) return;\n this.#mediaDispatcherStarted = true;\n const audio = new MultiCursorBuffer<AudioMedia>();\n const images = new MultiCursorBuffer<ImageMedia>();\n const video = new MultiCursorBuffer<VideoMedia>();\n const files = new MultiCursorBuffer<FileMedia>();\n this.#audioBuffer = audio;\n this.#imagesBuffer = images;\n this.#videoBuffer = video;\n this.#filesBuffer = files;\n const assembler = new MediaAssembler({\n onAudio: (m: AudioMedia) => audio.push(m),\n onImage: (m: ImageMedia) => images.push(m),\n onVideo: (m: VideoMedia) => video.push(m),\n onFile: (m: FileMedia) => files.push(m),\n });\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n assembler.consume(event as MessagesEvent);\n },\n () => {\n assembler.close();\n audio.close();\n images.close();\n video.close();\n files.close();\n }\n );\n }\n\n get subgraphs(): AsyncIterable<SubgraphHandle> {\n if (this.#subgraphsIterable) return this.#subgraphsIterable;\n const buffer = new MultiCursorBuffer<SubgraphHandle>();\n this.#subgraphsIterable = buffer;\n void (async () => {\n const rawHandle = await this.#session.subscribe({\n channels: [\"lifecycle\"],\n namespaces: [this.namespace],\n });\n const discovery = new SubgraphDiscoveryHandle(\n rawHandle,\n this.#session,\n this.namespace\n );\n for await (const sub of discovery) {\n buffer.push(sub);\n }\n buffer.close();\n })();\n return buffer;\n }\n\n /**\n * Create a raw channel subscription scoped to this subagent's namespace.\n */\n subscribe<TChannel extends Channel>(\n channel: TChannel,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannel<TChannel>, YieldForChannel<TChannel>>\n >;\n subscribe<const TChannels extends readonly Channel[]>(\n channels: TChannels,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannels<TChannels>, YieldForChannels<TChannels>>\n >;\n subscribe(params: SubscribeParams): Promise<SubscriptionHandle<Event>>;\n subscribe(\n paramsOrChannels: SubscribeParams | Channel | string | readonly Channel[],\n options: SubscribeOptions = {}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n if (\n typeof paramsOrChannels === \"object\" &&\n !Array.isArray(paramsOrChannels) &&\n \"channels\" in paramsOrChannels\n ) {\n return this.#session.subscribe({\n ...paramsOrChannels,\n namespaces: paramsOrChannels.namespaces ?? [this.namespace],\n });\n }\n\n return this.#session.subscribe(paramsOrChannels as Channel, {\n ...options,\n namespaces: options.namespaces ?? [this.namespace],\n });\n }\n\n async #startProjection(\n channels: Channel[],\n onEvent: (event: Event) => void,\n onDone: () => void\n ): Promise<void> {\n try {\n const rawHandle = await this.#session.subscribe({\n channels,\n namespaces: [this.namespace],\n });\n for await (const event of rawHandle) {\n onEvent(event);\n }\n } finally {\n onDone();\n }\n }\n}\n\n/**\n * Async iterable that yields {@link SubagentHandle} instances as task\n * tool calls are discovered from the `tools` channel.\n *\n * Mirrors the in-process `createSubagentTransformer` from DeepAgent:\n * watches for `tool_name === \"task\"` with `tool-started`, extracts\n * `subagent_type` and `description` from the input, and resolves\n * `output` on `tool-finished`.\n */\nexport class SubagentDiscoveryHandle implements AsyncIterable<SubagentHandle> {\n readonly #source: SubscriptionHandle<Event>;\n readonly #session: Subscribable;\n readonly #queue: SubagentHandle[] = [];\n readonly #waiters: Array<(value: IteratorResult<SubagentHandle>) => void> =\n [];\n readonly #pending = new Map<\n string,\n {\n resolveOutput: (v: unknown) => void;\n rejectOutput: (e: unknown) => void;\n }\n >();\n #sourcePump?: Promise<void>;\n #closed = false;\n\n constructor(source: SubscriptionHandle<Event>, session: Subscribable) {\n this.#source = source;\n this.#session = session;\n }\n\n #processEvent(event: Event): SubagentHandle | undefined {\n if (event.method !== \"tools\") return undefined;\n const tools = event as ToolsEvent;\n const data = tools.params.data;\n const toolCallId = (data as Record<string, unknown>).tool_call_id as string;\n const toolName = (data as Record<string, unknown>).tool_name as string;\n\n if (toolName === \"task\" && data.event === \"tool-started\") {\n const rawInput = (data as Record<string, unknown>).input;\n const input: { description?: string; subagent_type?: string } =\n typeof rawInput === \"string\"\n ? JSON.parse(rawInput)\n : ((rawInput as Record<string, unknown>) ?? {});\n\n const name = input.subagent_type ?? \"unknown\";\n const description = input.description ?? \"\";\n\n let resolveTaskInput!: (v: string) => void;\n let resolveOutput!: (v: unknown) => void;\n let rejectOutput!: (e: unknown) => void;\n\n const taskInput = new Promise<string>((r) => {\n resolveTaskInput = r;\n });\n const output = new Promise<unknown>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n resolveTaskInput(description);\n this.#pending.set(toolCallId, { resolveOutput, rejectOutput });\n\n const namespace = [...tools.params.namespace];\n\n return new SubagentHandle(\n name,\n toolCallId,\n namespace,\n taskInput,\n output,\n this.#session\n );\n }\n\n if (toolCallId) {\n const pending = this.#pending.get(toolCallId);\n if (pending) {\n if (data.event === \"tool-finished\") {\n pending.resolveOutput((data as Record<string, unknown>).output);\n this.#pending.delete(toolCallId);\n } else if (data.event === \"tool-error\") {\n const message =\n ((data as Record<string, unknown>).message as string) ??\n \"unknown error\";\n pending.rejectOutput(new Error(message));\n this.#pending.delete(toolCallId);\n }\n }\n }\n\n return undefined;\n }\n\n #start(): void {\n if (this.#sourcePump) return;\n this.#sourcePump = (async () => {\n for await (const event of this.#source) {\n const handle = this.#processEvent(event);\n if (!handle) continue;\n\n const waiter = this.#waiters.shift();\n if (waiter) {\n waiter({ done: false, value: handle });\n } else {\n this.#queue.push(handle);\n }\n }\n this.#closed = true;\n for (const pending of this.#pending.values()) {\n pending.resolveOutput(undefined);\n }\n this.#pending.clear();\n while (this.#waiters.length > 0) {\n this.#waiters.shift()?.({ done: true, value: undefined });\n }\n })();\n }\n\n async close(): Promise<void> {\n this.#closed = true;\n await this.#source.unsubscribe();\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SubagentHandle> {\n this.#start();\n return {\n next: async () => {\n if (this.#queue.length > 0) {\n return { done: false, value: this.#queue.shift()! };\n }\n if (this.#closed) {\n return { done: true, value: undefined };\n }\n return await new Promise<IteratorResult<SubagentHandle>>((resolve) => {\n this.#waiters.push(resolve);\n });\n },\n return: async () => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"subagents.d.cts","names":[],"sources":["../../../../src/client/stream/handles/subagents.ts"],"mappings":";;;;;;;;;;;AA4CA;;;;;;;;;cAAa,cAAA;EAAA;WACF,IAAA;EAAA,SACA,MAAA;EAAA,SACA,SAAA,EAAW,OAAA;EAAA,SACX,MAAA,EAAQ,OAAA;EAAA,SACR,SAAA;EAaT,WAAA,CACE,IAAA,UACA,MAAA,UACA,SAAA,YACA,SAAA,EAAW,OAAA,UACX,MAAA,EAAQ,OAAA,WACR,OAAA,EAAS,YAAA;EAAA,IAUP,QAAA,CAAA,GAAY,aAAA,CAAc,sBAAA;EAAA,IAiB1B,SAAA,CAAA,GAAa,aAAA,CAAc,uBAAA;EAAA,IAiB3B,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,MAAA,CAAA,GAAU,aAAA,CAAc,UAAA;EAAA,IAKxB,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,KAAA,CAAA,GAAS,aAAA,CAAc,SAAA;EAAA,IAsCvB,SAAA,CAAA,GAAa,aAAA,CAAc,cAAA;EA2BnB;;;EAFZ,SAAA,kBAA2B,OAAA,CAAA,CACzB,OAAA,EAAS,QAAA,EACT,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,eAAA,CAAgB,QAAA,GAAW,eAAA,CAAgB,QAAA;EAEhE,SAAA,kCAA2C,OAAA,GAAA,CACzC,QAAA,EAAU,SAAA,EACV,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,gBAAA,CAAiB,SAAA,GAAY,gBAAA,CAAiB,SAAA;EAEnE,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,kBAAA,CAAmB,KAAA;AAAA"}
1
+ {"version":3,"file":"subagents.d.cts","names":[],"sources":["../../../../src/client/stream/handles/subagents.ts"],"mappings":";;;;;;;;;;;AAgDA;;;;;;;;;cAAa,cAAA;EAAA;WACF,IAAA;EAAA,SACA,MAAA;EAAA,SACA,SAAA,EAAW,OAAA;EAAA,SACX,MAAA,EAAQ,OAAA;EAAA,SACR,SAAA;EAaT,WAAA,CACE,IAAA,UACA,MAAA,UACA,SAAA,YACA,SAAA,EAAW,OAAA,UACX,MAAA,EAAQ,OAAA,WACR,OAAA,EAAS,YAAA;EAAA,IAUP,QAAA,CAAA,GAAY,aAAA,CAAc,sBAAA;EAAA,IAiB1B,SAAA,CAAA,GAAa,aAAA,CAAc,uBAAA;EAAA,IAmB3B,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,MAAA,CAAA,GAAU,aAAA,CAAc,UAAA;EAAA,IAKxB,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,KAAA,CAAA,GAAS,aAAA,CAAc,SAAA;EAAA,IAsCvB,SAAA,CAAA,GAAa,aAAA,CAAc,cAAA;EA2BnB;;;EAFZ,SAAA,kBAA2B,OAAA,CAAA,CACzB,OAAA,EAAS,QAAA,EACT,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,eAAA,CAAgB,QAAA,GAAW,eAAA,CAAgB,QAAA;EAEhE,SAAA,kCAA2C,OAAA,GAAA,CACzC,QAAA,EAAU,SAAA,EACV,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,gBAAA,CAAiB,SAAA,GAAY,gBAAA,CAAiB,SAAA;EAEnE,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,kBAAA,CAAmB,KAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"subagents.d.ts","names":[],"sources":["../../../../src/client/stream/handles/subagents.ts"],"mappings":";;;;;;;;;;;AA4CA;;;;;;;;;cAAa,cAAA;EAAA;WACF,IAAA;EAAA,SACA,MAAA;EAAA,SACA,SAAA,EAAW,OAAA;EAAA,SACX,MAAA,EAAQ,OAAA;EAAA,SACR,SAAA;EAaT,WAAA,CACE,IAAA,UACA,MAAA,UACA,SAAA,YACA,SAAA,EAAW,OAAA,UACX,MAAA,EAAQ,OAAA,WACR,OAAA,EAAS,YAAA;EAAA,IAUP,QAAA,CAAA,GAAY,aAAA,CAAc,sBAAA;EAAA,IAiB1B,SAAA,CAAA,GAAa,aAAA,CAAc,uBAAA;EAAA,IAiB3B,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,MAAA,CAAA,GAAU,aAAA,CAAc,UAAA;EAAA,IAKxB,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,KAAA,CAAA,GAAS,aAAA,CAAc,SAAA;EAAA,IAsCvB,SAAA,CAAA,GAAa,aAAA,CAAc,cAAA;EA2BnB;;;EAFZ,SAAA,kBAA2B,OAAA,CAAA,CACzB,OAAA,EAAS,QAAA,EACT,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,eAAA,CAAgB,QAAA,GAAW,eAAA,CAAgB,QAAA;EAEhE,SAAA,kCAA2C,OAAA,GAAA,CACzC,QAAA,EAAU,SAAA,EACV,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,gBAAA,CAAiB,SAAA,GAAY,gBAAA,CAAiB,SAAA;EAEnE,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,kBAAA,CAAmB,KAAA;AAAA"}
1
+ {"version":3,"file":"subagents.d.ts","names":[],"sources":["../../../../src/client/stream/handles/subagents.ts"],"mappings":";;;;;;;;;;;AAgDA;;;;;;;;;cAAa,cAAA;EAAA;WACF,IAAA;EAAA,SACA,MAAA;EAAA,SACA,SAAA,EAAW,OAAA;EAAA,SACX,MAAA,EAAQ,OAAA;EAAA,SACR,SAAA;EAaT,WAAA,CACE,IAAA,UACA,MAAA,UACA,SAAA,YACA,SAAA,EAAW,OAAA,UACX,MAAA,EAAQ,OAAA,WACR,OAAA,EAAS,YAAA;EAAA,IAUP,QAAA,CAAA,GAAY,aAAA,CAAc,sBAAA;EAAA,IAiB1B,SAAA,CAAA,GAAa,aAAA,CAAc,uBAAA;EAAA,IAmB3B,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,MAAA,CAAA,GAAU,aAAA,CAAc,UAAA;EAAA,IAKxB,KAAA,CAAA,GAAS,aAAA,CAAc,UAAA;EAAA,IAKvB,KAAA,CAAA,GAAS,aAAA,CAAc,SAAA;EAAA,IAsCvB,SAAA,CAAA,GAAa,aAAA,CAAc,cAAA;EA2BnB;;;EAFZ,SAAA,kBAA2B,OAAA,CAAA,CACzB,OAAA,EAAS,QAAA,EACT,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,eAAA,CAAgB,QAAA,GAAW,eAAA,CAAgB,QAAA;EAEhE,SAAA,kCAA2C,OAAA,GAAA,CACzC,QAAA,EAAU,SAAA,EACV,OAAA,GAAU,gBAAA,GACT,OAAA,CACD,kBAAA,CAAmB,gBAAA,CAAiB,SAAA,GAAY,gBAAA,CAAiB,SAAA;EAEnE,SAAA,CAAU,MAAA,EAAQ,eAAA,GAAkB,OAAA,CAAQ,kBAAA,CAAmB,KAAA;AAAA"}
@@ -1,5 +1,5 @@
1
1
  import { MultiCursorBuffer } from "../multi-cursor-buffer.js";
2
- import { ToolCallAssembler, toClientAssembledToolCall } from "./tools.js";
2
+ import { ToolCallAssembler, shouldIgnoreScopedTaskToolEvent, toClientAssembledToolCall } from "./tools.js";
3
3
  import { StreamingMessageAssembler } from "../messages.js";
4
4
  import { MediaAssembler } from "../media.js";
5
5
  import { SubgraphDiscoveryHandle } from "./subgraphs.js";
@@ -57,7 +57,9 @@ var SubagentHandle = class {
57
57
  const assembler = new ToolCallAssembler();
58
58
  this.#startProjection(["tools"], (event) => {
59
59
  if (event.method !== "tools") return;
60
- const tc = assembler.consume(event);
60
+ const toolsEvent = event;
61
+ if (shouldIgnoreScopedTaskToolEvent(this.namespace, toolsEvent)) return;
62
+ const tc = assembler.consume(toolsEvent);
61
63
  if (tc) buffer.push(toClientAssembledToolCall(tc));
62
64
  }, () => buffer.close());
63
65
  return buffer;
@@ -1 +1 @@
1
- {"version":3,"file":"subagents.js","names":["#session","#messagesIterable","#startProjection","#toolCallsIterable","#ensureMediaDispatcher","#audioBuffer","#imagesBuffer","#videoBuffer","#filesBuffer","#mediaDispatcherStarted","#subgraphsIterable","#source","#queue","#waiters","#pending","#sourcePump","#processEvent","#closed","#start"],"sources":["../../../../src/client/stream/handles/subagents.ts"],"sourcesContent":["import type {\n Channel,\n Event,\n MessagesEvent,\n SubscribeParams,\n ToolsEvent,\n} from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../index.js\";\nimport { MultiCursorBuffer } from \"../multi-cursor-buffer.js\";\nimport { StreamingMessageAssembler } from \"../messages.js\";\nimport type { StreamingMessage, StreamingMessageHandle } from \"../messages.js\";\nimport { ToolCallAssembler, toClientAssembledToolCall } from \"./tools.js\";\nimport type { ClientAssembledToolCall } from \"./tools.js\";\nimport { MediaAssembler } from \"../media.js\";\nimport type {\n AudioMedia,\n FileMedia,\n ImageMedia,\n VideoMedia,\n} from \"../media.js\";\nimport type {\n EventForChannel,\n EventForChannels,\n SubscribeOptions,\n YieldForChannel,\n YieldForChannels,\n} from \"../types.js\";\nimport {\n type Subscribable,\n type SubgraphHandle,\n SubgraphDiscoveryHandle,\n} from \"./subgraphs.js\";\n\n/**\n * Discovered subagent within a streaming session. Mirrors the\n * in-process `SubagentRunStream` from DeepAgent.\n *\n * Each subagent is discovered when a `tool-started` event with\n * `tool_name === \"task\"` is observed. The `taskInput` and `output`\n * promises resolve from the task tool's lifecycle events.\n *\n * Use lazy getters (`sub.messages`, `sub.toolCalls`, etc.) for\n * namespace-scoped projections.\n */\nexport class SubagentHandle {\n readonly name: string;\n readonly callId: string;\n readonly taskInput: Promise<string>;\n readonly output: Promise<unknown>;\n readonly namespace: string[];\n readonly #session: Subscribable;\n\n #messagesIterable?: AsyncIterable<StreamingMessage>;\n #toolCallsIterable?: AsyncIterable<ClientAssembledToolCall>;\n #subgraphsIterable?: AsyncIterable<SubgraphHandle>;\n\n #mediaDispatcherStarted = false;\n #audioBuffer?: MultiCursorBuffer<AudioMedia>;\n #imagesBuffer?: MultiCursorBuffer<ImageMedia>;\n #videoBuffer?: MultiCursorBuffer<VideoMedia>;\n #filesBuffer?: MultiCursorBuffer<FileMedia>;\n\n constructor(\n name: string,\n callId: string,\n namespace: string[],\n taskInput: Promise<string>,\n output: Promise<unknown>,\n session: Subscribable\n ) {\n this.name = name;\n this.callId = callId;\n this.namespace = namespace;\n this.taskInput = taskInput;\n this.output = output;\n this.#session = session;\n }\n\n get messages(): AsyncIterable<StreamingMessageHandle> {\n if (this.#messagesIterable) return this.#messagesIterable;\n const buffer = new MultiCursorBuffer<StreamingMessage>();\n this.#messagesIterable = buffer;\n const assembler = new StreamingMessageAssembler();\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n const msg = assembler.consume(event as MessagesEvent);\n if (msg) buffer.push(msg);\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get toolCalls(): AsyncIterable<ClientAssembledToolCall> {\n if (this.#toolCallsIterable) return this.#toolCallsIterable;\n const buffer = new MultiCursorBuffer<ClientAssembledToolCall>();\n this.#toolCallsIterable = buffer;\n const assembler = new ToolCallAssembler();\n void this.#startProjection(\n [\"tools\"],\n (event) => {\n if (event.method !== \"tools\") return;\n const tc = assembler.consume(event as ToolsEvent);\n if (tc) buffer.push(toClientAssembledToolCall(tc));\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get audio(): AsyncIterable<AudioMedia> {\n this.#ensureMediaDispatcher();\n return this.#audioBuffer!;\n }\n\n get images(): AsyncIterable<ImageMedia> {\n this.#ensureMediaDispatcher();\n return this.#imagesBuffer!;\n }\n\n get video(): AsyncIterable<VideoMedia> {\n this.#ensureMediaDispatcher();\n return this.#videoBuffer!;\n }\n\n get files(): AsyncIterable<FileMedia> {\n this.#ensureMediaDispatcher();\n return this.#filesBuffer!;\n }\n\n #ensureMediaDispatcher(): void {\n if (this.#mediaDispatcherStarted) return;\n this.#mediaDispatcherStarted = true;\n const audio = new MultiCursorBuffer<AudioMedia>();\n const images = new MultiCursorBuffer<ImageMedia>();\n const video = new MultiCursorBuffer<VideoMedia>();\n const files = new MultiCursorBuffer<FileMedia>();\n this.#audioBuffer = audio;\n this.#imagesBuffer = images;\n this.#videoBuffer = video;\n this.#filesBuffer = files;\n const assembler = new MediaAssembler({\n onAudio: (m: AudioMedia) => audio.push(m),\n onImage: (m: ImageMedia) => images.push(m),\n onVideo: (m: VideoMedia) => video.push(m),\n onFile: (m: FileMedia) => files.push(m),\n });\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n assembler.consume(event as MessagesEvent);\n },\n () => {\n assembler.close();\n audio.close();\n images.close();\n video.close();\n files.close();\n }\n );\n }\n\n get subgraphs(): AsyncIterable<SubgraphHandle> {\n if (this.#subgraphsIterable) return this.#subgraphsIterable;\n const buffer = new MultiCursorBuffer<SubgraphHandle>();\n this.#subgraphsIterable = buffer;\n void (async () => {\n const rawHandle = await this.#session.subscribe({\n channels: [\"lifecycle\"],\n namespaces: [this.namespace],\n });\n const discovery = new SubgraphDiscoveryHandle(\n rawHandle,\n this.#session,\n this.namespace\n );\n for await (const sub of discovery) {\n buffer.push(sub);\n }\n buffer.close();\n })();\n return buffer;\n }\n\n /**\n * Create a raw channel subscription scoped to this subagent's namespace.\n */\n subscribe<TChannel extends Channel>(\n channel: TChannel,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannel<TChannel>, YieldForChannel<TChannel>>\n >;\n subscribe<const TChannels extends readonly Channel[]>(\n channels: TChannels,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannels<TChannels>, YieldForChannels<TChannels>>\n >;\n subscribe(params: SubscribeParams): Promise<SubscriptionHandle<Event>>;\n subscribe(\n paramsOrChannels: SubscribeParams | Channel | string | readonly Channel[],\n options: SubscribeOptions = {}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n if (\n typeof paramsOrChannels === \"object\" &&\n !Array.isArray(paramsOrChannels) &&\n \"channels\" in paramsOrChannels\n ) {\n return this.#session.subscribe({\n ...paramsOrChannels,\n namespaces: paramsOrChannels.namespaces ?? [this.namespace],\n });\n }\n\n return this.#session.subscribe(paramsOrChannels as Channel, {\n ...options,\n namespaces: options.namespaces ?? [this.namespace],\n });\n }\n\n async #startProjection(\n channels: Channel[],\n onEvent: (event: Event) => void,\n onDone: () => void\n ): Promise<void> {\n try {\n const rawHandle = await this.#session.subscribe({\n channels,\n namespaces: [this.namespace],\n });\n for await (const event of rawHandle) {\n onEvent(event);\n }\n } finally {\n onDone();\n }\n }\n}\n\n/**\n * Async iterable that yields {@link SubagentHandle} instances as task\n * tool calls are discovered from the `tools` channel.\n *\n * Mirrors the in-process `createSubagentTransformer` from DeepAgent:\n * watches for `tool_name === \"task\"` with `tool-started`, extracts\n * `subagent_type` and `description` from the input, and resolves\n * `output` on `tool-finished`.\n */\nexport class SubagentDiscoveryHandle implements AsyncIterable<SubagentHandle> {\n readonly #source: SubscriptionHandle<Event>;\n readonly #session: Subscribable;\n readonly #queue: SubagentHandle[] = [];\n readonly #waiters: Array<(value: IteratorResult<SubagentHandle>) => void> =\n [];\n readonly #pending = new Map<\n string,\n {\n resolveOutput: (v: unknown) => void;\n rejectOutput: (e: unknown) => void;\n }\n >();\n #sourcePump?: Promise<void>;\n #closed = false;\n\n constructor(source: SubscriptionHandle<Event>, session: Subscribable) {\n this.#source = source;\n this.#session = session;\n }\n\n #processEvent(event: Event): SubagentHandle | undefined {\n if (event.method !== \"tools\") return undefined;\n const tools = event as ToolsEvent;\n const data = tools.params.data;\n const toolCallId = (data as Record<string, unknown>).tool_call_id as string;\n const toolName = (data as Record<string, unknown>).tool_name as string;\n\n if (toolName === \"task\" && data.event === \"tool-started\") {\n const rawInput = (data as Record<string, unknown>).input;\n const input: { description?: string; subagent_type?: string } =\n typeof rawInput === \"string\"\n ? JSON.parse(rawInput)\n : ((rawInput as Record<string, unknown>) ?? {});\n\n const name = input.subagent_type ?? \"unknown\";\n const description = input.description ?? \"\";\n\n let resolveTaskInput!: (v: string) => void;\n let resolveOutput!: (v: unknown) => void;\n let rejectOutput!: (e: unknown) => void;\n\n const taskInput = new Promise<string>((r) => {\n resolveTaskInput = r;\n });\n const output = new Promise<unknown>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n resolveTaskInput(description);\n this.#pending.set(toolCallId, { resolveOutput, rejectOutput });\n\n const namespace = [...tools.params.namespace];\n\n return new SubagentHandle(\n name,\n toolCallId,\n namespace,\n taskInput,\n output,\n this.#session\n );\n }\n\n if (toolCallId) {\n const pending = this.#pending.get(toolCallId);\n if (pending) {\n if (data.event === \"tool-finished\") {\n pending.resolveOutput((data as Record<string, unknown>).output);\n this.#pending.delete(toolCallId);\n } else if (data.event === \"tool-error\") {\n const message =\n ((data as Record<string, unknown>).message as string) ??\n \"unknown error\";\n pending.rejectOutput(new Error(message));\n this.#pending.delete(toolCallId);\n }\n }\n }\n\n return undefined;\n }\n\n #start(): void {\n if (this.#sourcePump) return;\n this.#sourcePump = (async () => {\n for await (const event of this.#source) {\n const handle = this.#processEvent(event);\n if (!handle) continue;\n\n const waiter = this.#waiters.shift();\n if (waiter) {\n waiter({ done: false, value: handle });\n } else {\n this.#queue.push(handle);\n }\n }\n this.#closed = true;\n for (const pending of this.#pending.values()) {\n pending.resolveOutput(undefined);\n }\n this.#pending.clear();\n while (this.#waiters.length > 0) {\n this.#waiters.shift()?.({ done: true, value: undefined });\n }\n })();\n }\n\n async close(): Promise<void> {\n this.#closed = true;\n await this.#source.unsubscribe();\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SubagentHandle> {\n this.#start();\n return {\n next: async () => {\n if (this.#queue.length > 0) {\n return { done: false, value: this.#queue.shift()! };\n }\n if (this.#closed) {\n return { done: true, value: undefined };\n }\n return await new Promise<IteratorResult<SubagentHandle>>((resolve) => {\n this.#waiters.push(resolve);\n });\n },\n return: async () => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"subagents.js","names":["#session","#messagesIterable","#startProjection","#toolCallsIterable","#ensureMediaDispatcher","#audioBuffer","#imagesBuffer","#videoBuffer","#filesBuffer","#mediaDispatcherStarted","#subgraphsIterable","#source","#queue","#waiters","#pending","#sourcePump","#processEvent","#closed","#start"],"sources":["../../../../src/client/stream/handles/subagents.ts"],"sourcesContent":["import type {\n Channel,\n Event,\n MessagesEvent,\n SubscribeParams,\n ToolsEvent,\n} from \"@langchain/protocol\";\nimport type { SubscriptionHandle } from \"../index.js\";\nimport { MultiCursorBuffer } from \"../multi-cursor-buffer.js\";\nimport { StreamingMessageAssembler } from \"../messages.js\";\nimport type { StreamingMessage, StreamingMessageHandle } from \"../messages.js\";\nimport {\n shouldIgnoreScopedTaskToolEvent,\n ToolCallAssembler,\n toClientAssembledToolCall,\n} from \"./tools.js\";\nimport type { ClientAssembledToolCall } from \"./tools.js\";\nimport { MediaAssembler } from \"../media.js\";\nimport type {\n AudioMedia,\n FileMedia,\n ImageMedia,\n VideoMedia,\n} from \"../media.js\";\nimport type {\n EventForChannel,\n EventForChannels,\n SubscribeOptions,\n YieldForChannel,\n YieldForChannels,\n} from \"../types.js\";\nimport {\n type Subscribable,\n type SubgraphHandle,\n SubgraphDiscoveryHandle,\n} from \"./subgraphs.js\";\n\n/**\n * Discovered subagent within a streaming session. Mirrors the\n * in-process `SubagentRunStream` from DeepAgent.\n *\n * Each subagent is discovered when a `tool-started` event with\n * `tool_name === \"task\"` is observed. The `taskInput` and `output`\n * promises resolve from the task tool's lifecycle events.\n *\n * Use lazy getters (`sub.messages`, `sub.toolCalls`, etc.) for\n * namespace-scoped projections.\n */\nexport class SubagentHandle {\n readonly name: string;\n readonly callId: string;\n readonly taskInput: Promise<string>;\n readonly output: Promise<unknown>;\n readonly namespace: string[];\n readonly #session: Subscribable;\n\n #messagesIterable?: AsyncIterable<StreamingMessage>;\n #toolCallsIterable?: AsyncIterable<ClientAssembledToolCall>;\n #subgraphsIterable?: AsyncIterable<SubgraphHandle>;\n\n #mediaDispatcherStarted = false;\n #audioBuffer?: MultiCursorBuffer<AudioMedia>;\n #imagesBuffer?: MultiCursorBuffer<ImageMedia>;\n #videoBuffer?: MultiCursorBuffer<VideoMedia>;\n #filesBuffer?: MultiCursorBuffer<FileMedia>;\n\n constructor(\n name: string,\n callId: string,\n namespace: string[],\n taskInput: Promise<string>,\n output: Promise<unknown>,\n session: Subscribable\n ) {\n this.name = name;\n this.callId = callId;\n this.namespace = namespace;\n this.taskInput = taskInput;\n this.output = output;\n this.#session = session;\n }\n\n get messages(): AsyncIterable<StreamingMessageHandle> {\n if (this.#messagesIterable) return this.#messagesIterable;\n const buffer = new MultiCursorBuffer<StreamingMessage>();\n this.#messagesIterable = buffer;\n const assembler = new StreamingMessageAssembler();\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n const msg = assembler.consume(event as MessagesEvent);\n if (msg) buffer.push(msg);\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get toolCalls(): AsyncIterable<ClientAssembledToolCall> {\n if (this.#toolCallsIterable) return this.#toolCallsIterable;\n const buffer = new MultiCursorBuffer<ClientAssembledToolCall>();\n this.#toolCallsIterable = buffer;\n const assembler = new ToolCallAssembler();\n void this.#startProjection(\n [\"tools\"],\n (event) => {\n if (event.method !== \"tools\") return;\n const toolsEvent = event as ToolsEvent;\n if (shouldIgnoreScopedTaskToolEvent(this.namespace, toolsEvent)) return;\n const tc = assembler.consume(toolsEvent);\n if (tc) buffer.push(toClientAssembledToolCall(tc));\n },\n () => buffer.close()\n );\n return buffer;\n }\n\n get audio(): AsyncIterable<AudioMedia> {\n this.#ensureMediaDispatcher();\n return this.#audioBuffer!;\n }\n\n get images(): AsyncIterable<ImageMedia> {\n this.#ensureMediaDispatcher();\n return this.#imagesBuffer!;\n }\n\n get video(): AsyncIterable<VideoMedia> {\n this.#ensureMediaDispatcher();\n return this.#videoBuffer!;\n }\n\n get files(): AsyncIterable<FileMedia> {\n this.#ensureMediaDispatcher();\n return this.#filesBuffer!;\n }\n\n #ensureMediaDispatcher(): void {\n if (this.#mediaDispatcherStarted) return;\n this.#mediaDispatcherStarted = true;\n const audio = new MultiCursorBuffer<AudioMedia>();\n const images = new MultiCursorBuffer<ImageMedia>();\n const video = new MultiCursorBuffer<VideoMedia>();\n const files = new MultiCursorBuffer<FileMedia>();\n this.#audioBuffer = audio;\n this.#imagesBuffer = images;\n this.#videoBuffer = video;\n this.#filesBuffer = files;\n const assembler = new MediaAssembler({\n onAudio: (m: AudioMedia) => audio.push(m),\n onImage: (m: ImageMedia) => images.push(m),\n onVideo: (m: VideoMedia) => video.push(m),\n onFile: (m: FileMedia) => files.push(m),\n });\n void this.#startProjection(\n [\"messages\"],\n (event) => {\n if (event.method !== \"messages\") return;\n assembler.consume(event as MessagesEvent);\n },\n () => {\n assembler.close();\n audio.close();\n images.close();\n video.close();\n files.close();\n }\n );\n }\n\n get subgraphs(): AsyncIterable<SubgraphHandle> {\n if (this.#subgraphsIterable) return this.#subgraphsIterable;\n const buffer = new MultiCursorBuffer<SubgraphHandle>();\n this.#subgraphsIterable = buffer;\n void (async () => {\n const rawHandle = await this.#session.subscribe({\n channels: [\"lifecycle\"],\n namespaces: [this.namespace],\n });\n const discovery = new SubgraphDiscoveryHandle(\n rawHandle,\n this.#session,\n this.namespace\n );\n for await (const sub of discovery) {\n buffer.push(sub);\n }\n buffer.close();\n })();\n return buffer;\n }\n\n /**\n * Create a raw channel subscription scoped to this subagent's namespace.\n */\n subscribe<TChannel extends Channel>(\n channel: TChannel,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannel<TChannel>, YieldForChannel<TChannel>>\n >;\n subscribe<const TChannels extends readonly Channel[]>(\n channels: TChannels,\n options?: SubscribeOptions\n ): Promise<\n SubscriptionHandle<EventForChannels<TChannels>, YieldForChannels<TChannels>>\n >;\n subscribe(params: SubscribeParams): Promise<SubscriptionHandle<Event>>;\n subscribe(\n paramsOrChannels: SubscribeParams | Channel | string | readonly Channel[],\n options: SubscribeOptions = {}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n if (\n typeof paramsOrChannels === \"object\" &&\n !Array.isArray(paramsOrChannels) &&\n \"channels\" in paramsOrChannels\n ) {\n return this.#session.subscribe({\n ...paramsOrChannels,\n namespaces: paramsOrChannels.namespaces ?? [this.namespace],\n });\n }\n\n return this.#session.subscribe(paramsOrChannels as Channel, {\n ...options,\n namespaces: options.namespaces ?? [this.namespace],\n });\n }\n\n async #startProjection(\n channels: Channel[],\n onEvent: (event: Event) => void,\n onDone: () => void\n ): Promise<void> {\n try {\n const rawHandle = await this.#session.subscribe({\n channels,\n namespaces: [this.namespace],\n });\n for await (const event of rawHandle) {\n onEvent(event);\n }\n } finally {\n onDone();\n }\n }\n}\n\n/**\n * Async iterable that yields {@link SubagentHandle} instances as task\n * tool calls are discovered from the `tools` channel.\n *\n * Mirrors the in-process `createSubagentTransformer` from DeepAgent:\n * watches for `tool_name === \"task\"` with `tool-started`, extracts\n * `subagent_type` and `description` from the input, and resolves\n * `output` on `tool-finished`.\n */\nexport class SubagentDiscoveryHandle implements AsyncIterable<SubagentHandle> {\n readonly #source: SubscriptionHandle<Event>;\n readonly #session: Subscribable;\n readonly #queue: SubagentHandle[] = [];\n readonly #waiters: Array<(value: IteratorResult<SubagentHandle>) => void> =\n [];\n readonly #pending = new Map<\n string,\n {\n resolveOutput: (v: unknown) => void;\n rejectOutput: (e: unknown) => void;\n }\n >();\n #sourcePump?: Promise<void>;\n #closed = false;\n\n constructor(source: SubscriptionHandle<Event>, session: Subscribable) {\n this.#source = source;\n this.#session = session;\n }\n\n #processEvent(event: Event): SubagentHandle | undefined {\n if (event.method !== \"tools\") return undefined;\n const tools = event as ToolsEvent;\n const data = tools.params.data;\n const toolCallId = (data as Record<string, unknown>).tool_call_id as string;\n const toolName = (data as Record<string, unknown>).tool_name as string;\n\n if (toolName === \"task\" && data.event === \"tool-started\") {\n const rawInput = (data as Record<string, unknown>).input;\n const input: { description?: string; subagent_type?: string } =\n typeof rawInput === \"string\"\n ? JSON.parse(rawInput)\n : ((rawInput as Record<string, unknown>) ?? {});\n\n const name = input.subagent_type ?? \"unknown\";\n const description = input.description ?? \"\";\n\n let resolveTaskInput!: (v: string) => void;\n let resolveOutput!: (v: unknown) => void;\n let rejectOutput!: (e: unknown) => void;\n\n const taskInput = new Promise<string>((r) => {\n resolveTaskInput = r;\n });\n const output = new Promise<unknown>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n resolveTaskInput(description);\n this.#pending.set(toolCallId, { resolveOutput, rejectOutput });\n\n const namespace = [...tools.params.namespace];\n\n return new SubagentHandle(\n name,\n toolCallId,\n namespace,\n taskInput,\n output,\n this.#session\n );\n }\n\n if (toolCallId) {\n const pending = this.#pending.get(toolCallId);\n if (pending) {\n if (data.event === \"tool-finished\") {\n pending.resolveOutput((data as Record<string, unknown>).output);\n this.#pending.delete(toolCallId);\n } else if (data.event === \"tool-error\") {\n const message =\n ((data as Record<string, unknown>).message as string) ??\n \"unknown error\";\n pending.rejectOutput(new Error(message));\n this.#pending.delete(toolCallId);\n }\n }\n }\n\n return undefined;\n }\n\n #start(): void {\n if (this.#sourcePump) return;\n this.#sourcePump = (async () => {\n for await (const event of this.#source) {\n const handle = this.#processEvent(event);\n if (!handle) continue;\n\n const waiter = this.#waiters.shift();\n if (waiter) {\n waiter({ done: false, value: handle });\n } else {\n this.#queue.push(handle);\n }\n }\n this.#closed = true;\n for (const pending of this.#pending.values()) {\n pending.resolveOutput(undefined);\n }\n this.#pending.clear();\n while (this.#waiters.length > 0) {\n this.#waiters.shift()?.({ done: true, value: undefined });\n }\n })();\n }\n\n async close(): Promise<void> {\n this.#closed = true;\n await this.#source.unsubscribe();\n }\n\n [Symbol.asyncIterator](): AsyncIterator<SubagentHandle> {\n this.#start();\n return {\n next: async () => {\n if (this.#queue.length > 0) {\n return { done: false, value: this.#queue.shift()! };\n }\n if (this.#closed) {\n return { done: true, value: undefined };\n }\n return await new Promise<IteratorResult<SubagentHandle>>((resolve) => {\n this.#waiters.push(resolve);\n });\n },\n return: async () => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n}\n"],"mappings":"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"}
@@ -31,11 +31,34 @@ function parseToolPayload(value) {
31
31
  return value;
32
32
  }
33
33
  }
34
+ /**
35
+ * Skip wrapper `task` tool events scoped to a subagent namespace.
36
+ *
37
+ * Deep-agent subagents are discovered from root-level `task` tool calls;
38
+ * replaying the same dispatch tool inside the worker namespace would
39
+ * otherwise surface as a spurious entry in `sub.toolCalls`.
40
+ */
41
+ function shouldIgnoreScopedTaskToolEvent(scopeNamespace, event) {
42
+ const data = event.params.data;
43
+ return scopeNamespace.length > 0 && event.params.namespace.length === scopeNamespace.length && event.params.namespace.every((segment, index) => segment === scopeNamespace[index]) && "tool_name" in data && data.tool_name === "task";
44
+ }
45
+ function getWireMessageField(message, field) {
46
+ if (!message || typeof message !== "object" || Array.isArray(message)) return;
47
+ const record = message;
48
+ if (field in record) return record[field];
49
+ const kwargs = record.kwargs;
50
+ if (kwargs != null && field in kwargs) return kwargs[field];
51
+ const lcKwargs = record.lc_kwargs;
52
+ if (lcKwargs != null && field in lcKwargs) return lcKwargs[field];
53
+ }
34
54
  function isToolMessageLike(value) {
35
55
  if (!value || typeof value !== "object") return false;
36
- const record = value;
37
- if (record.type === "tool") return true;
38
- return typeof record.tool_call_id === "string" && "content" in record;
56
+ if (value.type === "tool") return true;
57
+ if (getWireMessageField(value, "type") === "tool") return true;
58
+ return typeof getWireMessageField(value, "tool_call_id") === "string" && getWireMessageField(value, "content") !== void 0;
59
+ }
60
+ function isCommandLike(value) {
61
+ return !!value && typeof value === "object" && value.lg_name === "Command";
39
62
  }
40
63
  function textFromContentBlocks(content) {
41
64
  let out = "";
@@ -64,18 +87,59 @@ function parseToolResultContent(content) {
64
87
  if (typeof content === "object") return content;
65
88
  return null;
66
89
  }
90
+ function parseToolMessageRecord(message) {
91
+ return parseToolResultContent(getWireMessageField(message, "content"));
92
+ }
93
+ function parseCommandToolOutput(command, toolCallId) {
94
+ const update = command.update;
95
+ if (update == null || typeof update !== "object" || Array.isArray(update)) return { found: false };
96
+ const messages = update.messages;
97
+ if (!Array.isArray(messages)) return { found: false };
98
+ const toolMessages = messages.filter((message) => isToolMessageLike(message));
99
+ if (toolMessages.length === 0) return { found: false };
100
+ if (toolCallId != null) {
101
+ for (const message of toolMessages) {
102
+ if (getWireMessageField(message, "tool_call_id") !== toolCallId) continue;
103
+ return {
104
+ found: true,
105
+ value: parseToolMessageRecord(message)
106
+ };
107
+ }
108
+ return { found: false };
109
+ }
110
+ if (toolMessages.length === 1) return {
111
+ found: true,
112
+ value: parseToolMessageRecord(toolMessages[0])
113
+ };
114
+ for (let i = toolMessages.length - 1; i >= 0; i -= 1) {
115
+ const parsed = parseToolMessageRecord(toolMessages[i]);
116
+ if (parsed != null) return {
117
+ found: true,
118
+ value: parsed
119
+ };
120
+ }
121
+ return {
122
+ found: true,
123
+ value: null
124
+ };
125
+ }
67
126
  /**
68
127
  * Parse a `tool-finished` output payload into the tool's return value.
69
128
  *
70
129
  * Wire events often wrap structured tool results in a ToolMessage-shaped
71
- * object (`{ type: "tool", content: "..." }`). This unwraps that envelope,
72
- * JSON-decodes string content when possible, and leaves plain strings as-is.
73
- * Returns `null` when a ToolMessage envelope is present but its content
74
- * cannot be normalised.
130
+ * object (`{ type: "tool", content: "..." }`) or a LangGraph
131
+ * {@link Command} whose `update.messages` carries the ToolMessage.
132
+ * This unwraps those envelopes, JSON-decodes string content when possible,
133
+ * and leaves plain strings as-is. Returns `null` when a ToolMessage envelope
134
+ * is present but its content cannot be normalised.
75
135
  */
76
- function parseToolOutput(value) {
136
+ function parseToolOutput(value, toolCallId) {
77
137
  const parsed = parseToolPayload(value);
78
- if (isToolMessageLike(parsed)) return parseToolResultContent(parsed.content);
138
+ if (isCommandLike(parsed)) {
139
+ const commandOutput = parseCommandToolOutput(parsed, toolCallId);
140
+ return commandOutput.found ? commandOutput.value : parsed;
141
+ }
142
+ if (isToolMessageLike(parsed)) return parseToolResultContent(getWireMessageField(parsed, "content"));
79
143
  return parsed ?? null;
80
144
  }
81
145
  /**
@@ -137,7 +201,7 @@ var ToolCallAssembler = class {
137
201
  const entry = this.active.get(data.tool_call_id);
138
202
  if (!entry) return void 0;
139
203
  this.active.delete(data.tool_call_id);
140
- const value = parseToolOutput(data.output);
204
+ const value = parseToolOutput(data.output, data.tool_call_id);
141
205
  entry.resolveOutput(value);
142
206
  entry.handle.output = value;
143
207
  entry.handle.status = "finished";
@@ -159,6 +223,7 @@ var ToolCallAssembler = class {
159
223
  exports.ToolCallAssembler = ToolCallAssembler;
160
224
  exports.parseToolOutput = parseToolOutput;
161
225
  exports.parseToolPayload = parseToolPayload;
226
+ exports.shouldIgnoreScopedTaskToolEvent = shouldIgnoreScopedTaskToolEvent;
162
227
  exports.toClientAssembledToolCall = toClientAssembledToolCall;
163
228
 
164
229
  //# sourceMappingURL=tools.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.cjs","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"sourcesContent":["import type {\n ToolsEvent,\n ToolStartedData,\n ToolFinishedData,\n ToolErrorData,\n} from \"@langchain/protocol\";\n\n/**\n * High-level outcome of a single tool call.\n */\nexport type ToolCallStatus = \"running\" | \"finished\" | \"error\";\n\n/** Shared metadata for assembled tool-call handles. */\ninterface ToolCallBase<TName extends string = string, TInput = unknown> {\n readonly name: TName;\n readonly callId: string;\n /**\n * Pre-v1 alias for {@link callId}. Matches `ToolCallWithResult.id` and\n * `ToolCall.id` on message-level tool calls.\n */\n readonly id: string;\n readonly namespace: string[];\n readonly input: TInput;\n /**\n * Pre-v1 alias for {@link input}. Matches `ToolCallFromTool` `args`.\n */\n readonly args: TInput;\n}\n\n/**\n * Script-oriented tool handle from the client SDK (`ThreadStream.toolCalls`,\n * subagent/subgraph projections). Completion and errors are surfaced only\n * through {@link output}.\n */\nexport interface ClientAssembledToolCall<\n TName extends string = string,\n TInput = unknown,\n TOutput = unknown,\n> extends ToolCallBase<TName, TInput> {\n readonly output: Promise<TOutput>;\n}\n\n/**\n * Reactive tool handle for framework bindings (`stream.toolCalls`,\n * `useToolCalls`, `injectToolCalls`).\n *\n * {@link status}, {@link error}, and {@link output} are plain values that\n * the assembler updates in place as tool events arrive. That lets React,\n * Vue, Svelte, and Angular re-render from a snapshot on each store tick\n * without `await`, effects, or Suspense boundaries around a promise.\n * {@link ClientAssembledToolCall} keeps a promise-based {@link output}\n * instead for script consumers that read tool results sequentially.\n *\n * {@link output} is `null` while the call is running or after it fails;\n * successful completion sets it to the parsed tool return value (objects\n * and strings are unwrapped from ToolMessage wire envelopes when needed).\n */\nexport interface AssembledToolCall<\n TName extends string = string,\n TInput = unknown,\n TOutput = unknown,\n> extends ToolCallBase<TName, TInput> {\n readonly output: TOutput | null;\n readonly status: ToolCallStatus;\n readonly error: string | undefined;\n}\n\n/** @internal Mutable runtime handle shared by client and framework views. */\ntype MutableToolCallHandle = {\n name: string;\n callId: string;\n id: string;\n namespace: string[];\n input: unknown;\n args: unknown;\n output: unknown | null;\n status: ToolCallStatus;\n error: string | undefined;\n outputPromise: Promise<unknown>;\n};\n\n/**\n * Project a runtime handle to the client SDK surface (promise-only\n * {@link output}, no {@link status} / {@link error} fields).\n */\nexport function toClientAssembledToolCall(\n handle: MutableToolCallHandle\n): ClientAssembledToolCall {\n return {\n name: handle.name,\n callId: handle.callId,\n id: handle.id,\n namespace: handle.namespace,\n input: handle.input,\n args: handle.args,\n output: handle.outputPromise as Promise<unknown>,\n };\n}\n\n/**\n * Parse wire-format tool payloads into structured values.\n *\n * Tool events may carry JSON-encoded object strings on the wire; this\n * helper normalises them to plain objects for consumers. Non-JSON strings\n * are returned unchanged.\n */\nexport function parseToolPayload(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n return value;\n }\n\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return value;\n }\n}\n\nfunction isToolMessageLike(\n value: unknown\n): value is Record<string, unknown> & { content: unknown } {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n if (record.type === \"tool\") return true;\n return typeof record.tool_call_id === \"string\" && \"content\" in record;\n}\n\nfunction textFromContentBlocks(content: unknown[]): string {\n let out = \"\";\n for (const block of content) {\n if (!block || typeof block !== \"object\") continue;\n const record = block as Record<string, unknown>;\n if (record.type === \"text\" && typeof record.text === \"string\") {\n out += record.text;\n }\n }\n return out;\n}\n\n/**\n * Normalise tool-result `content` from a wire ToolMessage into the value\n * a tool implementation returned (object, string, etc.).\n */\nfunction parseToolResultContent(content: unknown): unknown | null {\n if (content == null) return null;\n\n if (typeof content === \"string\") {\n const trimmed = content.trim();\n if (trimmed.length === 0) return null;\n return parseToolPayload(content);\n }\n\n if (Array.isArray(content)) {\n const text = textFromContentBlocks(content);\n if (text.length === 0) return null;\n return parseToolPayload(text);\n }\n\n if (typeof content === \"object\") {\n return content;\n }\n\n return null;\n}\n\n/**\n * Parse a `tool-finished` output payload into the tool's return value.\n *\n * Wire events often wrap structured tool results in a ToolMessage-shaped\n * object (`{ type: \"tool\", content: \"...\" }`). This unwraps that envelope,\n * JSON-decodes string content when possible, and leaves plain strings as-is.\n * Returns `null` when a ToolMessage envelope is present but its content\n * cannot be normalised.\n */\nexport function parseToolOutput(value: unknown): unknown | null {\n const parsed = parseToolPayload(value);\n if (isToolMessageLike(parsed)) {\n return parseToolResultContent(parsed.content);\n }\n return parsed ?? null;\n}\n\ntype ActiveToolCall = {\n handle: MutableToolCallHandle;\n resolveOutput: (value: unknown) => void;\n rejectOutput: (err: Error) => void;\n};\n\n/**\n * Incrementally assembles `tools` events into mutable tool-call handles.\n *\n * Framework consumers store the handle directly; client SDK consumers\n * should map with {@link toClientAssembledToolCall} before yielding.\n */\nexport class ToolCallAssembler {\n private readonly active = new Map<string, ActiveToolCall>();\n\n consume(event: ToolsEvent): MutableToolCallHandle | undefined {\n const data = event.params.data;\n\n if (data.event === \"tool-started\") {\n return this.handleStarted(event, data);\n }\n\n if (data.event === \"tool-finished\") {\n return this.handleFinished(data);\n }\n\n if (data.event === \"tool-error\") {\n return this.handleError(data);\n }\n\n // tool-output-delta: no action needed at assembly level\n return undefined;\n }\n\n /**\n * Reject any in-flight tool calls (e.g. on session close).\n */\n failAll(reason: Error): void {\n for (const entry of this.active.values()) {\n entry.rejectOutput(reason);\n entry.handle.status = \"error\";\n entry.handle.error = reason.message;\n }\n this.active.clear();\n }\n\n private handleStarted(\n event: ToolsEvent,\n data: ToolStartedData\n ): MutableToolCallHandle {\n let resolveOutput!: (value: unknown) => void;\n let rejectOutput!: (err: Error) => void;\n\n const outputPromise = new Promise<unknown>((resolve, reject) => {\n resolveOutput = resolve;\n rejectOutput = reject;\n });\n // Attach a default no-op catch so if no consumer awaits\n // `output` the eventual rejection on `tool-error` / `failAll`\n // doesn't surface as an unhandled Promise rejection.\n outputPromise.catch(() => undefined);\n\n const input = parseToolPayload(data.input);\n const name = data.tool_name;\n const callId = data.tool_call_id;\n const namespace = [...event.params.namespace];\n\n const handle: MutableToolCallHandle = {\n name,\n callId,\n id: callId,\n namespace,\n input,\n args: input,\n output: null,\n status: \"running\",\n error: undefined,\n outputPromise,\n };\n\n this.active.set(callId, {\n handle,\n resolveOutput,\n rejectOutput,\n });\n\n return handle;\n }\n\n private handleFinished(\n data: ToolFinishedData\n ): MutableToolCallHandle | undefined {\n const entry = this.active.get(data.tool_call_id);\n if (!entry) return undefined;\n this.active.delete(data.tool_call_id);\n const value = parseToolOutput(data.output);\n entry.resolveOutput(value);\n entry.handle.output = value;\n entry.handle.status = \"finished\";\n entry.handle.error = undefined;\n return entry.handle;\n }\n\n private handleError(data: ToolErrorData): MutableToolCallHandle | undefined {\n const entry = this.active.get(data.tool_call_id);\n if (!entry) return undefined;\n this.active.delete(data.tool_call_id);\n entry.rejectOutput(new Error(data.message));\n entry.handle.output = null;\n entry.handle.status = \"error\";\n entry.handle.error = data.message;\n return entry.handle;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tools.cjs","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"sourcesContent":["import type {\n ToolsEvent,\n ToolStartedData,\n ToolFinishedData,\n ToolErrorData,\n} from \"@langchain/protocol\";\n\n/**\n * High-level outcome of a single tool call.\n */\nexport type ToolCallStatus = \"running\" | \"finished\" | \"error\";\n\n/** Shared metadata for assembled tool-call handles. */\ninterface ToolCallBase<TName extends string = string, TInput = unknown> {\n readonly name: TName;\n readonly callId: string;\n /**\n * Pre-v1 alias for {@link callId}. Matches `ToolCallWithResult.id` and\n * `ToolCall.id` on message-level tool calls.\n */\n readonly id: string;\n readonly namespace: string[];\n readonly input: TInput;\n /**\n * Pre-v1 alias for {@link input}. Matches `ToolCallFromTool` `args`.\n */\n readonly args: TInput;\n}\n\n/**\n * Script-oriented tool handle from the client SDK (`ThreadStream.toolCalls`,\n * subagent/subgraph projections). Completion and errors are surfaced only\n * through {@link output}.\n */\nexport interface ClientAssembledToolCall<\n TName extends string = string,\n TInput = unknown,\n TOutput = unknown,\n> extends ToolCallBase<TName, TInput> {\n readonly output: Promise<TOutput>;\n}\n\n/**\n * Reactive tool handle for framework bindings (`stream.toolCalls`,\n * `useToolCalls`, `injectToolCalls`).\n *\n * {@link status}, {@link error}, and {@link output} are plain values that\n * the assembler updates in place as tool events arrive. That lets React,\n * Vue, Svelte, and Angular re-render from a snapshot on each store tick\n * without `await`, effects, or Suspense boundaries around a promise.\n * {@link ClientAssembledToolCall} keeps a promise-based {@link output}\n * instead for script consumers that read tool results sequentially.\n *\n * {@link output} is `null` while the call is running or after it fails;\n * successful completion sets it to the parsed tool return value (objects\n * and strings are unwrapped from ToolMessage wire envelopes when needed).\n */\nexport interface AssembledToolCall<\n TName extends string = string,\n TInput = unknown,\n TOutput = unknown,\n> extends ToolCallBase<TName, TInput> {\n readonly output: TOutput | null;\n readonly status: ToolCallStatus;\n readonly error: string | undefined;\n}\n\n/** @internal Mutable runtime handle shared by client and framework views. */\ntype MutableToolCallHandle = {\n name: string;\n callId: string;\n id: string;\n namespace: string[];\n input: unknown;\n args: unknown;\n output: unknown | null;\n status: ToolCallStatus;\n error: string | undefined;\n outputPromise: Promise<unknown>;\n};\n\n/**\n * Project a runtime handle to the client SDK surface (promise-only\n * {@link output}, no {@link status} / {@link error} fields).\n */\nexport function toClientAssembledToolCall(\n handle: MutableToolCallHandle\n): ClientAssembledToolCall {\n return {\n name: handle.name,\n callId: handle.callId,\n id: handle.id,\n namespace: handle.namespace,\n input: handle.input,\n args: handle.args,\n output: handle.outputPromise as Promise<unknown>,\n };\n}\n\n/**\n * Parse wire-format tool payloads into structured values.\n *\n * Tool events may carry JSON-encoded object strings on the wire; this\n * helper normalises them to plain objects for consumers. Non-JSON strings\n * are returned unchanged.\n */\nexport function parseToolPayload(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n return value;\n }\n\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return value;\n }\n}\n\n/**\n * Skip wrapper `task` tool events scoped to a subagent namespace.\n *\n * Deep-agent subagents are discovered from root-level `task` tool calls;\n * replaying the same dispatch tool inside the worker namespace would\n * otherwise surface as a spurious entry in `sub.toolCalls`.\n */\nexport function shouldIgnoreScopedTaskToolEvent(\n scopeNamespace: readonly string[],\n event: ToolsEvent\n): boolean {\n const data = event.params.data;\n return (\n scopeNamespace.length > 0 &&\n event.params.namespace.length === scopeNamespace.length &&\n event.params.namespace.every(\n (segment, index) => segment === scopeNamespace[index]\n ) &&\n \"tool_name\" in data &&\n data.tool_name === \"task\"\n );\n}\n\nfunction getWireMessageField(message: unknown, field: string): unknown {\n if (!message || typeof message !== \"object\" || Array.isArray(message)) {\n return undefined;\n }\n const record = message as Record<string, unknown>;\n if (field in record) return record[field];\n const kwargs = record.kwargs as Record<string, unknown> | undefined;\n if (kwargs != null && field in kwargs) return kwargs[field];\n const lcKwargs = record.lc_kwargs as Record<string, unknown> | undefined;\n if (lcKwargs != null && field in lcKwargs) return lcKwargs[field];\n return undefined;\n}\n\nfunction isToolMessageLike(\n value: unknown\n): value is Record<string, unknown> & { content: unknown } {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n if (record.type === \"tool\") return true;\n const type = getWireMessageField(value, \"type\");\n if (type === \"tool\") return true;\n return (\n typeof getWireMessageField(value, \"tool_call_id\") === \"string\" &&\n getWireMessageField(value, \"content\") !== undefined\n );\n}\n\nfunction isCommandLike(\n value: unknown\n): value is Record<string, unknown> & { update?: unknown } {\n return (\n !!value &&\n typeof value === \"object\" &&\n (value as Record<string, unknown>).lg_name === \"Command\"\n );\n}\n\nfunction textFromContentBlocks(content: unknown[]): string {\n let out = \"\";\n for (const block of content) {\n if (!block || typeof block !== \"object\") continue;\n const record = block as Record<string, unknown>;\n if (record.type === \"text\" && typeof record.text === \"string\") {\n out += record.text;\n }\n }\n return out;\n}\n\n/**\n * Normalise tool-result `content` from a wire ToolMessage into the value\n * a tool implementation returned (object, string, etc.).\n */\nfunction parseToolResultContent(content: unknown): unknown | null {\n if (content == null) return null;\n\n if (typeof content === \"string\") {\n const trimmed = content.trim();\n if (trimmed.length === 0) return null;\n return parseToolPayload(content);\n }\n\n if (Array.isArray(content)) {\n const text = textFromContentBlocks(content);\n if (text.length === 0) return null;\n return parseToolPayload(text);\n }\n\n if (typeof content === \"object\") {\n return content;\n }\n\n return null;\n}\n\nfunction parseToolMessageRecord(message: unknown): unknown | null {\n const content = getWireMessageField(message, \"content\");\n return parseToolResultContent(content);\n}\n\ntype ParsedCommandToolOutput =\n | { found: true; value: unknown | null }\n | { found: false };\n\nfunction parseCommandToolOutput(\n command: Record<string, unknown> & { update?: unknown },\n toolCallId?: string\n): ParsedCommandToolOutput {\n const update = command.update;\n if (update == null || typeof update !== \"object\" || Array.isArray(update)) {\n return { found: false };\n }\n\n const messages = (update as Record<string, unknown>).messages;\n if (!Array.isArray(messages)) return { found: false };\n\n const toolMessages = messages.filter((message) => isToolMessageLike(message));\n if (toolMessages.length === 0) return { found: false };\n\n if (toolCallId != null) {\n for (const message of toolMessages) {\n const callId = getWireMessageField(message, \"tool_call_id\");\n if (callId !== toolCallId) continue;\n return { found: true, value: parseToolMessageRecord(message) };\n }\n return { found: false };\n }\n\n if (toolMessages.length === 1) {\n return { found: true, value: parseToolMessageRecord(toolMessages[0]) };\n }\n\n for (let i = toolMessages.length - 1; i >= 0; i -= 1) {\n const parsed = parseToolMessageRecord(toolMessages[i]);\n if (parsed != null) return { found: true, value: parsed };\n }\n\n return { found: true, value: null };\n}\n\n/**\n * Parse a `tool-finished` output payload into the tool's return value.\n *\n * Wire events often wrap structured tool results in a ToolMessage-shaped\n * object (`{ type: \"tool\", content: \"...\" }`) or a LangGraph\n * {@link Command} whose `update.messages` carries the ToolMessage.\n * This unwraps those envelopes, JSON-decodes string content when possible,\n * and leaves plain strings as-is. Returns `null` when a ToolMessage envelope\n * is present but its content cannot be normalised.\n */\nexport function parseToolOutput(\n value: unknown,\n toolCallId?: string\n): unknown | null {\n const parsed = parseToolPayload(value);\n if (isCommandLike(parsed)) {\n const commandOutput = parseCommandToolOutput(parsed, toolCallId);\n return commandOutput.found ? commandOutput.value : parsed;\n }\n if (isToolMessageLike(parsed)) {\n return parseToolResultContent(getWireMessageField(parsed, \"content\"));\n }\n return parsed ?? null;\n}\n\ntype ActiveToolCall = {\n handle: MutableToolCallHandle;\n resolveOutput: (value: unknown) => void;\n rejectOutput: (err: Error) => void;\n};\n\n/**\n * Incrementally assembles `tools` events into mutable tool-call handles.\n *\n * Framework consumers store the handle directly; client SDK consumers\n * should map with {@link toClientAssembledToolCall} before yielding.\n */\nexport class ToolCallAssembler {\n private readonly active = new Map<string, ActiveToolCall>();\n\n consume(event: ToolsEvent): MutableToolCallHandle | undefined {\n const data = event.params.data;\n\n if (data.event === \"tool-started\") {\n return this.handleStarted(event, data);\n }\n\n if (data.event === \"tool-finished\") {\n return this.handleFinished(data);\n }\n\n if (data.event === \"tool-error\") {\n return this.handleError(data);\n }\n\n // tool-output-delta: no action needed at assembly level\n return undefined;\n }\n\n /**\n * Reject any in-flight tool calls (e.g. on session close).\n */\n failAll(reason: Error): void {\n for (const entry of this.active.values()) {\n entry.rejectOutput(reason);\n entry.handle.status = \"error\";\n entry.handle.error = reason.message;\n }\n this.active.clear();\n }\n\n private handleStarted(\n event: ToolsEvent,\n data: ToolStartedData\n ): MutableToolCallHandle {\n let resolveOutput!: (value: unknown) => void;\n let rejectOutput!: (err: Error) => void;\n\n const outputPromise = new Promise<unknown>((resolve, reject) => {\n resolveOutput = resolve;\n rejectOutput = reject;\n });\n // Attach a default no-op catch so if no consumer awaits\n // `output` the eventual rejection on `tool-error` / `failAll`\n // doesn't surface as an unhandled Promise rejection.\n outputPromise.catch(() => undefined);\n\n const input = parseToolPayload(data.input);\n const name = data.tool_name;\n const callId = data.tool_call_id;\n const namespace = [...event.params.namespace];\n\n const handle: MutableToolCallHandle = {\n name,\n callId,\n id: callId,\n namespace,\n input,\n args: input,\n output: null,\n status: \"running\",\n error: undefined,\n outputPromise,\n };\n\n this.active.set(callId, {\n handle,\n resolveOutput,\n rejectOutput,\n });\n\n return handle;\n }\n\n private handleFinished(\n data: ToolFinishedData\n ): MutableToolCallHandle | undefined {\n const entry = this.active.get(data.tool_call_id);\n if (!entry) return undefined;\n this.active.delete(data.tool_call_id);\n const value = parseToolOutput(data.output, data.tool_call_id);\n entry.resolveOutput(value);\n entry.handle.output = value;\n entry.handle.status = \"finished\";\n entry.handle.error = undefined;\n return entry.handle;\n }\n\n private handleError(data: ToolErrorData): MutableToolCallHandle | undefined {\n const entry = this.active.get(data.tool_call_id);\n if (!entry) return undefined;\n this.active.delete(data.tool_call_id);\n entry.rejectOutput(new Error(data.message));\n entry.handle.output = null;\n entry.handle.status = \"error\";\n entry.handle.error = data.message;\n return entry.handle;\n }\n}\n"],"mappings":"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"}
@@ -61,12 +61,13 @@ declare function parseToolPayload(value: unknown): unknown;
61
61
  * Parse a `tool-finished` output payload into the tool's return value.
62
62
  *
63
63
  * Wire events often wrap structured tool results in a ToolMessage-shaped
64
- * object (`{ type: "tool", content: "..." }`). This unwraps that envelope,
65
- * JSON-decodes string content when possible, and leaves plain strings as-is.
66
- * Returns `null` when a ToolMessage envelope is present but its content
67
- * cannot be normalised.
64
+ * object (`{ type: "tool", content: "..." }`) or a LangGraph
65
+ * {@link Command} whose `update.messages` carries the ToolMessage.
66
+ * This unwraps those envelopes, JSON-decodes string content when possible,
67
+ * and leaves plain strings as-is. Returns `null` when a ToolMessage envelope
68
+ * is present but its content cannot be normalised.
68
69
  */
69
- declare function parseToolOutput(value: unknown): unknown | null;
70
+ declare function parseToolOutput(value: unknown, toolCallId?: string): unknown | null;
70
71
  //#endregion
71
72
  export { AssembledToolCall, ClientAssembledToolCall, ToolCallStatus, parseToolOutput, parseToolPayload };
72
73
  //# sourceMappingURL=tools.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.cts","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"mappings":";;;;;AAUA;KAAY,cAAA;;UAGF,YAAA;EAAA,SACC,IAAA,EAAM,KAAA;EAAA,SACN,MAAA;EAFW;;;;EAAA,SAOX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,EAAO,MAAA;EATK;;;EAAA,SAaZ,IAAA,EAAM,MAAA;AAAA;;;;;;UAQA,uBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA,CAAQ,OAAA;AAAA;AAL3B;;;;;;;;;;;;;;;AAAA,UAuBiB,iBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA;EAAA,SACR,MAAA,EAAQ,cAAA;EAAA,SACR,KAAA;AAAA;;;;;;;AA0CX;iBAAgB,gBAAA,CAAiB,KAAA;;;;AAsEjC;;;;;;iBAAgB,eAAA,CAAgB,KAAA"}
1
+ {"version":3,"file":"tools.d.cts","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"mappings":";;;;;AAUA;KAAY,cAAA;;UAGF,YAAA;EAAA,SACC,IAAA,EAAM,KAAA;EAAA,SACN,MAAA;EAFW;;;;EAAA,SAOX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,EAAO,MAAA;EATK;;;EAAA,SAaZ,IAAA,EAAM,MAAA;AAAA;;;;;;UAQA,uBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA,CAAQ,OAAA;AAAA;AAL3B;;;;;;;;;;;;;;;AAAA,UAuBiB,iBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA;EAAA,SACR,MAAA,EAAQ,cAAA;EAAA,SACR,KAAA;AAAA;;;;;;;AA0CX;iBAAgB,gBAAA,CAAiB,KAAA;;;;;;;;;;;iBAuKjB,eAAA,CACd,KAAA,WACA,UAAA"}
@@ -61,12 +61,13 @@ declare function parseToolPayload(value: unknown): unknown;
61
61
  * Parse a `tool-finished` output payload into the tool's return value.
62
62
  *
63
63
  * Wire events often wrap structured tool results in a ToolMessage-shaped
64
- * object (`{ type: "tool", content: "..." }`). This unwraps that envelope,
65
- * JSON-decodes string content when possible, and leaves plain strings as-is.
66
- * Returns `null` when a ToolMessage envelope is present but its content
67
- * cannot be normalised.
64
+ * object (`{ type: "tool", content: "..." }`) or a LangGraph
65
+ * {@link Command} whose `update.messages` carries the ToolMessage.
66
+ * This unwraps those envelopes, JSON-decodes string content when possible,
67
+ * and leaves plain strings as-is. Returns `null` when a ToolMessage envelope
68
+ * is present but its content cannot be normalised.
68
69
  */
69
- declare function parseToolOutput(value: unknown): unknown | null;
70
+ declare function parseToolOutput(value: unknown, toolCallId?: string): unknown | null;
70
71
  //#endregion
71
72
  export { AssembledToolCall, ClientAssembledToolCall, ToolCallStatus, parseToolOutput, parseToolPayload };
72
73
  //# sourceMappingURL=tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"mappings":";;;;;AAUA;KAAY,cAAA;;UAGF,YAAA;EAAA,SACC,IAAA,EAAM,KAAA;EAAA,SACN,MAAA;EAFW;;;;EAAA,SAOX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,EAAO,MAAA;EATK;;;EAAA,SAaZ,IAAA,EAAM,MAAA;AAAA;;;;;;UAQA,uBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA,CAAQ,OAAA;AAAA;AAL3B;;;;;;;;;;;;;;;AAAA,UAuBiB,iBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA;EAAA,SACR,MAAA,EAAQ,cAAA;EAAA,SACR,KAAA;AAAA;;;;;;;AA0CX;iBAAgB,gBAAA,CAAiB,KAAA;;;;AAsEjC;;;;;;iBAAgB,eAAA,CAAgB,KAAA"}
1
+ {"version":3,"file":"tools.d.ts","names":[],"sources":["../../../../src/client/stream/handles/tools.ts"],"mappings":";;;;;AAUA;KAAY,cAAA;;UAGF,YAAA;EAAA,SACC,IAAA,EAAM,KAAA;EAAA,SACN,MAAA;EAFW;;;;EAAA,SAOX,EAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,EAAO,MAAA;EATK;;;EAAA,SAaZ,IAAA,EAAM,MAAA;AAAA;;;;;;UAQA,uBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA,CAAQ,OAAA;AAAA;AAL3B;;;;;;;;;;;;;;;AAAA,UAuBiB,iBAAA,6EAIP,YAAA,CAAa,KAAA,EAAO,MAAA;EAAA,SACnB,MAAA,EAAQ,OAAA;EAAA,SACR,MAAA,EAAQ,cAAA;EAAA,SACR,KAAA;AAAA;;;;;;;AA0CX;iBAAgB,gBAAA,CAAiB,KAAA;;;;;;;;;;;iBAuKjB,eAAA,CACd,KAAA,WACA,UAAA"}
@@ -31,11 +31,34 @@ function parseToolPayload(value) {
31
31
  return value;
32
32
  }
33
33
  }
34
+ /**
35
+ * Skip wrapper `task` tool events scoped to a subagent namespace.
36
+ *
37
+ * Deep-agent subagents are discovered from root-level `task` tool calls;
38
+ * replaying the same dispatch tool inside the worker namespace would
39
+ * otherwise surface as a spurious entry in `sub.toolCalls`.
40
+ */
41
+ function shouldIgnoreScopedTaskToolEvent(scopeNamespace, event) {
42
+ const data = event.params.data;
43
+ return scopeNamespace.length > 0 && event.params.namespace.length === scopeNamespace.length && event.params.namespace.every((segment, index) => segment === scopeNamespace[index]) && "tool_name" in data && data.tool_name === "task";
44
+ }
45
+ function getWireMessageField(message, field) {
46
+ if (!message || typeof message !== "object" || Array.isArray(message)) return;
47
+ const record = message;
48
+ if (field in record) return record[field];
49
+ const kwargs = record.kwargs;
50
+ if (kwargs != null && field in kwargs) return kwargs[field];
51
+ const lcKwargs = record.lc_kwargs;
52
+ if (lcKwargs != null && field in lcKwargs) return lcKwargs[field];
53
+ }
34
54
  function isToolMessageLike(value) {
35
55
  if (!value || typeof value !== "object") return false;
36
- const record = value;
37
- if (record.type === "tool") return true;
38
- return typeof record.tool_call_id === "string" && "content" in record;
56
+ if (value.type === "tool") return true;
57
+ if (getWireMessageField(value, "type") === "tool") return true;
58
+ return typeof getWireMessageField(value, "tool_call_id") === "string" && getWireMessageField(value, "content") !== void 0;
59
+ }
60
+ function isCommandLike(value) {
61
+ return !!value && typeof value === "object" && value.lg_name === "Command";
39
62
  }
40
63
  function textFromContentBlocks(content) {
41
64
  let out = "";
@@ -64,18 +87,59 @@ function parseToolResultContent(content) {
64
87
  if (typeof content === "object") return content;
65
88
  return null;
66
89
  }
90
+ function parseToolMessageRecord(message) {
91
+ return parseToolResultContent(getWireMessageField(message, "content"));
92
+ }
93
+ function parseCommandToolOutput(command, toolCallId) {
94
+ const update = command.update;
95
+ if (update == null || typeof update !== "object" || Array.isArray(update)) return { found: false };
96
+ const messages = update.messages;
97
+ if (!Array.isArray(messages)) return { found: false };
98
+ const toolMessages = messages.filter((message) => isToolMessageLike(message));
99
+ if (toolMessages.length === 0) return { found: false };
100
+ if (toolCallId != null) {
101
+ for (const message of toolMessages) {
102
+ if (getWireMessageField(message, "tool_call_id") !== toolCallId) continue;
103
+ return {
104
+ found: true,
105
+ value: parseToolMessageRecord(message)
106
+ };
107
+ }
108
+ return { found: false };
109
+ }
110
+ if (toolMessages.length === 1) return {
111
+ found: true,
112
+ value: parseToolMessageRecord(toolMessages[0])
113
+ };
114
+ for (let i = toolMessages.length - 1; i >= 0; i -= 1) {
115
+ const parsed = parseToolMessageRecord(toolMessages[i]);
116
+ if (parsed != null) return {
117
+ found: true,
118
+ value: parsed
119
+ };
120
+ }
121
+ return {
122
+ found: true,
123
+ value: null
124
+ };
125
+ }
67
126
  /**
68
127
  * Parse a `tool-finished` output payload into the tool's return value.
69
128
  *
70
129
  * Wire events often wrap structured tool results in a ToolMessage-shaped
71
- * object (`{ type: "tool", content: "..." }`). This unwraps that envelope,
72
- * JSON-decodes string content when possible, and leaves plain strings as-is.
73
- * Returns `null` when a ToolMessage envelope is present but its content
74
- * cannot be normalised.
130
+ * object (`{ type: "tool", content: "..." }`) or a LangGraph
131
+ * {@link Command} whose `update.messages` carries the ToolMessage.
132
+ * This unwraps those envelopes, JSON-decodes string content when possible,
133
+ * and leaves plain strings as-is. Returns `null` when a ToolMessage envelope
134
+ * is present but its content cannot be normalised.
75
135
  */
76
- function parseToolOutput(value) {
136
+ function parseToolOutput(value, toolCallId) {
77
137
  const parsed = parseToolPayload(value);
78
- if (isToolMessageLike(parsed)) return parseToolResultContent(parsed.content);
138
+ if (isCommandLike(parsed)) {
139
+ const commandOutput = parseCommandToolOutput(parsed, toolCallId);
140
+ return commandOutput.found ? commandOutput.value : parsed;
141
+ }
142
+ if (isToolMessageLike(parsed)) return parseToolResultContent(getWireMessageField(parsed, "content"));
79
143
  return parsed ?? null;
80
144
  }
81
145
  /**
@@ -137,7 +201,7 @@ var ToolCallAssembler = class {
137
201
  const entry = this.active.get(data.tool_call_id);
138
202
  if (!entry) return void 0;
139
203
  this.active.delete(data.tool_call_id);
140
- const value = parseToolOutput(data.output);
204
+ const value = parseToolOutput(data.output, data.tool_call_id);
141
205
  entry.resolveOutput(value);
142
206
  entry.handle.output = value;
143
207
  entry.handle.status = "finished";
@@ -156,6 +220,6 @@ var ToolCallAssembler = class {
156
220
  }
157
221
  };
158
222
  //#endregion
159
- export { ToolCallAssembler, parseToolOutput, parseToolPayload, toClientAssembledToolCall };
223
+ export { ToolCallAssembler, parseToolOutput, parseToolPayload, shouldIgnoreScopedTaskToolEvent, toClientAssembledToolCall };
160
224
 
161
225
  //# sourceMappingURL=tools.js.map