import { ToolContract } from "../tool/tool.mjs"; import { OrchestratorAsToolOptions, OrchestratorContract } from "../contracts/orchestrator/orchestrator.contract.mjs"; //#region ../ai/src/orchestrator/as-tool.d.ts /** * Wrap an {@link OrchestratorContract} as a {@link ToolContract} so an * outer agent can invoke it from its tool-call loop (design §13). * Mirrors `supervisor.asTool()` — same `compositeAsTool` composition and * error normalization — and adds `sessionScope`. * * The boundary is OPAQUE (§13, §18.6): the parent's `context` / events do * NOT auto-forward. Per-call data the wrapped orchestrator needs rides on * the tool's `inputSchema` payload — with ONE deliberate exception, the * session binding below, because the payload is written by an LLM. * * Session continuity: * - `"fresh"` (default) — each invocation gets a brand-new `sessionId` * (a generated id) and empty history; the session lives only for this * tool call. The whole validated payload is forwarded as the * orchestrator's `execute(input)` argument. * - `"shared"` — the orchestrator joins an EXISTING session named by the * developer through `options.session`: either a literal id fixed at * construction, or a resolver that reads the invocation's * {@link ToolContext} (`ctx.artifacts`, the out-of-band bag the model * cannot write to). The whole validated payload is forwarded as * `execute(input)`. A `"shared"` tool built without `session` throws at * construction. * * **Why the session id is not a schema field (4.15.0 security fix).** * Before this release, `"shared"` scope read `sessionId` straight out of * the model-generated tool arguments. A `sessionId` is bearer-equivalent * — naming one grants read/write on that session's persisted state — so * any prompt injection reaching the outer agent ("continue session * ``") made the nested orchestrator load a stranger's * conversation, mutate it, and echo its content back into the attacker's * transcript. The binding now lives on channels the model has no access * to. The old behavior survives only behind the loudly-named * `unsafeAllowModelSessionId` opt-in. * * On `result.error`, the typed orchestrator error is thrown so the tool * wrapper produces a `ToolExecutionError` with `cause` preserved — the * outer agent sees one uniform error class. * * @example * const support = ai.orchestrator({ name: "refund-support", intents }); * * // Fresh session per call — no continuity, nothing to hijack. * const supportTool = support.asTool({ * name: "handle_refund", * description: "Handle a refund conversation end-to-end.", * inputSchema: v.object({ message: v.string() }), * }); * * // Continuous session — bound from the authenticated request, never * // from the model's arguments. * const continuousTool = support.asTool({ * name: "handle_refund", * inputSchema: v.object({ message: v.string() }), * sessionScope: "shared", * session: (ctx) => ({ * sessionId: String(ctx?.artifacts?.refundSessionId ?? ""), * }), * }); */ declare function asTool(orchestrator: OrchestratorContract, options: OrchestratorAsToolOptions): ToolContract; //#endregion export { asTool }; //# sourceMappingURL=as-tool.d.mts.map