UNPKG

@langchain/langgraph-sdk

Version:

Client library for interacting with the LangGraph API

1 lines • 26.8 kB
{"version":3,"file":"subagents.cjs","names":["StreamStore","#onToolEvent","#onValuesEvent","#map","namespaceKey","#recordTaskNamespaceCandidate","#observedOwnNamespaces","#commit","#taskIdByObservedNamespace","#toolCallIdByTaskInput","#upsertTaskToolCall","#bindNamespaceByTaskInput","#recordObservedWorkNamespace","isConcreteToolNamespace","isToolNamespaceSegment","normalizeAIMessageToolCalls","isRootNamespace"],"sources":["../../../src/stream/discovery/subagents.ts"],"sourcesContent":["/**\n * Root-scoped subagent discovery.\n *\n * Populates a `Map<callId, SubagentDiscoverySnapshot>` by watching\n * `task` tool calls on the root subscription. No content channels\n * (subagent messages, tool calls, extensions) are opened here — that\n * layer is driven by selector hooks via the\n * {@link ChannelRegistry}, keyed on `SubagentDiscoverySnapshot.namespace`.\n *\n * Discovery data this runner populates per subagent:\n * - id, name, namespace, parentId, depth\n * - status (`running` | `complete` | `error`)\n * - taskInput / output / error / startedAt / completedAt\n *\n * The runner is fed events by the {@link StreamController}'s root\n * subscription; it does not open subscriptions of its own.\n */\nimport type { Event, ToolsEvent, ValuesEvent } from \"@langchain/protocol\";\nimport { StreamStore } from \"../store.js\";\nimport type { SubagentDiscoverySnapshot } from \"../types.js\";\nimport {\n isConcreteToolNamespace,\n isRootNamespace,\n isToolNamespaceSegment,\n namespaceKey,\n} from \"../namespace.js\";\nimport { normalizeAIMessageToolCalls } from \"../message-coercion.js\";\n\nexport type SubagentMap = ReadonlyMap<string, SubagentDiscoverySnapshot>;\n\n/** Stable empty map — reused on {@link SubagentDiscovery.reset}. */\nconst EMPTY_SUBAGENT_MAP: SubagentMap = new Map();\n\ninterface MutableSubagent {\n id: string;\n name: string;\n namespace: readonly string[];\n parentId: string | null;\n depth: number;\n status: \"running\" | \"complete\" | \"error\";\n taskInput: string | undefined;\n output: unknown;\n error: string | undefined;\n startedAt: Date;\n completedAt: Date | null;\n}\n\nexport class SubagentDiscovery {\n readonly store = new StreamStore<SubagentMap>(new Map());\n #map = new Map<string, MutableSubagent>();\n #taskIdByObservedNamespace = new Map<string, string>();\n #observedOwnNamespaces = new Set<string>();\n // Index from `taskInput` (the `description` arg) to a FIFO queue of\n // pending parent `tool_call_id`s. Bridges the wire's missing link\n // between a deepagents `task` dispatch and its subagent execution\n // namespace — the server seeds the subagent's first HumanMessage\n // with `taskInput` verbatim, so an exact-equality lookup is\n // deterministic. The queue (not a single value) handles the case\n // where the coordinator dispatches N task calls with identical\n // descriptions; pregel preserves dispatch order across executions,\n // so FIFO pop attributes them correctly.\n #toolCallIdByTaskInput = new Map<string, string[]>();\n\n /** Feed a single root event. Non-discovery events are ignored. */\n push(event: Event): void {\n if (event.method === \"tools\") {\n this.#onToolEvent(event as ToolsEvent);\n } else if (event.method === \"values\") {\n this.#onValuesEvent(event as ValuesEvent);\n }\n }\n\n /**\n * Seed discovery from a checkpoint's root `messages` array (as\n * returned by `client.threads.getState().values.messages`) so deep\n * agent cards render on thread refresh without waiting for SSE\n * replay.\n *\n * Drives the existing root `values` path via a synthetic event so it\n * reuses task discovery + completion marking with no new parsing\n * logic. Root namespace `[]` keeps namespaces at the default\n * `tools:<toolCallId>`; the always-on root pump (and {@link\n * applyExecutionNamespace}) promote them to the execution namespace\n * later. Idempotent by construction: re-driving root values for\n * already-discovered tasks is a no-op (the FIFO `taskInput` queue is\n * only populated on first discovery), so no `snapshot.size` guard is\n * needed.\n */\n seedFromCheckpointMessages(messages: unknown[]): void {\n if (!Array.isArray(messages) || messages.length === 0) return;\n this.push({\n type: \"event\",\n method: \"values\",\n params: { namespace: [], timestamp: Date.now(), data: { messages } },\n } as ValuesEvent & Event);\n }\n\n /**\n * Promote a discovered subagent to its execution namespace, derived\n * from checkpoint history (see `namespace-from-history`).\n *\n * Routes through the same guarded promotion machinery the live SSE\n * replay uses ({@link #recordTaskNamespaceCandidate} + the\n * `#observedOwnNamespaces` no-demote rule) so a getHistory-derived\n * namespace and an SSE-derived one cannot disagree. A no-op when the\n * subagent is unknown or already sits on the target namespace.\n *\n * @param toolCallId - Parent `task` tool-call id (the subagent's discovery key).\n * @param executionSegment - Single execution namespace segment, e.g. `tools:<uuid>`.\n */\n applyExecutionNamespace(toolCallId: string, executionSegment: string): void {\n if (typeof executionSegment !== \"string\" || executionSegment.length === 0) {\n return;\n }\n const entry = this.#map.get(toolCallId);\n if (entry == null) return;\n const namespace: readonly string[] = [executionSegment];\n const namespaceKeyed = namespaceKey(namespace);\n const ownNamespaceKey = `tools:${toolCallId}`;\n\n // Record the candidate so a later live `values` event at the same\n // namespace recognizes it as already-bound (mirrors\n // `#recordTaskNamespaceCandidate`).\n this.#recordTaskNamespaceCandidate(toolCallId, namespace);\n\n // Respect the no-demote rule: once discovery has observed the\n // subagent's own namespace carrying state, do not move it.\n if (\n namespaceKeyed !== ownNamespaceKey &&\n this.#observedOwnNamespaces.has(toolCallId)\n ) {\n return;\n }\n if (namespaceKey(entry.namespace) === namespaceKeyed) return;\n entry.namespace = namespace;\n this.#commit();\n }\n\n /** Current snapshot map. */\n get snapshot(): SubagentMap {\n return this.store.getSnapshot();\n }\n\n /**\n * Drop all discovery state. Called on thread rebind / dispose so a\n * new thread's subagents cannot bleed into the previous UI.\n */\n reset(): void {\n this.#map.clear();\n this.#taskIdByObservedNamespace.clear();\n this.#observedOwnNamespaces.clear();\n this.#toolCallIdByTaskInput.clear();\n this.store.setValue(EMPTY_SUBAGENT_MAP);\n }\n\n discoverFromMessage(message: unknown, namespace: readonly string[]): void {\n let changed = false;\n for (const toolCall of getTaskToolCalls(message)) {\n changed =\n this.#upsertTaskToolCall(toolCall.id, toolCall.input, namespace) ||\n changed;\n }\n if (changed) this.#commit();\n }\n\n #commit(): void {\n // Rebuild as a fresh Map so React / useSyncExternalStore sees a\n // new reference on every change.\n this.store.setValue(\n new Map(\n [...this.#map.values()].map((entry) => [entry.id, toSnapshot(entry)])\n )\n );\n }\n\n #onToolEvent(event: ToolsEvent): void {\n const data = event.params.data;\n const toolCallId = (data as { tool_call_id?: string }).tool_call_id;\n const toolName = (data as { tool_name?: string }).tool_name;\n\n if (data.event === \"tool-started\" && toolName === \"task\") {\n const input = parseTaskInput((data as { input?: unknown }).input);\n if (toolCallId == null) return;\n this.#upsertTaskToolCall(toolCallId, input, event.params.namespace);\n this.#commit();\n return;\n }\n\n if (toolCallId == null) return;\n const entry = this.#map.get(toolCallId);\n if (entry == null) return;\n\n if (data.event === \"tool-finished\") {\n entry.status = \"complete\";\n entry.output = (data as { output?: unknown }).output;\n entry.completedAt = new Date();\n this.#commit();\n return;\n }\n\n if (data.event === \"tool-error\") {\n entry.status = \"error\";\n entry.error = (data as { message?: string }).message ?? \"Subagent failed\";\n entry.completedAt = new Date();\n this.#commit();\n }\n }\n\n #onValuesEvent(event: ValuesEvent): void {\n const data = event.params.data;\n if (data == null || typeof data !== \"object\" || Array.isArray(data)) return;\n const messages = (data as { messages?: unknown }).messages;\n if (!Array.isArray(messages)) return;\n\n // If a `tools:<id>` namespace's first HumanMessage matches a known\n // taskInput, that's the subagent's execution scope. Record the\n // binding so `#recordObservedWorkNamespace` can promote it.\n this.#bindNamespaceByTaskInput(event.params.namespace, messages);\n\n let changed = this.#recordObservedWorkNamespace(event.params.namespace);\n for (const message of messages) {\n for (const toolCall of getTaskToolCalls(message)) {\n changed =\n this.#upsertTaskToolCall(\n toolCall.id,\n toolCall.input,\n event.params.namespace\n ) || changed;\n }\n\n const toolCallId = getToolMessageCallId(message);\n if (toolCallId == null) continue;\n const existing = this.#map.get(toolCallId);\n if (existing == null) continue;\n existing.status = \"complete\";\n existing.output = message;\n existing.completedAt = new Date();\n changed = true;\n }\n if (changed) this.#commit();\n }\n\n #upsertTaskToolCall(\n toolCallId: string,\n input: { description?: string; subagent_type?: string },\n eventNamespace: readonly string[]\n ): boolean {\n const namespace = taskWorkNamespace(toolCallId, eventNamespace);\n const existing = this.#map.get(toolCallId);\n if (existing != null) {\n let changed = false;\n this.#recordTaskNamespaceCandidate(toolCallId, eventNamespace);\n const nextName = input.subagent_type ?? existing.name;\n const nextTaskInput = input.description ?? existing.taskInput;\n if (existing.name !== nextName) {\n existing.name = nextName;\n changed = true;\n }\n if (existing.taskInput !== nextTaskInput) {\n existing.taskInput = nextTaskInput;\n changed = true;\n }\n const namespaceKeyed = namespaceKey(existing.namespace);\n const ownNamespaceKey = `tools:${toolCallId}`;\n const nextNamespaceKey = namespaceKey(namespace);\n if (\n isConcreteToolNamespace(eventNamespace) ||\n namespaceKeyed === ownNamespaceKey\n ) {\n // A wrapper task tool event can arrive under an execution namespace\n // like `tools:<uuid>`, while the subagent's actual message state is\n // under `tools:<tool_call_id>`. Once discovery has observed the own\n // namespace carrying state, do not demote it back to the wrapper\n // namespace.\n if (\n namespaceKeyed === ownNamespaceKey &&\n nextNamespaceKey !== ownNamespaceKey &&\n this.#observedOwnNamespaces.has(toolCallId)\n ) {\n return changed;\n }\n if (namespaceKeyed !== nextNamespaceKey) {\n existing.namespace = namespace;\n changed = true;\n }\n }\n if (existing.status !== \"complete\" && existing.status !== \"error\") {\n if (existing.status !== \"running\") {\n existing.status = \"running\";\n changed = true;\n }\n }\n return changed;\n }\n\n // Prefer the namespace where the task is first observed. Later\n // observations may move it between wrapper execution namespaces\n // and `[\"tools:<toolCallId>\"]`, depending on where the stream proves\n // the worker's scoped message/tool state exists.\n const { parentId, depth } = lineageFromNamespace(eventNamespace);\n this.#recordTaskNamespaceCandidate(toolCallId, eventNamespace);\n if (input.description != null) {\n const queue = this.#toolCallIdByTaskInput.get(input.description) ?? [];\n queue.push(toolCallId);\n this.#toolCallIdByTaskInput.set(input.description, queue);\n }\n this.#map.set(toolCallId, {\n id: toolCallId,\n name: input.subagent_type ?? \"unknown\",\n namespace,\n parentId,\n depth,\n status: \"running\",\n taskInput: input.description,\n output: undefined,\n error: undefined,\n startedAt: new Date(),\n completedAt: null,\n });\n return true;\n }\n\n #recordObservedWorkNamespace(namespace: readonly string[]): boolean {\n if (!isConcreteToolNamespace(namespace)) return false;\n const last = namespace.at(-1);\n if (last == null) return false;\n const namespaceKeyed = namespaceKey(namespace);\n const toolCallId =\n this.#taskIdByObservedNamespace.get(namespaceKeyed) ??\n last.slice(\"tools:\".length);\n const existing = this.#map.get(toolCallId);\n if (existing == null) return false;\n\n const ownNamespaceKey = `tools:${toolCallId}`;\n if (namespaceKeyed === ownNamespaceKey) {\n this.#observedOwnNamespaces.add(toolCallId);\n } else if (\n this.#observedOwnNamespaces.has(toolCallId) ||\n (!this.#taskIdByObservedNamespace.has(namespaceKeyed) &&\n !shouldPromoteToObservedNamespace(existing))\n ) {\n return false;\n }\n\n if (namespaceKey(existing.namespace) === namespaceKeyed) return false;\n existing.namespace = [...namespace];\n return true;\n }\n\n #recordTaskNamespaceCandidate(\n toolCallId: string,\n namespace: readonly string[]\n ): void {\n if (!isConcreteToolNamespace(namespace)) return;\n this.#taskIdByObservedNamespace.set(namespaceKey(namespace), toolCallId);\n }\n\n /**\n * Bind a `tools:<id>` namespace to a registered subagent by looking\n * up the first HumanMessage content in the `taskInput` index.\n */\n #bindNamespaceByTaskInput(\n namespace: readonly string[],\n messages: unknown[]\n ): void {\n if (!isConcreteToolNamespace(namespace)) return;\n const namespaceKeyed = namespaceKey(namespace);\n if (this.#taskIdByObservedNamespace.has(namespaceKeyed)) return;\n\n const text = getFirstHumanMessageText(messages);\n if (text == null) return;\n const toolCallId = this.#toolCallIdByTaskInput.get(text)?.shift();\n if (toolCallId == null) return;\n this.#taskIdByObservedNamespace.set(namespaceKeyed, toolCallId);\n }\n}\n\nfunction getFirstHumanMessageText(messages: unknown[]): string | null {\n for (const message of messages) {\n if (message == null || typeof message !== \"object\") continue;\n const record = message as {\n type?: unknown;\n role?: unknown;\n content?: unknown;\n kwargs?: { type?: unknown; content?: unknown };\n lc_kwargs?: { type?: unknown; content?: unknown };\n };\n const type =\n record.type ??\n record.role ??\n record.kwargs?.type ??\n record.lc_kwargs?.type;\n if (type !== \"human\") continue;\n const content =\n record.content ?? record.kwargs?.content ?? record.lc_kwargs?.content;\n return typeof content === \"string\" && content.length > 0 ? content : null;\n }\n return null;\n}\n\nfunction shouldPromoteToObservedNamespace(entry: MutableSubagent): boolean {\n return (\n entry.name === \"fanout-worker\" ||\n /^Worker worker-\\d+/i.test(entry.taskInput ?? \"\")\n );\n}\n\nfunction taskWorkNamespace(\n toolCallId: string,\n eventNamespace: readonly string[]\n): readonly string[] {\n const last = eventNamespace.at(-1);\n if (last != null && isToolNamespaceSegment(last)) return [...eventNamespace];\n return [`tools:${toolCallId}`];\n}\n\nfunction toSnapshot(entry: MutableSubagent): SubagentDiscoverySnapshot {\n return {\n id: entry.id,\n name: entry.name,\n namespace: entry.namespace,\n parentId: entry.parentId,\n depth: entry.depth,\n status: entry.status,\n taskInput: entry.taskInput,\n output: entry.output,\n error: entry.error,\n startedAt: entry.startedAt,\n completedAt: entry.completedAt,\n };\n}\n\nfunction parseTaskInput(raw: unknown): {\n description?: string;\n subagent_type?: string;\n} {\n if (raw == null) return {};\n if (typeof raw === \"string\") {\n try {\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n return {\n description:\n typeof parsed.description === \"string\"\n ? parsed.description\n : undefined,\n subagent_type:\n typeof parsed.subagent_type === \"string\"\n ? parsed.subagent_type\n : undefined,\n };\n } catch {\n return {};\n }\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n const obj = raw as Record<string, unknown>;\n return {\n description:\n typeof obj.description === \"string\" ? obj.description : undefined,\n subagent_type:\n typeof obj.subagent_type === \"string\" ? obj.subagent_type : undefined,\n };\n }\n return {};\n}\n\nfunction getTaskToolCalls(message: unknown): Array<{\n id: string;\n input: { description?: string; subagent_type?: string };\n}> {\n if (\n message == null ||\n typeof message !== \"object\" ||\n Array.isArray(message)\n ) {\n return [];\n }\n const record = normalizeAIMessageToolCalls(\n message as Parameters<typeof normalizeAIMessageToolCalls>[0]\n ) as {\n tool_calls?: unknown;\n kwargs?: { tool_calls?: unknown };\n lc_kwargs?: { tool_calls?: unknown };\n };\n const toolCalls =\n record.tool_calls ??\n record.kwargs?.tool_calls ??\n record.lc_kwargs?.tool_calls;\n if (!Array.isArray(toolCalls)) return [];\n\n const result: Array<{\n id: string;\n input: { description?: string; subagent_type?: string };\n }> = [];\n for (const toolCall of toolCalls) {\n if (\n toolCall == null ||\n typeof toolCall !== \"object\" ||\n Array.isArray(toolCall)\n ) {\n continue;\n }\n const record = toolCall as {\n id?: unknown;\n name?: unknown;\n args?: unknown;\n };\n if (typeof record.id !== \"string\" || record.name !== \"task\") continue;\n result.push({ id: record.id, input: parseTaskInput(record.args) });\n }\n return result;\n}\n\nfunction getToolMessageCallId(message: unknown): string | undefined {\n if (\n message == null ||\n typeof message !== \"object\" ||\n Array.isArray(message)\n ) {\n return undefined;\n }\n const record = message as {\n tool_call_id?: unknown;\n kwargs?: { tool_call_id?: unknown };\n lc_kwargs?: { tool_call_id?: unknown };\n };\n const id =\n record.tool_call_id ??\n record.kwargs?.tool_call_id ??\n record.lc_kwargs?.tool_call_id;\n return typeof id === \"string\" && id.length > 0 ? id : undefined;\n}\n\n/**\n * Derive (parentId, depth) from a namespace like\n * `[\"subagents:abc:def\"]`. Namespaces form a rooted tree; the last\n * `:` segment of the deepest namespace element is the current node's\n * call-id and the one before it is the parent.\n */\nfunction lineageFromNamespace(namespace: readonly string[]): {\n parentId: string | null;\n depth: number;\n} {\n if (isRootNamespace(namespace)) return { parentId: null, depth: 1 };\n const last = namespace[namespace.length - 1];\n if (last == null) return { parentId: null, depth: 1 };\n // Namespace segments typically look like\n // subagents:<parentCallId>:<thisCallId>\n // but the protocol doesn't mandate that shape; we best-effort.\n const parts = last.split(\":\").filter((part) => part.length > 0);\n const trimmed = parts.slice(1); // drop the leading \"subagents\" prefix\n const depth = Math.max(1, trimmed.length);\n const parentId = trimmed.length >= 2 ? trimmed[trimmed.length - 2] : null;\n return { parentId: parentId ?? null, depth };\n}\n"],"mappings":"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"}