require("../../_virtual/_rolldown/runtime.cjs");
const require_tool_call = require("./tool-call.cjs");
let _langchain_langgraph = require("@langchain/langgraph");
//#region src/agents/transformers/subagent.ts
function isRecord(value) {
	return typeof value === "object" && value !== null && !Array.isArray(value);
}
/** Stable string key for a namespace. */
function nsKey(ns) {
	return ns.join("\0");
}
/** Tests whether `ns` starts with every segment in `prefix`. */
function hasPrefix(ns, prefix) {
	if (prefix.length > ns.length) return false;
	for (let i = 0; i < prefix.length; i += 1) if (ns[i] !== prefix[i]) return false;
	return true;
}
/**
* Creates a native transformer that surfaces nested named agents on
* `run.subagents`.
*
* It watches `tasks` events to record each namespace's `lc_agent_name` (set by
* `createAgent({ name })`) and the triggering tool call, then — for any nested
* run one level below {@link scope} that carries an `lc_agent_name` — emits a
* typed {@link SubagentRunStream} handle.
*
* Each handle is backed by its own per-subagent transformer instances
* ({@link createMessagesTransformer}, {@link createToolCallTransformer}, and a
* nested {@link createSubagentTransformer}) scoped to the subagent's namespace.
* Every event in the subtree is fed straight into those transformers, which
* self-filter by namespace; the subagent's final `output` is resolved from its
* last `values` snapshot when its `lifecycle` completes.
*
* Marked `__native: true` — the `subagents` projection lands directly on the
* `GraphRunStream` instance as `run.subagents`.
*
* @param scope - Namespace prefix this transformer is scoped to. The root agent
*   uses `[]`; nested handles use their subagent's namespace, so grandchild
*   subagents are discovered recursively.
*/
function createSubagentTransformer(scope = []) {
	return () => {
		const subagentsLog = _langchain_langgraph.StreamChannel.local();
		/** `lc_agent_name` observed per namespace (first task event wins). */
		const lcByNs = /* @__PURE__ */ new Map();
		/** Triggering task id -> originating LLM `tool_call_id`. */
		const pendingToolCalls = /* @__PURE__ */ new Map();
		/**
		* Namespace key -> the `tool_call_id` of the most recent tool to start
		* executing there. A tool that invokes a subagent emits its `tool-started`
		* at the tools-node namespace (`tools:<task_id>`) where the subagent then
		* roots, so this is the tool call that caused the subagent.
		*/
		const activeToolCallByNs = /* @__PURE__ */ new Map();
		const handles = /* @__PURE__ */ new Map();
		const depth = scope.length;
		function recordIdentity(ns, data) {
			const key = nsKey(ns);
			if (lcByNs.has(key)) return;
			const lc = (isRecord(data) && isRecord(data.metadata) ? data.metadata : void 0)?.lc_agent_name;
			lcByNs.set(key, typeof lc === "string" ? lc : void 0);
		}
		function recordPendingToolCalls(data) {
			if (!isRecord(data)) return;
			const taskId = data.id;
			if (typeof taskId !== "string") return;
			const input = data.input;
			let toolCallId;
			if (isRecord(input) && isRecord(input.tool_call)) {
				const candidate = input.tool_call.id;
				if (typeof candidate === "string") toolCallId = candidate;
			} else if (Array.isArray(input)) {
				for (const toolCall of input) if (isRecord(toolCall) && typeof toolCall.id === "string") {
					toolCallId = toolCall.id;
					break;
				}
			}
			if (toolCallId != null) pendingToolCalls.set(taskId, toolCallId);
		}
		/**
		* Derive the `toolCall` cause for a named-subagent namespace.
		*
		* Primary signal: the tool whose `tool-started` event fired at the
		* subagent's own namespace (the tools node it roots under). Fallback: the
		* namespace segment's task id (`node:<task_id>`) joined to a tool call
		* harvested from a `tool_call_with_context`-shaped task input, so the
		* derivation stays correct if that shape reaches the stream in the future.
		*/
		function deriveCause(ns) {
			const active = activeToolCallByNs.get(nsKey(ns));
			if (typeof active === "string" && active.length > 0) return {
				type: "toolCall",
				tool_call_id: active
			};
			const segment = ns[ns.length - 1];
			const colon = segment.indexOf(":");
			if (colon === -1) return void 0;
			const triggerCallId = segment.slice(colon + 1);
			if (triggerCallId.length === 0) return void 0;
			const toolCallId = pendingToolCalls.get(triggerCallId);
			if (typeof toolCallId !== "string" || toolCallId.length === 0) return;
			return {
				type: "toolCall",
				tool_call_id: toolCallId
			};
		}
		function maybeStartSubagent(ns) {
			if (ns.length !== depth + 1 || !hasPrefix(ns, scope)) return;
			const key = nsKey(ns);
			if (handles.has(key)) return;
			const lc = lcByNs.get(key);
			if (typeof lc !== "string" || lc.length === 0) return;
			const messages = (0, _langchain_langgraph.createMessagesTransformer)(ns);
			const messagesProjection = messages.init();
			const toolCall = require_tool_call.createToolCallTransformer(ns)();
			const toolCallProjection = toolCall.init();
			const nested = createSubagentTransformer(ns)();
			const nestedProjection = nested.init();
			let resolveOutput;
			let rejectOutput;
			const output = new Promise((resolve, reject) => {
				resolveOutput = resolve;
				rejectOutput = reject;
			});
			handles.set(key, {
				key,
				path: ns,
				name: lc,
				messages,
				toolCall,
				nested,
				resolveOutput,
				rejectOutput,
				latestValues: void 0,
				done: false
			});
			subagentsLog.push({
				name: lc,
				cause: deriveCause(ns),
				output,
				messages: messagesProjection.messages,
				toolCalls: toolCallProjection.toolCalls,
				subagents: nestedProjection.subagents
			});
		}
		function finishHandle(handle, outcome) {
			if (handle.done) return;
			handle.done = true;
			if (outcome.type === "resolve") handle.resolveOutput(handle.latestValues);
			else handle.rejectOutput(outcome.error);
			handle.messages.finalize?.();
			handle.toolCall.finalize?.();
			handle.nested.finalize?.();
		}
		return {
			__native: true,
			init: () => ({ subagents: subagentsLog }),
			process(event) {
				const ns = event.params.namespace;
				const data = event.params.data;
				const isTaskResult = event.method === "tasks" && isRecord(data) && "result" in data;
				if (event.method === "tools" && isRecord(data) && data.event === "tool-started" && typeof data.tool_call_id === "string" && data.tool_call_id.length > 0) activeToolCallByNs.set(nsKey(ns), data.tool_call_id);
				if (event.method === "tasks" && !isTaskResult) {
					recordIdentity(ns, data);
					recordPendingToolCalls(data);
					maybeStartSubagent(ns);
				}
				for (const handle of handles.values()) {
					if (handle.done) continue;
					if (!hasPrefix(ns, handle.path)) continue;
					handle.messages.process(event);
					handle.toolCall.process(event);
					handle.nested.process(event);
					if (nsKey(ns) === handle.key) {
						if (event.method === "values" && isRecord(data)) handle.latestValues = data;
						else if (event.method === "lifecycle" && isRecord(data)) {
							const status = data.event;
							if (status === "completed" || status === "interrupted") finishHandle(handle, { type: "resolve" });
							else if (status === "failed") finishHandle(handle, {
								type: "reject",
								error: /* @__PURE__ */ new Error(`Subagent ${handle.name} failed`)
							});
						}
					}
				}
				return true;
			},
			finalize() {
				for (const handle of handles.values()) finishHandle(handle, { type: "resolve" });
				subagentsLog.close();
			},
			fail(err) {
				for (const handle of handles.values()) finishHandle(handle, {
					type: "reject",
					error: err
				});
				subagentsLog.fail(err);
			}
		};
	};
}
//#endregion
exports.createSubagentTransformer = createSubagentTransformer;

//# sourceMappingURL=subagent.cjs.map