@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.
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/react/index.cjs +6 -0
- package/dist/react/index.d.cts +7 -2
- package/dist/react/index.d.ts +7 -2
- package/dist/react/index.js +2 -1
- package/dist/react/stream.cjs.map +1 -1
- package/dist/react/stream.custom.cjs +36 -7
- package/dist/react/stream.custom.cjs.map +1 -1
- package/dist/react/stream.custom.d.cts.map +1 -1
- package/dist/react/stream.custom.d.ts.map +1 -1
- package/dist/react/stream.custom.js +36 -7
- package/dist/react/stream.custom.js.map +1 -1
- package/dist/react/stream.d.cts +51 -31
- package/dist/react/stream.d.cts.map +1 -1
- package/dist/react/stream.d.ts +51 -31
- package/dist/react/stream.d.ts.map +1 -1
- package/dist/react/stream.js.map +1 -1
- package/dist/react/stream.lgp.cjs +45 -13
- package/dist/react/stream.lgp.cjs.map +1 -1
- package/dist/react/stream.lgp.js +45 -13
- package/dist/react/stream.lgp.js.map +1 -1
- package/dist/react/types.d.cts +5 -88
- package/dist/react/types.d.cts.map +1 -1
- package/dist/react/types.d.ts +5 -88
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react-ui/client.cjs.map +1 -1
- package/dist/react-ui/client.d.cts +5 -3
- package/dist/react-ui/client.d.cts.map +1 -1
- package/dist/react-ui/client.d.ts +5 -3
- package/dist/react-ui/client.d.ts.map +1 -1
- package/dist/react-ui/client.js.map +1 -1
- package/dist/schema.d.cts.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/types.stream.d.ts.map +1 -1
- package/dist/ui/manager.cjs +140 -14
- package/dist/ui/manager.cjs.map +1 -1
- package/dist/ui/manager.js +140 -14
- package/dist/ui/manager.js.map +1 -1
- package/dist/ui/stream/agent.d.cts +143 -0
- package/dist/ui/stream/agent.d.cts.map +1 -0
- package/dist/ui/stream/agent.d.ts +143 -0
- package/dist/ui/stream/agent.d.ts.map +1 -0
- package/dist/ui/stream/base.d.cts +144 -0
- package/dist/ui/stream/base.d.cts.map +1 -0
- package/dist/ui/stream/base.d.ts +144 -0
- package/dist/ui/stream/base.d.ts.map +1 -0
- package/dist/ui/stream/deep-agent.d.cts +277 -0
- package/dist/ui/stream/deep-agent.d.cts.map +1 -0
- package/dist/ui/stream/deep-agent.d.ts +277 -0
- package/dist/ui/stream/deep-agent.d.ts.map +1 -0
- package/dist/ui/stream/index.d.cts +172 -0
- package/dist/ui/stream/index.d.cts.map +1 -0
- package/dist/ui/stream/index.d.ts +172 -0
- package/dist/ui/stream/index.d.ts.map +1 -0
- package/dist/ui/subagents.cjs +593 -0
- package/dist/ui/subagents.cjs.map +1 -0
- package/dist/ui/subagents.d.cts +291 -0
- package/dist/ui/subagents.d.cts.map +1 -0
- package/dist/ui/subagents.d.ts +291 -0
- package/dist/ui/subagents.d.ts.map +1 -0
- package/dist/ui/subagents.js +589 -0
- package/dist/ui/subagents.js.map +1 -0
- package/dist/ui/types.d.cts +384 -5
- package/dist/ui/types.d.cts.map +1 -1
- package/dist/ui/types.d.ts +384 -5
- package/dist/ui/types.d.ts.map +1 -1
- 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
|