@graphorin/agent 0.5.0

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +159 -0
  4. package/dist/errors/index.d.ts +170 -0
  5. package/dist/errors/index.d.ts.map +1 -0
  6. package/dist/errors/index.js +204 -0
  7. package/dist/errors/index.js.map +1 -0
  8. package/dist/evaluator-optimizer/index.d.ts +91 -0
  9. package/dist/evaluator-optimizer/index.d.ts.map +1 -0
  10. package/dist/evaluator-optimizer/index.js +85 -0
  11. package/dist/evaluator-optimizer/index.js.map +1 -0
  12. package/dist/factory.d.ts +13 -0
  13. package/dist/factory.d.ts.map +1 -0
  14. package/dist/factory.js +1853 -0
  15. package/dist/factory.js.map +1 -0
  16. package/dist/fallback/index.d.ts +52 -0
  17. package/dist/fallback/index.d.ts.map +1 -0
  18. package/dist/fallback/index.js +53 -0
  19. package/dist/fallback/index.js.map +1 -0
  20. package/dist/fanout/index.d.ts +142 -0
  21. package/dist/fanout/index.d.ts.map +1 -0
  22. package/dist/fanout/index.js +252 -0
  23. package/dist/fanout/index.js.map +1 -0
  24. package/dist/filters/index.d.ts +137 -0
  25. package/dist/filters/index.d.ts.map +1 -0
  26. package/dist/filters/index.js +273 -0
  27. package/dist/filters/index.js.map +1 -0
  28. package/dist/index.d.ts +51 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +49 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/internal/ids.js +46 -0
  33. package/dist/internal/ids.js.map +1 -0
  34. package/dist/internal/usage-accumulator.js +62 -0
  35. package/dist/internal/usage-accumulator.js.map +1 -0
  36. package/dist/lateral-leak/causality-monitor.d.ts +97 -0
  37. package/dist/lateral-leak/causality-monitor.d.ts.map +1 -0
  38. package/dist/lateral-leak/causality-monitor.js +139 -0
  39. package/dist/lateral-leak/causality-monitor.js.map +1 -0
  40. package/dist/lateral-leak/index.d.ts +4 -0
  41. package/dist/lateral-leak/index.js +5 -0
  42. package/dist/lateral-leak/merge-guard.d.ts +89 -0
  43. package/dist/lateral-leak/merge-guard.d.ts.map +1 -0
  44. package/dist/lateral-leak/merge-guard.js +65 -0
  45. package/dist/lateral-leak/merge-guard.js.map +1 -0
  46. package/dist/lateral-leak/protocol-guard.d.ts +76 -0
  47. package/dist/lateral-leak/protocol-guard.d.ts.map +1 -0
  48. package/dist/lateral-leak/protocol-guard.js +147 -0
  49. package/dist/lateral-leak/protocol-guard.js.map +1 -0
  50. package/dist/preferred-model/index.d.ts +53 -0
  51. package/dist/preferred-model/index.d.ts.map +1 -0
  52. package/dist/preferred-model/index.js +141 -0
  53. package/dist/preferred-model/index.js.map +1 -0
  54. package/dist/progress/index.d.ts +62 -0
  55. package/dist/progress/index.d.ts.map +1 -0
  56. package/dist/progress/index.js +150 -0
  57. package/dist/progress/index.js.map +1 -0
  58. package/dist/run-state/index.d.ts +152 -0
  59. package/dist/run-state/index.d.ts.map +1 -0
  60. package/dist/run-state/index.js +311 -0
  61. package/dist/run-state/index.js.map +1 -0
  62. package/dist/tooling/adapters.js +154 -0
  63. package/dist/tooling/adapters.js.map +1 -0
  64. package/dist/tooling/catalogue.js +37 -0
  65. package/dist/tooling/catalogue.js.map +1 -0
  66. package/dist/tooling/dataflow.js +99 -0
  67. package/dist/tooling/dataflow.js.map +1 -0
  68. package/dist/tooling/registry-build.js +85 -0
  69. package/dist/tooling/registry-build.js.map +1 -0
  70. package/dist/types.d.ts +413 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/package.json +115 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","names":["lastError: unknown","executeTool: CodeExecuteBridge","parts: MessageContent[]","fallbackPolicy: AgentFallbackPolicy","subAgent: Agent<TDeps, unknown>","pendingSteer: Message[]","pendingFollowUp: Message[]","abortController: AbortController | undefined","pendingAbort: AbortOptions | undefined","activeRunState: RunState | undefined","externalEventQueue: AgentEvent<TOutput>[]","pendingManualCompacts: PendingManualCompact[]","memory: Memory | undefined","progressIO: ProgressIO","resultReader: ResultReader","activeExecutorBridge: ExecutorEventBridge | undefined","toolApprovalGate: NonNullable<ExecutorOptions['approvalGate']>","toolStreamingSink: NonNullable<ExecutorOptions['streamingSink']>","codeModeAdvertised: ReadonlyArray<Tool<unknown, unknown, TDeps>>","messages: Message[]","instructionsText: string","finalSnapshot: InternalRunSnapshot<TOutput>","rewritten: Message","resumedApprovedCalls: ToolCall[]","stillPending: ToolApproval[]","runContextBase: RunContext<TDeps>","rebuilt: Message[]","envelope: CompactionEnvelope","lastStepCalledToolNames: ReadonlyArray<string>","stepCtx: RunContext<TDeps>","stepRegistry: ToolRegistry","stepExecutor: ToolExecutor","handoffTools: Tool<unknown, unknown, TDeps>[]","stepTools: ReadonlyArray<Tool<unknown, unknown, TDeps>>","primary: PreferredModelResolution","fallbackChain: Provider[]","toolDefs: ReadonlyArray<ToolDefinition>","baseRequest: ProviderRequest","stepUsage: Usage","lastError: ProviderError | undefined","finalCalls: ToolCall[]","stepReasoningParts: ReasoningContent[]","evState: ProviderEventCollector","providerError: ProviderError | undefined","providerStepUsage: Usage","stream","assistant: AssistantMessage","stepRecord: RunStep","execRunContext: RunContext<TDeps>","batch: ToolCall[]","filterLib","handoffRec: HandoffRecord","subOutputs: string[]","subResult: AgentResult<unknown> | undefined","toolError: ToolError","completed: CompletedToolCall","approval: ToolApproval","parsed: unknown","callOpts: AgentCallOptions<TDeps>","seed: AgentInput","turns: string[]","endResult: AgentResult<TOutput> | undefined","progress: AgentProgressIO","probeCtx: ToolExecutionContext"],"sources":["../src/factory.ts"],"sourcesContent":["/**\n * `createAgent({...})` — the agent factory entry point.\n *\n * Wires the typed `model -> tool calls -> model` loop, the streamed\n * event surface, the steering / followUp queues, durable HITL via\n * `RunState`, the multi-agent handoff layer, the agent-level model\n * fallback chain, and the per-tool preferred-model resolution.\n *\n * Custom adapters override behaviour by supplying alternative\n * `Provider` / `Memory` / `CheckpointStore` instances; the loop\n * never reaches into adapter internals.\n *\n * @packageDocumentation\n */\n\nimport { createHash } from 'node:crypto';\nimport type {\n AgentEvent,\n AgentResult,\n AssistantMessage,\n CompletedToolCall,\n HandoffRecord,\n Message,\n MessageContent,\n ModelSpec,\n Provider,\n ProviderError,\n ProviderErrorKind,\n ProviderEvent,\n ProviderRequest,\n ReasoningContent,\n ReasoningRetention,\n RunContext,\n RunState,\n RunStep,\n Sensitivity,\n Tool,\n ToolApproval,\n ToolCall,\n ToolChoice,\n ToolDefinition,\n ToolDefinitionExample,\n ToolError,\n ToolExecutionContext,\n Usage,\n} from '@graphorin/core';\nimport { isStepCount, NOOP_LOGGER, NOOP_TRACER, zeroUsage } from '@graphorin/core';\nimport type { Memory } from '@graphorin/memory';\n\n/** Return envelope of `ContextEngine.compactNow` (shared splice paths, CE-3). */\ntype CompactionEnvelope = Awaited<ReturnType<Memory['contextEngine']['compactNow']>>;\n\n/**\n * Replacement content committed in place of assistant commentary the\n * causality monitor blocked (AG-10). Worded to not match any built-in\n * denial pattern, so the notice itself never re-triggers the monitor.\n */\nconst LATERAL_LEAK_BLOCKED_NOTICE =\n '[graphorin] assistant commentary withheld by the lateral-leak defense.';\n\nimport { composeGuardrails } from '@graphorin/security/guardrails';\nimport { createReadResultTool, createToolSearchTool } from '@graphorin/tools/built-in';\nimport {\n type CodeExecuteBridge,\n createCodeExecuteTool,\n createCodeSearchTool,\n type ProjectableTool,\n projectToolApi,\n} from '@graphorin/tools/code-mode';\nimport {\n createToolExecutor,\n type ExecutorOptions,\n type ToolExecutor,\n} from '@graphorin/tools/executor';\nimport type { ToolRegistry } from '@graphorin/tools/registry';\nimport {\n createDefaultSpillWriter,\n createFileResultReader,\n type ResultReader,\n} from '@graphorin/tools/result';\nimport {\n AgentRuntimeError,\n ConcurrentRunError,\n InvalidAgentConfigError,\n InvalidPreferredModelError,\n MultipleHandoffsInStepError,\n ToolNotFoundError,\n} from './errors/index.js';\nimport { type AgentFallbackPolicy, isAgentFallbackEligible } from './fallback/index.js';\nimport {\n type FanOutResult,\n type FanOutOptions as RunFanOutOptions,\n runFanOut,\n} from './fanout/index.js';\nimport { type DescribedFilter, filters as filterLib } from './filters/index.js';\nimport { newId } from './internal/ids.js';\nimport { InMemoryUsageAccumulator } from './internal/usage-accumulator.js';\nimport { CausalityMonitor } from './lateral-leak/causality-monitor.js';\nimport { type PreferredModelResolution, resolvePreferredModel } from './preferred-model/index.js';\nimport {\n createProgressIO,\n type ProgressIO,\n type ProgressReadOptions,\n type ProgressWriteOptions,\n} from './progress/index.js';\nimport { addModelUsage, createInitialRunState, serializeRunState } from './run-state/index.js';\nimport {\n buildMemoryGuard,\n buildSecretResolver,\n buildToolTokenCounter,\n createExecutorEventBridge,\n createMemoryRegionReader,\n type ExecutorEventBridge,\n} from './tooling/adapters.js';\nimport { orderPromotedTools } from './tooling/catalogue.js';\nimport { buildDataFlowGuard } from './tooling/dataflow.js';\nimport { buildToolRegistry } from './tooling/registry-build.js';\nimport type {\n AbortOptions,\n Agent,\n AgentCallOptions,\n AgentConfig,\n AgentFanOutOptions,\n AgentInput,\n AgentProgressIO,\n AgentToToolOptions,\n CompactionApiResult,\n CompactOptions,\n} from './types.js';\n\nconst sha256Hex = (input: string): string =>\n createHash('sha256').update(input, 'utf8').digest('hex');\n\nconst HANDOFF_TOOL_PREFIX = 'transfer_to_';\n\n/** The built-in deferred-discovery tool's stable name (WI-05 / P0-3). */\nconst TOOL_SEARCH_NAME = 'tool_search';\n\n/**\n * Register the built-in `tool_search` into `registry` when — and only\n * when — the registry holds at least one deferred tool\n * (`defer_loading: true`). `tool_search` is itself eager (so it is\n * always advertised while a deferred pool exists) and resolvable by the\n * executor like any other tool, so a model can both *see* it in the\n * per-step catalogue and *call* it.\n *\n * No-op when nothing defers (zero overhead — the tool never appears) or\n * when a user tool already occupies the name (the user's tool wins; we\n * never clobber it). Because deferral is decided at registration time\n * (`normaliseTool`), the deferred set is fixed for the life of the\n * registry — this runs once per registry, not per step.\n */\nfunction registerToolSearch(registry: ToolRegistry): void {\n if (registry.listDeferred().length === 0) return;\n if (registry.get(TOOL_SEARCH_NAME) !== undefined) return;\n registry.register(createToolSearchTool({ registry }), {\n kind: 'built-in',\n subsystem: 'tool-discovery',\n });\n}\n\n/** The built-in result-handle reader tool's stable name (WI-10 / P1-4). */\nconst READ_RESULT_NAME = 'read_result';\n\n/**\n * Register the built-in `read_result` into `registry` when at least one\n * registered tool opts into the `'spill-to-file'` truncation strategy\n * (the sole producer of spill handles today) — or when `force` is set,\n * which the agent passes when an operator wires external result readers\n * (e.g. an MCP `resource_link` reader; WI-13). The tool is eager, so it\n * is advertised alongside the producing tool and the model can fetch a\n * handle back on demand instead of inlining the full blob. No-op when\n * nothing produces handles (zero overhead) or when a user tool already\n * occupies the name (the user's tool wins).\n */\nfunction registerReadResult(\n registry: ToolRegistry,\n reader: ResultReader,\n opts?: { readonly force?: boolean },\n): void {\n if (\n opts?.force !== true &&\n !registry.list().some((entry) => entry.truncationStrategy === 'spill-to-file')\n ) {\n return;\n }\n if (registry.get(READ_RESULT_NAME) !== undefined) return;\n registry.register(createReadResultTool({ reader }), {\n kind: 'built-in',\n subsystem: 'result-handle',\n });\n}\n\n/**\n * Compose result readers into one that tries each in order, returning\n * the first that resolves the handle (WI-13). The spill-file reader is\n * placed first so `graphorin-spill:` handles resolve locally; operator\n * readers (e.g. an MCP resource reader) resolve the rest. Each reader\n * rejects handles it does not own, so resolution falls through cleanly.\n */\nfunction composeResultReaders(readers: ReadonlyArray<ResultReader>): ResultReader {\n return {\n async read(uri, range) {\n let lastError: unknown;\n for (const r of readers) {\n try {\n return await r.read(uri, range);\n } catch (err) {\n lastError = err;\n }\n }\n throw lastError instanceof Error\n ? lastError\n : new Error(`No result reader resolved handle ${JSON.stringify(uri)}.`);\n },\n };\n}\n\n/** The code-mode meta-tools' stable names (WI-11 / P1-2). */\nconst CODE_EXECUTE_NAME = 'code_execute';\nconst CODE_SEARCH_NAME = 'code_search';\n\n/**\n * Wire code-mode (P1-2) into `registry`: register the `code_search` /\n * `code_execute` meta-tools and return them as the tools to advertise in\n * place of the full catalogue. The model reaches every other tool through\n * `code_execute`, whose in-script `tools.<name>(args)` calls route back\n * through `quietExecutor.executeOne(...)` under the calling step's\n * `runContext` — so per-tool ACL / sanitization / truncation still apply,\n * exactly as in direct mode. `quietExecutor` carries no `streamingSink`,\n * so the inner calls do not interleave `tool.execute.*` events into the\n * outer stream.\n *\n * Excluded from the code API (`reservedNames`): the meta-tools, the\n * discovery / handle built-ins, handoff tools (which stay first-class\n * provider tools), and — supplied by the caller — any approval-gated\n * tool, since code-mode has no durable-HITL path to suspend mid-script.\n *\n * Returns `[]` (registering nothing) when no real tool is exposable.\n */\nfunction registerCodeMode(\n registry: ToolRegistry,\n quietExecutor: ToolExecutor,\n reservedNames: ReadonlySet<string>,\n): ReadonlyArray<Tool<unknown, unknown, unknown>> {\n if (registry.get(CODE_EXECUTE_NAME) !== undefined) return []; // already wired\n const isApprovalGated = (t: { readonly needsApproval?: unknown }): boolean =>\n t.needsApproval === true || typeof t.needsApproval === 'function';\n const codeTools = registry\n .list()\n .filter((entry) => !reservedNames.has(entry.name) && !isApprovalGated(entry));\n if (codeTools.length === 0) return [];\n\n // TL-8: gated tools cannot suspend for HITL mid-script, so they are\n // excluded from the code API — but VISIBLY: they appear in the\n // catalogue/search with a call-directly marker, and a bridged call\n // fails with the same hint instead of an opaque unknown-tool error.\n const approvalGatedTools = registry\n .list()\n .filter((entry) => !reservedNames.has(entry.name) && isApprovalGated(entry))\n .map((entry) => entry.name);\n const approvalGatedSet = new Set(approvalGatedTools);\n\n const allowedTools = [...codeTools.map((entry) => entry.name), ...approvalGatedTools];\n const allowedSet = new Set(codeTools.map((entry) => entry.name));\n const eagerProjectable = codeTools.filter(\n (entry) => entry.__effectiveDeferLoading !== true,\n ) as unknown as ReadonlyArray<ProjectableTool>;\n const projection = projectToolApi(eagerProjectable);\n\n const executeTool: CodeExecuteBridge = async (call, ctx) => {\n if (approvalGatedSet.has(call.name)) {\n throw new Error(\n `${call.name} requires human approval and cannot run inside code_execute — call it directly as a standalone tool call so the run can suspend for the approval.`,\n );\n }\n const completed = await quietExecutor.executeOne({\n call: { toolCallId: newId('codecall'), toolName: call.name, args: call.args },\n runContext: ctx.runContext,\n stepNumber: ctx.runContext.stepNumber,\n });\n const { outcome } = completed;\n if ('kind' in outcome) throw new Error(`${call.name}: ${outcome.message}`);\n return outcome.output;\n };\n\n const codeSearch = createCodeSearchTool({\n projection,\n approvalGatedTools,\n searchDeferred: async (query, k) =>\n (await registry.searchDeferred(query, k)).filter((match) => allowedSet.has(match.name)),\n });\n const codeExecute = createCodeExecuteTool({\n projection,\n allowedTools,\n executeTool,\n approvalGatedTools,\n });\n registry.register(codeSearch, { kind: 'built-in', subsystem: 'code-mode' });\n registry.register(codeExecute, { kind: 'built-in', subsystem: 'code-mode' });\n return [codeSearch, codeExecute] as ReadonlyArray<Tool<unknown, unknown, unknown>>;\n}\n\n/**\n * Fold a completed `tool_search` result into the per-run promotion set:\n * every matched tool name becomes advertised (and thus callable) on the\n * next step. Tolerant of unexpected shapes (e.g. a user-shadowed\n * `tool_search`) — only string `name`s inside a `matches` array promote.\n */\nfunction recordToolSearchPromotions(output: unknown, promoted: Set<string>): void {\n if (typeof output !== 'object' || output === null) return;\n const matches = (output as { readonly matches?: unknown }).matches;\n if (!Array.isArray(matches)) return;\n for (const match of matches) {\n const name = (match as { readonly name?: unknown } | null)?.name;\n if (typeof name === 'string') promoted.add(name);\n }\n}\n\n/**\n * Internal mutable view of {@link RunState}. The public type marks\n * most fields `readonly` to guard against accidental mutation by\n * consumers; the runtime owns the lifecycle and writes through\n * this view.\n */\ninterface MutableRunState {\n status: RunState['status'];\n currentAgentId: string;\n readonly steps: RunStep[];\n readonly messages: Message[];\n readonly pendingApprovals: ToolApproval[];\n readonly handoffs: HandoffRecord[];\n usage: Usage;\n error?: RunState['error'];\n finishedAt?: string;\n usageByModel?: RunState['usageByModel'];\n}\n\ninterface InternalRunSnapshot<TOutput> {\n output: TOutput;\n}\n\nfunction isModelHintLike(value: unknown): boolean {\n return value === 'fast' || value === 'balanced' || value === 'smart';\n}\n\nfunction isModelSpecLike(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n if (typeof v.modelId === 'string' && typeof v.name === 'string') return true;\n if (typeof v.provider === 'object' && v.provider !== null && typeof v.model === 'string') {\n return true;\n }\n return false;\n}\n\nfunction validatePreferredModel(value: unknown): void {\n if (value === undefined) return;\n if (isModelHintLike(value)) return;\n if (isModelSpecLike(value)) return;\n throw new InvalidPreferredModelError(value);\n}\n\nfunction isMessageObject(value: unknown): value is Message {\n if (typeof value !== 'object' || value === null) return false;\n const role = (value as { role?: unknown }).role;\n return role === 'system' || role === 'user' || role === 'assistant' || role === 'tool';\n}\n\nfunction isRunStateObject(value: unknown): value is RunState {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n return (\n typeof v.id === 'string' &&\n typeof v.agentId === 'string' &&\n Array.isArray(v.messages) &&\n Array.isArray(v.steps)\n );\n}\n\nfunction asMessages(input: AgentInput | RunState): {\n readonly seed: Message[];\n readonly resumed?: RunState;\n} {\n if (typeof input === 'string') {\n return { seed: [{ role: 'user', content: input }] };\n }\n if (Array.isArray(input)) {\n return { seed: [...input] as Message[] };\n }\n if (isMessageObject(input)) {\n return { seed: [input] };\n }\n if (isRunStateObject(input)) {\n return { seed: [], resumed: input };\n }\n throw new InvalidAgentConfigError(`unrecognized AgentInput shape`);\n}\n\n/**\n * Strip a single Markdown code fence around a JSON payload (AG-3).\n * Models often wrap structured output in ```json fences even when told\n * not to. ReDoS-safe: the info string is matched with `[^\\n]*`.\n */\nfunction stripJsonFence(text: string): string {\n const trimmed = text.trim();\n const match = /^```[^\\n]*\\n([\\s\\S]*?)\\n?```$/.exec(trimmed);\n return match?.[1] ?? trimmed;\n}\n\n/**\n * The AG-3 fallback instruction: one trailing system message that\n * pins JSON-only output and embeds the wire schema / description.\n * This is the documented structured-output contract for adapters that\n * do not yet consume `ProviderRequest.outputType` natively (PS-24).\n */\nfunction buildStructuredInstruction(spec: {\n readonly description?: string;\n readonly jsonSchema?: Readonly<Record<string, unknown>>;\n}): string {\n const parts = [\n 'Respond with a single valid JSON value only — no prose, no Markdown code fences.',\n ];\n if (spec.description !== undefined && spec.description.length > 0) {\n parts.push(spec.description);\n }\n if (spec.jsonSchema !== undefined) {\n parts.push(`The JSON MUST conform to this JSON Schema:\\n${JSON.stringify(spec.jsonSchema)}`);\n }\n return parts.join('\\n');\n}\n\n/** Most-recent user-role text in `messages` (for context-engine auto-recall). */\nfunction lastUserText(messages: ReadonlyArray<Message>): string | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m?.role !== 'user') continue;\n if (typeof m.content === 'string') return m.content;\n const text = m.content\n .filter((p): p is { readonly type: 'text'; readonly text: string } => p.type === 'text')\n .map((p) => p.text)\n .join(' ');\n return text.length > 0 ? text : undefined;\n }\n return undefined;\n}\n\n/**\n * AG-21: classify a **thrown** provider error into a {@link ProviderErrorKind}\n * so the fallback chain can act on it, instead of flattening every exception to\n * `'unknown'` (which is always fallback-ineligible). Structural — reads the\n * `kind` carried by `@graphorin/provider`'s `GraphorinProviderError` subclasses\n * without importing them, keeping the agent decoupled from the provider package.\n */\nfunction classifyThrownProviderErrorKind(cause: unknown): ProviderErrorKind {\n if (typeof cause === 'object' && cause !== null && 'kind' in cause) {\n switch ((cause as { readonly kind?: unknown }).kind) {\n case 'rate-limit-exceeded':\n return 'rate-limit';\n }\n }\n return 'unknown';\n}\n\n/** Resolve a Zod-like schema to a JSON-Schema record (via `toJSON`), else pass an object through. */\nfunction projectSchema(raw: unknown): Readonly<Record<string, unknown>> | undefined {\n if (raw === null || raw === undefined) return undefined;\n const toJson = (raw as { toJSON?: () => unknown }).toJSON;\n if (typeof toJson === 'function') return toJson.call(raw) as Readonly<Record<string, unknown>>;\n if (typeof raw === 'object') return raw as Readonly<Record<string, unknown>>;\n return undefined;\n}\n\nfunction toolToDefinition(tool: Tool): ToolDefinition {\n const ts = tool as Tool & {\n readonly inputSchema?: unknown;\n readonly outputSchema?: unknown;\n };\n const inputSchema = projectSchema(ts.inputSchema) ?? {};\n // A5: project the output schema so structured-output providers + typed\n // code-mode see the tool's result shape.\n const outputSchema = projectSchema(ts.outputSchema);\n const examples = renderToolExamples(tool);\n return {\n name: tool.name,\n description: tool.description,\n inputSchema,\n ...(outputSchema !== undefined ? { outputSchema } : {}),\n ...(examples !== undefined ? { examples } : {}),\n };\n}\n\n/**\n * Project a tool's worked `examples` onto the provider wire contract\n * (WI-06 / P2-3). Examples are rendered only when the tool eagerly\n * renders them: the registry resolves the `defer_loading` auto-rule into\n * `examplesEagerlyRendered`, so a deferred tool resolves to `false` and is\n * skipped (its examples stay out of context even once `tool_search`\n * promotes it). `undefined` — the \"runtime decides\" case for a plain\n * eager tool — renders, since the tool is already advertised this step.\n *\n * Bounded to ≤5 to honour the `ToolExample` `[1,5]` contract even when a\n * tool slipped past the registry's overflow WARN (which does not truncate).\n */\nfunction renderToolExamples(tool: Tool): ReadonlyArray<ToolDefinitionExample> | undefined {\n const examples = tool.examples;\n if (examples === undefined || examples.length === 0) return undefined;\n if (tool.examplesEagerlyRendered === false) return undefined;\n return examples.slice(0, 5).map((ex) => ({\n input: ex.input,\n output: ex.output,\n ...(ex.comment !== undefined ? { comment: ex.comment } : {}),\n }));\n}\n\nconst PASSTHROUGH_SCHEMA = {\n parse: <T>(value: unknown): T => value as T,\n safeParse: <T>(value: unknown) => ({ success: true as const, data: value as T }),\n toJSON: (): Record<string, unknown> => ({ type: 'object' }),\n} as const;\n\nfunction isDescribedFilter(value: unknown): value is DescribedFilter {\n return (\n typeof value === 'function' &&\n 'descriptor' in value &&\n typeof (value as DescribedFilter).descriptor === 'object'\n );\n}\n\nfunction buildHandoffTool<TDeps>(target: Agent<TDeps, unknown>): Tool<unknown, unknown, TDeps> {\n const cfg = target.config;\n const name = `${HANDOFF_TOOL_PREFIX}${cfg.name}`;\n const tool: Tool<unknown, unknown, TDeps> = {\n name,\n description: `Hand off control to agent '${cfg.name}'.`,\n inputSchema: PASSTHROUGH_SCHEMA as unknown as Tool<unknown, unknown, TDeps>['inputSchema'],\n sideEffectClass: 'pure',\n async execute(): Promise<string> {\n return `[handoff: ${cfg.name}]`;\n },\n };\n return tool;\n}\n\nfunction specToProvider(spec: ModelSpec): Provider {\n if ('provider' in spec) return spec.provider as Provider;\n return spec as Provider;\n}\n\ninterface ToolCallAccumulator {\n readonly toolCallId: string;\n toolName: string;\n argsBuffer: string;\n}\n\ninterface ProviderEventOutcome {\n readonly emit?: AgentEvent;\n readonly providerError?: ProviderError;\n readonly usage?: Usage;\n readonly finished?: boolean;\n}\n\ninterface ProviderEventCollector {\n textBuffer: string;\n reasoningBuffer: string;\n reasoningParts: ReasoningContent[];\n calls: Map<string, ToolCallAccumulator>;\n finalCalls: ToolCall[];\n}\n\nfunction handleProviderEvent(\n ev: ProviderEvent,\n state: ProviderEventCollector,\n): ProviderEventOutcome {\n switch (ev.type) {\n case 'stream-start':\n return {};\n case 'reasoning-delta':\n state.reasoningBuffer += ev.delta;\n return { emit: { type: 'reasoning.delta', delta: ev.delta } };\n case 'text-delta':\n state.textBuffer += ev.delta;\n return { emit: { type: 'text.delta', delta: ev.delta } };\n case 'tool-call-start':\n state.calls.set(ev.toolCallId, {\n toolCallId: ev.toolCallId,\n toolName: ev.toolName,\n argsBuffer: '',\n });\n return {\n emit: {\n type: 'tool.call.start',\n toolCallId: ev.toolCallId,\n toolName: ev.toolName,\n args: undefined,\n },\n };\n case 'tool-call-input-delta': {\n const acc = state.calls.get(ev.toolCallId);\n if (acc !== undefined) acc.argsBuffer += ev.argsDelta;\n return {\n emit: { type: 'tool.call.delta', toolCallId: ev.toolCallId, argsDelta: ev.argsDelta },\n };\n }\n case 'tool-call-end': {\n const acc = state.calls.get(ev.toolCallId);\n if (acc === undefined) {\n // AG-26: an end without a matching start has no tool name — the\n // old path dispatched it as the unknown tool ''. Drop it loudly.\n process.stderr.write(\n `[graphorin/agent] dropped tool-call-end '${ev.toolCallId}' with no matching tool-call-start.\\n`,\n );\n return {};\n }\n state.finalCalls.push({\n toolCallId: ev.toolCallId,\n toolName: acc.toolName,\n args: ev.finalArgs,\n });\n return {\n emit: { type: 'tool.call.end', toolCallId: ev.toolCallId, finalArgs: ev.finalArgs },\n };\n }\n // AG-26: provider-generated files / citations are consumer-observable\n // events instead of silently vanishing.\n case 'file':\n return { emit: { type: 'file.generated', mimeType: ev.mimeType, data: ev.data } };\n case 'source':\n return {\n emit: {\n type: 'source.cited',\n uri: ev.uri,\n ...(ev.title !== undefined ? { title: ev.title } : {}),\n },\n };\n case 'finish':\n return { usage: ev.usage, finished: true };\n case 'error':\n return { providerError: ev.error };\n default: {\n const _exhaustive: never = ev;\n void _exhaustive;\n return {};\n }\n }\n}\n\n/**\n * Resolve the effective {@link ReasoningRetention} for a step. The\n * agent-level setting wins over the provider-level default; when\n * neither is supplied, the provider's `reasoningContract`\n * capability drives the default per RB-42 / suggested DEC-158.\n */\nfunction effectiveReasoningRetention(\n agentOverride: ReasoningRetention | undefined,\n provider: Provider,\n): ReasoningRetention {\n if (agentOverride !== undefined) return agentOverride;\n const contract = provider.capabilities.reasoningContract;\n switch (contract) {\n case 'round-trip-required':\n return 'pass-through-claude';\n case 'optional':\n return 'pass-through-all';\n case 'hidden':\n return 'strip';\n default:\n return 'strip';\n }\n}\n\n/**\n * Build the assistant message that the runtime appends to the\n * message buffer after a successful provider call. When the\n * effective {@link ReasoningRetention} is not `'strip'`, the\n * assembled `reasoning` content parts ride along on `content` so\n * the next provider call honours the wire-correct round-trip\n * contract per RB-42.\n */\nfunction buildAssistantMessage(\n text: string,\n reasoningParts: ReadonlyArray<ReasoningContent>,\n toolCalls: ReadonlyArray<ToolCall>,\n agentId: string,\n retention: ReasoningRetention,\n): AssistantMessage {\n const preserveReasoning = retention !== 'strip' && reasoningParts.length > 0;\n if (preserveReasoning) {\n const parts: MessageContent[] = [...reasoningParts];\n if (text.length > 0) parts.push({ type: 'text', text });\n return {\n role: 'assistant',\n content: parts,\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n agentId,\n };\n }\n return {\n role: 'assistant',\n content: text,\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n agentId,\n };\n}\n\n/**\n * Strip every {@link ReasoningContent} part from each message in\n * the supplied list. Used at the swap point when `prepareStep`\n * downgrades the provider's `reasoningContract` mid-run.\n */\nfunction stripReasoningFromMessages(messages: Message[]): { stripped: number } {\n let stripped = 0;\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg === undefined) continue;\n if (msg.role === 'system' || msg.role === 'tool') continue;\n if (typeof msg.content === 'string') continue;\n const filtered = msg.content.filter((p) => p.type !== 'reasoning');\n if (filtered.length === msg.content.length) continue;\n stripped += msg.content.length - filtered.length;\n if (msg.role === 'assistant') {\n messages[i] = { ...msg, content: filtered };\n } else {\n messages[i] = { ...msg, content: filtered };\n }\n }\n return { stripped };\n}\n\n/**\n * Count the leading contiguous run of `system` messages in the initial\n * buffer — the trusted, KV-cache-stable instruction prefix. Captured\n * once at run start (WI-09 / P1-1): auto-compaction summarises only the\n * messages after this prefix, so the prefix stays byte-identical across\n * every step (the provider's cache breakpoint is real) and a long run\n * never re-pays for the system prompt.\n *\n * The length is fixed for the run rather than re-derived per compaction\n * on purpose: each compaction inserts its summary as a `system` message\n * right after the prefix, so re-scanning the leading run would absorb\n * that summary into the prefix and shield it from the next compaction —\n * summaries would stack unbounded. Pinning the original length keeps\n * each prior summary inside the compactable body, where the next pass\n * folds it into a fresh summary-of-summary.\n */\nfunction countLeadingSystemMessages(messages: ReadonlyArray<Message>): number {\n let i = 0;\n while (i < messages.length && messages[i]?.role === 'system') i += 1;\n return i;\n}\n\n/**\n * Build a fresh {@link Agent} from the supplied configuration.\n *\n * @stable\n */\nexport function createAgent<TDeps = unknown, TOutput = string>(\n config: AgentConfig<TDeps, TOutput>,\n): Agent<TDeps, TOutput> {\n if (typeof config.name !== 'string' || config.name.length === 0) {\n throw new InvalidAgentConfigError(\"missing 'name'\");\n }\n if (config.provider === undefined || config.provider === null) {\n throw new InvalidAgentConfigError(\"missing 'provider'\");\n }\n // AG-3: a schema on a text-kind output spec is a config mistake (the\n // schema would never run) — reject instead of silently ignoring.\n if (config.outputType?.kind === 'text' && config.outputType.schema !== undefined) {\n throw new InvalidAgentConfigError(\n \"outputType.kind 'text' with a schema — did you mean kind: 'structured'?\",\n );\n }\n validatePreferredModel(config.preferredModel);\n if (config.modelTierMap !== undefined) {\n for (const [tier, spec] of Object.entries(config.modelTierMap)) {\n if (!isModelHintLike(tier)) throw new InvalidPreferredModelError({ tier });\n if (spec === undefined) continue;\n if (!isModelSpecLike(spec)) throw new InvalidPreferredModelError(spec);\n }\n }\n if (config.fallbackModels !== undefined) {\n for (const spec of config.fallbackModels) {\n if (!isModelSpecLike(spec)) throw new InvalidPreferredModelError(spec);\n }\n }\n\n const agentId = newId('agent');\n const tracer = config.tracer ?? NOOP_TRACER;\n const stopWhen = config.stopWhen ?? isStepCount(50);\n const fallbackPolicy: AgentFallbackPolicy = config.fallbackPolicy ?? {};\n const handoffMap = new Map<\n string,\n { readonly agent: Agent<TDeps, unknown>; readonly filter: DescribedFilter | undefined }\n >();\n for (const entry of config.handoffs ?? []) {\n const isWrappedHandoff = typeof entry === 'object' && entry !== null && 'target' in entry;\n const subAgent: Agent<TDeps, unknown> = isWrappedHandoff\n ? (entry as { readonly target: Agent<TDeps, unknown> }).target\n : (entry as Agent<TDeps, unknown>);\n const userFilter = isWrappedHandoff\n ? (\n entry as {\n readonly inputFilter?:\n | DescribedFilter\n | ((history: readonly Message[]) => readonly Message[]);\n }\n ).inputFilter\n : undefined;\n const filter = isDescribedFilter(userFilter) ? userFilter : undefined;\n const toolName = `${HANDOFF_TOOL_PREFIX}${subAgent.config.name}`;\n handoffMap.set(toolName, { agent: subAgent, filter });\n }\n\n let pendingSteer: Message[] = [];\n const pendingFollowUp: Message[] = [];\n let abortController: AbortController | undefined;\n let pendingAbort: AbortOptions | undefined;\n // Per-run scratch refs surfaced through the public surface for\n // event emission from `steer(...)` / `followUp(...)`.\n let activeRunState: RunState | undefined;\n /** AG-11: guards the one-in-flight-run-per-instance invariant. */\n let runInFlight = false;\n const externalEventQueue: AgentEvent<TOutput>[] = [];\n\n /**\n * Manual-compaction requests enqueued by `agent.compact()` (CE-3 /\n * AG-13). The run loop owns the live message buffer, so the splice\n * must happen inside the loop: `maybeAutoCompact` services the queue\n * at the next step boundary, and `finishRun` settles leftovers as\n * explicit no-ops.\n */\n interface PendingManualCompact {\n readonly options: CompactOptions | undefined;\n readonly resolve: (result: CompactionApiResult) => void;\n readonly reject: (cause: unknown) => void;\n }\n const pendingManualCompacts: PendingManualCompact[] = [];\n\n const noopCompactionResult = (\n skippedReason: NonNullable<CompactionApiResult['skippedReason']>,\n ): CompactionApiResult => ({\n beforeTokens: 0,\n afterTokens: 0,\n summaryTokens: 0,\n durationMs: 0,\n hooksFiredCount: 0,\n summary: '',\n applied: false,\n skippedReason,\n });\n\n const memory: Memory | undefined = config.memory;\n const progressIO: ProgressIO = createProgressIO({\n ...(config.sensitivity !== undefined ? { defaultSensitivity: config.sensitivity } : {}),\n });\n\n // Assemble the unified tool registry at warm-up (Principle #12): one\n // registry across first-party + skill sources, with deterministic\n // cross-source collision resolution. Exposed read-only as\n // `agent.registry`; the run loop and `tool_search` consume it. The\n // registry is the tool-validation authority, so a malformed tool\n // fails fast here at construction.\n const toolRegistry = buildToolRegistry({\n ...(config.tools !== undefined\n ? { tools: config.tools as ReadonlyArray<Tool<unknown, unknown, unknown>> }\n : {}),\n ...(config.skills !== undefined ? { skills: config.skills } : {}),\n }).registry;\n\n // WI-05 (deferred loading + tool_search / P0-3): if any registered\n // tool sets `defer_loading: true`, register the built-in `tool_search`\n // so the model can discover those tools on demand. Tools that defer are\n // withheld from the per-step catalogue (see the loop below) until a\n // `tool_search` match promotes them, keeping large tool sets out of the\n // context window. When nothing defers this is a no-op.\n registerToolSearch(toolRegistry);\n\n // WI-10 (result references / handles / P1-4): construct one spill\n // writer + reader pair at warm-up. The writer is handed to the executor\n // so a tool's `'spill-to-file'` truncation strategy externalises large\n // bodies to disk (0600, run-scoped); the reader — over the *same*\n // artifact root — backs the built-in `read_result` tool so the model can\n // page through a spilled artifact on demand instead of inlining the\n // whole blob. `read_result` is registered only when some tool spills.\n const spillWriter = createDefaultSpillWriter();\n const fileResultReader = createFileResultReader({ artifactRoot: spillWriter.artifactRoot });\n // WI-13 (P2-2): compose any operator-supplied result readers (e.g. an\n // MCP resource reader from `createMcpResourceReader`, for resolving\n // `resource_link` handles) after the spill-file reader. `read_result`\n // then pages both `graphorin-spill:` artifacts and external handles,\n // and is force-registered when external readers exist (even if no tool\n // spills) so those handles are resolvable.\n const externalResultReaders = config.resultReaders ?? [];\n const resultReader: ResultReader =\n externalResultReaders.length === 0\n ? fileResultReader\n : composeResultReaders([fileResultReader, ...externalResultReaders]);\n registerReadResult(toolRegistry, resultReader, { force: externalResultReaders.length > 0 });\n\n // Construct the unified ToolExecutor once at warm-up (WI-03 / P0-1),\n // bound to the registry above. Routing tool execution through the\n // executor activates the documented tool fields the inline loop\n // bypassed: per-tool `secretsAllowed` ACL, result truncation\n // (`maxResultTokens` / `truncationStrategy`), inbound sanitization,\n // memory-guard, idempotency keys and single-round repair.\n //\n // Durable HITL stays in the agent: approval is pre-screened below and\n // suspends the run, so the executor's `ApprovalGate` only ever sees\n // no-approval / pre-approved calls — it auto-grants and never blocks\n // the generator (Adapter G).\n //\n // Sandbox note: `config.tools` are inline `tool({...})` closures that\n // cannot be serialised to an out-of-process sandbox, and\n // `resolveSandbox` defaults user-defined tools to `worker-threads`.\n // Wiring a resolver that returned a real sandbox for that kind would\n // break every inline tool, so `sandboxResolver` is intentionally left\n // unset (the executor then runs inline — its documented fallback).\n // The resolved policy is still surfaced on the tool-execute span /\n // audit; real isolation applies to module-loadable (skill / MCP)\n // tools and is wired when those land.\n let activeExecutorBridge: ExecutorEventBridge | undefined;\n const toolApprovalGate: NonNullable<ExecutorOptions['approvalGate']> = {\n request: async () => ({ granted: true }),\n };\n const toolSecretResolver = buildSecretResolver();\n const toolTokenCounter = buildToolTokenCounter();\n // SDF-1: when memory is wired, bind a scope-aware region reader so the\n // executor's DEC-153 snapshot/verify cycle actually runs (the scope\n // resolves lazily from the in-flight run — the executor only invokes\n // the reader mid-run). Without memory the guard tiers stay skipped,\n // and a one-time WARN below makes that silent no-op visible.\n const memoryGuardWiring = buildMemoryGuard(\n memory,\n memory === undefined\n ? {}\n : {\n regionReader: createMemoryRegionReader(['working'], async (region) => {\n if (region !== 'working') return '';\n const scope = {\n userId: activeRunState?.userId ?? agentId,\n ...(activeRunState?.sessionId !== undefined\n ? { sessionId: activeRunState.sessionId }\n : {}),\n agentId,\n };\n const working = (\n memory as unknown as {\n working?: { compile?: (s: unknown, a?: string) => Promise<string> };\n }\n ).working;\n if (working?.compile === undefined) return '';\n try {\n return await working.compile(scope, agentId);\n } catch {\n // The reader is best-effort: a failed region read must not\n // turn the guard step into a run failure.\n return '';\n }\n }),\n },\n );\n const toolMemoryGuardFactory = memoryGuardWiring.memoryGuardFactory;\n if (memory === undefined) {\n const guarded = (config.tools ?? []).filter((t) => t.memoryGuardTier !== undefined);\n if (guarded.length > 0) {\n console.warn(\n `[graphorin/agent] ${guarded.length} tool(s) declare memoryGuardTier but no memory is wired — ` +\n 'the DEC-153 snapshot/verify guard is skipped (SDF-1). Wire `memory` to activate it.',\n );\n }\n }\n // Provenance / data-flow guard (WI-12 / P1-3, opt-in). Built once and\n // shared by every executor (direct + code-mode quiet), so the sink gate\n // and taint recording apply uniformly. Off unless configured with a\n // non-`'off'` mode — zero overhead on the default path.\n const toolDataFlowGuard =\n config.dataFlowPolicy !== undefined && config.dataFlowPolicy.mode !== 'off'\n ? buildDataFlowGuard(config.dataFlowPolicy)\n : undefined;\n const toolStreamingSink: NonNullable<ExecutorOptions['streamingSink']> = (event) =>\n activeExecutorBridge?.sink(event);\n // `quiet` builds an executor without the streaming sink — used for\n // code-mode's in-script tool calls (WI-11), whose `tool.execute.*`\n // events must not interleave into the outer agent stream.\n const makeToolExecutor = (\n registry: ToolRegistry,\n opts?: { readonly quiet?: boolean },\n ): ToolExecutor =>\n createToolExecutor({\n registry,\n approvalGate: toolApprovalGate,\n secretResolver: toolSecretResolver,\n tokenCounter: toolTokenCounter,\n memoryGuardFactory: toolMemoryGuardFactory,\n ...(memoryGuardWiring.memoryRegionReader !== undefined\n ? { memoryRegionReader: memoryGuardWiring.memoryRegionReader }\n : {}),\n spill: spillWriter,\n ...(toolDataFlowGuard !== undefined ? { dataFlowGuard: toolDataFlowGuard } : {}),\n ...(opts?.quiet === true ? {} : { streamingSink: toolStreamingSink }),\n ...(config.maxParallelTools !== undefined\n ? { maxParallelTools: config.maxParallelTools }\n : {}),\n });\n const toolExecutor = makeToolExecutor(toolRegistry);\n\n // Code-mode (WI-11 / P1-2, opt-in): advertise only the `code_search` /\n // `code_execute` meta-tools and let the model orchestrate tools inside a\n // sandbox, so intermediate results stay out of context. A quiet executor\n // backs the in-script tool bridge (same per-tool governance as direct\n // mode). `read_result` is registered after the meta-tools because\n // `code_execute` opts into `'spill-to-file'`, so a large final result can\n // be fetched back on demand. Default `'direct'` mode leaves all of this\n // untouched — `codeModeAdvertised` stays empty and the loop is unchanged.\n const isCodeMode = config.toolInvocation === 'code-mode';\n let codeModeAdvertised: ReadonlyArray<Tool<unknown, unknown, TDeps>> = [];\n if (isCodeMode) {\n const reserved = new Set<string>([\n CODE_EXECUTE_NAME,\n CODE_SEARCH_NAME,\n TOOL_SEARCH_NAME,\n READ_RESULT_NAME,\n ...handoffMap.keys(),\n ]);\n const metas = registerCodeMode(\n toolRegistry,\n makeToolExecutor(toolRegistry, { quiet: true }),\n reserved,\n );\n registerReadResult(toolRegistry, resultReader);\n const readResult = toolRegistry.get(READ_RESULT_NAME);\n codeModeAdvertised = [\n ...metas,\n ...(readResult !== undefined ? [readResult] : []),\n ] as ReadonlyArray<Tool<unknown, unknown, TDeps>>;\n }\n\n const causalityMonitor = config.causalityMonitor\n ? new CausalityMonitor(config.causalityMonitor)\n : undefined;\n\n /**\n * AG-11: one in-flight run per Agent instance. `steer` / `followUp` /\n * `abort` / `compact` address \"the run\" with no run handle, so\n * overlapping runs on one instance cannot be expressed safely — they\n * would share the abort controller, steer queue, active-run ref and\n * executor bridge. A second concurrent `run()` / `stream()` rejects\n * with {@link ConcurrentRunError}; run-scoped state is reset on entry\n * (a steer/abort queued after the previous run ended belongs to NO\n * run) and cleared in a `finally` that also covers abandoned streams\n * (consumer `break`) and thrown runs.\n */\n async function* runLoop(\n input: AgentInput | RunState,\n options: AgentCallOptions<TDeps>,\n ): AsyncGenerator<AgentEvent<TOutput>, AgentResult<TOutput>, void> {\n if (runInFlight) {\n throw new ConcurrentRunError();\n }\n runInFlight = true;\n pendingSteer = [];\n pendingAbort = undefined;\n // AG-10: the causality chain is a per-run artifact — a denial\n // recorded in one run must not poison detection in the next.\n causalityMonitor?.reset();\n try {\n return yield* runLoopInner(input, options);\n } finally {\n runInFlight = false;\n activeRunState = undefined;\n // Backstop for exits that bypass `finishRun` (abandoned stream,\n // generator teardown): settle queued manual compactions so no\n // `agent.compact()` promise is left hanging (CE-3/AG-13).\n while (pendingManualCompacts.length > 0) {\n pendingManualCompacts.shift()?.resolve(noopCompactionResult('no-active-run'));\n }\n }\n }\n\n async function* runLoopInner(\n input: AgentInput | RunState,\n options: AgentCallOptions<TDeps>,\n ): AsyncGenerator<AgentEvent<TOutput>, AgentResult<TOutput>, void> {\n const { seed: rawSeed, resumed } = asMessages(input);\n // AG-12: queued follow-ups are next-turn metadata — they ride into\n // the next FRESH run as leading user turns. The old path mutated a\n // finished run back to 'running' and appended the message to a loop\n // that never processed it, leaving a non-terminal persisted RunState\n // with a dangling user turn. Resumed runs keep the queue intact.\n const seed =\n resumed === undefined && pendingFollowUp.length > 0\n ? [...pendingFollowUp.splice(0, pendingFollowUp.length), ...rawSeed]\n : rawSeed;\n const sessionId = options.sessionId ?? config.sessionId ?? `session_${newId()}`;\n const userId = options.userId ?? config.userId;\n const localCtl = new AbortController();\n abortController = localCtl;\n // AG-5: the loop + every provider request must observe the LOCAL\n // controller, so `agent.abort()` (which aborts `localCtl`) is honoured even\n // when the caller supplied their own `options.signal`. The caller's signal\n // is propagated INTO `localCtl` by the listener below; the listener is torn\n // down in the run's `finally` so it does not accumulate across runs that\n // share one long-lived parent signal.\n const signal = localCtl.signal;\n const parentSignal = options.signal;\n const onParentAbort = (): void => localCtl.abort();\n if (parentSignal !== undefined) {\n if (parentSignal.aborted) localCtl.abort();\n else parentSignal.addEventListener('abort', onParentAbort);\n }\n\n const usageAcc = new InMemoryUsageAccumulator();\n const baseState: RunState = resumed\n ? resumed\n : createInitialRunState({\n id: newId('run'),\n agentId,\n sessionId,\n ...(userId !== undefined ? { userId } : {}),\n });\n // Mutable view (the public RunState is `readonly` but the runtime\n // owns the lifecycle; cast to a writable shape here).\n const state = baseState as RunState as unknown as MutableRunState & RunState;\n activeRunState = state;\n\n // AG-19: rehydrate the run-scoped security state BEFORE any tool runs this\n // resume. Seeding the data-flow ledger with the persisted coarse taint\n // summary keeps an enforce-mode sink gated across the suspend/resume\n // boundary (the promoted-tool set is restored below, once it exists).\n if (resumed && state.taintSummary !== undefined) {\n toolDataFlowGuard?.seedLedger(state.id, state.taintSummary);\n }\n\n const messages: Message[] = resumed ? [...state.messages] : [];\n if (!resumed) {\n // Inject the agent's system prompt at the top of the buffer\n // exactly once per run, before any seed messages.\n const instructionsRaw = config.instructions;\n // AG-8: resolve the function form of `instructions` (sync or async). It is\n // resolved ONCE per run (the per-run contract documented on `AgentConfig`),\n // against a RunContext snapshot at step 0; the result is pinned as the\n // run's system-prompt prefix. A function that previously returned nothing\n // observable now actually seeds the system message.\n let instructionsText: string;\n if (typeof instructionsRaw === 'string') {\n instructionsText = instructionsRaw;\n } else {\n const instructionsCtx: RunContext<TDeps> = {\n runId: state.id,\n sessionId,\n ...(userId !== undefined ? { userId } : {}),\n agentId,\n deps: (options.deps ?? config.deps) as TDeps,\n tracer,\n signal,\n usage: usageAcc,\n stepNumber: 0,\n messages,\n state,\n };\n instructionsText = await instructionsRaw(instructionsCtx);\n }\n let systemPrompt = instructionsText;\n if (config.autoAssembleContext === true && memory !== undefined) {\n // CE-1 (opt-in): build the memory-aware 6-layer system prompt via the\n // context engine. The instructions become Layer 2; the engine prepends\n // the memory base and appends working blocks, procedural rules, skill\n // cards, the metadata counts, and (when `factsAutoRecall` is configured)\n // auto-recalled facts. Default-off keeps the explicit memory-tools\n // pattern, so the system prompt is `instructions` alone.\n const lastUser = lastUserText(seed);\n const assembled = await memory.contextEngine.assemble(memory, {\n scope: { userId: userId ?? agentId, sessionId, agentId },\n agentId,\n sessionId,\n runId: state.id,\n ...(instructionsText.length > 0 ? { agentInstructions: instructionsText } : {}),\n ...(lastUser !== undefined ? { lastUserMessage: lastUser } : {}),\n });\n systemPrompt = assembled.systemMessage.content;\n }\n if (systemPrompt.length > 0) {\n messages.push({ role: 'system', content: systemPrompt });\n }\n messages.push(...seed);\n // Mirror the assembled messages into RunState so the JSONL\n // session export and any downstream consumers see what the\n // agent saw.\n for (const m of messages) state.messages.push(m);\n }\n\n const finalSnapshot: InternalRunSnapshot<TOutput> = {\n output: '' as unknown as TOutput,\n };\n\n yield { type: 'agent.start', runId: state.id, agentId };\n\n // AG-2 / SDF-4: input guardrails screen each fresh-run seed user\n // message (string content) BEFORE the first provider call, using the\n // canonical `@graphorin/security` composer. 'block' fails the run\n // without reaching the model; 'rewrite' replaces the content in both\n // the working buffer and the persisted RunState; 'warn' logs and\n // continues. Resumed runs skip the pass — their seed was screened\n // when first submitted.\n const inputGuards = config.guardrails?.input;\n if (!resumed && inputGuards !== undefined && inputGuards.length > 0) {\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg === undefined || msg.role !== 'user' || typeof msg.content !== 'string') continue;\n const composed = await composeGuardrails(inputGuards, msg.content, {\n stage: 'input',\n runId: state.id,\n sessionId,\n agentId,\n });\n if (!composed.ok) {\n yield {\n type: 'guardrail.tripped',\n guardrailName: composed.name,\n phase: 'input',\n reason: composed.message,\n };\n const message = `input guardrail '${composed.name}' blocked the run: ${composed.message}`;\n yield { type: 'agent.error', error: { message, code: 'guardrail-blocked' } };\n state.status = 'failed';\n state.error = { message, code: 'guardrail-blocked' };\n return yield* finishRun(state, finalSnapshot);\n }\n if (composed.value !== msg.content) {\n const rewritten: Message = { ...msg, content: composed.value };\n const stateIdx = state.messages.indexOf(msg);\n messages[i] = rewritten;\n if (stateIdx !== -1) state.messages[stateIdx] = rewritten;\n }\n }\n }\n\n // AG-3: one per-run JSON instruction for structured output, appended\n // to each provider request (never the shared buffer / RunState).\n const structuredInstruction =\n config.outputType?.kind === 'structured'\n ? buildStructuredInstruction(config.outputType)\n : undefined;\n\n // AG-1: approved gated calls collected from a resume directive, executed\n // for real once every approval is resolved (see the dispatch below).\n const resumedApprovedCalls: ToolCall[] = [];\n // Step-journal: tool calls already completed on a prior resume are recorded\n // in the journal (`state.steps`); a re-resume must not run their side effects\n // again. Collect their ids so an approved call already journaled is replayed,\n // not re-executed (exactly-once; AG-1).\n const journaledCallIds = new Set<string>();\n for (const step of state.steps) {\n for (const completed of step.toolCalls) journaledCallIds.add(completed.call.toolCallId);\n }\n\n // Process resume directive — apply approval decisions to any\n // pending approvals captured in the previous suspend.\n if (\n resumed &&\n options.directive?.approvals !== undefined &&\n state.pendingApprovals.length > 0\n ) {\n const decisions = new Map(options.directive.approvals.map((d) => [d.toolCallId, d]));\n const stillPending: ToolApproval[] = [];\n for (const approval of state.pendingApprovals) {\n const decision = decisions.get(approval.toolCallId);\n if (decision === undefined) {\n stillPending.push(approval);\n continue;\n }\n if (decision.granted) {\n yield {\n type: 'tool.approval.granted',\n toolCallId: approval.toolCallId,\n };\n // Step-journal: if this approved call already ran on a prior resume —\n // journaled in `state.steps` with its result still in the message\n // buffer — replay it instead of running the side effect again\n // (exactly-once across re-resumes). If the journal entry exists but its\n // result message was lost, fall through to a single re-execution (the\n // documented \"at most one re-execution\" bound).\n if (\n journaledCallIds.has(approval.toolCallId) &&\n messages.some((m) => m.role === 'tool' && m.toolCallId === approval.toolCallId)\n ) {\n continue;\n }\n // AG-1: queue the approved call for REAL execution once every\n // approval is resolved (dispatched below). It runs through the same\n // ToolExecutor as any other tool call — taint / audit / result\n // recording — instead of pushing a \"[not actually executed]\"\n // placeholder that left the gated side effect unreachable.\n resumedApprovedCalls.push({\n toolCallId: approval.toolCallId,\n toolName: approval.toolName,\n args: approval.args,\n });\n } else {\n yield {\n type: 'tool.approval.denied',\n toolCallId: approval.toolCallId,\n ...(decision.reason !== undefined ? { reason: decision.reason } : {}),\n };\n messages.push({\n role: 'tool',\n toolCallId: approval.toolCallId,\n content: `Error: tool approval denied${decision.reason ? `: ${decision.reason}` : ''}`,\n });\n state.messages.push({\n role: 'tool',\n toolCallId: approval.toolCallId,\n content: `Error: tool approval denied${decision.reason ? `: ${decision.reason}` : ''}`,\n });\n }\n }\n // Clear the queue + restore the running status so the loop\n // resumes from where it paused.\n state.pendingApprovals.splice(0, state.pendingApprovals.length, ...stillPending);\n if (stillPending.length === 0) {\n state.status = 'running';\n }\n }\n // AG-14: the resumed status is left untouched here. A 'failed' run is NOT\n // silently rewritten to 'completed' (the terminal/suspended guard below\n // returns it as-is); a 'completed' run keeps its status and re-enters the\n // loop for a follow-up; an unresolved 'awaiting_approval' run is caught by\n // that same guard.\n\n // WI-09: pin the trusted system-prompt prefix length now, on the\n // fully-assembled initial buffer, so auto-compaction never rewrites\n // it and prior summaries stay re-compactable (see\n // `countLeadingSystemMessages`).\n const systemPrefixLength = countLeadingSystemMessages(messages);\n\n const runContextBase: RunContext<TDeps> = {\n runId: state.id,\n sessionId,\n ...(userId !== undefined ? { userId } : {}),\n agentId,\n deps: (options.deps ?? config.deps) as TDeps,\n tracer,\n signal,\n usage: usageAcc,\n stepNumber: 0,\n messages,\n state,\n };\n\n // AG-14: a resumed run that is still suspended (`awaiting_approval` with\n // approvals the directive did not resolve) or already terminal-failed must\n // not re-enter the provider loop — that would re-issue a dangling tool_use\n // real providers reject, or silently complete a failed run. Return it as-is.\n if (resumed && (state.status === 'awaiting_approval' || state.status === 'failed')) {\n return yield* finishRun(state, finalSnapshot);\n }\n\n // AG-1: every approval is now resolved (status is 'running'), so execute the\n // approved gated calls for REAL before the provider loop — the model sees\n // their genuine results on the first step. They run through the shared\n // ToolExecutor (taint / audit) and record CompletedToolCalls in a resume\n // step. Dispatching here (outside the loop's approval pre-screen) also means\n // the gated call never re-suspends, so there is no livelock.\n if (resumed && resumedApprovedCalls.length > 0) {\n state.steps.push({\n stepNumber: 0,\n startedAt: new Date().toISOString(),\n endedAt: new Date().toISOString(),\n usage: zeroUsage(),\n toolCalls: [],\n agentId: state.currentAgentId,\n });\n yield* dispatchBatch(\n resumedApprovedCalls,\n toolExecutor,\n { ...runContextBase, stepNumber: 0, messages },\n 0,\n );\n }\n\n // WI-05: deferred tools promoted by a `tool_search` call this run.\n // Membership grows as the model discovers tools and gates which\n // deferred entries the per-step catalogue advertises. TL-7/AG-19:\n // persisted onto `RunState.promotedTools` at suspend and rehydrated\n // below, so a resumed run keeps its discoveries.\n const promotedDeferred = new Set<string>();\n // AG-19: restore deferred tools promoted by `tool_search` before the suspend\n // so they remain in the per-step catalogue after a resume.\n if (resumed && state.promotedTools !== undefined) {\n for (const name of state.promotedTools) promotedDeferred.add(name);\n }\n\n /**\n * Dispatch a batch of (non-handoff) tool calls through the\n * {@link ToolExecutor} and surface the results as `AgentEvent`s.\n *\n * The agent owns the `tool.execute.start` / `.end` / `.error`\n * lifecycle (derived deterministically from the returned\n * {@link CompletedToolCall} outcomes) so every outcome kind —\n * success, unknown-tool, invalid-input, sanitization-blocked,\n * execution error — yields a consistent event and tool message,\n * preserving the pre-WI-03 stream shape (R10). The executor's\n * genuinely-live streaming events (`tool.execute.progress` /\n * `.partial`, emitted only by streaming-hint tools) are bridged\n * through Adapter E while the batch runs and are purely additive.\n *\n * Parallelism (WI-04): the executor runs independent calls in this\n * batch concurrently, bounded by `maxParallelTools`. `tool.execute.start`\n * is emitted up-front in call order and `.end` / `.error` after the\n * batch settles, also in call order — so result mapping and tool-message\n * history are deterministic regardless of which call finishes first,\n * while `.progress` / `.partial` events for concurrent calls interleave\n * (keyed by `toolCallId`). Tools declaring `executionMode: 'sequential'`\n * are serialised by the executor and never overlap.\n */\n async function* dispatchBatch(\n calls: ReadonlyArray<ToolCall>,\n executor: ToolExecutor,\n runContext: RunContext<TDeps>,\n stepNum: number,\n ): AsyncGenerator<AgentEvent<TOutput>, void, void> {\n if (calls.length === 0) return;\n for (const call of calls) {\n yield { type: 'tool.execute.start', toolCallId: call.toolCallId };\n }\n\n const bridge = createExecutorEventBridge();\n activeExecutorBridge = bridge;\n const resultsPromise = executor.executeBatch({ calls, runContext, stepNumber: stepNum });\n // Close the bridge once the batch settles so `drain()` ends; the\n // executor catches per-call errors, so the batch never rejects.\n const closeOnSettle = resultsPromise.then(\n () => bridge.close(),\n () => bridge.close(),\n );\n for await (const event of bridge.drain()) {\n if (event.type === 'tool.execute.progress' || event.type === 'tool.execute.partial') {\n yield event as AgentEvent<TOutput>;\n }\n }\n await closeOnSettle;\n activeExecutorBridge = undefined;\n\n const completed = await resultsPromise;\n const byCallId = new Map(completed.map((c) => [c.outcome.toolCallId, c]));\n const stepEntry = state.steps[state.steps.length - 1];\n for (const call of calls) {\n const result = byCallId.get(call.toolCallId);\n if (result === undefined) continue;\n if (stepEntry !== undefined) {\n (stepEntry.toolCalls as CompletedToolCall[]).push(result);\n }\n const outcome = result.outcome;\n if ('kind' in outcome) {\n yield { type: 'tool.execute.error', toolCallId: call.toolCallId, error: outcome };\n const text = `Error: ${outcome.message}`;\n messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n state.messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n causalityMonitor?.recordCall(`tool.error:${call.toolName}`);\n } else {\n const output = outcome.output;\n yield {\n type: 'tool.execute.end',\n toolCallId: call.toolCallId,\n result: output,\n durationMs: outcome.durationMs,\n };\n // WI-10 (P1-4): when the result spilled to a handle, inline only\n // the bounded preview plus a retrieval hint so the full blob never\n // enters the context window — the model fetches the rest on demand\n // via `read_result`. Inlined results serialise exactly as before\n // (preserves the happy-path message contract, R10).\n const handle = outcome.resultHandle;\n const text =\n handle !== undefined\n ? `${handle.preview}\\n\\n[Full result${\n handle.bytes !== undefined ? ` (${handle.bytes} bytes)` : ''\n } stored behind a handle. Call read_result with handle ${JSON.stringify(\n handle.uri,\n )} to retrieve it — optionally narrow with offset/length (bytes) or startLine/endLine.]`\n : typeof output === 'string'\n ? output\n : JSON.stringify(output);\n messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n state.messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n causalityMonitor?.recordCall(`tool:${call.toolName}`);\n // WI-05: a successful `tool_search` promotes its matches so the\n // catalogue advertises them on the next step.\n if (call.toolName === TOOL_SEARCH_NAME) {\n recordToolSearchPromotions(output, promotedDeferred);\n }\n }\n }\n }\n\n /**\n * Auto-compaction trigger (WI-09 / P1-1). Before assembling each\n * provider request, ask the memory {@link ContextEngine} whether the\n * in-flight buffer has crossed its per-provider threshold\n * (`shouldCompact`); when it has, summarise the older turns\n * (`compactNow`, `source: 'auto-trigger'`), splice the result back in\n * — preserving the byte-stable system prefix and the most-recent\n * turns verbatim — and emit `context.compacted`. The compaction is\n * configured on the memory facade (`createMemory({ contextEngine })`,\n * RB-46); there is no parallel agent-level knob.\n *\n * No-op when no memory is wired, when compaction is disabled or below\n * threshold (the engine returns `false`), or for `secret`-tier runs\n * (secret history is never shipped to the summarizer — a less-trusted\n * external sink; per-result handle references land in WI-10). Best\n * effort: a misconfigured engine (e.g. no summarizer) is swallowed and\n * the run proceeds uncompacted rather than aborting mid-flight.\n *\n * Operator-requested compactions (`agent.compact()`, CE-3/AG-13) are\n * serviced here too, FIRST — the queue carries the `compact()` promise\n * resolvers, and manual requests bypass the trigger evaluation.\n */\n async function* maybeAutoCompact(): AsyncGenerator<AgentEvent<TOutput>, void, void> {\n while (pendingManualCompacts.length > 0) {\n const pending = pendingManualCompacts.shift();\n if (pending !== undefined) yield* serviceManualCompact(pending);\n }\n const mem = memory;\n if (mem === undefined) return;\n // Sensitivity gate (WI-09 step 2): drop, never re-route, secret-tier\n // content. Auto-compaction is an LLM summarizer call, so a secret\n // run is left un-compacted here.\n if (config.sensitivity === 'secret') return;\n const engine = mem.contextEngine;\n const triggered = await engine.shouldCompact(messages).catch(() => false);\n if (!triggered) return;\n\n const startedAt = Date.now();\n const envelope = await engine\n .compactNow({\n scope: { userId: state.userId ?? agentId, sessionId, agentId },\n runId: state.id,\n sessionId,\n agentId,\n source: 'auto-trigger',\n messages: messages.slice(systemPrefixLength),\n memory: mem,\n })\n // No summarizer configured (or the strategy threw) — proceed with\n // the un-compacted buffer rather than failing a live run.\n .catch(() => undefined);\n if (envelope === undefined) return;\n // Nothing was old enough to trim (body ≤ preserve-recent) — skip the\n // splice + event so `context.compacted` only fires on real work.\n if (envelope.result.droppedMessageIndices.length === 0) return;\n\n spliceCompacted(envelope);\n yield {\n type: 'context.compacted',\n runId: state.id,\n sessionId,\n agentId,\n beforeTokens: envelope.result.beforeTokens,\n afterTokens: envelope.result.afterTokens,\n summaryTokens: envelope.result.summaryTokens,\n durationMs: Date.now() - startedAt,\n source: 'auto-trigger',\n hooksFiredCount: envelope.result.hooksFiredCount,\n };\n }\n\n /**\n * Prefix-pinned splice shared by the auto + manual compaction paths\n * (CE-3): stable system prefix + [summary, ...recent turns], with the\n * post-compaction hooks' text Context Essentials re-anchored as a\n * trailing system message so they survive the trim (RB-46). Mutates\n * BOTH the live loop buffer and `state.messages`.\n */\n function spliceCompacted(envelope: CompactionEnvelope): void {\n const prefix = messages.slice(0, systemPrefixLength);\n const rebuilt: Message[] = [...prefix, ...envelope.result.trimmedMessages];\n const essentials = envelope.extraContent\n .map((part) =>\n typeof part === 'object' && part !== null && 'text' in part\n ? String((part as { readonly text: unknown }).text)\n : '',\n )\n .filter((text) => text.length > 0)\n .join('\\n\\n');\n if (essentials.length > 0) {\n rebuilt.push({ role: 'system', content: essentials });\n }\n messages.splice(0, messages.length, ...rebuilt);\n state.messages.splice(0, state.messages.length, ...rebuilt);\n }\n\n /**\n * Service one `agent.compact()` request inside the loop (CE-3/AG-13):\n * same prefix-pinned splice as the auto path, `source: 'manual'` (or\n * the caller's `'pre-step'`), `preserveRecentTurns` forwarded as a\n * per-call strategy override. An engine failure rejects the caller's\n * promise but never aborts the live run; a summarize that trims\n * nothing resolves `applied: false` without an event.\n */\n async function* serviceManualCompact(\n pending: PendingManualCompact,\n ): AsyncGenerator<AgentEvent<TOutput>, void, void> {\n const mem = memory;\n if (mem === undefined) {\n pending.resolve(noopCompactionResult('no-memory'));\n return;\n }\n const source = pending.options?.source ?? 'manual';\n const startedAt = Date.now();\n let envelope: CompactionEnvelope;\n try {\n envelope = await mem.contextEngine.compactNow({\n scope: { userId: state.userId ?? agentId, sessionId, agentId },\n runId: state.id,\n sessionId,\n agentId,\n source,\n messages: messages.slice(systemPrefixLength),\n memory: mem,\n ...(pending.options?.preserveRecentTurns !== undefined\n ? { preserveRecentTurns: pending.options.preserveRecentTurns }\n : {}),\n });\n } catch (cause) {\n pending.reject(cause);\n return;\n }\n const { result } = envelope;\n const applied = result.droppedMessageIndices.length > 0;\n if (applied) {\n spliceCompacted(envelope);\n yield {\n type: 'context.compacted',\n runId: state.id,\n sessionId,\n agentId,\n beforeTokens: result.beforeTokens,\n afterTokens: result.afterTokens,\n summaryTokens: result.summaryTokens,\n durationMs: Date.now() - startedAt,\n source,\n hooksFiredCount: result.hooksFiredCount,\n };\n }\n pending.resolve({\n beforeTokens: result.beforeTokens,\n afterTokens: result.afterTokens,\n summaryTokens: result.summaryTokens,\n durationMs: Date.now() - startedAt,\n hooksFiredCount: result.hooksFiredCount,\n summary: result.summary ?? '',\n applied,\n ...(applied ? {} : { skippedReason: 'nothing-to-trim' as const }),\n });\n }\n\n const handoffNames = Array.from(handoffMap.keys());\n let stepNumber = 0;\n // AG-15: tools the model actually called on the PREVIOUS step — the\n // per-tool preferred-model ladder consults these, never the full\n // advertised catalogue.\n let lastStepCalledToolNames: ReadonlyArray<string> = [];\n\n // AG-6: shared cancellation path for both the loop-top abort check and a\n // mid-stream provider abort. Yields `agent.cancelling`, applies the\n // `onPendingApprovals` policy, and returns `true` when the run was finalized\n // as 'failed' (the 'fail' policy — the caller must `return finalize(...)`);\n // otherwise it sets `state.status = 'aborted'` and returns `false`.\n async function* emitCancellation(): AsyncGenerator<AgentEvent<TOutput>, boolean, void> {\n yield {\n type: 'agent.cancelling',\n runId: state.id,\n drain: pendingAbort?.drain ?? false,\n onPendingApprovals: pendingAbort?.onPendingApprovals ?? 'deny',\n };\n const policy = pendingAbort?.onPendingApprovals ?? 'deny';\n if (policy === 'deny') {\n const drained = state.pendingApprovals.splice(0, state.pendingApprovals.length);\n for (const approval of drained) {\n yield {\n type: 'tool.approval.denied',\n toolCallId: approval.toolCallId,\n reason: 'auto-denied: agent.abort()',\n };\n }\n } else if (policy === 'fail') {\n state.status = 'failed';\n state.error = { message: 'aborted with pending approvals', code: 'run-aborted' };\n yield {\n type: 'agent.error',\n error: { message: 'aborted with pending approvals', code: 'run-aborted' },\n };\n return true;\n }\n state.status = 'aborted';\n return false;\n }\n\n try {\n while (!stopWhen.check(state)) {\n // Drain any externally-queued lifecycle events\n // (`agent.steered`, `agent.followup.queued`).\n while (externalEventQueue.length > 0) {\n const ev = externalEventQueue.shift();\n if (ev !== undefined) yield ev;\n }\n if (signal.aborted) {\n if (yield* emitCancellation()) return yield* finishRun(state, finalSnapshot);\n break;\n }\n stepNumber += 1;\n const stepStart = new Date().toISOString();\n\n // Drain steering queue.\n if (pendingSteer.length > 0) {\n for (const m of pendingSteer) {\n messages.push(m);\n state.messages.push(m);\n }\n pendingSteer = [];\n }\n\n yield { type: 'step.start', stepNumber };\n\n // WI-09 (P1-1): bound context growth before the provider call.\n // Fires `context.compacted` and rewrites the buffer in place only\n // when the memory ContextEngine's trigger crosses threshold; a\n // no-memory / below-threshold / secret-tier step is a no-op, so\n // the happy-path event stream is unchanged (R10).\n yield* maybeAutoCompact();\n\n const stepCtx: RunContext<TDeps> = { ...runContextBase, stepNumber, messages };\n const overrides = config.prepareStep ? await config.prepareStep(stepCtx) : {};\n\n // Resolve the registry + executor for this step. The warm-up\n // pair is bound to config.tools + skills; a `prepareStep` tool\n // override builds a step-scoped pair so the advertised catalogue\n // and the executor agree on the same tool set (incl. deferred\n // discovery for the overridden set). Code-mode does not honour a\n // per-step `tools` override (the meta-tools + bridge are bound to\n // the warm-up registry), so it always uses the warm-up pair.\n const useOverrideRegistry = overrides.tools !== undefined && !isCodeMode;\n const stepRegistry: ToolRegistry = useOverrideRegistry\n ? buildToolRegistry({\n tools: overrides.tools as ReadonlyArray<Tool<unknown, unknown, unknown>>,\n }).registry\n : toolRegistry;\n if (useOverrideRegistry) {\n registerToolSearch(stepRegistry);\n registerReadResult(stepRegistry, resultReader);\n }\n const stepExecutor: ToolExecutor = useOverrideRegistry\n ? makeToolExecutor(stepRegistry)\n : toolExecutor;\n\n // Build the per-step tool catalogue. Handoff tools are synthetic\n // per-step entries and are always advertised.\n const handoffTools: Tool<unknown, unknown, TDeps>[] = handoffNames.map((n) => {\n const h = handoffMap.get(n);\n if (h === undefined) throw new ToolNotFoundError(n);\n return buildHandoffTool<TDeps>(h.agent);\n });\n // Code-mode (WI-11): advertise only the `code_search` /\n // `code_execute` (+ `read_result`) meta-tools — the model reaches\n // every real tool through `code_execute`, so the real tools stay\n // registered (executable via the in-script bridge) but out of the\n // model's catalogue. Otherwise (WI-05): advertise the eager tools\n // (`tool_search` is itself eager iff a deferred tool exists) plus\n // any deferred tools already promoted by a `tool_search` this run —\n // never the rest of the deferred pool.\n let stepTools: ReadonlyArray<Tool<unknown, unknown, TDeps>>;\n if (isCodeMode) {\n stepTools = [...codeModeAdvertised, ...handoffTools];\n } else {\n const eagerTools = stepRegistry.listEager() as ReadonlyArray<\n Tool<unknown, unknown, TDeps>\n >;\n // A7: emit promoted deferred tools in PROMOTION order (append-only) so\n // a later promotion joins the END and the prompt-cache prefix (eager\n // tools + earlier promotions) stays byte-stable across steps.\n const promotedTools = (\n promotedDeferred.size === 0\n ? []\n : orderPromotedTools(promotedDeferred, stepRegistry.listDeferred())\n ) as ReadonlyArray<Tool<unknown, unknown, TDeps>>;\n stepTools = [...eagerTools, ...promotedTools, ...handoffTools];\n }\n\n // AG-15: consult the hints of the tools the model CALLED on the\n // previous step — a smart-hinted but never-called tool must not\n // pin the whole conversation to the top cost tier. Steps with no\n // prior calls fall through to the agent-preferred default.\n const calledLastStep = new Set(lastStepCalledToolNames);\n const toolPreferences = stepTools\n .filter((t) => calledLastStep.has(t.name))\n .map((t) => {\n const tt = t as Tool<unknown, unknown, TDeps> & { readonly preferredModel?: unknown };\n return tt.preferredModel as Parameters<\n typeof resolvePreferredModel\n >[0]['toolPreferredModels'][number];\n });\n\n const primary: PreferredModelResolution = resolvePreferredModel({\n ...(overrides.provider !== undefined ? { prepareStepProvider: overrides.provider } : {}),\n toolPreferredModels: toolPreferences,\n ...(config.preferredModel !== undefined\n ? { agentPreferredModel: config.preferredModel }\n : {}),\n agentDefaultProvider: config.provider,\n ...(config.modelTierMap !== undefined ? { modelTierMap: config.modelTierMap } : {}),\n });\n\n // RB-48: when `prepareStep` returns an explicit provider\n // override, the fallback chain is NOT consulted for this\n // step (the operator's explicit choice supersedes the\n // implicit fallback chain).\n const fallbackChain: Provider[] =\n primary.source === 'prepare-step'\n ? [primary.resolvedProvider]\n : [primary.resolvedProvider, ...(config.fallbackModels ?? []).map(specToProvider)];\n\n // Resolve the effective reasoning-retention policy for\n // this step (RB-42). Drop any buffered reasoning when the\n // contract downgrades to `'strip'`.\n const reasoningPolicy = effectiveReasoningRetention(\n config.reasoningRetention,\n primary.resolvedProvider,\n );\n if (reasoningPolicy === 'strip') {\n const { stripped } = stripReasoningFromMessages(messages);\n // Mirror the strip into RunState so the persisted state\n // matches the in-flight buffer.\n if (stripped > 0) {\n // The structural drop is bytes-equal across `messages`\n // and `state.messages` (both arrays carry the same\n // references); re-strip RunState explicitly to be safe.\n stripReasoningFromMessages(state.messages);\n }\n }\n\n const toolDefs: ReadonlyArray<ToolDefinition> = stepTools.map((t) =>\n toolToDefinition(t as Tool<unknown, unknown, unknown>),\n );\n\n const baseRequest: ProviderRequest = {\n // AG-3 fallback contract: for structured output the request\n // carries ONE trailing system instruction (JSON-only + schema)\n // in the request copy — never in the shared buffer or the\n // persisted RunState. Adapters with native structured output\n // additionally receive `outputType` below (PS-24 consumes it).\n messages:\n structuredInstruction === undefined\n ? messages\n : [...messages, { role: 'system' as const, content: structuredInstruction }],\n ...(config.outputType !== undefined\n ? {\n outputType: {\n kind: config.outputType.kind,\n ...(config.outputType.description !== undefined\n ? { description: config.outputType.description }\n : {}),\n ...(config.outputType.jsonSchema !== undefined\n ? { jsonSchema: config.outputType.jsonSchema }\n : {}),\n },\n }\n : {}),\n tools: toolDefs,\n ...(overrides.toolChoice !== undefined\n ? { toolChoice: overrides.toolChoice }\n : config.toolChoice !== undefined\n ? { toolChoice: config.toolChoice as ToolChoice }\n : {}),\n metadata: {\n sessionId,\n agentId,\n ...(userId !== undefined ? { userId } : {}),\n runId: state.id,\n stepNumber,\n },\n signal,\n ...(overrides.temperature !== undefined ? { temperature: overrides.temperature } : {}),\n ...(overrides.maxTokens !== undefined ? { maxTokens: overrides.maxTokens } : {}),\n reasoningRetention: reasoningPolicy,\n };\n\n const stepUsage: Usage = zeroUsage();\n let attempt = 0;\n let textBuffer = '';\n let providerForStep = primary.resolvedProvider;\n let lastModelId = primary.resolvedModelId;\n let modelSucceeded = false;\n let lastError: ProviderError | undefined;\n let finalCalls: ToolCall[] = [];\n let stepReasoningParts: ReasoningContent[] = [];\n\n for (let chainIdx = 0; chainIdx < fallbackChain.length; chainIdx++) {\n const candidate = fallbackChain[chainIdx];\n if (candidate === undefined) continue;\n providerForStep = candidate;\n const providerModelId = providerForStep.modelId;\n if (chainIdx > 0) {\n attempt += 1;\n const reason = lastError\n ? (isAgentFallbackEligible(lastError, fallbackPolicy).reason ?? 'transient')\n : 'transient';\n yield {\n type: 'agent.model.fellback',\n runId: state.id,\n sessionId,\n agentId,\n from: lastModelId,\n to: providerModelId,\n reason,\n stepNumber,\n attempt,\n };\n lastModelId = providerModelId;\n }\n const evState: ProviderEventCollector = {\n textBuffer: '',\n reasoningBuffer: '',\n reasoningParts: [],\n calls: new Map<string, ToolCallAccumulator>(),\n finalCalls: [] as ToolCall[],\n };\n let providerError: ProviderError | undefined;\n let providerCallCompleted = false;\n let providerStepUsage: Usage = zeroUsage();\n try {\n const stream = providerForStep.stream(baseRequest);\n for await (const ev of stream) {\n // AG-6 `drain`: the default hard-kills the in-flight provider\n // stream mid-event; `abort({ drain: true })` instead lets the\n // current step finish (the documented \"wait for the current step\n // to complete\") and stops gracefully at the next loop-top check.\n if (signal.aborted && pendingAbort?.drain !== true) {\n throw new AgentRuntimeError('run-aborted', 'aborted');\n }\n const out = handleProviderEvent(ev, evState);\n if (out.emit !== undefined) {\n yield out.emit as AgentEvent<TOutput>;\n }\n if (out.providerError !== undefined) {\n providerError = out.providerError;\n }\n if (out.usage !== undefined) {\n providerStepUsage = {\n promptTokens: providerStepUsage.promptTokens + out.usage.promptTokens,\n completionTokens: providerStepUsage.completionTokens + out.usage.completionTokens,\n totalTokens: providerStepUsage.totalTokens + out.usage.totalTokens,\n ...(out.usage.reasoningTokens !== undefined ||\n providerStepUsage.reasoningTokens !== undefined\n ? {\n reasoningTokens:\n (providerStepUsage.reasoningTokens ?? 0) +\n (out.usage.reasoningTokens ?? 0),\n }\n : {}),\n };\n }\n if (out.finished === true) providerCallCompleted = true;\n }\n } catch (cause) {\n // AG-6: a mid-stream abort (our run-aborted sentinel, or any error\n // once the signal is aborted — e.g. a native AbortError from the\n // provider) is NOT a provider failure. Break out of the fallback\n // chain WITHOUT a providerError; the post-stream abort check below\n // ends the run as 'aborted', never 'no-provider-completed'. Don't\n // continue the fallback chain against an already-aborted signal.\n if (\n signal.aborted ||\n (cause instanceof AgentRuntimeError && cause.code === 'run-aborted')\n ) {\n break;\n }\n const message = cause instanceof Error ? cause.message : String(cause);\n // AG-21: preserve the thrown error's kind (e.g. a RateLimitExceededError\n // from `withRateLimit`) so the fallback chain treats it like the same\n // error emitted as a structured event, instead of flattening it to\n // an always-ineligible 'unknown'.\n providerError = { kind: classifyThrownProviderErrorKind(cause), message, cause };\n }\n if (providerError !== undefined) {\n lastError = providerError;\n const eligibility = isAgentFallbackEligible(providerError, fallbackPolicy);\n if (!eligibility.eligible || chainIdx === fallbackChain.length - 1) {\n yield {\n type: 'agent.error',\n error: { message: providerError.message, code: providerError.kind },\n };\n state.status = 'failed';\n state.error = { message: providerError.message, code: providerError.kind };\n return yield* finishRun(state, finalSnapshot);\n }\n continue;\n }\n if (providerCallCompleted) {\n modelSucceeded = true;\n textBuffer = evState.textBuffer;\n finalCalls = evState.finalCalls;\n // Materialize the streamed reasoning deltas into a\n // single `ReasoningContent` part. Adapters that expose\n // structured reasoning blocks may emit multiple\n // deltas; v0.1 collapses them into one part — Phase\n // 06 owns the per-block structure when it lands.\n if (evState.reasoningBuffer.length > 0) {\n stepReasoningParts = [\n {\n type: 'reasoning',\n text: evState.reasoningBuffer,\n },\n ];\n }\n stepUsage.promptTokens += providerStepUsage.promptTokens;\n stepUsage.completionTokens += providerStepUsage.completionTokens;\n stepUsage.totalTokens += providerStepUsage.totalTokens;\n if (providerStepUsage.reasoningTokens !== undefined) {\n stepUsage.reasoningTokens =\n (stepUsage.reasoningTokens ?? 0) + providerStepUsage.reasoningTokens;\n }\n break;\n }\n }\n\n // AG-6: a mid-stream abort that interrupted the stream (no completed\n // model) ends the run as a cancellation ('aborted', or 'failed' under\n // the `onPendingApprovals: 'fail'` policy) rather than falling through\n // to a 'no-provider-completed' failure. When the model DID complete\n // (e.g. `drain: true` let the step finish), fall through so the step's\n // tool calls run and the graceful stop happens at the loop top.\n if (signal.aborted && !modelSucceeded) {\n yield* emitCancellation();\n return yield* finishRun(state, finalSnapshot);\n }\n\n if (!modelSucceeded) {\n yield {\n type: 'agent.error',\n error: {\n message: 'all configured providers failed without finishing',\n code: 'no-provider-completed',\n },\n };\n state.status = 'failed';\n state.error = { message: 'no provider completed', code: 'no-provider-completed' };\n return yield* finishRun(state, finalSnapshot);\n }\n\n usageAcc.add(lastModelId, stepUsage);\n addModelUsage(state, lastModelId, stepUsage);\n state.usage.promptTokens += stepUsage.promptTokens;\n state.usage.completionTokens += stepUsage.completionTokens;\n state.usage.totalTokens += stepUsage.totalTokens;\n if (stepUsage.reasoningTokens !== undefined) {\n state.usage.reasoningTokens =\n (state.usage.reasoningTokens ?? 0) + stepUsage.reasoningTokens;\n }\n\n // Lateral-leak (RB-55 / AG-10): scan the outgoing assistant\n // content BEFORE it is appended, so a 'block' decision keeps\n // the laundered commentary out of the durable history — and\n // therefore out of every subsequent provider request. The\n // deltas already streamed; what 'block' protects is the\n // persistent buffer and the run's final output.\n const leakCheck =\n causalityMonitor !== undefined && textBuffer.length > 0\n ? causalityMonitor.checkMessage(textBuffer)\n : undefined;\n const leakBlocked = leakCheck?.leakDetected === true && leakCheck.decision === 'block';\n\n const assistant: AssistantMessage = buildAssistantMessage(\n leakBlocked ? LATERAL_LEAK_BLOCKED_NOTICE : textBuffer,\n stepReasoningParts,\n finalCalls,\n agentId,\n reasoningPolicy,\n );\n messages.push(assistant);\n state.messages.push(assistant);\n\n if (leakCheck?.leakDetected === true) {\n const sha = sha256Hex(textBuffer);\n yield {\n type: 'agent.lateral-leak.detected',\n runId: state.id,\n sessionId,\n agentId,\n vector: leakCheck.vector,\n severity: leakCheck.severity,\n causalityChain: leakCheck.causalityChain,\n messageContentSha256: sha,\n ...(leakCheck.matchedPattern !== undefined\n ? { matchedPattern: leakCheck.matchedPattern }\n : {}),\n decision: leakCheck.decision,\n detectedAtIso: new Date().toISOString(),\n };\n }\n\n const handoffCalls = finalCalls.filter((c) => handoffMap.has(c.toolName));\n if (handoffCalls.length > 1) {\n throw new MultipleHandoffsInStepError(handoffCalls.map((c) => c.toolName));\n }\n\n const stepRecord: RunStep = {\n stepNumber,\n startedAt: stepStart,\n endedAt: new Date().toISOString(),\n usage: stepUsage,\n toolCalls: [],\n agentId: state.currentAgentId,\n };\n state.steps.push(stepRecord);\n lastStepCalledToolNames = finalCalls.map((c) => c.toolName);\n\n if (textBuffer.length > 0 && !leakBlocked) {\n finalSnapshot.output = textBuffer as unknown as TOutput;\n yield { type: 'text.complete', text: textBuffer };\n }\n\n if (finalCalls.length > 0) {\n // `stepRegistry` / `stepExecutor` were resolved with the\n // catalogue above (so the advertised tools and the executor's\n // resolvable tools agree, including any `prepareStep` override).\n const execRunContext: RunContext<TDeps> = { ...runContextBase, stepNumber, messages };\n\n // Walk calls in finalCalls order. Handoffs are special-cased\n // inline (≤1 per step) and never routed through the executor.\n // Non-handoff calls accumulate into a batch dispatched through\n // the ToolExecutor; the batch is flushed before a handoff and\n // before a durable-HITL suspend so execution order is kept.\n let batch: ToolCall[] = [];\n\n for (const call of finalCalls) {\n const handoff = handoffMap.get(call.toolName);\n if (handoff !== undefined) {\n if (batch.length > 0) {\n yield* dispatchBatch(batch, stepExecutor, execRunContext, stepNumber);\n batch = [];\n }\n yield { type: 'tool.execute.start', toolCallId: call.toolCallId };\n const filter = (handoff.filter ??\n filterLib.defaultHandoffFilter()) as DescribedFilter;\n const filtered = filter(messages);\n const targetId = handoff.agent.id;\n // The secrets fields record the structural reality: no\n // inheritance mechanism exists at this boundary, so the\n // target receives nothing — an empty allowlist is the\n // factually-true provenance (AG-17).\n const handoffRec: HandoffRecord = {\n fromAgentId: agentId,\n toAgentId: targetId,\n stepNumber,\n at: new Date().toISOString(),\n inputFilter: filter.descriptor,\n secretsInheritance: 'inherit-allowlist',\n inheritedSecrets: [],\n };\n state.handoffs.push(handoffRec);\n yield { type: 'handoff', fromAgentId: agentId, toAgentId: targetId };\n state.currentAgentId = targetId;\n const subAgent = handoff.agent;\n // AG-22: the sub-agent inherits the parent's abort signal,\n // deps, and sessionId; its terminal `agent.end` is observed\n // so a failed/aborted sub-run surfaces as a TOOL ERROR —\n // never an empty-string success with durationMs 0.\n const subStart = Date.now();\n const subOutputs: string[] = [];\n let subResult: AgentResult<unknown> | undefined;\n const subStream = subAgent.stream(filtered as Message[], {\n signal,\n ...(options.deps !== undefined || config.deps !== undefined\n ? { deps: (options.deps ?? config.deps) as TDeps }\n : {}),\n sessionId,\n });\n for await (const subEv of subStream) {\n if (subEv.type === 'text.complete') subOutputs.push(subEv.text);\n else if (subEv.type === 'agent.end') {\n subResult = subEv.result as AgentResult<unknown>;\n }\n }\n const subDurationMs = Date.now() - subStart;\n const stepEntry = state.steps[state.steps.length - 1];\n if (subResult !== undefined && subResult.status !== 'completed') {\n const toolError: ToolError = {\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n kind: subResult.status === 'aborted' ? 'aborted' : 'execution_failed',\n message: `handoff to '${targetId}' ${subResult.status}${\n subResult.error !== undefined ? `: ${subResult.error.message}` : ''\n }`,\n };\n if (stepEntry !== undefined) {\n (stepEntry.toolCalls as CompletedToolCall[]).push({\n call,\n outcome: toolError,\n stepNumber,\n });\n }\n yield {\n type: 'tool.execute.error',\n toolCallId: call.toolCallId,\n error: toolError,\n };\n const text = `Error: ${toolError.message}`;\n messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n state.messages.push({ role: 'tool', toolCallId: call.toolCallId, content: text });\n continue;\n }\n const result = subOutputs.join('');\n const completed: CompletedToolCall = {\n call,\n outcome: {\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n output: result,\n durationMs: subDurationMs,\n },\n stepNumber,\n };\n if (stepEntry !== undefined) {\n (stepEntry.toolCalls as CompletedToolCall[]).push(completed);\n }\n yield {\n type: 'tool.execute.end',\n toolCallId: call.toolCallId,\n result,\n durationMs: subDurationMs,\n };\n messages.push({ role: 'tool', toolCallId: call.toolCallId, content: result });\n state.messages.push({\n role: 'tool',\n toolCallId: call.toolCallId,\n content: result,\n });\n continue;\n }\n\n // Approval pre-screen (Adapter G / durable HITL). Evaluate the\n // registry-resolved `needsApproval`; an unapproved gated call\n // suspends the run exactly as before — after flushing any\n // queued batch so prior calls' side-effects complete first.\n const resolvedTool = stepRegistry.get(call.toolName);\n const needsApproval = await invokeNeedsApproval(\n resolvedTool,\n call.args,\n execRunContext,\n signal,\n );\n if (needsApproval) {\n if (batch.length > 0) {\n yield* dispatchBatch(batch, stepExecutor, execRunContext, stepNumber);\n batch = [];\n }\n yield { type: 'tool.execute.start', toolCallId: call.toolCallId };\n const approval: ToolApproval = {\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n args: call.args,\n requestedAt: new Date().toISOString(),\n };\n state.pendingApprovals.push(approval);\n state.status = 'awaiting_approval';\n // AG-19: persist the coarse taint summary + promoted-tool set into\n // the suspended state so a resume rehydrates the sink gate and the\n // discovered-tool catalogue instead of starting empty.\n const taintSnap = toolDataFlowGuard?.snapshotLedger(state.id);\n if (taintSnap !== undefined) state.taintSummary = taintSnap;\n if (promotedDeferred.size > 0) state.promotedTools = [...promotedDeferred];\n yield {\n type: 'tool.approval.requested',\n toolCallId: call.toolCallId,\n };\n if (config.checkpointStore !== undefined) {\n await config.checkpointStore.put(\n state.id,\n 'agent',\n {\n id: state.id,\n threadId: state.id,\n namespace: 'agent',\n // AG-23: persist a detached, secret-redacted snapshot —\n // never the live MutableRunState reference.\n state: serializeRunState(state, { stripTracingApiKey: true }),\n channelVersions: {},\n stepNumber,\n createdAt: new Date().toISOString(),\n },\n { source: 'sync', status: 'suspended', nodeName: 'agent.run' },\n );\n }\n return yield* finishRun(state, finalSnapshot);\n }\n\n batch.push(call);\n }\n\n if (batch.length > 0) {\n yield* dispatchBatch(batch, stepExecutor, execRunContext, stepNumber);\n }\n }\n\n yield { type: 'step.end', stepNumber, usage: stepUsage };\n\n if (finalCalls.length === 0) {\n state.status = 'completed';\n break;\n }\n }\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n const code = cause instanceof AgentRuntimeError ? (cause.code as string) : 'unknown';\n yield { type: 'agent.error', error: { message, code } };\n state.status = 'failed';\n state.error = { message, code };\n return yield* finishRun(state, finalSnapshot);\n } finally {\n // AG-5: drop the parent-signal listener so it does not accumulate across\n // runs that share one long-lived `options.signal`. Runs after this point\n // (the follow-up loop) keep working via `agent.abort()` on `localCtl`.\n if (parentSignal !== undefined) {\n parentSignal.removeEventListener('abort', onParentAbort);\n }\n }\n\n if (state.status === 'running') {\n // AG-24: the loop exited via the stop condition (default\n // isStepCount(50)) with work still pending — that is a CUT run,\n // not a completion. Surface it as a typed failure so consumers\n // can tell it apart from a clean finish.\n const message = `run stopped by stop condition: ${stopWhen.description}`;\n state.status = 'failed';\n state.error = { message, code: 'stop-condition' };\n yield { type: 'agent.error', error: { message, code: 'stop-condition' } };\n }\n // AG-3: structured output is parsed + validated on the completed\n // path — a failure is a typed run failure (`output-validation-failed`),\n // never a silent text-cast. Runs BEFORE output guardrails so they\n // screen the PARSED value.\n if (state.status === 'completed' && config.outputType?.kind === 'structured') {\n const raw = String(finalSnapshot.output ?? '');\n try {\n const parsed: unknown = JSON.parse(stripJsonFence(raw));\n finalSnapshot.output = (\n config.outputType.schema !== undefined ? config.outputType.schema.parse(parsed) : parsed\n ) as TOutput;\n } catch (cause) {\n const message = `structured output validation failed: ${\n cause instanceof Error ? cause.message : String(cause)\n }`;\n yield { type: 'agent.error', error: { message, code: 'output-validation-failed' } };\n state.status = 'failed';\n state.error = { message, code: 'output-validation-failed' };\n }\n }\n\n // AG-2 / SDF-4: output guardrails screen the final output on the\n // completed path before `agent.end`. 'block' fails the run;\n // 'rewrite' replaces the durable result (`result.output`) — the\n // text deltas were already streamed, so the rewrite governs what\n // is persisted/returned, not the live token stream.\n const outputGuards = config.guardrails?.output;\n if (state.status === 'completed' && outputGuards !== undefined && outputGuards.length > 0) {\n const composed = await composeGuardrails(outputGuards, finalSnapshot.output, {\n stage: 'output',\n runId: state.id,\n sessionId,\n agentId,\n });\n if (!composed.ok) {\n yield {\n type: 'guardrail.tripped',\n guardrailName: composed.name,\n phase: 'output',\n reason: composed.message,\n };\n const message = `output guardrail '${composed.name}' blocked the run: ${composed.message}`;\n yield { type: 'agent.error', error: { message, code: 'guardrail-blocked' } };\n state.status = 'failed';\n state.error = { message, code: 'guardrail-blocked' };\n } else if (composed.value !== finalSnapshot.output) {\n finalSnapshot.output = composed.value;\n }\n }\n activeRunState = undefined;\n return yield* finishRun(state, finalSnapshot);\n }\n\n /**\n * Terminal wrapper around {@link finalize}: every exit path of the run\n * loop — completed, failed, aborted, suspended — ends the stream with\n * an `agent.end` event carrying the final {@link AgentResult} (AG-20).\n */\n async function* finishRun(\n state: MutableRunState,\n snapshot: InternalRunSnapshot<TOutput>,\n ): AsyncGenerator<AgentEvent<TOutput>, AgentResult<TOutput>, void> {\n // CE-3/AG-13: settle manual-compact requests the loop never serviced —\n // the run is over, there is no live buffer left to splice.\n while (pendingManualCompacts.length > 0) {\n pendingManualCompacts.shift()?.resolve(noopCompactionResult('no-active-run'));\n }\n const result = finalize(state, snapshot);\n // TL-10: spill artifacts are run-scoped scratch — drop them once the\n // run is terminal. `awaiting_approval` and `aborted` runs keep\n // theirs (handles must survive resume); orphans fall to the writer's\n // startup TTL sweep.\n if (result.status === 'completed' || result.status === 'failed') {\n await spillWriter.clear?.(result.state.id).catch(() => {});\n }\n yield { type: 'agent.end', runId: result.state.id, result };\n return result;\n }\n\n function finalize(\n state: MutableRunState,\n snapshot: InternalRunSnapshot<TOutput>,\n ): AgentResult<TOutput> {\n state.finishedAt = state.finishedAt ?? new Date().toISOString();\n // AG-9: the result carries the terminal status, the failure (when\n // any), and the final RunState — a suspended run is resumable from\n // the result alone, no checkpointStore required.\n return {\n output: snapshot.output,\n usage: state.usage,\n status: state.status,\n ...(state.error !== undefined ? { error: state.error } : {}),\n state: state as unknown as RunState,\n };\n }\n\n const stream = (\n input: AgentInput | RunState,\n options?: AgentCallOptions<TDeps>,\n ): AsyncIterable<AgentEvent<TOutput>> => {\n const opts = options ?? {};\n return {\n [Symbol.asyncIterator]: () => {\n const gen = runLoop(input, opts);\n return {\n async next(): Promise<IteratorResult<AgentEvent<TOutput>, void>> {\n const r = await gen.next();\n if (r.done === true) {\n return { done: true, value: undefined };\n }\n return { done: false, value: r.value };\n },\n async return(): Promise<IteratorResult<AgentEvent<TOutput>, void>> {\n await gen.return(undefined as unknown as AgentResult<TOutput>);\n return { done: true, value: undefined };\n },\n };\n },\n };\n };\n\n const run = async (\n input: AgentInput | RunState,\n options?: AgentCallOptions<TDeps>,\n ): Promise<AgentResult<TOutput>> => {\n const opts = options ?? {};\n const gen = runLoop(input, opts);\n let next = await gen.next();\n while (next.done !== true) {\n next = await gen.next();\n }\n // Every terminal path of the run loop returns `finalize(...)`; an\n // undefined return value would mean the generator was torn down\n // externally — an invariant violation, not a run outcome (AG-9).\n const result = next.value;\n if (result === undefined) {\n throw new Error('unreachable: agent run loop ended without a result');\n }\n return result;\n };\n\n const steer = (message: AgentInput): void => {\n const { seed } = asMessages(message);\n pendingSteer.push(...seed);\n if (activeRunState !== undefined) {\n externalEventQueue.push({\n type: 'agent.steered',\n runId: activeRunState.id,\n } as AgentEvent<TOutput>);\n }\n };\n\n const followUp = (message: AgentInput): void => {\n const { seed } = asMessages(message);\n pendingFollowUp.push(...seed);\n if (activeRunState !== undefined) {\n externalEventQueue.push({\n type: 'agent.followup.queued',\n runId: activeRunState.id,\n } as AgentEvent<TOutput>);\n }\n };\n\n const abort = (options?: AbortOptions): void => {\n pendingAbort = options ?? {};\n abortController?.abort();\n };\n\n const toTool = (\n options: AgentToToolOptions = {},\n ): Tool<{ readonly input: string }, TOutput, TDeps> => {\n const exposeTurns = options.exposeTurns ?? 'final';\n const toolName = options.name ?? `subagent_${config.name}`;\n const description = options.description ?? `Invoke sub-agent '${config.name}'.`;\n const schema = {\n parse: (v: unknown): { readonly input: string } => v as { readonly input: string },\n safeParse: (v: unknown) => ({\n success: true as const,\n data: v as { readonly input: string },\n }),\n toJSON: (): Record<string, unknown> => ({\n type: 'object',\n properties: { input: { type: 'string' } },\n required: ['input'],\n }),\n };\n const tool: Tool<{ readonly input: string }, TOutput, TDeps> = {\n name: toolName,\n description,\n inputSchema: schema as unknown as Tool<\n { readonly input: string },\n TOutput,\n TDeps\n >['inputSchema'],\n sideEffectClass: 'side-effecting',\n async execute(input, ctx) {\n // AG-17: the parent ToolExecutionContext propagates — the\n // parent's abort stops the sub-agent, deps/sessionId flow\n // through, and the optional `inputFilter` shapes a seed from\n // the parent history. Least authority by default: without a\n // filter the sub-agent sees ONLY the input string, never the\n // parent conversation.\n const callOpts: AgentCallOptions<TDeps> = {\n ...(ctx?.signal !== undefined ? { signal: ctx.signal } : {}),\n ...(ctx?.runContext.deps !== undefined ? { deps: ctx.runContext.deps as TDeps } : {}),\n ...(ctx?.runContext.sessionId !== undefined\n ? { sessionId: ctx.runContext.sessionId }\n : {}),\n };\n const seed: AgentInput =\n options.inputFilter !== undefined && ctx !== undefined\n ? ([\n ...options.inputFilter(ctx.runContext.messages),\n { role: 'user' as const, content: input.input },\n ] as Message[])\n : input.input;\n if (exposeTurns === 'all') {\n // Replay the streamed text completions as the result so\n // the parent agent sees every turn the sub-agent\n // produced. `exposeTurns: 'final'` (default) and\n // `'none'` skip the per-turn assembly.\n const turns: string[] = [];\n let endResult: AgentResult<TOutput> | undefined;\n for await (const ev of stream(seed, callOpts)) {\n if (ev.type === 'text.complete') turns.push(ev.text);\n else if (ev.type === 'agent.end') endResult = ev.result;\n }\n if (endResult !== undefined && endResult.status !== 'completed') {\n throw new Error(\n `sub-agent '${config.name}' ${endResult.status}${\n endResult.error !== undefined ? `: ${endResult.error.message}` : ''\n }`,\n );\n }\n return turns.join('\\n\\n') as unknown as TOutput;\n }\n const result = await run(seed, callOpts);\n // AG-17/AG-22 class: a non-completed sub-run is a TOOL ERROR,\n // never an empty-string success.\n if (result.status !== 'completed') {\n throw new Error(\n `sub-agent '${config.name}' ${result.status}${\n result.error !== undefined ? `: ${result.error.message}` : ''\n }`,\n );\n }\n if (exposeTurns === 'none') return '' as unknown as TOutput;\n return result.output;\n },\n };\n return tool;\n };\n\n const compact = async (options?: CompactOptions): Promise<CompactionApiResult> => {\n // No memory wired — an explicit no-op (AG-13), intentionally\n // forgiving so example apps that don't wire memory don't crash\n // on `agent.compact()`.\n if (memory === undefined) return noopCompactionResult('no-memory');\n // Sensitivity gate (WI-09 step 2) applies to MANUAL compaction\n // too: secret-tier history never ships to the summarizer.\n if (config.sensitivity === 'secret') return noopCompactionResult('sensitivity-gated');\n // Idle — there is no live buffer to splice (AG-13's explicit\n // no-op marker, where the old surface silently reported zeros).\n if (activeRunState === undefined) return noopCompactionResult('no-active-run');\n // CE-3/AG-13: the run loop owns the live buffer, so the splice\n // happens there — enqueue and let `maybeAutoCompact` service the\n // request at the next step boundary with the same prefix-pinned\n // splice as auto-compaction. Don't await this from inside a tool\n // handler: the loop can't reach the next step until the tool\n // returns.\n return await new Promise<CompactionApiResult>((resolve, reject) => {\n pendingManualCompacts.push({ options, resolve, reject });\n });\n };\n\n const fanOut = async <TFanOutOutput = unknown>(\n options: AgentFanOutOptions<TFanOutOutput>,\n ): Promise<FanOutResult<TFanOutOutput>> => {\n const runId = activeRunState?.id ?? `run_${newId()}`;\n const sessionId = activeRunState?.sessionId ?? `session_${newId()}`;\n const fanOutOptions: RunFanOutOptions<TFanOutOutput> = {\n children: options.children,\n ...(options.maxConcurrentChildren !== undefined\n ? { maxConcurrentChildren: options.maxConcurrentChildren }\n : {}),\n ...(options.perBudget !== undefined ? { perBudget: options.perBudget } : {}),\n ...(options.mergeStrategy !== undefined ? { mergeStrategy: options.mergeStrategy } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n // AG-7: fanout lifecycle events reach the agent stream — queued\n // on the external-event queue and drained into the active (or\n // next consumed) run, like steer/follow-up/progress events.\n emit: (event) => {\n externalEventQueue.push(event as AgentEvent<TOutput>);\n },\n // AG-7: the configured sideways-injection merge guard finally\n // applies to the judge-merge path.\n ...(config.mergeGuard !== undefined ? { mergeGuard: config.mergeGuard } : {}),\n runId,\n sessionId,\n agentId,\n };\n return runFanOut<TFanOutOutput>(fanOutOptions);\n };\n\n // Stable fallback id so out-of-run `progress.write` → `progress.read`\n // pairs resolve to the same artifact directory (a fresh id per call\n // could never find what it just wrote).\n const progressFallbackRunId = `run_${newId()}`;\n const progress: AgentProgressIO = {\n write: async (content: string, opts?: ProgressWriteOptions) => {\n const runId = activeRunState?.id ?? progressFallbackRunId;\n const ref = await progressIO.write(runId, content, opts);\n // AG-20: surface the documented `agent.progress.written` event —\n // queued here and drained into the active (or next consumed) stream.\n externalEventQueue.push({\n type: 'agent.progress.written',\n runId,\n sessionId: activeRunState?.sessionId ?? '',\n agentId,\n ref,\n } as AgentEvent<TOutput>);\n return ref;\n },\n read: async (opts?: ProgressReadOptions) => {\n const queriedRunId = opts?.runId ?? activeRunState?.id ?? progressFallbackRunId;\n const refs = await progressIO.read(queriedRunId, opts);\n externalEventQueue.push({\n type: 'agent.progress.read',\n runId: activeRunState?.id ?? queriedRunId,\n sessionId: activeRunState?.sessionId ?? '',\n agentId,\n refs,\n queriedRunId,\n queriedRole: opts?.role,\n } as AgentEvent<TOutput>);\n return refs;\n },\n };\n\n void config.sensitivity as Sensitivity | undefined;\n\n const agent: Agent<TDeps, TOutput> = {\n id: agentId,\n config,\n stream,\n run,\n steer,\n followUp,\n abort,\n toTool,\n compact,\n fanOut,\n progress,\n registry: toolRegistry,\n };\n\n return agent;\n}\n\n/**\n * Pre-execution approval screen (Adapter G / durable HITL). Evaluates a\n * (registry-resolved) tool's `needsApproval` against the realized args.\n * Returns `true` when the run must suspend before the tool executes.\n *\n * Actual execution flows through the `@graphorin/tools` executor, whose\n * `ApprovalGate` auto-grants because only no-approval / pre-approved\n * calls ever reach it; this probe is what keeps the suspend in the\n * agent so the durable-HITL contract (persist `RunState`, resume via\n * directive) is preserved.\n */\nasync function invokeNeedsApproval(\n tool: Pick<Tool, 'needsApproval'> | undefined,\n args: unknown,\n baseCtx: RunContext,\n signal: AbortSignal,\n): Promise<boolean> {\n const predicate = tool?.needsApproval;\n if (predicate === undefined || predicate === false) return false;\n if (predicate === true) return true;\n const probeCtx: ToolExecutionContext = {\n toolCallId: 'probe',\n runContext: baseCtx,\n signal,\n tracer: baseCtx.tracer,\n logger: NOOP_LOGGER,\n secrets: probeSecretsAccessor(),\n reportProgress: () => {},\n streamContent: () => {},\n };\n return Boolean(await predicate(args as never, probeCtx));\n}\n\n/**\n * Rejecting secrets accessor used only by the {@link invokeNeedsApproval}\n * probe. Real tool execution resolves secrets through the executor's\n * ACL-scoped accessor; an approval predicate has no legitimate need to\n * read secret material, so every `require(...)` rejects.\n */\nfunction probeSecretsAccessor(): ToolExecutionContext['secrets'] {\n const rejector = (_key: string, _options?: { readonly optional?: boolean }): Promise<never> =>\n Promise.reject(new Error('secrets.require is unavailable inside a needsApproval predicate'));\n return { require: rejector } as unknown as ToolExecutionContext['secrets'];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAM,8BACJ;AAwEF,MAAM,aAAa,UACjB,WAAW,SAAS,CAAC,OAAO,OAAO,OAAO,CAAC,OAAO,MAAM;AAE1D,MAAM,sBAAsB;;AAG5B,MAAM,mBAAmB;;;;;;;;;;;;;;;AAgBzB,SAAS,mBAAmB,UAA8B;AACxD,KAAI,SAAS,cAAc,CAAC,WAAW,EAAG;AAC1C,KAAI,SAAS,IAAI,iBAAiB,KAAK,OAAW;AAClD,UAAS,SAAS,qBAAqB,EAAE,UAAU,CAAC,EAAE;EACpD,MAAM;EACN,WAAW;EACZ,CAAC;;;AAIJ,MAAM,mBAAmB;;;;;;;;;;;;AAazB,SAAS,mBACP,UACA,QACA,MACM;AACN,KACE,MAAM,UAAU,QAChB,CAAC,SAAS,MAAM,CAAC,MAAM,UAAU,MAAM,uBAAuB,gBAAgB,CAE9E;AAEF,KAAI,SAAS,IAAI,iBAAiB,KAAK,OAAW;AAClD,UAAS,SAAS,qBAAqB,EAAE,QAAQ,CAAC,EAAE;EAClD,MAAM;EACN,WAAW;EACZ,CAAC;;;;;;;;;AAUJ,SAAS,qBAAqB,SAAoD;AAChF,QAAO,EACL,MAAM,KAAK,KAAK,OAAO;EACrB,IAAIA;AACJ,OAAK,MAAM,KAAK,QACd,KAAI;AACF,UAAO,MAAM,EAAE,KAAK,KAAK,MAAM;WACxB,KAAK;AACZ,eAAY;;AAGhB,QAAM,qBAAqB,QACvB,4BACA,IAAI,MAAM,oCAAoC,KAAK,UAAU,IAAI,CAAC,GAAG;IAE5E;;;AAIH,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;AAoBzB,SAAS,iBACP,UACA,eACA,eACgD;AAChD,KAAI,SAAS,IAAI,kBAAkB,KAAK,OAAW,QAAO,EAAE;CAC5D,MAAM,mBAAmB,MACvB,EAAE,kBAAkB,QAAQ,OAAO,EAAE,kBAAkB;CACzD,MAAM,YAAY,SACf,MAAM,CACN,QAAQ,UAAU,CAAC,cAAc,IAAI,MAAM,KAAK,IAAI,CAAC,gBAAgB,MAAM,CAAC;AAC/E,KAAI,UAAU,WAAW,EAAG,QAAO,EAAE;CAMrC,MAAM,qBAAqB,SACxB,MAAM,CACN,QAAQ,UAAU,CAAC,cAAc,IAAI,MAAM,KAAK,IAAI,gBAAgB,MAAM,CAAC,CAC3E,KAAK,UAAU,MAAM,KAAK;CAC7B,MAAM,mBAAmB,IAAI,IAAI,mBAAmB;CAEpD,MAAM,eAAe,CAAC,GAAG,UAAU,KAAK,UAAU,MAAM,KAAK,EAAE,GAAG,mBAAmB;CACrF,MAAM,aAAa,IAAI,IAAI,UAAU,KAAK,UAAU,MAAM,KAAK,CAAC;CAIhE,MAAM,aAAa,eAHM,UAAU,QAChC,UAAU,MAAM,4BAA4B,KAC9C,CACkD;CAEnD,MAAMC,cAAiC,OAAO,MAAM,QAAQ;AAC1D,MAAI,iBAAiB,IAAI,KAAK,KAAK,CACjC,OAAM,IAAI,MACR,GAAG,KAAK,KAAK,mJACd;EAOH,MAAM,EAAE,YALU,MAAM,cAAc,WAAW;GAC/C,MAAM;IAAE,YAAY,MAAM,WAAW;IAAE,UAAU,KAAK;IAAM,MAAM,KAAK;IAAM;GAC7E,YAAY,IAAI;GAChB,YAAY,IAAI,WAAW;GAC5B,CAAC;AAEF,MAAI,UAAU,QAAS,OAAM,IAAI,MAAM,GAAG,KAAK,KAAK,IAAI,QAAQ,UAAU;AAC1E,SAAO,QAAQ;;CAGjB,MAAM,aAAa,qBAAqB;EACtC;EACA;EACA,gBAAgB,OAAO,OAAO,OAC3B,MAAM,SAAS,eAAe,OAAO,EAAE,EAAE,QAAQ,UAAU,WAAW,IAAI,MAAM,KAAK,CAAC;EAC1F,CAAC;CACF,MAAM,cAAc,sBAAsB;EACxC;EACA;EACA;EACA;EACD,CAAC;AACF,UAAS,SAAS,YAAY;EAAE,MAAM;EAAY,WAAW;EAAa,CAAC;AAC3E,UAAS,SAAS,aAAa;EAAE,MAAM;EAAY,WAAW;EAAa,CAAC;AAC5E,QAAO,CAAC,YAAY,YAAY;;;;;;;;AASlC,SAAS,2BAA2B,QAAiB,UAA6B;AAChF,KAAI,OAAO,WAAW,YAAY,WAAW,KAAM;CACnD,MAAM,UAAW,OAA0C;AAC3D,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE;AAC7B,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,OAAQ,OAA8C;AAC5D,MAAI,OAAO,SAAS,SAAU,UAAS,IAAI,KAAK;;;AA2BpD,SAAS,gBAAgB,OAAyB;AAChD,QAAO,UAAU,UAAU,UAAU,cAAc,UAAU;;AAG/D,SAAS,gBAAgB,OAAyB;AAChD,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;CACxD,MAAM,IAAI;AACV,KAAI,OAAO,EAAE,YAAY,YAAY,OAAO,EAAE,SAAS,SAAU,QAAO;AACxE,KAAI,OAAO,EAAE,aAAa,YAAY,EAAE,aAAa,QAAQ,OAAO,EAAE,UAAU,SAC9E,QAAO;AAET,QAAO;;AAGT,SAAS,uBAAuB,OAAsB;AACpD,KAAI,UAAU,OAAW;AACzB,KAAI,gBAAgB,MAAM,CAAE;AAC5B,KAAI,gBAAgB,MAAM,CAAE;AAC5B,OAAM,IAAI,2BAA2B,MAAM;;AAG7C,SAAS,gBAAgB,OAAkC;AACzD,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;CACxD,MAAM,OAAQ,MAA6B;AAC3C,QAAO,SAAS,YAAY,SAAS,UAAU,SAAS,eAAe,SAAS;;AAGlF,SAAS,iBAAiB,OAAmC;AAC3D,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;CACxD,MAAM,IAAI;AACV,QACE,OAAO,EAAE,OAAO,YAChB,OAAO,EAAE,YAAY,YACrB,MAAM,QAAQ,EAAE,SAAS,IACzB,MAAM,QAAQ,EAAE,MAAM;;AAI1B,SAAS,WAAW,OAGlB;AACA,KAAI,OAAO,UAAU,SACnB,QAAO,EAAE,MAAM,CAAC;EAAE,MAAM;EAAQ,SAAS;EAAO,CAAC,EAAE;AAErD,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,EAAE,MAAM,CAAC,GAAG,MAAM,EAAe;AAE1C,KAAI,gBAAgB,MAAM,CACxB,QAAO,EAAE,MAAM,CAAC,MAAM,EAAE;AAE1B,KAAI,iBAAiB,MAAM,CACzB,QAAO;EAAE,MAAM,EAAE;EAAE,SAAS;EAAO;AAErC,OAAM,IAAI,wBAAwB,gCAAgC;;;;;;;AAQpE,SAAS,eAAe,MAAsB;CAC5C,MAAM,UAAU,KAAK,MAAM;AAE3B,QADc,gCAAgC,KAAK,QAAQ,GAC5C,MAAM;;;;;;;;AASvB,SAAS,2BAA2B,MAGzB;CACT,MAAM,QAAQ,CACZ,mFACD;AACD,KAAI,KAAK,gBAAgB,UAAa,KAAK,YAAY,SAAS,EAC9D,OAAM,KAAK,KAAK,YAAY;AAE9B,KAAI,KAAK,eAAe,OACtB,OAAM,KAAK,+CAA+C,KAAK,UAAU,KAAK,WAAW,GAAG;AAE9F,QAAO,MAAM,KAAK,KAAK;;;AAIzB,SAAS,aAAa,UAAsD;AAC1E,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,MAAM,IAAI,SAAS;AACnB,MAAI,GAAG,SAAS,OAAQ;AACxB,MAAI,OAAO,EAAE,YAAY,SAAU,QAAO,EAAE;EAC5C,MAAM,OAAO,EAAE,QACZ,QAAQ,MAA6D,EAAE,SAAS,OAAO,CACvF,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,IAAI;AACZ,SAAO,KAAK,SAAS,IAAI,OAAO;;;;;;;;;;AAYpC,SAAS,gCAAgC,OAAmC;AAC1E,KAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,MAC3D,SAAS,MAAsC,MAA/C;EACE,KAAK,sBACH,QAAO;;AAGb,QAAO;;;AAIT,SAAS,cAAc,KAA6D;AAClF,KAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;CAC9C,MAAM,SAAU,IAAmC;AACnD,KAAI,OAAO,WAAW,WAAY,QAAO,OAAO,KAAK,IAAI;AACzD,KAAI,OAAO,QAAQ,SAAU,QAAO;;AAItC,SAAS,iBAAiB,MAA4B;CACpD,MAAM,KAAK;CAIX,MAAM,cAAc,cAAc,GAAG,YAAY,IAAI,EAAE;CAGvD,MAAM,eAAe,cAAc,GAAG,aAAa;CACnD,MAAM,WAAW,mBAAmB,KAAK;AACzC,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK;EAClB;EACA,GAAI,iBAAiB,SAAY,EAAE,cAAc,GAAG,EAAE;EACtD,GAAI,aAAa,SAAY,EAAE,UAAU,GAAG,EAAE;EAC/C;;;;;;;;;;;;;;AAeH,SAAS,mBAAmB,MAA8D;CACxF,MAAM,WAAW,KAAK;AACtB,KAAI,aAAa,UAAa,SAAS,WAAW,EAAG,QAAO;AAC5D,KAAI,KAAK,4BAA4B,MAAO,QAAO;AACnD,QAAO,SAAS,MAAM,GAAG,EAAE,CAAC,KAAK,QAAQ;EACvC,OAAO,GAAG;EACV,QAAQ,GAAG;EACX,GAAI,GAAG,YAAY,SAAY,EAAE,SAAS,GAAG,SAAS,GAAG,EAAE;EAC5D,EAAE;;AAGL,MAAM,qBAAqB;CACzB,QAAW,UAAsB;CACjC,YAAe,WAAoB;EAAE,SAAS;EAAe,MAAM;EAAY;CAC/E,eAAwC,EAAE,MAAM,UAAU;CAC3D;AAED,SAAS,kBAAkB,OAA0C;AACnE,QACE,OAAO,UAAU,cACjB,gBAAgB,SAChB,OAAQ,MAA0B,eAAe;;AAIrD,SAAS,iBAAwB,QAA8D;CAC7F,MAAM,MAAM,OAAO;AAWnB,QAT4C;EAC1C,MAFW,GAAG,sBAAsB,IAAI;EAGxC,aAAa,8BAA8B,IAAI,KAAK;EACpD,aAAa;EACb,iBAAiB;EACjB,MAAM,UAA2B;AAC/B,UAAO,aAAa,IAAI,KAAK;;EAEhC;;AAIH,SAAS,eAAe,MAA2B;AACjD,KAAI,cAAc,KAAM,QAAO,KAAK;AACpC,QAAO;;AAwBT,SAAS,oBACP,IACA,OACsB;AACtB,SAAQ,GAAG,MAAX;EACE,KAAK,eACH,QAAO,EAAE;EACX,KAAK;AACH,SAAM,mBAAmB,GAAG;AAC5B,UAAO,EAAE,MAAM;IAAE,MAAM;IAAmB,OAAO,GAAG;IAAO,EAAE;EAC/D,KAAK;AACH,SAAM,cAAc,GAAG;AACvB,UAAO,EAAE,MAAM;IAAE,MAAM;IAAc,OAAO,GAAG;IAAO,EAAE;EAC1D,KAAK;AACH,SAAM,MAAM,IAAI,GAAG,YAAY;IAC7B,YAAY,GAAG;IACf,UAAU,GAAG;IACb,YAAY;IACb,CAAC;AACF,UAAO,EACL,MAAM;IACJ,MAAM;IACN,YAAY,GAAG;IACf,UAAU,GAAG;IACb,MAAM;IACP,EACF;EACH,KAAK,yBAAyB;GAC5B,MAAM,MAAM,MAAM,MAAM,IAAI,GAAG,WAAW;AAC1C,OAAI,QAAQ,OAAW,KAAI,cAAc,GAAG;AAC5C,UAAO,EACL,MAAM;IAAE,MAAM;IAAmB,YAAY,GAAG;IAAY,WAAW,GAAG;IAAW,EACtF;;EAEH,KAAK,iBAAiB;GACpB,MAAM,MAAM,MAAM,MAAM,IAAI,GAAG,WAAW;AAC1C,OAAI,QAAQ,QAAW;AAGrB,YAAQ,OAAO,MACb,4CAA4C,GAAG,WAAW,uCAC3D;AACD,WAAO,EAAE;;AAEX,SAAM,WAAW,KAAK;IACpB,YAAY,GAAG;IACf,UAAU,IAAI;IACd,MAAM,GAAG;IACV,CAAC;AACF,UAAO,EACL,MAAM;IAAE,MAAM;IAAiB,YAAY,GAAG;IAAY,WAAW,GAAG;IAAW,EACpF;;EAIH,KAAK,OACH,QAAO,EAAE,MAAM;GAAE,MAAM;GAAkB,UAAU,GAAG;GAAU,MAAM,GAAG;GAAM,EAAE;EACnF,KAAK,SACH,QAAO,EACL,MAAM;GACJ,MAAM;GACN,KAAK,GAAG;GACR,GAAI,GAAG,UAAU,SAAY,EAAE,OAAO,GAAG,OAAO,GAAG,EAAE;GACtD,EACF;EACH,KAAK,SACH,QAAO;GAAE,OAAO,GAAG;GAAO,UAAU;GAAM;EAC5C,KAAK,QACH,QAAO,EAAE,eAAe,GAAG,OAAO;EACpC,QAGE,QAAO,EAAE;;;;;;;;;AAWf,SAAS,4BACP,eACA,UACoB;AACpB,KAAI,kBAAkB,OAAW,QAAO;AAExC,SADiB,SAAS,aAAa,mBACvC;EACE,KAAK,sBACH,QAAO;EACT,KAAK,WACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,QACE,QAAO;;;;;;;;;;;AAYb,SAAS,sBACP,MACA,gBACA,WACA,SACA,WACkB;AAElB,KAD0B,cAAc,WAAW,eAAe,SAAS,GACpD;EACrB,MAAMC,QAA0B,CAAC,GAAG,eAAe;AACnD,MAAI,KAAK,SAAS,EAAG,OAAM,KAAK;GAAE,MAAM;GAAQ;GAAM,CAAC;AACvD,SAAO;GACL,MAAM;GACN,SAAS;GACT,GAAI,UAAU,SAAS,IAAI,EAAE,WAAW,GAAG,EAAE;GAC7C;GACD;;AAEH,QAAO;EACL,MAAM;EACN,SAAS;EACT,GAAI,UAAU,SAAS,IAAI,EAAE,WAAW,GAAG,EAAE;EAC7C;EACD;;;;;;;AAQH,SAAS,2BAA2B,UAA2C;CAC7E,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,MAAM,SAAS;AACrB,MAAI,QAAQ,OAAW;AACvB,MAAI,IAAI,SAAS,YAAY,IAAI,SAAS,OAAQ;AAClD,MAAI,OAAO,IAAI,YAAY,SAAU;EACrC,MAAM,WAAW,IAAI,QAAQ,QAAQ,MAAM,EAAE,SAAS,YAAY;AAClE,MAAI,SAAS,WAAW,IAAI,QAAQ,OAAQ;AAC5C,cAAY,IAAI,QAAQ,SAAS,SAAS;AAC1C,MAAI,IAAI,SAAS,YACf,UAAS,KAAK;GAAE,GAAG;GAAK,SAAS;GAAU;MAE3C,UAAS,KAAK;GAAE,GAAG;GAAK,SAAS;GAAU;;AAG/C,QAAO,EAAE,UAAU;;;;;;;;;;;;;;;;;;AAmBrB,SAAS,2BAA2B,UAA0C;CAC5E,IAAI,IAAI;AACR,QAAO,IAAI,SAAS,UAAU,SAAS,IAAI,SAAS,SAAU,MAAK;AACnE,QAAO;;;;;;;AAQT,SAAgB,YACd,QACuB;AACvB,KAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,WAAW,EAC5D,OAAM,IAAI,wBAAwB,iBAAiB;AAErD,KAAI,OAAO,aAAa,UAAa,OAAO,aAAa,KACvD,OAAM,IAAI,wBAAwB,qBAAqB;AAIzD,KAAI,OAAO,YAAY,SAAS,UAAU,OAAO,WAAW,WAAW,OACrE,OAAM,IAAI,wBACR,0EACD;AAEH,wBAAuB,OAAO,eAAe;AAC7C,KAAI,OAAO,iBAAiB,OAC1B,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,OAAO,aAAa,EAAE;AAC9D,MAAI,CAAC,gBAAgB,KAAK,CAAE,OAAM,IAAI,2BAA2B,EAAE,MAAM,CAAC;AAC1E,MAAI,SAAS,OAAW;AACxB,MAAI,CAAC,gBAAgB,KAAK,CAAE,OAAM,IAAI,2BAA2B,KAAK;;AAG1E,KAAI,OAAO,mBAAmB,QAC5B;OAAK,MAAM,QAAQ,OAAO,eACxB,KAAI,CAAC,gBAAgB,KAAK,CAAE,OAAM,IAAI,2BAA2B,KAAK;;CAI1E,MAAM,UAAU,MAAM,QAAQ;CAC9B,MAAM,SAAS,OAAO,UAAU;CAChC,MAAM,WAAW,OAAO,YAAY,YAAY,GAAG;CACnD,MAAMC,iBAAsC,OAAO,kBAAkB,EAAE;CACvE,MAAM,6BAAa,IAAI,KAGpB;AACH,MAAK,MAAM,SAAS,OAAO,YAAY,EAAE,EAAE;EACzC,MAAM,mBAAmB,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY;EACpF,MAAMC,WAAkC,mBACnC,MAAqD,SACrD;EACL,MAAM,aAAa,mBAEb,MAKA,cACF;EACJ,MAAM,SAAS,kBAAkB,WAAW,GAAG,aAAa;EAC5D,MAAM,WAAW,GAAG,sBAAsB,SAAS,OAAO;AAC1D,aAAW,IAAI,UAAU;GAAE,OAAO;GAAU;GAAQ,CAAC;;CAGvD,IAAIC,eAA0B,EAAE;CAChC,MAAMC,kBAA6B,EAAE;CACrC,IAAIC;CACJ,IAAIC;CAGJ,IAAIC;;CAEJ,IAAI,cAAc;CAClB,MAAMC,qBAA4C,EAAE;CAcpD,MAAMC,wBAAgD,EAAE;CAExD,MAAM,wBACJ,mBACyB;EACzB,cAAc;EACd,aAAa;EACb,eAAe;EACf,YAAY;EACZ,iBAAiB;EACjB,SAAS;EACT,SAAS;EACT;EACD;CAED,MAAMC,SAA6B,OAAO;CAC1C,MAAMC,aAAyB,iBAAiB,EAC9C,GAAI,OAAO,gBAAgB,SAAY,EAAE,oBAAoB,OAAO,aAAa,GAAG,EAAE,EACvF,CAAC;CAQF,MAAM,eAAe,kBAAkB;EACrC,GAAI,OAAO,UAAU,SACjB,EAAE,OAAO,OAAO,OAAyD,GACzE,EAAE;EACN,GAAI,OAAO,WAAW,SAAY,EAAE,QAAQ,OAAO,QAAQ,GAAG,EAAE;EACjE,CAAC,CAAC;AAQH,oBAAmB,aAAa;CAShC,MAAM,cAAc,0BAA0B;CAC9C,MAAM,mBAAmB,uBAAuB,EAAE,cAAc,YAAY,cAAc,CAAC;CAO3F,MAAM,wBAAwB,OAAO,iBAAiB,EAAE;CACxD,MAAMC,eACJ,sBAAsB,WAAW,IAC7B,mBACA,qBAAqB,CAAC,kBAAkB,GAAG,sBAAsB,CAAC;AACxE,oBAAmB,cAAc,cAAc,EAAE,OAAO,sBAAsB,SAAS,GAAG,CAAC;CAuB3F,IAAIC;CACJ,MAAMC,mBAAiE,EACrE,SAAS,aAAa,EAAE,SAAS,MAAM,GACxC;CACD,MAAM,qBAAqB,qBAAqB;CAChD,MAAM,mBAAmB,uBAAuB;CAMhD,MAAM,oBAAoB,iBACxB,QACA,WAAW,SACP,EAAE,GACF,EACE,cAAc,yBAAyB,CAAC,UAAU,EAAE,OAAO,WAAW;AACpE,MAAI,WAAW,UAAW,QAAO;EACjC,MAAM,QAAQ;GACZ,QAAQ,gBAAgB,UAAU;GAClC,GAAI,gBAAgB,cAAc,SAC9B,EAAE,WAAW,eAAe,WAAW,GACvC,EAAE;GACN;GACD;EACD,MAAM,UACJ,OAGA;AACF,MAAI,SAAS,YAAY,OAAW,QAAO;AAC3C,MAAI;AACF,UAAO,MAAM,QAAQ,QAAQ,OAAO,QAAQ;UACtC;AAGN,UAAO;;GAET,EACH,CACN;CACD,MAAM,yBAAyB,kBAAkB;AACjD,KAAI,WAAW,QAAW;EACxB,MAAM,WAAW,OAAO,SAAS,EAAE,EAAE,QAAQ,MAAM,EAAE,oBAAoB,OAAU;AACnF,MAAI,QAAQ,SAAS,EACnB,SAAQ,KACN,qBAAqB,QAAQ,OAAO,iJAErC;;CAOL,MAAM,oBACJ,OAAO,mBAAmB,UAAa,OAAO,eAAe,SAAS,QAClE,mBAAmB,OAAO,eAAe,GACzC;CACN,MAAMC,qBAAoE,UACxE,sBAAsB,KAAK,MAAM;CAInC,MAAM,oBACJ,UACA,SAEA,mBAAmB;EACjB;EACA,cAAc;EACd,gBAAgB;EAChB,cAAc;EACd,oBAAoB;EACpB,GAAI,kBAAkB,uBAAuB,SACzC,EAAE,oBAAoB,kBAAkB,oBAAoB,GAC5D,EAAE;EACN,OAAO;EACP,GAAI,sBAAsB,SAAY,EAAE,eAAe,mBAAmB,GAAG,EAAE;EAC/E,GAAI,MAAM,UAAU,OAAO,EAAE,GAAG,EAAE,eAAe,mBAAmB;EACpE,GAAI,OAAO,qBAAqB,SAC5B,EAAE,kBAAkB,OAAO,kBAAkB,GAC7C,EAAE;EACP,CAAC;CACJ,MAAM,eAAe,iBAAiB,aAAa;CAUnD,MAAM,aAAa,OAAO,mBAAmB;CAC7C,IAAIC,qBAAmE,EAAE;AACzE,KAAI,YAAY;EACd,MAAM,WAAW,IAAI,IAAY;GAC/B;GACA;GACA;GACA;GACA,GAAG,WAAW,MAAM;GACrB,CAAC;EACF,MAAM,QAAQ,iBACZ,cACA,iBAAiB,cAAc,EAAE,OAAO,MAAM,CAAC,EAC/C,SACD;AACD,qBAAmB,cAAc,aAAa;EAC9C,MAAM,aAAa,aAAa,IAAI,iBAAiB;AACrD,uBAAqB,CACnB,GAAG,OACH,GAAI,eAAe,SAAY,CAAC,WAAW,GAAG,EAAE,CACjD;;CAGH,MAAM,mBAAmB,OAAO,mBAC5B,IAAI,iBAAiB,OAAO,iBAAiB,GAC7C;;;;;;;;;;;;CAaJ,gBAAgB,QACd,OACA,SACiE;AACjE,MAAI,YACF,OAAM,IAAI,oBAAoB;AAEhC,gBAAc;AACd,iBAAe,EAAE;AACjB,iBAAe;AAGf,oBAAkB,OAAO;AACzB,MAAI;AACF,UAAO,OAAO,aAAa,OAAO,QAAQ;YAClC;AACR,iBAAc;AACd,oBAAiB;AAIjB,UAAO,sBAAsB,SAAS,EACpC,uBAAsB,OAAO,EAAE,QAAQ,qBAAqB,gBAAgB,CAAC;;;CAKnF,gBAAgB,aACd,OACA,SACiE;EACjE,MAAM,EAAE,MAAM,SAAS,YAAY,WAAW,MAAM;EAMpD,MAAM,OACJ,YAAY,UAAa,gBAAgB,SAAS,IAC9C,CAAC,GAAG,gBAAgB,OAAO,GAAG,gBAAgB,OAAO,EAAE,GAAG,QAAQ,GAClE;EACN,MAAM,YAAY,QAAQ,aAAa,OAAO,aAAa,WAAW,OAAO;EAC7E,MAAM,SAAS,QAAQ,UAAU,OAAO;EACxC,MAAM,WAAW,IAAI,iBAAiB;AACtC,oBAAkB;EAOlB,MAAM,SAAS,SAAS;EACxB,MAAM,eAAe,QAAQ;EAC7B,MAAM,sBAA4B,SAAS,OAAO;AAClD,MAAI,iBAAiB,OACnB,KAAI,aAAa,QAAS,UAAS,OAAO;MACrC,cAAa,iBAAiB,SAAS,cAAc;EAG5D,MAAM,WAAW,IAAI,0BAA0B;EAW/C,MAAM,QAVsB,UACxB,UACA,sBAAsB;GACpB,IAAI,MAAM,MAAM;GAChB;GACA;GACA,GAAI,WAAW,SAAY,EAAE,QAAQ,GAAG,EAAE;GAC3C,CAAC;AAIN,mBAAiB;AAMjB,MAAI,WAAW,MAAM,iBAAiB,OACpC,oBAAmB,WAAW,MAAM,IAAI,MAAM,aAAa;EAG7D,MAAMC,WAAsB,UAAU,CAAC,GAAG,MAAM,SAAS,GAAG,EAAE;AAC9D,MAAI,CAAC,SAAS;GAGZ,MAAM,kBAAkB,OAAO;GAM/B,IAAIC;AACJ,OAAI,OAAO,oBAAoB,SAC7B,oBAAmB;OAenB,oBAAmB,MAAM,gBAbkB;IACzC,OAAO,MAAM;IACb;IACA,GAAI,WAAW,SAAY,EAAE,QAAQ,GAAG,EAAE;IAC1C;IACA,MAAO,QAAQ,QAAQ,OAAO;IAC9B;IACA;IACA,OAAO;IACP,YAAY;IACZ;IACA;IACD,CACwD;GAE3D,IAAI,eAAe;AACnB,OAAI,OAAO,wBAAwB,QAAQ,WAAW,QAAW;IAO/D,MAAM,WAAW,aAAa,KAAK;AASnC,oBARkB,MAAM,OAAO,cAAc,SAAS,QAAQ;KAC5D,OAAO;MAAE,QAAQ,UAAU;MAAS;MAAW;MAAS;KACxD;KACA;KACA,OAAO,MAAM;KACb,GAAI,iBAAiB,SAAS,IAAI,EAAE,mBAAmB,kBAAkB,GAAG,EAAE;KAC9E,GAAI,aAAa,SAAY,EAAE,iBAAiB,UAAU,GAAG,EAAE;KAChE,CAAC,EACuB,cAAc;;AAEzC,OAAI,aAAa,SAAS,EACxB,UAAS,KAAK;IAAE,MAAM;IAAU,SAAS;IAAc,CAAC;AAE1D,YAAS,KAAK,GAAG,KAAK;AAItB,QAAK,MAAM,KAAK,SAAU,OAAM,SAAS,KAAK,EAAE;;EAGlD,MAAMC,gBAA8C,EAClD,QAAQ,IACT;AAED,QAAM;GAAE,MAAM;GAAe,OAAO,MAAM;GAAI;GAAS;EASvD,MAAM,cAAc,OAAO,YAAY;AACvC,MAAI,CAAC,WAAW,gBAAgB,UAAa,YAAY,SAAS,EAChE,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GACxC,MAAM,MAAM,SAAS;AACrB,OAAI,QAAQ,UAAa,IAAI,SAAS,UAAU,OAAO,IAAI,YAAY,SAAU;GACjF,MAAM,WAAW,MAAM,kBAAkB,aAAa,IAAI,SAAS;IACjE,OAAO;IACP,OAAO,MAAM;IACb;IACA;IACD,CAAC;AACF,OAAI,CAAC,SAAS,IAAI;AAChB,UAAM;KACJ,MAAM;KACN,eAAe,SAAS;KACxB,OAAO;KACP,QAAQ,SAAS;KAClB;IACD,MAAM,UAAU,oBAAoB,SAAS,KAAK,qBAAqB,SAAS;AAChF,UAAM;KAAE,MAAM;KAAe,OAAO;MAAE;MAAS,MAAM;MAAqB;KAAE;AAC5E,UAAM,SAAS;AACf,UAAM,QAAQ;KAAE;KAAS,MAAM;KAAqB;AACpD,WAAO,OAAO,UAAU,OAAO,cAAc;;AAE/C,OAAI,SAAS,UAAU,IAAI,SAAS;IAClC,MAAMC,YAAqB;KAAE,GAAG;KAAK,SAAS,SAAS;KAAO;IAC9D,MAAM,WAAW,MAAM,SAAS,QAAQ,IAAI;AAC5C,aAAS,KAAK;AACd,QAAI,aAAa,GAAI,OAAM,SAAS,YAAY;;;EAOtD,MAAM,wBACJ,OAAO,YAAY,SAAS,eACxB,2BAA2B,OAAO,WAAW,GAC7C;EAIN,MAAMC,uBAAmC,EAAE;EAK3C,MAAM,mCAAmB,IAAI,KAAa;AAC1C,OAAK,MAAM,QAAQ,MAAM,MACvB,MAAK,MAAM,aAAa,KAAK,UAAW,kBAAiB,IAAI,UAAU,KAAK,WAAW;AAKzF,MACE,WACA,QAAQ,WAAW,cAAc,UACjC,MAAM,iBAAiB,SAAS,GAChC;GACA,MAAM,YAAY,IAAI,IAAI,QAAQ,UAAU,UAAU,KAAK,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;GACpF,MAAMC,eAA+B,EAAE;AACvC,QAAK,MAAM,YAAY,MAAM,kBAAkB;IAC7C,MAAM,WAAW,UAAU,IAAI,SAAS,WAAW;AACnD,QAAI,aAAa,QAAW;AAC1B,kBAAa,KAAK,SAAS;AAC3B;;AAEF,QAAI,SAAS,SAAS;AACpB,WAAM;MACJ,MAAM;MACN,YAAY,SAAS;MACtB;AAOD,SACE,iBAAiB,IAAI,SAAS,WAAW,IACzC,SAAS,MAAM,MAAM,EAAE,SAAS,UAAU,EAAE,eAAe,SAAS,WAAW,CAE/E;AAOF,0BAAqB,KAAK;MACxB,YAAY,SAAS;MACrB,UAAU,SAAS;MACnB,MAAM,SAAS;MAChB,CAAC;WACG;AACL,WAAM;MACJ,MAAM;MACN,YAAY,SAAS;MACrB,GAAI,SAAS,WAAW,SAAY,EAAE,QAAQ,SAAS,QAAQ,GAAG,EAAE;MACrE;AACD,cAAS,KAAK;MACZ,MAAM;MACN,YAAY,SAAS;MACrB,SAAS,8BAA8B,SAAS,SAAS,KAAK,SAAS,WAAW;MACnF,CAAC;AACF,WAAM,SAAS,KAAK;MAClB,MAAM;MACN,YAAY,SAAS;MACrB,SAAS,8BAA8B,SAAS,SAAS,KAAK,SAAS,WAAW;MACnF,CAAC;;;AAKN,SAAM,iBAAiB,OAAO,GAAG,MAAM,iBAAiB,QAAQ,GAAG,aAAa;AAChF,OAAI,aAAa,WAAW,EAC1B,OAAM,SAAS;;EAanB,MAAM,qBAAqB,2BAA2B,SAAS;EAE/D,MAAMC,iBAAoC;GACxC,OAAO,MAAM;GACb;GACA,GAAI,WAAW,SAAY,EAAE,QAAQ,GAAG,EAAE;GAC1C;GACA,MAAO,QAAQ,QAAQ,OAAO;GAC9B;GACA;GACA,OAAO;GACP,YAAY;GACZ;GACA;GACD;AAMD,MAAI,YAAY,MAAM,WAAW,uBAAuB,MAAM,WAAW,UACvE,QAAO,OAAO,UAAU,OAAO,cAAc;AAS/C,MAAI,WAAW,qBAAqB,SAAS,GAAG;AAC9C,SAAM,MAAM,KAAK;IACf,YAAY;IACZ,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,0BAAS,IAAI,MAAM,EAAC,aAAa;IACjC,OAAO,WAAW;IAClB,WAAW,EAAE;IACb,SAAS,MAAM;IAChB,CAAC;AACF,UAAO,cACL,sBACA,cACA;IAAE,GAAG;IAAgB,YAAY;IAAG;IAAU,EAC9C,EACD;;EAQH,MAAM,mCAAmB,IAAI,KAAa;AAG1C,MAAI,WAAW,MAAM,kBAAkB,OACrC,MAAK,MAAM,QAAQ,MAAM,cAAe,kBAAiB,IAAI,KAAK;;;;;;;;;;;;;;;;;;;;;;;;EA0BpE,gBAAgB,cACd,OACA,UACA,YACA,SACiD;AACjD,OAAI,MAAM,WAAW,EAAG;AACxB,QAAK,MAAM,QAAQ,MACjB,OAAM;IAAE,MAAM;IAAsB,YAAY,KAAK;IAAY;GAGnE,MAAM,SAAS,2BAA2B;AAC1C,0BAAuB;GACvB,MAAM,iBAAiB,SAAS,aAAa;IAAE;IAAO;IAAY,YAAY;IAAS,CAAC;GAGxF,MAAM,gBAAgB,eAAe,WAC7B,OAAO,OAAO,QACd,OAAO,OAAO,CACrB;AACD,cAAW,MAAM,SAAS,OAAO,OAAO,CACtC,KAAI,MAAM,SAAS,2BAA2B,MAAM,SAAS,uBAC3D,OAAM;AAGV,SAAM;AACN,0BAAuB;GAEvB,MAAM,YAAY,MAAM;GACxB,MAAM,WAAW,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,EAAE,QAAQ,YAAY,EAAE,CAAC,CAAC;GACzE,MAAM,YAAY,MAAM,MAAM,MAAM,MAAM,SAAS;AACnD,QAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,SAAS,SAAS,IAAI,KAAK,WAAW;AAC5C,QAAI,WAAW,OAAW;AAC1B,QAAI,cAAc,OAChB,CAAC,UAAU,UAAkC,KAAK,OAAO;IAE3D,MAAM,UAAU,OAAO;AACvB,QAAI,UAAU,SAAS;AACrB,WAAM;MAAE,MAAM;MAAsB,YAAY,KAAK;MAAY,OAAO;MAAS;KACjF,MAAM,OAAO,UAAU,QAAQ;AAC/B,cAAS,KAAK;MAAE,MAAM;MAAQ,YAAY,KAAK;MAAY,SAAS;MAAM,CAAC;AAC3E,WAAM,SAAS,KAAK;MAAE,MAAM;MAAQ,YAAY,KAAK;MAAY,SAAS;MAAM,CAAC;AACjF,uBAAkB,WAAW,cAAc,KAAK,WAAW;WACtD;KACL,MAAM,SAAS,QAAQ;AACvB,WAAM;MACJ,MAAM;MACN,YAAY,KAAK;MACjB,QAAQ;MACR,YAAY,QAAQ;MACrB;KAMD,MAAM,SAAS,QAAQ;KACvB,MAAM,OACJ,WAAW,SACP,GAAG,OAAO,QAAQ,kBAChB,OAAO,UAAU,SAAY,KAAK,OAAO,MAAM,WAAW,GAC3D,wDAAwD,KAAK,UAC5D,OAAO,IACR,CAAC,yFACF,OAAO,WAAW,WAChB,SACA,KAAK,UAAU,OAAO;AAC9B,cAAS,KAAK;MAAE,MAAM;MAAQ,YAAY,KAAK;MAAY,SAAS;MAAM,CAAC;AAC3E,WAAM,SAAS,KAAK;MAAE,MAAM;MAAQ,YAAY,KAAK;MAAY,SAAS;MAAM,CAAC;AACjF,uBAAkB,WAAW,QAAQ,KAAK,WAAW;AAGrD,SAAI,KAAK,aAAa,iBACpB,4BAA2B,QAAQ,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B5D,gBAAgB,mBAAoE;AAClF,UAAO,sBAAsB,SAAS,GAAG;IACvC,MAAM,UAAU,sBAAsB,OAAO;AAC7C,QAAI,YAAY,OAAW,QAAO,qBAAqB,QAAQ;;GAEjE,MAAM,MAAM;AACZ,OAAI,QAAQ,OAAW;AAIvB,OAAI,OAAO,gBAAgB,SAAU;GACrC,MAAM,SAAS,IAAI;AAEnB,OAAI,CADc,MAAM,OAAO,cAAc,SAAS,CAAC,YAAY,MAAM,CACzD;GAEhB,MAAM,YAAY,KAAK,KAAK;GAC5B,MAAM,WAAW,MAAM,OACpB,WAAW;IACV,OAAO;KAAE,QAAQ,MAAM,UAAU;KAAS;KAAW;KAAS;IAC9D,OAAO,MAAM;IACb;IACA;IACA,QAAQ;IACR,UAAU,SAAS,MAAM,mBAAmB;IAC5C,QAAQ;IACT,CAAC,CAGD,YAAY,OAAU;AACzB,OAAI,aAAa,OAAW;AAG5B,OAAI,SAAS,OAAO,sBAAsB,WAAW,EAAG;AAExD,mBAAgB,SAAS;AACzB,SAAM;IACJ,MAAM;IACN,OAAO,MAAM;IACb;IACA;IACA,cAAc,SAAS,OAAO;IAC9B,aAAa,SAAS,OAAO;IAC7B,eAAe,SAAS,OAAO;IAC/B,YAAY,KAAK,KAAK,GAAG;IACzB,QAAQ;IACR,iBAAiB,SAAS,OAAO;IAClC;;;;;;;;;EAUH,SAAS,gBAAgB,UAAoC;GAE3D,MAAMC,UAAqB,CAAC,GADb,SAAS,MAAM,GAAG,mBAAmB,EACb,GAAG,SAAS,OAAO,gBAAgB;GAC1E,MAAM,aAAa,SAAS,aACzB,KAAK,SACJ,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU,OACnD,OAAQ,KAAoC,KAAK,GACjD,GACL,CACA,QAAQ,SAAS,KAAK,SAAS,EAAE,CACjC,KAAK,OAAO;AACf,OAAI,WAAW,SAAS,EACtB,SAAQ,KAAK;IAAE,MAAM;IAAU,SAAS;IAAY,CAAC;AAEvD,YAAS,OAAO,GAAG,SAAS,QAAQ,GAAG,QAAQ;AAC/C,SAAM,SAAS,OAAO,GAAG,MAAM,SAAS,QAAQ,GAAG,QAAQ;;;;;;;;;;EAW7D,gBAAgB,qBACd,SACiD;GACjD,MAAM,MAAM;AACZ,OAAI,QAAQ,QAAW;AACrB,YAAQ,QAAQ,qBAAqB,YAAY,CAAC;AAClD;;GAEF,MAAM,SAAS,QAAQ,SAAS,UAAU;GAC1C,MAAM,YAAY,KAAK,KAAK;GAC5B,IAAIC;AACJ,OAAI;AACF,eAAW,MAAM,IAAI,cAAc,WAAW;KAC5C,OAAO;MAAE,QAAQ,MAAM,UAAU;MAAS;MAAW;MAAS;KAC9D,OAAO,MAAM;KACb;KACA;KACA;KACA,UAAU,SAAS,MAAM,mBAAmB;KAC5C,QAAQ;KACR,GAAI,QAAQ,SAAS,wBAAwB,SACzC,EAAE,qBAAqB,QAAQ,QAAQ,qBAAqB,GAC5D,EAAE;KACP,CAAC;YACK,OAAO;AACd,YAAQ,OAAO,MAAM;AACrB;;GAEF,MAAM,EAAE,WAAW;GACnB,MAAM,UAAU,OAAO,sBAAsB,SAAS;AACtD,OAAI,SAAS;AACX,oBAAgB,SAAS;AACzB,UAAM;KACJ,MAAM;KACN,OAAO,MAAM;KACb;KACA;KACA,cAAc,OAAO;KACrB,aAAa,OAAO;KACpB,eAAe,OAAO;KACtB,YAAY,KAAK,KAAK,GAAG;KACzB;KACA,iBAAiB,OAAO;KACzB;;AAEH,WAAQ,QAAQ;IACd,cAAc,OAAO;IACrB,aAAa,OAAO;IACpB,eAAe,OAAO;IACtB,YAAY,KAAK,KAAK,GAAG;IACzB,iBAAiB,OAAO;IACxB,SAAS,OAAO,WAAW;IAC3B;IACA,GAAI,UAAU,EAAE,GAAG,EAAE,eAAe,mBAA4B;IACjE,CAAC;;EAGJ,MAAM,eAAe,MAAM,KAAK,WAAW,MAAM,CAAC;EAClD,IAAI,aAAa;EAIjB,IAAIC,0BAAiD,EAAE;EAOvD,gBAAgB,mBAAuE;AACrF,SAAM;IACJ,MAAM;IACN,OAAO,MAAM;IACb,OAAO,cAAc,SAAS;IAC9B,oBAAoB,cAAc,sBAAsB;IACzD;GACD,MAAM,SAAS,cAAc,sBAAsB;AACnD,OAAI,WAAW,QAAQ;IACrB,MAAM,UAAU,MAAM,iBAAiB,OAAO,GAAG,MAAM,iBAAiB,OAAO;AAC/E,SAAK,MAAM,YAAY,QACrB,OAAM;KACJ,MAAM;KACN,YAAY,SAAS;KACrB,QAAQ;KACT;cAEM,WAAW,QAAQ;AAC5B,UAAM,SAAS;AACf,UAAM,QAAQ;KAAE,SAAS;KAAkC,MAAM;KAAe;AAChF,UAAM;KACJ,MAAM;KACN,OAAO;MAAE,SAAS;MAAkC,MAAM;MAAe;KAC1E;AACD,WAAO;;AAET,SAAM,SAAS;AACf,UAAO;;AAGT,MAAI;AACF,UAAO,CAAC,SAAS,MAAM,MAAM,EAAE;AAG7B,WAAO,mBAAmB,SAAS,GAAG;KACpC,MAAM,KAAK,mBAAmB,OAAO;AACrC,SAAI,OAAO,OAAW,OAAM;;AAE9B,QAAI,OAAO,SAAS;AAClB,SAAI,OAAO,kBAAkB,CAAE,QAAO,OAAO,UAAU,OAAO,cAAc;AAC5E;;AAEF,kBAAc;IACd,MAAM,6BAAY,IAAI,MAAM,EAAC,aAAa;AAG1C,QAAI,aAAa,SAAS,GAAG;AAC3B,UAAK,MAAM,KAAK,cAAc;AAC5B,eAAS,KAAK,EAAE;AAChB,YAAM,SAAS,KAAK,EAAE;;AAExB,oBAAe,EAAE;;AAGnB,UAAM;KAAE,MAAM;KAAc;KAAY;AAOxC,WAAO,kBAAkB;IAEzB,MAAMC,UAA6B;KAAE,GAAG;KAAgB;KAAY;KAAU;IAC9E,MAAM,YAAY,OAAO,cAAc,MAAM,OAAO,YAAY,QAAQ,GAAG,EAAE;IAS7E,MAAM,sBAAsB,UAAU,UAAU,UAAa,CAAC;IAC9D,MAAMC,eAA6B,sBAC/B,kBAAkB,EAChB,OAAO,UAAU,OAClB,CAAC,CAAC,WACH;AACJ,QAAI,qBAAqB;AACvB,wBAAmB,aAAa;AAChC,wBAAmB,cAAc,aAAa;;IAEhD,MAAMC,eAA6B,sBAC/B,iBAAiB,aAAa,GAC9B;IAIJ,MAAMC,eAAgD,aAAa,KAAK,MAAM;KAC5E,MAAM,IAAI,WAAW,IAAI,EAAE;AAC3B,SAAI,MAAM,OAAW,OAAM,IAAI,kBAAkB,EAAE;AACnD,YAAO,iBAAwB,EAAE,MAAM;MACvC;IASF,IAAIC;AACJ,QAAI,WACF,aAAY,CAAC,GAAG,oBAAoB,GAAG,aAAa;SAC/C;KACL,MAAM,aAAa,aAAa,WAAW;KAM3C,MAAM,gBACJ,iBAAiB,SAAS,IACtB,EAAE,GACF,mBAAmB,kBAAkB,aAAa,cAAc,CAAC;AAEvE,iBAAY;MAAC,GAAG;MAAY,GAAG;MAAe,GAAG;MAAa;;IAOhE,MAAM,iBAAiB,IAAI,IAAI,wBAAwB;IACvD,MAAM,kBAAkB,UACrB,QAAQ,MAAM,eAAe,IAAI,EAAE,KAAK,CAAC,CACzC,KAAK,MAAM;AAEV,YADW,EACD;MAGV;IAEJ,MAAMC,UAAoC,sBAAsB;KAC9D,GAAI,UAAU,aAAa,SAAY,EAAE,qBAAqB,UAAU,UAAU,GAAG,EAAE;KACvF,qBAAqB;KACrB,GAAI,OAAO,mBAAmB,SAC1B,EAAE,qBAAqB,OAAO,gBAAgB,GAC9C,EAAE;KACN,sBAAsB,OAAO;KAC7B,GAAI,OAAO,iBAAiB,SAAY,EAAE,cAAc,OAAO,cAAc,GAAG,EAAE;KACnF,CAAC;IAMF,MAAMC,gBACJ,QAAQ,WAAW,iBACf,CAAC,QAAQ,iBAAiB,GAC1B,CAAC,QAAQ,kBAAkB,IAAI,OAAO,kBAAkB,EAAE,EAAE,IAAI,eAAe,CAAC;IAKtF,MAAM,kBAAkB,4BACtB,OAAO,oBACP,QAAQ,iBACT;AACD,QAAI,oBAAoB,SAAS;KAC/B,MAAM,EAAE,aAAa,2BAA2B,SAAS;AAGzD,SAAI,WAAW,EAIb,4BAA2B,MAAM,SAAS;;IAI9C,MAAMC,WAA0C,UAAU,KAAK,MAC7D,iBAAiB,EAAqC,CACvD;IAED,MAAMC,cAA+B;KAMnC,UACE,0BAA0B,SACtB,WACA,CAAC,GAAG,UAAU;MAAE,MAAM;MAAmB,SAAS;MAAuB,CAAC;KAChF,GAAI,OAAO,eAAe,SACtB,EACE,YAAY;MACV,MAAM,OAAO,WAAW;MACxB,GAAI,OAAO,WAAW,gBAAgB,SAClC,EAAE,aAAa,OAAO,WAAW,aAAa,GAC9C,EAAE;MACN,GAAI,OAAO,WAAW,eAAe,SACjC,EAAE,YAAY,OAAO,WAAW,YAAY,GAC5C,EAAE;MACP,EACF,GACD,EAAE;KACN,OAAO;KACP,GAAI,UAAU,eAAe,SACzB,EAAE,YAAY,UAAU,YAAY,GACpC,OAAO,eAAe,SACpB,EAAE,YAAY,OAAO,YAA0B,GAC/C,EAAE;KACR,UAAU;MACR;MACA;MACA,GAAI,WAAW,SAAY,EAAE,QAAQ,GAAG,EAAE;MAC1C,OAAO,MAAM;MACb;MACD;KACD;KACA,GAAI,UAAU,gBAAgB,SAAY,EAAE,aAAa,UAAU,aAAa,GAAG,EAAE;KACrF,GAAI,UAAU,cAAc,SAAY,EAAE,WAAW,UAAU,WAAW,GAAG,EAAE;KAC/E,oBAAoB;KACrB;IAED,MAAMC,YAAmB,WAAW;IACpC,IAAI,UAAU;IACd,IAAI,aAAa;IACjB,IAAI,kBAAkB,QAAQ;IAC9B,IAAI,cAAc,QAAQ;IAC1B,IAAI,iBAAiB;IACrB,IAAIC;IACJ,IAAIC,aAAyB,EAAE;IAC/B,IAAIC,qBAAyC,EAAE;AAE/C,SAAK,IAAI,WAAW,GAAG,WAAW,cAAc,QAAQ,YAAY;KAClE,MAAM,YAAY,cAAc;AAChC,SAAI,cAAc,OAAW;AAC7B,uBAAkB;KAClB,MAAM,kBAAkB,gBAAgB;AACxC,SAAI,WAAW,GAAG;AAChB,iBAAW;MACX,MAAM,SAAS,YACV,wBAAwB,WAAW,eAAe,CAAC,UAAU,cAC9D;AACJ,YAAM;OACJ,MAAM;OACN,OAAO,MAAM;OACb;OACA;OACA,MAAM;OACN,IAAI;OACJ;OACA;OACA;OACD;AACD,oBAAc;;KAEhB,MAAMC,UAAkC;MACtC,YAAY;MACZ,iBAAiB;MACjB,gBAAgB,EAAE;MAClB,uBAAO,IAAI,KAAkC;MAC7C,YAAY,EAAE;MACf;KACD,IAAIC;KACJ,IAAI,wBAAwB;KAC5B,IAAIC,oBAA2B,WAAW;AAC1C,SAAI;MACF,MAAMC,WAAS,gBAAgB,OAAO,YAAY;AAClD,iBAAW,MAAM,MAAMA,UAAQ;AAK7B,WAAI,OAAO,WAAW,cAAc,UAAU,KAC5C,OAAM,IAAI,kBAAkB,eAAe,UAAU;OAEvD,MAAM,MAAM,oBAAoB,IAAI,QAAQ;AAC5C,WAAI,IAAI,SAAS,OACf,OAAM,IAAI;AAEZ,WAAI,IAAI,kBAAkB,OACxB,iBAAgB,IAAI;AAEtB,WAAI,IAAI,UAAU,OAChB,qBAAoB;QAClB,cAAc,kBAAkB,eAAe,IAAI,MAAM;QACzD,kBAAkB,kBAAkB,mBAAmB,IAAI,MAAM;QACjE,aAAa,kBAAkB,cAAc,IAAI,MAAM;QACvD,GAAI,IAAI,MAAM,oBAAoB,UAClC,kBAAkB,oBAAoB,SAClC,EACE,kBACG,kBAAkB,mBAAmB,MACrC,IAAI,MAAM,mBAAmB,IACjC,GACD,EAAE;QACP;AAEH,WAAI,IAAI,aAAa,KAAM,yBAAwB;;cAE9C,OAAO;AAOd,UACE,OAAO,WACN,iBAAiB,qBAAqB,MAAM,SAAS,cAEtD;MAEF,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAKtE,sBAAgB;OAAE,MAAM,gCAAgC,MAAM;OAAE;OAAS;OAAO;;AAElF,SAAI,kBAAkB,QAAW;AAC/B,kBAAY;AAEZ,UAAI,CADgB,wBAAwB,eAAe,eAAe,CACzD,YAAY,aAAa,cAAc,SAAS,GAAG;AAClE,aAAM;QACJ,MAAM;QACN,OAAO;SAAE,SAAS,cAAc;SAAS,MAAM,cAAc;SAAM;QACpE;AACD,aAAM,SAAS;AACf,aAAM,QAAQ;QAAE,SAAS,cAAc;QAAS,MAAM,cAAc;QAAM;AAC1E,cAAO,OAAO,UAAU,OAAO,cAAc;;AAE/C;;AAEF,SAAI,uBAAuB;AACzB,uBAAiB;AACjB,mBAAa,QAAQ;AACrB,mBAAa,QAAQ;AAMrB,UAAI,QAAQ,gBAAgB,SAAS,EACnC,sBAAqB,CACnB;OACE,MAAM;OACN,MAAM,QAAQ;OACf,CACF;AAEH,gBAAU,gBAAgB,kBAAkB;AAC5C,gBAAU,oBAAoB,kBAAkB;AAChD,gBAAU,eAAe,kBAAkB;AAC3C,UAAI,kBAAkB,oBAAoB,OACxC,WAAU,mBACP,UAAU,mBAAmB,KAAK,kBAAkB;AAEzD;;;AAUJ,QAAI,OAAO,WAAW,CAAC,gBAAgB;AACrC,YAAO,kBAAkB;AACzB,YAAO,OAAO,UAAU,OAAO,cAAc;;AAG/C,QAAI,CAAC,gBAAgB;AACnB,WAAM;MACJ,MAAM;MACN,OAAO;OACL,SAAS;OACT,MAAM;OACP;MACF;AACD,WAAM,SAAS;AACf,WAAM,QAAQ;MAAE,SAAS;MAAyB,MAAM;MAAyB;AACjF,YAAO,OAAO,UAAU,OAAO,cAAc;;AAG/C,aAAS,IAAI,aAAa,UAAU;AACpC,kBAAc,OAAO,aAAa,UAAU;AAC5C,UAAM,MAAM,gBAAgB,UAAU;AACtC,UAAM,MAAM,oBAAoB,UAAU;AAC1C,UAAM,MAAM,eAAe,UAAU;AACrC,QAAI,UAAU,oBAAoB,OAChC,OAAM,MAAM,mBACT,MAAM,MAAM,mBAAmB,KAAK,UAAU;IASnD,MAAM,YACJ,qBAAqB,UAAa,WAAW,SAAS,IAClD,iBAAiB,aAAa,WAAW,GACzC;IACN,MAAM,cAAc,WAAW,iBAAiB,QAAQ,UAAU,aAAa;IAE/E,MAAMC,YAA8B,sBAClC,cAAc,8BAA8B,YAC5C,oBACA,YACA,SACA,gBACD;AACD,aAAS,KAAK,UAAU;AACxB,UAAM,SAAS,KAAK,UAAU;AAE9B,QAAI,WAAW,iBAAiB,MAAM;KACpC,MAAM,MAAM,UAAU,WAAW;AACjC,WAAM;MACJ,MAAM;MACN,OAAO,MAAM;MACb;MACA;MACA,QAAQ,UAAU;MAClB,UAAU,UAAU;MACpB,gBAAgB,UAAU;MAC1B,sBAAsB;MACtB,GAAI,UAAU,mBAAmB,SAC7B,EAAE,gBAAgB,UAAU,gBAAgB,GAC5C,EAAE;MACN,UAAU,UAAU;MACpB,gCAAe,IAAI,MAAM,EAAC,aAAa;MACxC;;IAGH,MAAM,eAAe,WAAW,QAAQ,MAAM,WAAW,IAAI,EAAE,SAAS,CAAC;AACzE,QAAI,aAAa,SAAS,EACxB,OAAM,IAAI,4BAA4B,aAAa,KAAK,MAAM,EAAE,SAAS,CAAC;IAG5E,MAAMC,aAAsB;KAC1B;KACA,WAAW;KACX,0BAAS,IAAI,MAAM,EAAC,aAAa;KACjC,OAAO;KACP,WAAW,EAAE;KACb,SAAS,MAAM;KAChB;AACD,UAAM,MAAM,KAAK,WAAW;AAC5B,8BAA0B,WAAW,KAAK,MAAM,EAAE,SAAS;AAE3D,QAAI,WAAW,SAAS,KAAK,CAAC,aAAa;AACzC,mBAAc,SAAS;AACvB,WAAM;MAAE,MAAM;MAAiB,MAAM;MAAY;;AAGnD,QAAI,WAAW,SAAS,GAAG;KAIzB,MAAMC,iBAAoC;MAAE,GAAG;MAAgB;MAAY;MAAU;KAOrF,IAAIC,QAAoB,EAAE;AAE1B,UAAK,MAAM,QAAQ,YAAY;MAC7B,MAAM,UAAU,WAAW,IAAI,KAAK,SAAS;AAC7C,UAAI,YAAY,QAAW;AACzB,WAAI,MAAM,SAAS,GAAG;AACpB,eAAO,cAAc,OAAO,cAAc,gBAAgB,WAAW;AACrE,gBAAQ,EAAE;;AAEZ,aAAM;QAAE,MAAM;QAAsB,YAAY,KAAK;QAAY;OACjE,MAAM,SAAU,QAAQ,UACtBC,QAAU,sBAAsB;OAClC,MAAM,WAAW,OAAO,SAAS;OACjC,MAAM,WAAW,QAAQ,MAAM;OAK/B,MAAMC,aAA4B;QAChC,aAAa;QACb,WAAW;QACX;QACA,qBAAI,IAAI,MAAM,EAAC,aAAa;QAC5B,aAAa,OAAO;QACpB,oBAAoB;QACpB,kBAAkB,EAAE;QACrB;AACD,aAAM,SAAS,KAAK,WAAW;AAC/B,aAAM;QAAE,MAAM;QAAW,aAAa;QAAS,WAAW;QAAU;AACpE,aAAM,iBAAiB;OACvB,MAAM,WAAW,QAAQ;OAKzB,MAAM,WAAW,KAAK,KAAK;OAC3B,MAAMC,aAAuB,EAAE;OAC/B,IAAIC;OACJ,MAAM,YAAY,SAAS,OAAO,UAAuB;QACvD;QACA,GAAI,QAAQ,SAAS,UAAa,OAAO,SAAS,SAC9C,EAAE,MAAO,QAAQ,QAAQ,OAAO,MAAgB,GAChD,EAAE;QACN;QACD,CAAC;AACF,kBAAW,MAAM,SAAS,UACxB,KAAI,MAAM,SAAS,gBAAiB,YAAW,KAAK,MAAM,KAAK;gBACtD,MAAM,SAAS,YACtB,aAAY,MAAM;OAGtB,MAAM,gBAAgB,KAAK,KAAK,GAAG;OACnC,MAAM,YAAY,MAAM,MAAM,MAAM,MAAM,SAAS;AACnD,WAAI,cAAc,UAAa,UAAU,WAAW,aAAa;QAC/D,MAAMC,YAAuB;SAC3B,YAAY,KAAK;SACjB,UAAU,KAAK;SACf,MAAM,UAAU,WAAW,YAAY,YAAY;SACnD,SAAS,eAAe,SAAS,IAAI,UAAU,SAC7C,UAAU,UAAU,SAAY,KAAK,UAAU,MAAM,YAAY;SAEpE;AACD,YAAI,cAAc,OAChB,CAAC,UAAU,UAAkC,KAAK;SAChD;SACA,SAAS;SACT;SACD,CAAC;AAEJ,cAAM;SACJ,MAAM;SACN,YAAY,KAAK;SACjB,OAAO;SACR;QACD,MAAM,OAAO,UAAU,UAAU;AACjC,iBAAS,KAAK;SAAE,MAAM;SAAQ,YAAY,KAAK;SAAY,SAAS;SAAM,CAAC;AAC3E,cAAM,SAAS,KAAK;SAAE,MAAM;SAAQ,YAAY,KAAK;SAAY,SAAS;SAAM,CAAC;AACjF;;OAEF,MAAM,SAAS,WAAW,KAAK,GAAG;OAClC,MAAMC,YAA+B;QACnC;QACA,SAAS;SACP,YAAY,KAAK;SACjB,UAAU,KAAK;SACf,QAAQ;SACR,YAAY;SACb;QACD;QACD;AACD,WAAI,cAAc,OAChB,CAAC,UAAU,UAAkC,KAAK,UAAU;AAE9D,aAAM;QACJ,MAAM;QACN,YAAY,KAAK;QACjB;QACA,YAAY;QACb;AACD,gBAAS,KAAK;QAAE,MAAM;QAAQ,YAAY,KAAK;QAAY,SAAS;QAAQ,CAAC;AAC7E,aAAM,SAAS,KAAK;QAClB,MAAM;QACN,YAAY,KAAK;QACjB,SAAS;QACV,CAAC;AACF;;AAcF,UANsB,MAAM,oBADP,aAAa,IAAI,KAAK,SAAS,EAGlD,KAAK,MACL,gBACA,OACD,EACkB;AACjB,WAAI,MAAM,SAAS,GAAG;AACpB,eAAO,cAAc,OAAO,cAAc,gBAAgB,WAAW;AACrE,gBAAQ,EAAE;;AAEZ,aAAM;QAAE,MAAM;QAAsB,YAAY,KAAK;QAAY;OACjE,MAAMC,WAAyB;QAC7B,YAAY,KAAK;QACjB,UAAU,KAAK;QACf,MAAM,KAAK;QACX,8BAAa,IAAI,MAAM,EAAC,aAAa;QACtC;AACD,aAAM,iBAAiB,KAAK,SAAS;AACrC,aAAM,SAAS;OAIf,MAAM,YAAY,mBAAmB,eAAe,MAAM,GAAG;AAC7D,WAAI,cAAc,OAAW,OAAM,eAAe;AAClD,WAAI,iBAAiB,OAAO,EAAG,OAAM,gBAAgB,CAAC,GAAG,iBAAiB;AAC1E,aAAM;QACJ,MAAM;QACN,YAAY,KAAK;QAClB;AACD,WAAI,OAAO,oBAAoB,OAC7B,OAAM,OAAO,gBAAgB,IAC3B,MAAM,IACN,SACA;QACE,IAAI,MAAM;QACV,UAAU,MAAM;QAChB,WAAW;QAGX,OAAO,kBAAkB,OAAO,EAAE,oBAAoB,MAAM,CAAC;QAC7D,iBAAiB,EAAE;QACnB;QACA,4BAAW,IAAI,MAAM,EAAC,aAAa;QACpC,EACD;QAAE,QAAQ;QAAQ,QAAQ;QAAa,UAAU;QAAa,CAC/D;AAEH,cAAO,OAAO,UAAU,OAAO,cAAc;;AAG/C,YAAM,KAAK,KAAK;;AAGlB,SAAI,MAAM,SAAS,EACjB,QAAO,cAAc,OAAO,cAAc,gBAAgB,WAAW;;AAIzE,UAAM;KAAE,MAAM;KAAY;KAAY,OAAO;KAAW;AAExD,QAAI,WAAW,WAAW,GAAG;AAC3B,WAAM,SAAS;AACf;;;WAGG,OAAO;GACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACtE,MAAM,OAAO,iBAAiB,oBAAqB,MAAM,OAAkB;AAC3E,SAAM;IAAE,MAAM;IAAe,OAAO;KAAE;KAAS;KAAM;IAAE;AACvD,SAAM,SAAS;AACf,SAAM,QAAQ;IAAE;IAAS;IAAM;AAC/B,UAAO,OAAO,UAAU,OAAO,cAAc;YACrC;AAIR,OAAI,iBAAiB,OACnB,cAAa,oBAAoB,SAAS,cAAc;;AAI5D,MAAI,MAAM,WAAW,WAAW;GAK9B,MAAM,UAAU,kCAAkC,SAAS;AAC3D,SAAM,SAAS;AACf,SAAM,QAAQ;IAAE;IAAS,MAAM;IAAkB;AACjD,SAAM;IAAE,MAAM;IAAe,OAAO;KAAE;KAAS,MAAM;KAAkB;IAAE;;AAM3E,MAAI,MAAM,WAAW,eAAe,OAAO,YAAY,SAAS,cAAc;GAC5E,MAAM,MAAM,OAAO,cAAc,UAAU,GAAG;AAC9C,OAAI;IACF,MAAMC,SAAkB,KAAK,MAAM,eAAe,IAAI,CAAC;AACvD,kBAAc,SACZ,OAAO,WAAW,WAAW,SAAY,OAAO,WAAW,OAAO,MAAM,OAAO,GAAG;YAE7E,OAAO;IACd,MAAM,UAAU,wCACd,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAExD,UAAM;KAAE,MAAM;KAAe,OAAO;MAAE;MAAS,MAAM;MAA4B;KAAE;AACnF,UAAM,SAAS;AACf,UAAM,QAAQ;KAAE;KAAS,MAAM;KAA4B;;;EAS/D,MAAM,eAAe,OAAO,YAAY;AACxC,MAAI,MAAM,WAAW,eAAe,iBAAiB,UAAa,aAAa,SAAS,GAAG;GACzF,MAAM,WAAW,MAAM,kBAAkB,cAAc,cAAc,QAAQ;IAC3E,OAAO;IACP,OAAO,MAAM;IACb;IACA;IACD,CAAC;AACF,OAAI,CAAC,SAAS,IAAI;AAChB,UAAM;KACJ,MAAM;KACN,eAAe,SAAS;KACxB,OAAO;KACP,QAAQ,SAAS;KAClB;IACD,MAAM,UAAU,qBAAqB,SAAS,KAAK,qBAAqB,SAAS;AACjF,UAAM;KAAE,MAAM;KAAe,OAAO;MAAE;MAAS,MAAM;MAAqB;KAAE;AAC5E,UAAM,SAAS;AACf,UAAM,QAAQ;KAAE;KAAS,MAAM;KAAqB;cAC3C,SAAS,UAAU,cAAc,OAC1C,eAAc,SAAS,SAAS;;AAGpC,mBAAiB;AACjB,SAAO,OAAO,UAAU,OAAO,cAAc;;;;;;;CAQ/C,gBAAgB,UACd,OACA,UACiE;AAGjE,SAAO,sBAAsB,SAAS,EACpC,uBAAsB,OAAO,EAAE,QAAQ,qBAAqB,gBAAgB,CAAC;EAE/E,MAAM,SAAS,SAAS,OAAO,SAAS;AAKxC,MAAI,OAAO,WAAW,eAAe,OAAO,WAAW,SACrD,OAAM,YAAY,QAAQ,OAAO,MAAM,GAAG,CAAC,YAAY,GAAG;AAE5D,QAAM;GAAE,MAAM;GAAa,OAAO,OAAO,MAAM;GAAI;GAAQ;AAC3D,SAAO;;CAGT,SAAS,SACP,OACA,UACsB;AACtB,QAAM,aAAa,MAAM,+BAAc,IAAI,MAAM,EAAC,aAAa;AAI/D,SAAO;GACL,QAAQ,SAAS;GACjB,OAAO,MAAM;GACb,QAAQ,MAAM;GACd,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,OAAO,GAAG,EAAE;GACpD;GACR;;CAGH,MAAM,UACJ,OACA,YACuC;EACvC,MAAM,OAAO,WAAW,EAAE;AAC1B,SAAO,GACJ,OAAO,sBAAsB;GAC5B,MAAM,MAAM,QAAQ,OAAO,KAAK;AAChC,UAAO;IACL,MAAM,OAA2D;KAC/D,MAAM,IAAI,MAAM,IAAI,MAAM;AAC1B,SAAI,EAAE,SAAS,KACb,QAAO;MAAE,MAAM;MAAM,OAAO;MAAW;AAEzC,YAAO;MAAE,MAAM;MAAO,OAAO,EAAE;MAAO;;IAExC,MAAM,SAA6D;AACjE,WAAM,IAAI,OAAO,OAA6C;AAC9D,YAAO;MAAE,MAAM;MAAM,OAAO;MAAW;;IAE1C;KAEJ;;CAGH,MAAM,MAAM,OACV,OACA,YACkC;EAElC,MAAM,MAAM,QAAQ,OADP,WAAW,EAAE,CACM;EAChC,IAAI,OAAO,MAAM,IAAI,MAAM;AAC3B,SAAO,KAAK,SAAS,KACnB,QAAO,MAAM,IAAI,MAAM;EAKzB,MAAM,SAAS,KAAK;AACpB,MAAI,WAAW,OACb,OAAM,IAAI,MAAM,qDAAqD;AAEvE,SAAO;;CAGT,MAAM,SAAS,YAA8B;EAC3C,MAAM,EAAE,SAAS,WAAW,QAAQ;AACpC,eAAa,KAAK,GAAG,KAAK;AAC1B,MAAI,mBAAmB,OACrB,oBAAmB,KAAK;GACtB,MAAM;GACN,OAAO,eAAe;GACvB,CAAwB;;CAI7B,MAAM,YAAY,YAA8B;EAC9C,MAAM,EAAE,SAAS,WAAW,QAAQ;AACpC,kBAAgB,KAAK,GAAG,KAAK;AAC7B,MAAI,mBAAmB,OACrB,oBAAmB,KAAK;GACtB,MAAM;GACN,OAAO,eAAe;GACvB,CAAwB;;CAI7B,MAAM,SAAS,YAAiC;AAC9C,iBAAe,WAAW,EAAE;AAC5B,mBAAiB,OAAO;;CAG1B,MAAM,UACJ,UAA8B,EAAE,KACqB;EACrD,MAAM,cAAc,QAAQ,eAAe;AA+E3C,SAhE+D;GAC7D,MAfe,QAAQ,QAAQ,YAAY,OAAO;GAgBlD,aAfkB,QAAQ,eAAe,qBAAqB,OAAO,KAAK;GAgB1E,aAfa;IACb,QAAQ,MAA2C;IACnD,YAAY,OAAgB;KAC1B,SAAS;KACT,MAAM;KACP;IACD,eAAwC;KACtC,MAAM;KACN,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,EAAE;KACzC,UAAU,CAAC,QAAQ;KACpB;IACF;GASC,iBAAiB;GACjB,MAAM,QAAQ,OAAO,KAAK;IAOxB,MAAMC,WAAoC;KACxC,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,IAAI,QAAQ,GAAG,EAAE;KAC3D,GAAI,KAAK,WAAW,SAAS,SAAY,EAAE,MAAM,IAAI,WAAW,MAAe,GAAG,EAAE;KACpF,GAAI,KAAK,WAAW,cAAc,SAC9B,EAAE,WAAW,IAAI,WAAW,WAAW,GACvC,EAAE;KACP;IACD,MAAMC,OACJ,QAAQ,gBAAgB,UAAa,QAAQ,SACxC,CACC,GAAG,QAAQ,YAAY,IAAI,WAAW,SAAS,EAC/C;KAAE,MAAM;KAAiB,SAAS,MAAM;KAAO,CAChD,GACD,MAAM;AACZ,QAAI,gBAAgB,OAAO;KAKzB,MAAMC,QAAkB,EAAE;KAC1B,IAAIC;AACJ,gBAAW,MAAM,MAAM,OAAO,MAAM,SAAS,CAC3C,KAAI,GAAG,SAAS,gBAAiB,OAAM,KAAK,GAAG,KAAK;cAC3C,GAAG,SAAS,YAAa,aAAY,GAAG;AAEnD,SAAI,cAAc,UAAa,UAAU,WAAW,YAClD,OAAM,IAAI,MACR,cAAc,OAAO,KAAK,IAAI,UAAU,SACtC,UAAU,UAAU,SAAY,KAAK,UAAU,MAAM,YAAY,KAEpE;AAEH,YAAO,MAAM,KAAK,OAAO;;IAE3B,MAAM,SAAS,MAAM,IAAI,MAAM,SAAS;AAGxC,QAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MACR,cAAc,OAAO,KAAK,IAAI,OAAO,SACnC,OAAO,UAAU,SAAY,KAAK,OAAO,MAAM,YAAY,KAE9D;AAEH,QAAI,gBAAgB,OAAQ,QAAO;AACnC,WAAO,OAAO;;GAEjB;;CAIH,MAAM,UAAU,OAAO,YAA2D;AAIhF,MAAI,WAAW,OAAW,QAAO,qBAAqB,YAAY;AAGlE,MAAI,OAAO,gBAAgB,SAAU,QAAO,qBAAqB,oBAAoB;AAGrF,MAAI,mBAAmB,OAAW,QAAO,qBAAqB,gBAAgB;AAO9E,SAAO,MAAM,IAAI,SAA8B,SAAS,WAAW;AACjE,yBAAsB,KAAK;IAAE;IAAS;IAAS;IAAQ,CAAC;IACxD;;CAGJ,MAAM,SAAS,OACb,YACyC;EACzC,MAAM,QAAQ,gBAAgB,MAAM,OAAO,OAAO;EAClD,MAAM,YAAY,gBAAgB,aAAa,WAAW,OAAO;AAsBjE,SAAO,UArBgD;GACrD,UAAU,QAAQ;GAClB,GAAI,QAAQ,0BAA0B,SAClC,EAAE,uBAAuB,QAAQ,uBAAuB,GACxD,EAAE;GACN,GAAI,QAAQ,cAAc,SAAY,EAAE,WAAW,QAAQ,WAAW,GAAG,EAAE;GAC3E,GAAI,QAAQ,kBAAkB,SAAY,EAAE,eAAe,QAAQ,eAAe,GAAG,EAAE;GACvF,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,QAAQ,GAAG,EAAE;GAIlE,OAAO,UAAU;AACf,uBAAmB,KAAK,MAA6B;;GAIvD,GAAI,OAAO,eAAe,SAAY,EAAE,YAAY,OAAO,YAAY,GAAG,EAAE;GAC5E;GACA;GACA;GACD,CAC6C;;CAMhD,MAAM,wBAAwB,OAAO,OAAO;CAC5C,MAAMC,WAA4B;EAChC,OAAO,OAAO,SAAiB,SAAgC;GAC7D,MAAM,QAAQ,gBAAgB,MAAM;GACpC,MAAM,MAAM,MAAM,WAAW,MAAM,OAAO,SAAS,KAAK;AAGxD,sBAAmB,KAAK;IACtB,MAAM;IACN;IACA,WAAW,gBAAgB,aAAa;IACxC;IACA;IACD,CAAwB;AACzB,UAAO;;EAET,MAAM,OAAO,SAA+B;GAC1C,MAAM,eAAe,MAAM,SAAS,gBAAgB,MAAM;GAC1D,MAAM,OAAO,MAAM,WAAW,KAAK,cAAc,KAAK;AACtD,sBAAmB,KAAK;IACtB,MAAM;IACN,OAAO,gBAAgB,MAAM;IAC7B,WAAW,gBAAgB,aAAa;IACxC;IACA;IACA;IACA,aAAa,MAAM;IACpB,CAAwB;AACzB,UAAO;;EAEV;AAED,CAAK,OAAO;AAiBZ,QAfqC;EACnC,IAAI;EACJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;EACX;;;;;;;;;;;;;AAgBH,eAAe,oBACb,MACA,MACA,SACA,QACkB;CAClB,MAAM,YAAY,MAAM;AACxB,KAAI,cAAc,UAAa,cAAc,MAAO,QAAO;AAC3D,KAAI,cAAc,KAAM,QAAO;CAC/B,MAAMC,WAAiC;EACrC,YAAY;EACZ,YAAY;EACZ;EACA,QAAQ,QAAQ;EAChB,QAAQ;EACR,SAAS,sBAAsB;EAC/B,sBAAsB;EACtB,qBAAqB;EACtB;AACD,QAAO,QAAQ,MAAM,UAAU,MAAe,SAAS,CAAC;;;;;;;;AAS1D,SAAS,uBAAwD;CAC/D,MAAM,YAAY,MAAc,aAC9B,QAAQ,uBAAO,IAAI,MAAM,kEAAkE,CAAC;AAC9F,QAAO,EAAE,SAAS,UAAU"}
@@ -0,0 +1,52 @@
1
+ import { ProviderError } from "@graphorin/core";
2
+
3
+ //#region src/fallback/index.d.ts
4
+
5
+ /**
6
+ * Operator-supplied policy that lets the consumer toggle which
7
+ * `ProviderError` kinds the agent runtime should consider eligible
8
+ * for whole-step retries against the next model in the chain.
9
+ *
10
+ * @stable
11
+ */
12
+ interface AgentFallbackPolicy {
13
+ /** Default `true`. */
14
+ readonly rateLimitEligible?: boolean;
15
+ /** Default `true`. */
16
+ readonly capacityEligible?: boolean;
17
+ /** Default `true`. */
18
+ readonly contextLengthEligible?: boolean;
19
+ /** Default `false` — `withRetry` already covers transient errors. */
20
+ readonly transientEligible?: boolean;
21
+ }
22
+ /**
23
+ * Stable taxonomy returned by {@link isAgentFallbackEligible} on
24
+ * eligible errors.
25
+ *
26
+ * @stable
27
+ */
28
+ type AgentFallbackReason = 'rate-limit' | 'capacity' | 'context-length' | 'transient';
29
+ /**
30
+ * Outcome of {@link isAgentFallbackEligible}.
31
+ *
32
+ * @stable
33
+ */
34
+ interface AgentFallbackEligibility {
35
+ readonly eligible: boolean;
36
+ readonly reason?: AgentFallbackReason;
37
+ }
38
+ /**
39
+ * Pure dispatcher that maps a {@link ProviderError} to one of four
40
+ * eligible reasons or to `eligible: false` if the error is on the
41
+ * bypass list (`auth | invalid-input | content-filter | cancelled`).
42
+ *
43
+ * The function is intentionally allocation-free on the hot path so
44
+ * the agent runtime can call it once per provider error per step
45
+ * without budget concerns.
46
+ *
47
+ * @stable
48
+ */
49
+ declare function isAgentFallbackEligible(error: ProviderError, policy?: AgentFallbackPolicy): AgentFallbackEligibility;
50
+ //#endregion
51
+ export { AgentFallbackEligibility, AgentFallbackPolicy, AgentFallbackReason, isAgentFallbackEligible };
52
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/fallback/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;UA4BiB,mBAAA;;;;;;;;;;;;;;;;KAiBL,mBAAA;;;;;;UAOK,wBAAA;;oBAEG;;;;;;;;;;;;;iBAqBJ,uBAAA,QACP,wBACC,sBACP"}
@@ -0,0 +1,53 @@
1
+ //#region src/fallback/index.ts
2
+ const DEFAULT_POLICY = {
3
+ rateLimitEligible: true,
4
+ capacityEligible: true,
5
+ contextLengthEligible: true,
6
+ transientEligible: false
7
+ };
8
+ /**
9
+ * Pure dispatcher that maps a {@link ProviderError} to one of four
10
+ * eligible reasons or to `eligible: false` if the error is on the
11
+ * bypass list (`auth | invalid-input | content-filter | cancelled`).
12
+ *
13
+ * The function is intentionally allocation-free on the hot path so
14
+ * the agent runtime can call it once per provider error per step
15
+ * without budget concerns.
16
+ *
17
+ * @stable
18
+ */
19
+ function isAgentFallbackEligible(error, policy = {}) {
20
+ const merged = {
21
+ ...DEFAULT_POLICY,
22
+ ...policy
23
+ };
24
+ switch (error.kind) {
25
+ case "rate-limit": return merged.rateLimitEligible ? {
26
+ eligible: true,
27
+ reason: "rate-limit"
28
+ } : { eligible: false };
29
+ case "capacity": return merged.capacityEligible ? {
30
+ eligible: true,
31
+ reason: "capacity"
32
+ } : { eligible: false };
33
+ case "context-length": return merged.contextLengthEligible ? {
34
+ eligible: true,
35
+ reason: "context-length"
36
+ } : { eligible: false };
37
+ case "transient": return merged.transientEligible ? {
38
+ eligible: true,
39
+ reason: "transient"
40
+ } : { eligible: false };
41
+ case "invalid-request":
42
+ case "unauthorized":
43
+ case "content-filter":
44
+ case "unknown": return { eligible: false };
45
+ default:
46
+ error.kind;
47
+ return { eligible: false };
48
+ }
49
+ }
50
+
51
+ //#endregion
52
+ export { isAgentFallbackEligible };
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["DEFAULT_POLICY: Required<AgentFallbackPolicy>","merged: Required<AgentFallbackPolicy>"],"sources":["../../src/fallback/index.ts"],"sourcesContent":["/**\n * Agent-level model fallback chain primitives.\n *\n * The agent runtime walks `[primaryModel, ...Agent.fallbackModels]`\n * on fallback-eligible errors during the per-step provider call.\n * `isAgentFallbackEligible(...)` is the pure decision function the\n * runtime calls once per `ProviderError`.\n *\n * Layering: this module is the **agent-step-level** fallback\n * (re-tries the whole step against a different model on rate-limit\n * / capacity / context-length / transient errors). The\n * **request-level** `withFallback` provider middleware\n * (`@graphorin/provider`) is a separate concern — it retries against\n * an alternate provider serving the **same** model concept on\n * transient errors inside one `provider.stream(...)` call.\n *\n * @packageDocumentation\n */\n\nimport type { ProviderError } from '@graphorin/core';\n\n/**\n * Operator-supplied policy that lets the consumer toggle which\n * `ProviderError` kinds the agent runtime should consider eligible\n * for whole-step retries against the next model in the chain.\n *\n * @stable\n */\nexport interface AgentFallbackPolicy {\n /** Default `true`. */\n readonly rateLimitEligible?: boolean;\n /** Default `true`. */\n readonly capacityEligible?: boolean;\n /** Default `true`. */\n readonly contextLengthEligible?: boolean;\n /** Default `false` — `withRetry` already covers transient errors. */\n readonly transientEligible?: boolean;\n}\n\n/**\n * Stable taxonomy returned by {@link isAgentFallbackEligible} on\n * eligible errors.\n *\n * @stable\n */\nexport type AgentFallbackReason = 'rate-limit' | 'capacity' | 'context-length' | 'transient';\n\n/**\n * Outcome of {@link isAgentFallbackEligible}.\n *\n * @stable\n */\nexport interface AgentFallbackEligibility {\n readonly eligible: boolean;\n readonly reason?: AgentFallbackReason;\n}\n\nconst DEFAULT_POLICY: Required<AgentFallbackPolicy> = {\n rateLimitEligible: true,\n capacityEligible: true,\n contextLengthEligible: true,\n transientEligible: false,\n};\n\n/**\n * Pure dispatcher that maps a {@link ProviderError} to one of four\n * eligible reasons or to `eligible: false` if the error is on the\n * bypass list (`auth | invalid-input | content-filter | cancelled`).\n *\n * The function is intentionally allocation-free on the hot path so\n * the agent runtime can call it once per provider error per step\n * without budget concerns.\n *\n * @stable\n */\nexport function isAgentFallbackEligible(\n error: ProviderError,\n policy: AgentFallbackPolicy = {},\n): AgentFallbackEligibility {\n const merged: Required<AgentFallbackPolicy> = { ...DEFAULT_POLICY, ...policy };\n switch (error.kind) {\n case 'rate-limit':\n return merged.rateLimitEligible\n ? { eligible: true, reason: 'rate-limit' }\n : { eligible: false };\n case 'capacity':\n return merged.capacityEligible ? { eligible: true, reason: 'capacity' } : { eligible: false };\n case 'context-length':\n return merged.contextLengthEligible\n ? { eligible: true, reason: 'context-length' }\n : { eligible: false };\n case 'transient':\n return merged.transientEligible\n ? { eligible: true, reason: 'transient' }\n : { eligible: false };\n case 'invalid-request':\n case 'unauthorized':\n case 'content-filter':\n case 'unknown':\n return { eligible: false };\n default: {\n // Defensive: unknown error kind treated as ineligible.\n const _exhaustive: never = error.kind;\n void _exhaustive;\n return { eligible: false };\n }\n }\n}\n"],"mappings":";AAyDA,MAAMA,iBAAgD;CACpD,mBAAmB;CACnB,kBAAkB;CAClB,uBAAuB;CACvB,mBAAmB;CACpB;;;;;;;;;;;;AAaD,SAAgB,wBACd,OACA,SAA8B,EAAE,EACN;CAC1B,MAAMC,SAAwC;EAAE,GAAG;EAAgB,GAAG;EAAQ;AAC9E,SAAQ,MAAM,MAAd;EACE,KAAK,aACH,QAAO,OAAO,oBACV;GAAE,UAAU;GAAM,QAAQ;GAAc,GACxC,EAAE,UAAU,OAAO;EACzB,KAAK,WACH,QAAO,OAAO,mBAAmB;GAAE,UAAU;GAAM,QAAQ;GAAY,GAAG,EAAE,UAAU,OAAO;EAC/F,KAAK,iBACH,QAAO,OAAO,wBACV;GAAE,UAAU;GAAM,QAAQ;GAAkB,GAC5C,EAAE,UAAU,OAAO;EACzB,KAAK,YACH,QAAO,OAAO,oBACV;GAAE,UAAU;GAAM,QAAQ;GAAa,GACvC,EAAE,UAAU,OAAO;EACzB,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACH,QAAO,EAAE,UAAU,OAAO;EAC5B;AAE6B,SAAM;AAEjC,UAAO,EAAE,UAAU,OAAO"}