@langchain/langgraph-sdk 1.5.6 → 1.6.1

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 (68) hide show
  1. package/dist/index.d.cts +5 -1
  2. package/dist/index.d.ts +5 -1
  3. package/dist/react/index.cjs +6 -0
  4. package/dist/react/index.d.cts +7 -2
  5. package/dist/react/index.d.ts +7 -2
  6. package/dist/react/index.js +2 -1
  7. package/dist/react/stream.cjs.map +1 -1
  8. package/dist/react/stream.custom.cjs +36 -7
  9. package/dist/react/stream.custom.cjs.map +1 -1
  10. package/dist/react/stream.custom.d.cts.map +1 -1
  11. package/dist/react/stream.custom.d.ts.map +1 -1
  12. package/dist/react/stream.custom.js +36 -7
  13. package/dist/react/stream.custom.js.map +1 -1
  14. package/dist/react/stream.d.cts +51 -31
  15. package/dist/react/stream.d.cts.map +1 -1
  16. package/dist/react/stream.d.ts +51 -31
  17. package/dist/react/stream.d.ts.map +1 -1
  18. package/dist/react/stream.js.map +1 -1
  19. package/dist/react/stream.lgp.cjs +45 -13
  20. package/dist/react/stream.lgp.cjs.map +1 -1
  21. package/dist/react/stream.lgp.js +45 -13
  22. package/dist/react/stream.lgp.js.map +1 -1
  23. package/dist/react/types.d.cts +5 -88
  24. package/dist/react/types.d.cts.map +1 -1
  25. package/dist/react/types.d.ts +5 -88
  26. package/dist/react/types.d.ts.map +1 -1
  27. package/dist/react-ui/client.cjs.map +1 -1
  28. package/dist/react-ui/client.d.cts +5 -3
  29. package/dist/react-ui/client.d.cts.map +1 -1
  30. package/dist/react-ui/client.d.ts +5 -3
  31. package/dist/react-ui/client.d.ts.map +1 -1
  32. package/dist/react-ui/client.js.map +1 -1
  33. package/dist/schema.d.cts.map +1 -1
  34. package/dist/schema.d.ts.map +1 -1
  35. package/dist/types.stream.d.ts.map +1 -1
  36. package/dist/ui/manager.cjs +140 -14
  37. package/dist/ui/manager.cjs.map +1 -1
  38. package/dist/ui/manager.js +140 -14
  39. package/dist/ui/manager.js.map +1 -1
  40. package/dist/ui/stream/agent.d.cts +143 -0
  41. package/dist/ui/stream/agent.d.cts.map +1 -0
  42. package/dist/ui/stream/agent.d.ts +143 -0
  43. package/dist/ui/stream/agent.d.ts.map +1 -0
  44. package/dist/ui/stream/base.d.cts +144 -0
  45. package/dist/ui/stream/base.d.cts.map +1 -0
  46. package/dist/ui/stream/base.d.ts +144 -0
  47. package/dist/ui/stream/base.d.ts.map +1 -0
  48. package/dist/ui/stream/deep-agent.d.cts +277 -0
  49. package/dist/ui/stream/deep-agent.d.cts.map +1 -0
  50. package/dist/ui/stream/deep-agent.d.ts +277 -0
  51. package/dist/ui/stream/deep-agent.d.ts.map +1 -0
  52. package/dist/ui/stream/index.d.cts +172 -0
  53. package/dist/ui/stream/index.d.cts.map +1 -0
  54. package/dist/ui/stream/index.d.ts +172 -0
  55. package/dist/ui/stream/index.d.ts.map +1 -0
  56. package/dist/ui/subagents.cjs +593 -0
  57. package/dist/ui/subagents.cjs.map +1 -0
  58. package/dist/ui/subagents.d.cts +291 -0
  59. package/dist/ui/subagents.d.cts.map +1 -0
  60. package/dist/ui/subagents.d.ts +291 -0
  61. package/dist/ui/subagents.d.ts.map +1 -0
  62. package/dist/ui/subagents.js +589 -0
  63. package/dist/ui/subagents.js.map +1 -0
  64. package/dist/ui/types.d.cts +384 -5
  65. package/dist/ui/types.d.cts.map +1 -1
  66. package/dist/ui/types.d.ts +384 -5
  67. package/dist/ui/types.d.ts.map +1 -1
  68. package/package.json +6 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":["DefaultToolCall","BagTemplate","InferAgentState","InferAgentToolCalls","SubagentStateMap","DefaultSubagentStates","AgentTypeConfigLike","DeepAgentTypeConfigLike","UseStreamOptions","BaseStream","UseAgentStream","UseAgentStreamOptions","UseDeepAgentStream","UseDeepAgentStreamOptions","IsDeepAgent","T","IsReactAgent","InferStateType","S","Record","O","InferNodeNames","N","Exclude","InferNodeReturnTypes","R","InferToolCalls","InferSubagentStates","ResolveStreamInterface","Bag","ResolveStreamOptions","InferBag","B"],"sources":["../../../src/ui/stream/index.d.ts"],"sourcesContent":["/**\n * Unified stream type system for LangGraph.\n *\n * This module provides the type resolution system that automatically selects\n * the appropriate stream interface based on the agent/graph type:\n *\n * - **CompiledStateGraph** → {@link UseGraphStream}\n * - **ReactAgent** (createAgent) → {@link UseAgentStream}\n * - **DeepAgent** (createDeepAgent) → {@link UseDeepAgentStream}\n *\n * @module\n */\nimport type { DefaultToolCall } from \"../../types.messages.js\";\nimport type { BagTemplate } from \"../../types.template.js\";\nimport type { InferAgentState, InferAgentToolCalls, SubagentStateMap, DefaultSubagentStates, AgentTypeConfigLike, DeepAgentTypeConfigLike, UseStreamOptions } from \"../types.js\";\nimport type { BaseStream } from \"./base.js\";\nimport type { UseAgentStream, UseAgentStreamOptions } from \"./agent.js\";\nimport type { UseDeepAgentStream, UseDeepAgentStreamOptions } from \"./deep-agent.js\";\nexport type { BaseStream } from \"./base.js\";\nexport type { UseAgentStream, UseAgentStreamOptions } from \"./agent.js\";\nexport type { UseDeepAgentStream, UseDeepAgentStreamOptions, } from \"./deep-agent.js\";\n/**\n * Check if a type is a DeepAgent (has `~deepAgentTypes` phantom property).\n */\ntype IsDeepAgent<T> = T extends {\n \"~deepAgentTypes\": DeepAgentTypeConfigLike;\n} ? true : false;\n/**\n * Check if a type is a ReactAgent (has `~agentTypes` but not `~deepAgentTypes`).\n */\ntype IsReactAgent<T> = T extends {\n \"~agentTypes\": AgentTypeConfigLike;\n} ? T extends {\n \"~deepAgentTypes\": unknown;\n} ? false : true : false;\n/**\n * Infer the state type from an agent, graph, or direct state type.\n *\n * Detection order:\n * 1. Agent-like (`~agentTypes`) → InferAgentState\n * 2. CompiledGraph (`~RunOutput`) → Extract RunOutput\n * 3. Pregel (`~OutputType`) → Extract OutputType\n * 4. Direct state type → Return as-is\n */\nexport type InferStateType<T> = T extends {\n \"~agentTypes\": unknown;\n} ? InferAgentState<T> : T extends {\n \"~RunOutput\": infer S;\n} ? S extends Record<string, unknown> ? S : Record<string, unknown> : T extends {\n \"~OutputType\": infer O;\n} ? O extends Record<string, unknown> ? O : Record<string, unknown> : T extends Record<string, unknown> ? T : Record<string, unknown>;\n/**\n * Infer the node names from a compiled graph.\n *\n * Extracts the `~NodeType` phantom property from CompiledGraph instances,\n * providing a union of all node names defined in the graph.\n *\n * @example\n * ```typescript\n * const graph = new StateGraph(StateAnnotation)\n * .addNode(\"agent\", agentFn)\n * .addNode(\"tool\", toolFn)\n * .compile();\n *\n * type NodeNames = InferNodeNames<typeof graph>; // \"agent\" | \"tool\"\n * ```\n */\nexport type InferNodeNames<T> = T extends {\n \"~NodeType\": infer N;\n} ? N extends string ? Exclude<N, \"__start__\"> : string : string;\n/**\n * Infer the per-node return types from a compiled graph.\n *\n * Extracts the `~NodeReturnType` phantom property from CompiledGraph instances,\n * which is a mapped type of `{ [nodeName]: ReturnType }` for each node.\n *\n * @example\n * ```typescript\n * const graph = new StateGraph(StateAnnotation)\n * .addNode(\"dispatcher\", async () => ({ topic: \"foo\" }))\n * .addNode(\"researcher\", async () => ({ research: \"bar\" }))\n * .compile();\n *\n * type NodeReturns = InferNodeReturnTypes<typeof graph>;\n * // { dispatcher: { topic: string }; researcher: { research: string } }\n * ```\n */\nexport type InferNodeReturnTypes<T> = T extends {\n \"~NodeReturnType\": infer R;\n} ? R extends Record<string, unknown> ? R : Record<string, Record<string, unknown>> : Record<string, Record<string, unknown>>;\n/**\n * Infer tool call types from an agent.\n *\n * For agents, extracts typed tool calls from the agent's tools.\n * For non-agents, returns DefaultToolCall.\n */\nexport type InferToolCalls<T> = T extends {\n \"~agentTypes\": unknown;\n} ? InferAgentToolCalls<T> : DefaultToolCall;\n/**\n * Infer subagent state map from a DeepAgent.\n *\n * For DeepAgent, creates a map of subagent names to their state types.\n * For non-DeepAgent, returns DefaultSubagentStates.\n */\nexport type InferSubagentStates<T> = T extends {\n \"~deepAgentTypes\": unknown;\n} ? SubagentStateMap<T, InferAgentToolCalls<T>> : DefaultSubagentStates;\n/**\n * Resolves the appropriate stream interface based on the agent/graph type.\n *\n * This type automatically selects the correct stream interface based on\n * the type of agent or graph passed to `useStream`:\n *\n * 1. **DeepAgent** (`~deepAgentTypes`) → {@link UseDeepAgentStream}\n * - Includes: values, messages, toolCalls, subagents, getSubagentsByType, getSubagentsByMessage\n *\n * 2. **ReactAgent** (`~agentTypes`) → {@link UseAgentStream}\n * - Includes: values, messages, toolCalls, getToolCalls\n * - Excludes: subagents, getSubagentsByType\n *\n * 3. **CompiledGraph** (`~RunOutput`/`~OutputType`) → {@link UseGraphStream}\n * - Includes: values, messages, submit, stop, nodes, getNodeStreamsByName\n * - Excludes: toolCalls, subagents\n * - Node names are inferred from `~NodeType` for type-safe access\n *\n * 4. **Default** → {@link UseGraphStream}\n *\n * @template T - The agent or graph type (use `typeof agent` or `typeof graph`)\n * @template Bag - Type configuration bag for interrupts, configurable, etc.\n *\n * @example\n * ```typescript\n * // Automatic detection based on agent type\n * type GraphStream = ResolveStreamInterface<typeof compiledGraph, BagTemplate>;\n * // → UseGraphStream (with typed node names)\n *\n * type AgentStream = ResolveStreamInterface<typeof reactAgent, BagTemplate>;\n * // → UseAgentStream (has toolCalls)\n *\n * type DeepStream = ResolveStreamInterface<typeof deepAgent, BagTemplate>;\n * // → UseDeepAgentStream (has toolCalls AND subagents)\n * ```\n */\nexport type ResolveStreamInterface<T, Bag extends BagTemplate = BagTemplate> = IsDeepAgent<T> extends true ? UseDeepAgentStream<InferStateType<T>, InferToolCalls<T>, InferSubagentStates<T>, Bag> : IsReactAgent<T> extends true ? UseAgentStream<InferStateType<T>, InferToolCalls<T>, Bag> : BaseStream<InferStateType<T>, InferToolCalls<T>, Bag>;\n/**\n * Resolves the appropriate options interface based on the agent/graph type.\n *\n * This type automatically selects the correct options interface based on\n * the type of agent or graph:\n *\n * 1. **DeepAgent** → {@link UseDeepAgentStreamOptions}\n * - Includes: `filterSubagentMessages` option\n *\n * 2. **ReactAgent** → {@link UseAgentStreamOptions}\n *\n * 3. **CompiledGraph** / **Default** → {@link UseGraphStreamOptions}\n *\n * @template T - The agent or graph type\n * @template Bag - Type configuration bag\n *\n * @example\n * ```typescript\n * // Only DeepAgent options include filterSubagentMessages\n * type DeepOptions = ResolveStreamOptions<typeof deepAgent, BagTemplate>;\n * // DeepOptions.filterSubagentMessages exists\n *\n * type AgentOptions = ResolveStreamOptions<typeof reactAgent, BagTemplate>;\n * // AgentOptions.filterSubagentMessages does NOT exist\n * ```\n */\nexport type ResolveStreamOptions<T, Bag extends BagTemplate = BagTemplate> = IsDeepAgent<T> extends true ? UseDeepAgentStreamOptions<InferStateType<T>, Bag> : IsReactAgent<T> extends true ? UseAgentStreamOptions<InferStateType<T>, Bag> : UseStreamOptions<InferStateType<T>, Bag>;\n/**\n * Infer the Bag type from an agent, defaulting to the provided Bag.\n *\n * Currently returns the provided Bag for all types.\n * Can be extended in the future to extract Bag from agent types.\n */\nexport type InferBag<T, B extends BagTemplate = BagTemplate> = T extends {\n \"~agentTypes\": unknown;\n} ? BagTemplate : B;\n"],"mappings":"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"}
