@langchain/langgraph
Version:
1 lines • 30.5 kB
Source Map (JSON)
{"version":3,"file":"lifecycle.cjs","names":["hasPrefix","StreamChannel","nsKey"],"sources":["../../../src/stream/transformers/lifecycle.ts"],"sourcesContent":["/**\n * LifecycleTransformer - synthesizes `lifecycle` channel events that\n * track the status of the root run and every subgraph it spawns.\n *\n * The transformer is registered first in `createGraphRunStream` so that\n * every other transformer / consumer sees a coherent, authoritative\n * lifecycle stream. It is product-agnostic: deeper semantics (e.g.\n * DeepAgents' `SubagentTransformer` tool-call causation) reach the wire\n * by way of the re-entrant {@link StreamEmitter} - the transformer\n * stashes any `cause` attached upstream and re-emits its own\n * authoritative `lifecycle.started` with the correlation in place.\n *\n * Events are also pushed to a local {@link StreamChannel} so in-process\n * consumers can iterate `run.lifecycle` without filtering the main\n * event stream.\n */\n\nimport type {\n AgentStatus,\n LifecycleCause,\n LifecycleData,\n} from \"@langchain/protocol\";\n\nimport { hasPrefix, nsKey } from \"../mux.js\";\nimport { StreamChannel } from \"../stream-channel.js\";\nimport type {\n NativeStreamTransformer,\n Namespace,\n ProtocolEvent,\n StreamEmitter,\n} from \"../types.js\";\nimport type { LifecycleEntry, LifecycleTransformerOptions } from \"./types.js\";\n\n/**\n * Projection returned from the lifecycle transformer's `init()`.\n *\n * The local `StreamChannel` is closed automatically when the transformer\n * finalizes or fails. `_lifecycleLog` is intentionally underscore-prefixed to\n * signal that it is consumed by the run stream wiring\n * (see `run-stream.ts`) and not meant for direct user access -\n * consumers should read `run.lifecycle` instead.\n *\n * The `lifecycle` iterable is the root-scoped projection (prefix\n * `[]`, starting at offset `0`) mirroring the pattern used by the\n * subgraph discovery transformer. Root stream wiring consumes it\n * via `SET_LIFECYCLE_ITERABLE`; child streams are wired with their\n * own path-scoped iterable produced by `filterLifecycleEntries`.\n */\nexport interface LifecycleProjection {\n _lifecycleLog: StreamChannel<LifecycleEntry>;\n lifecycle: AsyncIterable<LifecycleEntry>;\n}\n\n/**\n * Filter a lifecycle {@link StreamChannel} to only the entries whose\n * namespace lies within the subtree rooted at {@link path}.\n *\n * Returns an `AsyncIterable` whose iterator yields every entry whose\n * namespace either equals {@link path} or is a descendant of it.\n * Iteration begins at {@link startAt}, so callers can capture the\n * log's current size at construction time to skip entries emitted\n * before the caller existed (e.g. a subgraph stream discovered\n * mid-run shouldn't replay the root's `started`).\n *\n * @param log - The shared lifecycle log owned by the transformer.\n * @param path - Namespace prefix to scope entries by (use `[]` for\n * the root subtree, i.e. everything).\n * @param startAt - Zero-based index into the log to begin from.\n * @returns An async iterable of matching lifecycle entries.\n */\nexport function filterLifecycleEntries(\n log: StreamChannel<LifecycleEntry>,\n path: Namespace,\n startAt = 0\n): AsyncIterable<LifecycleEntry> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<LifecycleEntry> {\n const base = log.iterate(startAt);\n return {\n async next(): Promise<IteratorResult<LifecycleEntry>> {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const result = await base.next();\n if (result.done) {\n return {\n value: undefined as unknown as LifecycleEntry,\n done: true,\n };\n }\n if (hasPrefix(result.value.namespace, path)) {\n return { value: result.value, done: false };\n }\n }\n },\n };\n },\n };\n}\n\nconst DEFAULT_ROOT_GRAPH_NAME = \"root\";\n\nfunction defaultGuessGraphName(ns: Namespace): string {\n if (ns.length === 0) return DEFAULT_ROOT_GRAPH_NAME;\n const last = ns[ns.length - 1];\n const colon = last.indexOf(\":\");\n return colon === -1 ? last : last.slice(0, colon);\n}\n\nfunction defaultSerializeError(err: unknown): string {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (err instanceof Error) return err.message;\n if (typeof err === \"string\") return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Extract an upstream `cause` from a `lifecycle.started` payload, if\n * the shape matches one of the known variants. Shape validation is\n * intentionally loose: any object with a string `type` is accepted, so\n * future protocol variants flow through unchanged.\n */\nfunction extractCause(data: unknown): LifecycleCause | undefined {\n if (!isRecord(data)) return undefined;\n if (data.event !== \"started\") return undefined;\n const cause = data.cause;\n if (!isRecord(cause)) return undefined;\n if (typeof cause.type !== \"string\") return undefined;\n return cause as unknown as LifecycleCause;\n}\n\nfunction extractTaskResultCompletion(\n data: unknown\n): TaskResultCompletion | undefined {\n if (!isRecord(data)) return undefined;\n if (!(\"result\" in data)) return undefined;\n if (typeof data.name !== \"string\") return undefined;\n if (typeof data.id !== \"string\") return undefined;\n if (data.name.startsWith(\"__\")) return undefined;\n return { name: data.name, id: data.id };\n}\n\ninterface NamespaceRecord {\n readonly namespace: Namespace;\n readonly graphName: string;\n /** Last emitted status; `undefined` until `emit` fires for this namespace. */\n status: AgentStatus | undefined;\n}\n\ninterface TaskResultCompletion {\n readonly name: string;\n readonly id: string;\n}\n\ninterface PendingCompletion {\n readonly namespace: Namespace;\n readonly source:\n | { readonly type: \"task\" }\n | {\n readonly type: \"node\";\n readonly parent: Namespace;\n readonly node: string;\n };\n}\n\n/**\n * Create the built-in lifecycle transformer.\n *\n * Marked as a {@link NativeStreamTransformer} so the run stream\n * factory can expose `_lifecycleLog` via a dedicated getter\n * (`run.lifecycle`) rather than through `run.extensions`.\n */\nexport function createLifecycleTransformer(\n options: LifecycleTransformerOptions = {}\n): NativeStreamTransformer<LifecycleProjection> {\n const rootGraphName = options.rootGraphName ?? DEFAULT_ROOT_GRAPH_NAME;\n const initialStatus: AgentStatus = options.initialStatus ?? \"running\";\n const emitRootOnRegister = options.emitRootOnRegister ?? true;\n const getGraphName = options.getGraphName ?? defaultGuessGraphName;\n const serializeError = options.serializeError ?? defaultSerializeError;\n const getTerminalStatusOverride = options.getTerminalStatusOverride;\n\n const log = StreamChannel.local<LifecycleEntry>();\n const namespaces = new Map<string, NamespaceRecord>();\n const namespaceCause = new Map<string, LifecycleCause>();\n /**\n * `lc_agent_name` observed at each namespace (first task event wins). A\n * nested run carrying an `lc_agent_name` (set by `createAgent`) is treated\n * as a named subagent: its `graph_name` becomes that name and a tool-call\n * `cause` is recovered (see {@link deriveToolCallCause}). Namespaces without\n * one fall back to the parsed namespace segment, preserving the prior\n * product-agnostic behavior for plain subgraphs.\n */\n const lcByNs = new Map<string, string | undefined>();\n /**\n * Pregel task id -> triggering LLM `tool_call_id`, harvested from a task\n * whose `input` is a `tool_call_with_context` dict (current shape) or a list\n * of tool-call dicts (legacy shape). The child subgraph's namespace segment\n * `node:<task_id>` shares this task id, so a named subagent recovers the tool\n * call that spawned it across payloads.\n */\n const pendingToolCalls = new Map<string, string>();\n const pendingInterruptIds = new Set<string>();\n /**\n * Child namespaces whose parent just saw an `updates` event with a\n * `node` attribution. We defer the `lifecycle.completed` emission\n * until the *next* inbound event (or `finalize`) so the parent's\n * `updates` lands on the wire before its child is marked complete -\n * matching the previous session behavior.\n */\n const pendingCompletions: PendingCompletion[] = [];\n\n let emitter: StreamEmitter | undefined;\n let inSelfEmit = 0;\n let finalized = false;\n\n const resolveGraphName = (ns: Namespace): string => {\n if (ns.length === 0) return rootGraphName;\n // A nested run that carried an `lc_agent_name` is a named subagent; its\n // agent name wins over the parsed namespace segment.\n const lc = lcByNs.get(nsKey(ns));\n if (typeof lc === \"string\" && lc.length > 0) return lc;\n return getGraphName(ns);\n };\n\n /**\n * Record a namespace's `lc_agent_name` from a task-start payload (first\n * event wins). The presence of a name is what marks the namespace a named\n * subagent; the value may be `undefined` for unnamed runs (still recorded so\n * a later event doesn't re-evaluate it).\n */\n const recordIdentity = (ns: Namespace, data: unknown): void => {\n const key = nsKey(ns);\n if (lcByNs.has(key)) return;\n const metadata =\n isRecord(data) && isRecord(data.metadata) ? data.metadata : undefined;\n const lc = metadata?.lc_agent_name;\n lcByNs.set(key, typeof lc === \"string\" ? lc : undefined);\n };\n\n /**\n * Harvest a task's triggering `tool_call_id` keyed by its task id. The\n * spawned subgraph's namespace segment `node:<task_id>` shares that id, so a\n * subagent can later recover the tool call that caused it. Two input shapes\n * are handled: a `tool_call_with_context` object (`input.tool_call.id`) and a\n * legacy list of tool-call objects (first with a string `id`).\n */\n const recordPendingToolCalls = (data: unknown): void => {\n if (!isRecord(data)) return;\n const taskId = data.id;\n if (typeof taskId !== \"string\") return;\n const input = data.input;\n let toolCallId: string | undefined;\n if (isRecord(input) && isRecord(input.tool_call)) {\n const candidate = input.tool_call.id;\n if (typeof candidate === \"string\") toolCallId = candidate;\n } else if (Array.isArray(input)) {\n for (const toolCall of input) {\n if (isRecord(toolCall) && typeof toolCall.id === \"string\") {\n toolCallId = toolCall.id;\n break;\n }\n }\n }\n if (toolCallId != null) pendingToolCalls.set(taskId, toolCallId);\n };\n\n /**\n * Derive a `toolCall` cause for a named subagent namespace by joining the\n * namespace segment's task id (`node:<task_id>`) to a previously harvested\n * `tool_call_id`. Only fires for namespaces carrying an `lc_agent_name`, so\n * plain subgraphs never get a spurious cause.\n */\n const deriveToolCallCause = (ns: Namespace): LifecycleCause | undefined => {\n if (ns.length === 0) return undefined;\n const lc = lcByNs.get(nsKey(ns));\n if (typeof lc !== \"string\" || lc.length === 0) return undefined;\n const segment = ns[ns.length - 1];\n const colon = segment.indexOf(\":\");\n if (colon === -1) return undefined;\n const triggerCallId = segment.slice(colon + 1);\n if (triggerCallId.length === 0) return undefined;\n const toolCallId = pendingToolCalls.get(triggerCallId);\n if (typeof toolCallId !== \"string\" || toolCallId.length === 0) {\n return undefined;\n }\n return { type: \"toolCall\", tool_call_id: toolCallId };\n };\n\n /**\n * Resolve the `cause` to attach to a namespace's `started`. An upstream\n * `cause` stashed from a product-specific transformer (e.g. deepagents'\n * SubagentTransformer) wins; otherwise a tool-call cause is recovered for\n * named subagents.\n */\n const resolveStartCause = (ns: Namespace): LifecycleCause | undefined =>\n namespaceCause.get(nsKey(ns)) ?? deriveToolCallCause(ns);\n\n const emit = (\n ns: Namespace,\n status: AgentStatus,\n extras?: { cause?: LifecycleCause; error?: string }\n ): void => {\n const key = nsKey(ns);\n let current = namespaces.get(key);\n const graphName = current?.graphName ?? resolveGraphName(ns);\n\n // Dedup: identical status + graph name + no error override => skip.\n if (\n current != null &&\n current.status === status &&\n current.graphName === graphName &&\n extras?.error == null\n ) {\n return;\n }\n\n if (current == null) {\n current = { namespace: ns, graphName, status };\n namespaces.set(key, current);\n } else {\n current.status = status;\n }\n\n const data: LifecycleData = {\n event: status,\n graph_name: graphName,\n ...(extras?.cause != null ? { cause: extras.cause } : {}),\n ...(extras?.error != null ? { error: extras.error } : {}),\n };\n\n const timestamp = Date.now();\n\n log.push({ namespace: ns, timestamp, ...data });\n\n if (ns.length === 0 && !emitRootOnRegister) return;\n\n if (emitter == null) return;\n\n inSelfEmit += 1;\n try {\n emitter.push(ns, {\n type: \"event\",\n seq: 0,\n method: \"lifecycle\",\n params: { namespace: ns, timestamp, data },\n });\n } finally {\n inSelfEmit -= 1;\n }\n };\n\n /**\n * Ensures a record exists for `ns` without mutating its status. Used\n * by hooks that need a canonical `graphName` for lookups before emit\n * writes the first status. Status remains `undefined` until `emit`\n * fires.\n */\n const trackNamespace = (ns: Namespace): NamespaceRecord => {\n const key = nsKey(ns);\n let rec = namespaces.get(key);\n if (rec == null) {\n rec = {\n namespace: ns,\n graphName: resolveGraphName(ns),\n status: undefined,\n };\n namespaces.set(key, rec);\n }\n return rec;\n };\n\n const flushPendingCompletions = (): void => {\n if (pendingCompletions.length === 0) return;\n const toFlush = pendingCompletions.splice(0, pendingCompletions.length);\n for (const completion of toFlush) {\n const key = nsKey(completion.namespace);\n const rec = namespaces.get(key);\n if (rec == null || rec.status !== \"started\") continue;\n emit(completion.namespace, \"completed\");\n }\n };\n\n const enqueueCompletion = (completion: PendingCompletion): void => {\n const key = nsKey(completion.namespace);\n const rec = namespaces.get(key);\n if (rec == null || rec.status !== \"started\") return;\n if (\n pendingCompletions.some((pending) => nsKey(pending.namespace) === key)\n ) {\n return;\n }\n pendingCompletions.push(completion);\n };\n\n const removePendingNodeCompletions = (\n parent: Namespace,\n node: string\n ): void => {\n for (let index = pendingCompletions.length - 1; index >= 0; index -= 1) {\n const pending = pendingCompletions[index];\n if (pending.source.type !== \"node\") continue;\n if (pending.source.node !== node) continue;\n if (nsKey(pending.source.parent) !== nsKey(parent)) continue;\n pendingCompletions.splice(index, 1);\n }\n };\n\n const ensureStarted = (ns: Namespace): void => {\n // Synthesize `lifecycle.started` for each unseen prefix of `ns`,\n // outermost first. Deepest-first would force consumers to see a\n // child's started before its parent, which is wrong.\n for (let length = 1; length <= ns.length; length += 1) {\n const prefix = ns.slice(0, length);\n const key = nsKey(prefix);\n if (namespaces.has(key)) continue;\n trackNamespace(prefix);\n const cause = resolveStartCause(prefix);\n emit(prefix, \"started\", cause != null ? { cause } : undefined);\n }\n };\n\n const defaultTerminalStatus = (): AgentStatus =>\n pendingInterruptIds.size > 0 ? \"interrupted\" : \"completed\";\n\n const cascadeTerminalStatus = (status: AgentStatus): void => {\n for (const rec of namespaces.values()) {\n if (rec.namespace.length === 0) continue;\n if (rec.status !== \"started\") continue;\n emit(rec.namespace, status);\n }\n emit([], status);\n log.close();\n };\n\n const resolveTerminalStatusOverride = async (): Promise<AgentStatus> => {\n if (getTerminalStatusOverride == null) return defaultTerminalStatus();\n try {\n return (await getTerminalStatusOverride()) ?? defaultTerminalStatus();\n } catch {\n return defaultTerminalStatus();\n }\n };\n\n const findStartedChildForNode = (\n parentNamespace: Namespace,\n node: string\n ): Namespace | undefined => {\n const prefix = `${node}:`;\n for (const rec of namespaces.values()) {\n if (rec.namespace.length !== parentNamespace.length + 1) continue;\n if (rec.status !== \"started\") continue;\n if (!hasPrefix(rec.namespace, parentNamespace)) continue;\n const last = rec.namespace[rec.namespace.length - 1];\n if (last === node || last.startsWith(prefix)) return rec.namespace;\n }\n return undefined;\n };\n\n const findStartedChildForTask = (\n parentNamespace: Namespace,\n task: TaskResultCompletion\n ): Namespace | undefined => {\n const namespace = [...parentNamespace, `${task.name}:${task.id}`];\n const rec = namespaces.get(nsKey(namespace));\n return rec?.status === \"started\" ? namespace : undefined;\n };\n\n const transformer: NativeStreamTransformer<LifecycleProjection> = {\n __native: true,\n\n init() {\n return {\n _lifecycleLog: log,\n lifecycle: filterLifecycleEntries(log, [], 0),\n };\n },\n\n onRegister(handle: StreamEmitter) {\n emitter = handle;\n // Seed root record so cascade logic can see it, even when the\n // outer authority owns root emission.\n trackNamespace([]);\n if (emitRootOnRegister) {\n emit([], initialStatus);\n }\n },\n\n process(event: ProtocolEvent): boolean {\n const ns = event.params.namespace;\n\n // Re-entrant loopback: an event we emitted via `emitter.push`\n // is being routed back through this transformer by the mux.\n // Allow it through the wire unchanged.\n if (inSelfEmit > 0) return true;\n\n const taskCompletion =\n event.method === \"tasks\"\n ? extractTaskResultCompletion(event.params.data)\n : undefined;\n if (taskCompletion != null) {\n // Prefer exact task-result attribution over any ambiguous\n // `updates.node` completion deferred from the previous event.\n removePendingNodeCompletions(ns, taskCompletion.name);\n } else if (event.method === \"tasks\") {\n // Task-start event: record the namespace's subagent identity and any\n // triggering tool call *before* `ensureStarted` synthesizes `started`,\n // so a named subagent's `graph_name`/`cause` are resolved in time.\n // Pregel emits parent-namespace tasks before child-namespace tasks, so\n // the parent's tool-call seed is in place when the child is evaluated.\n recordIdentity(ns, event.params.data);\n recordPendingToolCalls(event.params.data);\n }\n\n // Flush any completions deferred by the previous event so the\n // wire order is [triggering event] -> [deferred completed].\n flushPendingCompletions();\n\n // Upstream `lifecycle` events: stash any `cause` attached by a\n // product-specific transformer (e.g. deepagents' SubagentTransformer),\n // synthesize our authoritative started/... for the namespace, and\n // suppress the original so we are the single source of truth.\n if (event.method === \"lifecycle\") {\n const cause = extractCause(event.params.data);\n if (cause != null) {\n namespaceCause.set(nsKey(ns), cause);\n }\n ensureStarted(ns);\n return false;\n }\n\n // Lifecycle for parent + any unseen prefix => synthesize started.\n ensureStarted(ns);\n\n // Track interrupt ids so `finalize` can decide between\n // `completed` and `interrupted`.\n if (\n event.method === \"input\" &&\n isRecord(event.params.data) &&\n event.params.data.event === \"requested\"\n ) {\n const id = (event.params.data as { id?: unknown }).id;\n if (typeof id === \"string\") {\n pendingInterruptIds.add(id);\n }\n }\n\n if (taskCompletion != null) {\n const childNamespace = findStartedChildForTask(ns, taskCompletion);\n if (childNamespace != null) {\n enqueueCompletion({\n namespace: childNamespace,\n source: { type: \"task\" },\n });\n }\n }\n\n // Defer child-node completion: the `updates` event carries the\n // node attribution; the corresponding child namespace is\n // `[...ns, \"<node>:<uuid>\"]`. We pick the oldest still-started\n // matching child (LangGraph emits one updates per completed task\n // so repeated calls drain parallel fan-outs in order).\n if (event.method === \"updates\") {\n const node = event.params.node;\n if (typeof node === \"string\" && !node.startsWith(\"__\")) {\n const childNamespace = findStartedChildForNode(ns, node);\n if (childNamespace != null) {\n enqueueCompletion({\n namespace: childNamespace,\n source: { type: \"node\", parent: ns, node },\n });\n }\n }\n }\n\n return true;\n },\n\n finalize(): void | PromiseLike<void> {\n if (finalized) return;\n finalized = true;\n flushPendingCompletions();\n\n if (getTerminalStatusOverride == null) {\n cascadeTerminalStatus(defaultTerminalStatus());\n return;\n }\n\n return resolveTerminalStatusOverride()\n .then(cascadeTerminalStatus)\n .catch((err) => {\n log.fail(err);\n });\n },\n\n fail(err: unknown) {\n if (finalized) return;\n finalized = true;\n const errorMessage = serializeError(err);\n\n // Cascade `failed` to every still-started namespace. Children\n // that had already entered a terminal state are left untouched\n // by the dedup guard in `emit`.\n for (const rec of namespaces.values()) {\n if (rec.namespace.length === 0) continue;\n if (rec.status !== \"started\") continue;\n emit(rec.namespace, \"failed\");\n }\n\n emit([], \"failed\", { error: errorMessage });\n log.fail(err);\n },\n };\n\n return transformer;\n}\n"],"mappings":"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"}