@@ -0,0 +1,593 @@
1
+ const require_messages = require('./messages.cjs');
2
+ const require_tools = require('../utils/tools.cjs');
3
+
4
+ //#region src/ui/subagents.ts
5
+ /**
6
+ * Default tool names that indicate subagent invocation.
7
+ * Can be customized via SubagentManager options.
8
+ */
9
+ const DEFAULT_SUBAGENT_TOOL_NAMES = ["task"];
10
+ /**
11
+ * Checks if a namespace indicates a subagent/subgraph message.
12
+ *
13
+ * Subagent namespaces contain a "tools:" segment indicating they
14
+ * originate from a tool call that spawned a subgraph.
15
+ *
16
+ * @param namespace - The namespace array from stream events (or checkpoint_ns string)
17
+ * @returns True if this is a subagent namespace
18
+ */
19
+ function isSubagentNamespace(namespace) {
20
+ if (!namespace) return false;
21
+ if (typeof namespace === "string") return namespace.includes("tools:");
22
+ return namespace.some((s) => s.startsWith("tools:"));
23
+ }
24
+ /**
25
+ * Extracts the tool call ID from a namespace path.
26
+ *
27
+ * Namespaces follow the pattern: ["tools:call_abc123", "model_request:xyz", ...]
28
+ * This function extracts "call_abc123" from the first "tools:" segment.
29
+ *
30
+ * @param namespace - The namespace array from stream events
31
+ * @returns The tool call ID, or undefined if not found
32
+ */
33
+ function extractToolCallIdFromNamespace(namespace) {
34
+ if (!namespace || namespace.length === 0) return void 0;
35
+ for (const segment of namespace) if (segment.startsWith("tools:")) return segment.slice(6);
36
+ }
37
+ /**
38
+ * Calculates the depth of a subagent based on its namespace.
39
+ * Counts the number of "tools:" segments in the namespace.
40
+ *
41
+ * @param namespace - The namespace array
42
+ * @returns The depth (0 for main agent, 1+ for subagents)
43
+ */
44
+ function calculateDepthFromNamespace(namespace) {
45
+ if (!namespace) return 0;
46
+ return namespace.filter((s) => s.startsWith("tools:")).length;
47
+ }
48
+ /**
49
+ * Extracts the parent tool call ID from a namespace.
50
+ *
51
+ * For nested subagents, the namespace looks like:
52
+ * ["tools:parent_id", "tools:child_id", ...]
53
+ *
54
+ * @param namespace - The namespace array
55
+ * @returns The parent tool call ID, or null if this is a top-level subagent
56
+ */
57
+ function extractParentIdFromNamespace(namespace) {
58
+ if (!namespace || namespace.length < 2) return null;
59
+ const toolSegments = namespace.filter((s) => s.startsWith("tools:"));
60
+ if (toolSegments.length < 2) return null;
61
+ return toolSegments[toolSegments.length - 2]?.slice(6) ?? null;
62
+ }
63
+ /**
64
+ * Manages subagent execution state.
65
+ *
66
+ * Tracks subagents from the moment they are invoked (AI message with tool calls)
67
+ * through streaming to completion (tool message result).
68
+ */
69
+ var SubagentManager = class {
70
+ subagents = /* @__PURE__ */ new Map();
71
+ /**
72
+ * Maps namespace IDs (pregel task IDs) to tool call IDs.
73
+ * LangGraph subgraphs use internal pregel task IDs in their namespace,
74
+ * which are different from the tool_call_id used to invoke them.
75
+ */
76
+ namespaceToToolCallId = /* @__PURE__ */ new Map();
77
+ /**
78
+ * Pending namespace matches that couldn't be resolved immediately.
79
+ * These are retried when new tool calls are registered.
80
+ */
81
+ pendingMatches = /* @__PURE__ */ new Map();
82
+ /**
83
+ * Message managers for each subagent.
84
+ * Uses the same MessageTupleManager as the main stream for proper
85
+ * message chunk concatenation.
86
+ */
87
+ messageManagers = /* @__PURE__ */ new Map();
88
+ subagentToolNames;
89
+ onSubagentChange;
90
+ constructor(options) {
91
+ this.subagentToolNames = new Set(options?.subagentToolNames ?? DEFAULT_SUBAGENT_TOOL_NAMES);
92
+ this.onSubagentChange = options?.onSubagentChange;
93
+ }
94
+ /**
95
+ * Get or create a MessageTupleManager for a subagent.
96
+ */
97
+ getMessageManager(toolCallId) {
98
+ let manager = this.messageManagers.get(toolCallId);
99
+ if (!manager) {
100
+ manager = new require_messages.MessageTupleManager();
101
+ this.messageManagers.set(toolCallId, manager);
102
+ }
103
+ return manager;
104
+ }
105
+ /**
106
+ * Get messages for a subagent with proper chunk concatenation.
107
+ * This mirrors how the main stream handles messages.
108
+ */
109
+ getMessagesForSubagent(toolCallId) {
110
+ const manager = this.messageManagers.get(toolCallId);
111
+ if (!manager) return [];
112
+ const messages = [];
113
+ for (const entry of Object.values(manager.chunks)) if (entry.chunk) messages.push(require_messages.toMessageDict(entry.chunk));
114
+ return messages;
115
+ }
116
+ /**
117
+ * Create a complete SubagentStream object with all derived properties.
118
+ * This ensures consistency with UseStream interface.
119
+ */
120
+ createSubagentStream(base) {
121
+ const { messages } = base;
122
+ const allToolCalls = require_tools.getToolCallsWithResults(messages);
123
+ return {
124
+ ...base,
125
+ isLoading: base.status === "running",
126
+ toolCalls: allToolCalls,
127
+ getToolCalls: (message) => {
128
+ return allToolCalls.filter((tc) => tc.aiMessage.id === message.id);
129
+ },
130
+ interrupt: void 0,
131
+ interrupts: [],
132
+ subagents: /* @__PURE__ */ new Map(),
133
+ activeSubagents: [],
134
+ getSubagent: () => void 0,
135
+ getSubagentsByType: () => [],
136
+ getSubagentsByMessage: () => []
137
+ };
138
+ }
139
+ /**
140
+ * Get the tool call ID for a given namespace ID.
141
+ * Returns the namespace ID itself if no mapping exists.
142
+ */
143
+ getToolCallIdFromNamespace(namespaceId) {
144
+ return this.namespaceToToolCallId.get(namespaceId) ?? namespaceId;
145
+ }
146
+ /**
147
+ * Try to match a subgraph to a pending subagent by description.
148
+ * Creates a mapping from namespace ID to tool call ID if a match is found.
149
+ *
150
+ * Uses a multi-pass matching strategy:
151
+ * 1. Exact description match
152
+ * 2. Description contains/partial match
153
+ * 3. Any unmapped pending subagent (fallback)
154
+ *
155
+ * @param namespaceId - The namespace ID (pregel task ID) from the subgraph
156
+ * @param description - The description from the subgraph's initial message
157
+ * @returns The matched tool call ID, or undefined if no match
158
+ */
159
+ matchSubgraphToSubagent(namespaceId, description) {
160
+ if (this.namespaceToToolCallId.has(namespaceId)) return this.namespaceToToolCallId.get(namespaceId);
161
+ const mappedToolCallIds = new Set(this.namespaceToToolCallId.values());
162
+ const establishMapping = (toolCallId) => {
163
+ this.namespaceToToolCallId.set(namespaceId, toolCallId);
164
+ const subagent = this.subagents.get(toolCallId);
165
+ if (subagent && subagent.status === "pending") {
166
+ this.subagents.set(toolCallId, {
167
+ ...subagent,
168
+ status: "running",
169
+ namespace: [namespaceId],
170
+ startedAt: /* @__PURE__ */ new Date()
171
+ });
172
+ this.onSubagentChange?.();
173
+ }
174
+ return toolCallId;
175
+ };
176
+ for (const [toolCallId, subagent] of this.subagents) if ((subagent.status === "pending" || subagent.status === "running") && !mappedToolCallIds.has(toolCallId) && subagent.toolCall.args.description === description) return establishMapping(toolCallId);
177
+ for (const [toolCallId, subagent] of this.subagents) if ((subagent.status === "pending" || subagent.status === "running") && !mappedToolCallIds.has(toolCallId)) {
178
+ const subagentDesc = subagent.toolCall.args.description || "";
179
+ if (subagentDesc && description.includes(subagentDesc) || subagentDesc && subagentDesc.includes(description)) {
180
+ if (description.length > subagentDesc.length) this.subagents.set(toolCallId, {
181
+ ...subagent,
182
+ toolCall: {
183
+ ...subagent.toolCall,
184
+ args: {
185
+ ...subagent.toolCall.args,
186
+ description
187
+ }
188
+ }
189
+ });
190
+ return establishMapping(toolCallId);
191
+ }
192
+ }
193
+ if (description) this.pendingMatches.set(namespaceId, description);
194
+ }
195
+ /**
196
+ * Check if a tool call is a subagent invocation.
197
+ */
198
+ isSubagentToolCall(toolName) {
199
+ return this.subagentToolNames.has(toolName);
200
+ }
201
+ /**
202
+ * Check if a subagent_type value is valid.
203
+ * Valid types are proper identifiers like "weather-scout", "experience-curator".
204
+ */
205
+ isValidSubagentType(type) {
206
+ if (!type || typeof type !== "string") return false;
207
+ if (type.length < 3) return false;
208
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(type)) return false;
209
+ if (type.length > 50) return false;
210
+ return true;
211
+ }
212
+ /**
213
+ * Check if a subagent should be shown to the user.
214
+ * Subagents are only shown once they've actually started running.
215
+ *
216
+ * This filters out:
217
+ * - Pending subagents that haven't been matched to a namespace yet
218
+ * - Streaming artifacts with partial/corrupted data
219
+ *
220
+ * The idea is: we register subagents internally when we see tool calls,
221
+ * but we only show them to the user once LangGraph confirms they're
222
+ * actually executing (via namespace events).
223
+ */
224
+ isValidSubagent(subagent) {
225
+ return subagent.status === "running" || subagent.status === "complete";
226
+ }
227
+ /**
228
+ * Build a complete SubagentStream from internal state.
229
+ * Adds messages and derived properties.
230
+ */
231
+ buildExecution(base) {
232
+ const messages = this.getMessagesForSubagent(base.id);
233
+ return this.createSubagentStream({
234
+ ...base,
235
+ messages
236
+ });
237
+ }
238
+ /**
239
+ * Get all subagents as a Map.
240
+ * Filters out incomplete/phantom subagents that lack subagent_type.
241
+ */
242
+ getSubagents() {
243
+ const result = /* @__PURE__ */ new Map();
244
+ for (const [id, subagent] of this.subagents) if (this.isValidSubagent(subagent)) result.set(id, this.buildExecution(subagent));
245
+ return result;
246
+ }
247
+ /**
248
+ * Get all currently running subagents.
249
+ * Filters out incomplete/phantom subagents.
250
+ */
251
+ getActiveSubagents() {
252
+ return [...this.subagents.values()].filter((s) => s.status === "running" && this.isValidSubagent(s)).map((s) => this.buildExecution(s));
253
+ }
254
+ /**
255
+ * Get a specific subagent by tool call ID.
256
+ */
257
+ getSubagent(toolCallId) {
258
+ const subagent = this.subagents.get(toolCallId);
259
+ return subagent ? this.buildExecution(subagent) : void 0;
260
+ }
261
+ /**
262
+ * Get all subagents of a specific type.
263
+ */
264
+ getSubagentsByType(type) {
265
+ return [...this.subagents.values()].filter((s) => s.toolCall.args.subagent_type === type).map((s) => this.buildExecution(s));
266
+ }
267
+ /**
268
+ * Get all subagents triggered by a specific AI message.
269
+ *
270
+ * @param messageId - The ID of the AI message.
271
+ * @returns Array of subagent streams triggered by that message.
272
+ */
273
+ getSubagentsByMessage(messageId) {
274
+ return [...this.subagents.values()].filter((s) => s.aiMessageId === messageId && this.isValidSubagent(s)).map((s) => this.buildExecution(s));
275
+ }
276
+ /**
277
+ * Parse tool call args, handling both object and string formats.
278
+ * During streaming, args might come as a string that needs parsing.
279
+ */
280
+ parseArgs(args) {
281
+ if (!args) return {};
282
+ if (typeof args === "string") try {
283
+ return JSON.parse(args);
284
+ } catch {
285
+ return {};
286
+ }
287
+ return args;
288
+ }
289
+ /**
290
+ * Register new subagent(s) from AI message tool calls.
291
+ *
292
+ * Called when an AI message is received with tool calls.
293
+ * Creates pending subagent entries for each subagent tool call.
294
+ *
295
+ * @param toolCalls - The tool calls from an AI message
296
+ * @param aiMessageId - The ID of the AI message that triggered the tool calls
297
+ */
298
+ registerFromToolCalls(toolCalls, aiMessageId) {
299
+ let hasChanges = false;
300
+ for (const toolCall of toolCalls) {
301
+ if (!toolCall.id) continue;
302
+ if (!this.isSubagentToolCall(toolCall.name)) continue;
303
+ const parsedArgs = this.parseArgs(toolCall.args);
304
+ const hasValidType = this.isValidSubagentType(parsedArgs.subagent_type);
305
+ const existing = this.subagents.get(toolCall.id);
306
+ if (existing) {
307
+ const newType = parsedArgs.subagent_type || "";
308
+ const oldType = existing.toolCall.args.subagent_type || "";
309
+ const newDesc = parsedArgs.description || "";
310
+ const oldDesc = existing.toolCall.args.description || "";
311
+ const shouldUpdateType = this.isValidSubagentType(newType) && newType.length > oldType.length;
312
+ const shouldUpdateDesc = newDesc.length > oldDesc.length;
313
+ if (shouldUpdateType || shouldUpdateDesc) {
314
+ this.subagents.set(toolCall.id, {
315
+ ...existing,
316
+ toolCall: {
317
+ ...existing.toolCall,
318
+ args: {
319
+ ...existing.toolCall.args,
320
+ ...parsedArgs,
321
+ description: shouldUpdateDesc ? newDesc : oldDesc,
322
+ subagent_type: shouldUpdateType ? newType : oldType
323
+ }
324
+ }
325
+ });
326
+ hasChanges = true;
327
+ }
328
+ continue;
329
+ }
330
+ if (!hasValidType) continue;
331
+ const subagentToolCall = {
332
+ id: toolCall.id,
333
+ name: toolCall.name,
334
+ args: {
335
+ description: parsedArgs.description,
336
+ subagent_type: parsedArgs.subagent_type,
337
+ ...parsedArgs
338
+ }
339
+ };
340
+ const execution = {
341
+ id: toolCall.id,
342
+ toolCall: subagentToolCall,
343
+ status: "pending",
344
+ values: {},
345
+ result: null,
346
+ error: null,
347
+ namespace: [],
348
+ messages: [],
349
+ aiMessageId: aiMessageId ?? null,
350
+ parentId: null,
351
+ depth: 0,
352
+ startedAt: null,
353
+ completedAt: null
354
+ };
355
+ this.subagents.set(toolCall.id, execution);
356
+ this.getMessageManager(toolCall.id);
357
+ hasChanges = true;
358
+ }
359
+ if (hasChanges) {
360
+ this.retryPendingMatches();
361
+ this.onSubagentChange?.();
362
+ }
363
+ }
364
+ /**
365
+ * Retry matching pending namespaces to newly registered tool calls.
366
+ */
367
+ retryPendingMatches() {
368
+ if (this.pendingMatches.size === 0) return;
369
+ for (const [namespaceId, description] of this.pendingMatches) {
370
+ if (this.namespaceToToolCallId.has(namespaceId)) {
371
+ this.pendingMatches.delete(namespaceId);
372
+ continue;
373
+ }
374
+ if (this.matchSubgraphToSubagent(namespaceId, description)) this.pendingMatches.delete(namespaceId);
375
+ }
376
+ }
377
+ /**
378
+ * Mark a subagent as running and update its namespace.
379
+ *
380
+ * Called when update events are received with a namespace indicating
381
+ * which subagent is streaming.
382
+ *
383
+ * @param toolCallId - The tool call ID of the subagent
384
+ * @param options - Additional update options
385
+ */
386
+ markRunning(toolCallId, options) {
387
+ const existing = this.subagents.get(toolCallId);
388
+ if (!existing) return;
389
+ const namespace = options?.namespace ?? existing.namespace;
390
+ this.subagents.set(toolCallId, {
391
+ ...existing,
392
+ status: "running",
393
+ namespace,
394
+ parentId: existing.parentId ?? extractParentIdFromNamespace(namespace) ?? null,
395
+ depth: existing.depth || calculateDepthFromNamespace(namespace),
396
+ startedAt: existing.startedAt ?? /* @__PURE__ */ new Date()
397
+ });
398
+ this.onSubagentChange?.();
399
+ }
400
+ /**
401
+ * Mark a subagent as running using a namespace ID.
402
+ * Resolves the namespace ID to the actual tool call ID via the mapping.
403
+ *
404
+ * @param namespaceId - The namespace ID (pregel task ID) from the subgraph
405
+ * @param namespace - The full namespace array
406
+ */
407
+ markRunningFromNamespace(namespaceId, namespace) {
408
+ const toolCallId = this.getToolCallIdFromNamespace(namespaceId);
409
+ this.markRunning(toolCallId, { namespace });
410
+ }
411
+ /**
412
+ * Add a serialized message to a subagent from stream events.
413
+ *
414
+ * This method handles the raw serialized message data from SSE events.
415
+ * Uses MessageTupleManager for proper chunk concatenation, matching
416
+ * how the main stream handles messages.
417
+ *
418
+ * @param namespaceId - The namespace ID (pregel task ID) from the stream
419
+ * @param serialized - The serialized message from the stream
420
+ * @param metadata - Optional metadata from the stream event
421
+ */
422
+ addMessageToSubagent(namespaceId, serialized, metadata) {
423
+ if (serialized.type === "human" && typeof serialized.content === "string") this.matchSubgraphToSubagent(namespaceId, serialized.content);
424
+ const toolCallId = this.getToolCallIdFromNamespace(namespaceId);
425
+ const existing = this.subagents.get(toolCallId);
426
+ if (!existing) return;
427
+ if (this.getMessageManager(toolCallId).add(serialized, metadata)) if (serialized.type === "ai") this.subagents.set(toolCallId, {
428
+ ...existing,
429
+ status: "running",
430
+ startedAt: existing.startedAt ?? /* @__PURE__ */ new Date(),
431
+ messages: this.getMessagesForSubagent(toolCallId)
432
+ });
433
+ else this.subagents.set(toolCallId, {
434
+ ...existing,
435
+ messages: this.getMessagesForSubagent(toolCallId)
436
+ });
437
+ this.onSubagentChange?.();
438
+ }
439
+ /**
440
+ * Update subagent values from a values stream event.
441
+ *
442
+ * Called when a values event is received from a subagent's namespace.
443
+ * This populates the subagent's state values, making them accessible
444
+ * via the `values` property.
445
+ *
446
+ * @param namespaceId - The namespace ID (pregel task ID) from the stream
447
+ * @param values - The state values from the stream event
448
+ */
449
+ updateSubagentValues(namespaceId, values) {
450
+ const toolCallId = this.getToolCallIdFromNamespace(namespaceId);
451
+ const existing = this.subagents.get(toolCallId);
452
+ if (!existing) return;
453
+ this.subagents.set(toolCallId, {
454
+ ...existing,
455
+ values,
456
+ status: existing.status === "pending" ? "running" : existing.status,
457
+ startedAt: existing.startedAt ?? /* @__PURE__ */ new Date()
458
+ });
459
+ this.onSubagentChange?.();
460
+ }
461
+ /**
462
+ * Complete a subagent with a result.
463
+ *
464
+ * Called when a tool message is received for the subagent.
465
+ *
466
+ * @param toolCallId - The tool call ID of the subagent
467
+ * @param result - The result content
468
+ * @param status - The final status (complete or error)
469
+ */
470
+ complete(toolCallId, result, status = "complete") {
471
+ const existing = this.subagents.get(toolCallId);
472
+ if (!existing) return;
473
+ this.subagents.set(toolCallId, {
474
+ ...existing,
475
+ status,
476
+ result: status === "complete" ? result : null,
477
+ error: status === "error" ? result : null,
478
+ completedAt: /* @__PURE__ */ new Date()
479
+ });
480
+ this.onSubagentChange?.();
481
+ }
482
+ /**
483
+ * Clear all subagent state.
484
+ */
485
+ clear() {
486
+ this.subagents.clear();
487
+ this.namespaceToToolCallId.clear();
488
+ this.messageManagers.clear();
489
+ this.pendingMatches.clear();
490
+ this.onSubagentChange?.();
491
+ }
492
+ /**
493
+ * Process a tool message to complete a subagent.
494
+ *
495
+ * @param toolCallId - The tool call ID from the tool message
496
+ * @param content - The result content
497
+ * @param status - Whether the tool execution was successful
498
+ */
499
+ processToolMessage(toolCallId, content, status = "success") {
500
+ if (!this.subagents.get(toolCallId)) return;
501
+ this.complete(toolCallId, content, status === "success" ? "complete" : "error");
502
+ }
503
+ /**
504
+ * Reconstruct subagent state from historical messages.
505
+ *
506
+ * This method parses an array of messages (typically from thread history)
507
+ * to identify subagent executions and their results. It's used to restore
508
+ * subagent state after:
509
+ * - Page refresh (when stream has already completed)
510
+ * - Loading thread history
511
+ * - Navigating between threads
512
+ *
513
+ * The reconstruction process:
514
+ * 1. Find AI messages with tool calls matching subagent tool names
515
+ * 2. Find corresponding tool messages with results
516
+ * 3. Create SubagentStream entries with "complete" status
517
+ *
518
+ * Note: Internal subagent messages (their streaming conversation) are not
519
+ * reconstructed since they are not persisted in the main thread state.
520
+ *
521
+ * @param messages - Array of messages from thread history
522
+ * @param options - Optional configuration
523
+ * @param options.skipIfPopulated - If true, skip reconstruction if subagents already exist
524
+ */
525
+ reconstructFromMessages(messages, options) {
526
+ if (options?.skipIfPopulated && this.subagents.size > 0) return;
527
+ const toolResults = /* @__PURE__ */ new Map();
528
+ for (const message of messages) if (message.type === "tool" && "tool_call_id" in message) {
529
+ const toolCallId = message.tool_call_id;
530
+ const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
531
+ const status = "status" in message && message.status === "error" ? "error" : "success";
532
+ toolResults.set(toolCallId, {
533
+ content,
534
+ status
535
+ });
536
+ }
537
+ let hasChanges = false;
538
+ for (const message of messages) {
539
+ if (message.type !== "ai" || !("tool_calls" in message) || !Array.isArray(message.tool_calls)) continue;
540
+ for (const toolCall of message.tool_calls) {
541
+ if (!toolCall.id) continue;
542
+ if (!this.isSubagentToolCall(toolCall.name)) continue;
543
+ if (this.subagents.has(toolCall.id)) continue;
544
+ const parsedArgs = this.parseArgs(toolCall.args);
545
+ if (!this.isValidSubagentType(parsedArgs.subagent_type)) continue;
546
+ const subagentToolCall = {
547
+ id: toolCall.id,
548
+ name: toolCall.name,
549
+ args: {
550
+ description: parsedArgs.description,
551
+ subagent_type: parsedArgs.subagent_type,
552
+ ...parsedArgs
553
+ }
554
+ };
555
+ const toolResult = toolResults.get(toolCall.id);
556
+ const isComplete = !!toolResult;
557
+ const status = isComplete ? toolResult.status === "error" ? "error" : "complete" : "running";
558
+ const execution = {
559
+ id: toolCall.id,
560
+ toolCall: subagentToolCall,
561
+ status,
562
+ values: {},
563
+ result: isComplete && status === "complete" ? toolResult.content : null,
564
+ error: isComplete && status === "error" ? toolResult.content : null,
565
+ namespace: [],
566
+ messages: [],
567
+ aiMessageId: message.id ?? null,
568
+ parentId: null,
569
+ depth: 0,
570
+ startedAt: null,
571
+ completedAt: isComplete ? /* @__PURE__ */ new Date() : null
572
+ };
573
+ this.subagents.set(toolCall.id, execution);
574
+ hasChanges = true;
575
+ }
576
+ }
577
+ if (hasChanges) this.onSubagentChange?.();
578
+ }
579
+ /**
580
+ * Check if any subagents are currently tracked.
581
+ */
582
+ hasSubagents() {
583
+ return this.subagents.size > 0;
584
+ }
585
+ };
586
+
587
+ //#endregion
588
+ exports.SubagentManager = SubagentManager;
589
+ exports.calculateDepthFromNamespace = calculateDepthFromNamespace;
590
+ exports.extractParentIdFromNamespace = extractParentIdFromNamespace;
591
+ exports.extractToolCallIdFromNamespace = extractToolCallIdFromNamespace;
592
+ exports.isSubagentNamespace = isSubagentNamespace;
593
+ //# sourceMappingURL=subagents.cjs.map