@genesislcap/ai-assistant 15.15.2 → 15.16.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.
- package/dist/ai-assistant.api.json +271 -2
- package/dist/ai-assistant.d.ts +90 -1
- package/dist/chat-driver.cjs +72 -0
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +72 -0
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +221 -97
- package/dist/dts/components/ai-driver/ai-driver.d.ts +11 -0
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +31 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +10 -0
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +2 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +1 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +3 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/index.d.ts +1 -1
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/file-attachments.test.d.ts +2 -0
- package/dist/dts/main/file-attachments.test.d.ts.map +1 -0
- package/dist/dts/main/interaction-cost.test.d.ts +2 -0
- package/dist/dts/main/interaction-cost.test.d.ts.map +1 -0
- package/dist/dts/main/main.d.ts +27 -0
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/react.d.ts +2 -1
- package/dist/dts/state/debug-event-log.d.ts +1 -1
- package/dist/dts/state/debug-event-log.d.ts.map +1 -1
- package/dist/dts/types/ai-chat-widget.d.ts +8 -0
- package/dist/dts/types/ai-chat-widget.d.ts.map +1 -1
- package/dist/esm/components/chat-driver/chat-driver.js +75 -1
- package/dist/esm/components/chat-driver/chat-driver.test.js +90 -0
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +22 -0
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +76 -0
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +14 -0
- package/dist/esm/main/file-attachments.test.js +164 -0
- package/dist/esm/main/interaction-cost.test.js +107 -0
- package/dist/esm/main/main.js +193 -21
- package/dist/esm/main/main.template.js +1 -0
- package/dist/esm/state/debug-event-log.js +6 -0
- package/dist/react.cjs +6 -1
- package/dist/react.mjs +6 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/components/ai-driver/ai-driver.ts +11 -0
- package/src/components/chat-driver/chat-driver.test.ts +109 -0
- package/src/components/chat-driver/chat-driver.ts +78 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +29 -0
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +107 -0
- package/src/components/orchestrating-driver/orchestrating-driver.ts +17 -0
- package/src/index.ts +4 -1
- package/src/main/file-attachments.test.ts +215 -0
- package/src/main/interaction-cost.test.ts +140 -0
- package/src/main/main.template.ts +1 -0
- package/src/main/main.ts +204 -22
- package/src/state/debug-event-log.ts +8 -0
- package/src/types/ai-chat-widget.ts +8 -0
package/dist/chat-driver.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/chat-driver-node.ts", "../../../../../node_modules/tslib/tslib.es6.mjs", "../../../foundation-ai/dist/esm/utils/combine-signals.js", "../../../../../node_modules/consola/dist/core.mjs", "../../../../../node_modules/consola/dist/browser.mjs", "../../../foundation-logger/dist/esm/logger.js", "../../../foundation-ai/dist/esm/utils/logger.js", "../../../foundation-ai/dist/esm/interactions/criteria-interpretation.js", "../../../foundation-ai/dist/esm/providers/anthropic-provider.js", "../../../foundation-ai/dist/esm/providers/default-provider.js", "../../../foundation-ai/dist/esm/providers/gemini-provider.js", "../../../foundation-ai/dist/esm/transports/budget-exhausted-error.js", "../../../foundation-ai/dist/esm/transports/provider-refused.js", "../../../foundation-ai/dist/esm/types/config.types.js", "../../../foundation-ai/dist/esm/utils/image-mime.js", "../../../foundation-ai/dist/esm/utils/temperature.js", "../../../foundation-ai/dist/esm/utils/token-cost.js", "../../../foundation-ai/dist/esm/utils/tool-schema.js", "../../../foundation-ai/dist/esm/utils/abort-reason.js", "../../../foundation-ai/dist/esm/utils/abortable-delay.js", "../../../foundation-ai/dist/esm/transports/ndjson-frames.js", "../../../foundation-ai/dist/esm/transports/retry-hints.js", "../../../foundation-ai/dist/esm/transports/post-with-retry.js", "../../../foundation-ai/dist/esm/transports/anthropic-transport.js", "../../../foundation-ai/dist/esm/transports/gemini-malformed-call.js", "../../../foundation-ai/dist/esm/transports/gemini-transport.js", "../../../foundation-ai/dist/esm/ai-provider.js", "../src/channel/ai-activity-bus.ts", "../src/config/validate-providers.ts", "../src/state/debug-event-log.ts", "../src/utils/logger.ts", "../src/state/interaction-context.ts", "../src/utils/condense-history.ts", "../src/utils/history-transform.ts", "../src/utils/sum-usage.ts", "../src/utils/tool-fold.ts", "../src/components/chat-driver/chat-driver.ts", "../src/components/orchestrating-driver/orchestrating-driver.ts", "../src/config/config.ts", "../src/config/define-stateful-agent.ts", "../src/config/fallback-agents.ts", "../src/utils/usage-rows.ts", "../src/utils/flatten-sub-agent-messages.ts", "../src/state/persistence/build-timeline-entries.ts", "../src/state/persistence/diagnostics.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Node-safe headless entry point for the AI assistant driver stack (`@genesislcap/ai-assistant/chat-driver`).\n *\n * Re-exports ONLY the framework-agnostic pieces \u2014 {@link ChatDriver}, `OrchestratingDriver`, the\n * agent-config surface (`defineAgent`, `defineStatefulAgent`, and the config/input types), and the\n * activity-bus types/`NOOP_ACTIVITY_BUS` \u2014 WITHOUT the DOM/FAST component layer that the package's\n * main entry (`.`) pulls in via `main/main`. This lets a Node / CommonJS host (server, unit tests,\n * benches) construct and drive `ChatDriver` over `foundation-ai` providers with no jsdom and no\n * custom-element registration.\n *\n * Every module re-exported here is DOM-clean at import time (no `window`/`document`/`sessionStorage`\n * eval-time access, no `@genesislcap/web-core`). The activity bus is imported for its types and the\n * no-op default; its cross-tab `BroadcastChannel` is created lazily and only in a browser, so\n * pulling this entry into Node opens nothing.\n *\n * @packageDocumentation\n * @beta\n */\nexport * from './components/chat-driver';\nexport * from './components/orchestrating-driver';\nexport * from './channel/ai-activity-channel';\nexport * from './channel/ai-activity-bus';\nexport * from './config/config';\nexport * from './config/define-stateful-agent';\nexport * from './config/fallback-agents';\n\n// Provider-construction surface, re-exported from `@genesislcap/foundation-ai` so a headless\n// consumer builds its registry from the SAME bundled foundation-ai instance the driver uses. That\n// shared identity matters: `ChatDriver`'s malformed/truncated handling does `instanceof` on the\n// transports' error classes, so a second foundation-ai copy (a separate dep) would silently break\n// those checks. NAMED re-exports only \u2014 `export *` would drag in the FAST-DI module\n// (`@microsoft/fast-foundation` \u2192 `fast-element` \u2192 `document` at eval); by naming just these,\n// esbuild tree-shakes the DI module out and the bundle stays Node-loadable.\nexport {\n AnthropicProvider,\n AnthropicTransport,\n GeminiProvider,\n GeminiTransport,\n MutableAIProviderRegistry,\n // Supported-model allowlists \u2014 so a headless consumer validates a configured model id against\n // foundation-ai's REAL list instead of maintaining a parallel hardcoded copy that silently drifts\n // as the platform adds models (a valid new model would otherwise look like a misconfiguration).\n // GENC-1461, create PR #1644 review.\n SUPPORTED_ANTHROPIC_MODEL_IDS,\n SUPPORTED_GEMINI_MODEL_IDS,\n // The provider wall (GENC-1506). Re-exported for the same anti-drift reason as the model lists\n // above, and it matters more here because the other end of this contract is in ANOTHER REPO:\n // genesis-create's ai-service stamps `PROVIDER_REFUSED_CODE` onto its proxy responses and shows\n // `DEFAULT_PROVIDER_REFUSED_MESSAGE` on its own generation surfaces. Hand-copying either would\n // drift silently \u2014 a renamed code stops classifying, and a second copy of the sentence survives\n // the first reword. `ProviderRefusedError` is here so a headless caller can `instanceof` it\n // against the same bundled instance the driver throws from.\n DEFAULT_PROVIDER_REFUSED_MESSAGE,\n PROVIDER_REFUSED_CODE,\n ProviderRefusedError,\n isObservableAIProviderRegistry,\n // Request pricing. Re-exported HERE, not left to a direct `@genesislcap/foundation-ai`\n // import, for the same reason as everything above it: a headless host that adds its own\n // foundation-ai dependency gets a second copy, and the driver's malformed/truncated\n // handling does `instanceof` on the transports' error classes. Reaching the pricing\n // should not cost a consumer that guarantee.\n //\n // These take RAW provider usage rather than a `ChatMessage` \u2014 see the foundation-ai\n // module docs. They are for the path where nothing stamped a cost (a proxied or\n // server-side call holding a usage block); when a message already carries `cost`, use\n // it, because it was computed with the per-TTL cache split the message no longer has.\n ANTHROPIC_CACHE_READ_MULTIPLIER,\n ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER,\n ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER,\n anthropicRatesFor,\n anthropicTokenCost,\n GEMINI_CACHED_INPUT_MULTIPLIER,\n GEMINI_LONG_CONTEXT_THRESHOLD,\n geminiRatesFor,\n geminiTokenCost,\n // Resolves a model id to its vendor, so a caller holding only `message.model` can pick\n // between the two cost functions above without maintaining its own model\u2192vendor map.\n vendorOfModel,\n} from '@genesislcap/foundation-ai';\nexport type {\n // Re-exported alongside `sumUsage` below \u2014 a consumer that can call the function but cannot NAME\n // its return type has to restate the shape by hand, which is how the buckets get mis-summed.\n AggregateUsage,\n AIProvider,\n AIProviderRegistry,\n AnthropicModelId,\n CachePolicy,\n // The attachment union, so a headless caller can hand a screenshot to a model or return one\n // from a tool handler without restating the shape \u2014 and, more to the point, without missing\n // that the image arm's `kind` is REQUIRED and is the only thing the transports branch on.\n ChatAttachment,\n ChatFallback,\n ChatImageAttachment,\n ChatMessage,\n ChatRequestOptions,\n ChatTextAttachment,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n ChatToolResult,\n GeminiModelId,\n // Pricing input/output shapes, alongside the functions re-exported above \u2014 a caller that\n // can invoke them but cannot name their argument or result has to restate the shape by\n // hand, which is how the token buckets get mixed up between the two providers.\n AnthropicUsageRecord,\n GeminiUsageRecord,\n TokenCost,\n TokenCostBreakdown,\n TokenRates,\n} from '@genesislcap/foundation-ai';\n\n// Usage/cost summation. A headless consumer attributing spend to a run has no other route to it:\n// the transports' `getLifetimeCost()` is per-instance and lifetime-scoped, so a shared registry\n// makes it unattributable, and re-deriving cost from token counts is wrong in the one direction\n// that matters (`inputTokens` is total prompt size INCLUDING the cached part, so re-pricing charges\n// every cached token at full rate). `sumUsage` reads the per-request cost the transports already\n// stamped, and recurses into `toolCalls[].subAgentTrace` \u2014 where the entire spend of a delegating\n// agent lives \u2014 and into `compaction.rolledUpUsage`, which is spend whose messages no longer exist.\n// Both are invisible when omitted: the total is merely too low, which reads as a cheap run.\n//\n// `addUsage`/`emptyUsage` are the composition primitives for a conversation that CONTINUES across\n// rounds \u2014 see the guidance on `sumUsage` itself. `totalTokens` exists because the four buckets of\n// an `AggregateUsage` are disjoint and safe to add, which the per-message fields are NOT.\n//\n// `messageUsage` is the single-message projection of the same arithmetic \u2014 what ONE request\n// cost, in the same four-bucket shape. It is what prices a turn snapshot (see\n// `TurnSnapshot.usage`), and the reason a consumer needs it separately is that the response\n// to a *failed* attempt never reaches history, so `sumUsage` over the transcript cannot see\n// that spend at all.\nexport { addUsage, emptyUsage, messageUsage, sumUsage, totalTokens } from './utils/sum-usage';\n\n// Per-call projection, for the cases an aggregate cannot serve: usage rows for\n// per-project attribution, a cost dashboard, or auditing which turns came back\n// unpriced. `usageRows` is guaranteed to reconcile with `sumUsage` \u2014 including spend a\n// compaction banked, which has no message of its own and which a naive per-message walk\n// therefore drops while the total keeps it. Both take RAW history; `UsageRow` is\n// deliberately not a `ChatMessage`, so passing rows back into `sumUsage` (which recurses\n// itself, and would double-count) does not compile.\nexport { usageRows } from './utils/usage-rows';\nexport type { UsageRow } from './utils/usage-rows';\n\n// Debug-log harvesting (GENC-1461 unified diagnostics). A headless consumer collates its driver's\n// log \u2014 `buildTimelineEntries({ turnSnapshots: driver.getTurnSnapshots(), messages:\n// driver.getHistory(), metaEvents: getMetaEvents(sessionKey) })` \u2192 `DiagnosticEntry[]` \u2014 ships it to\n// the client, which folds it into the assistant's debug log via `InteractionResult.diagnostics`\n// (see `ChatDriver.getExternalDiagnostics`). `clearSession(sessionKey)` drops the per-request\n// meta-event bucket so the long-lived server process's module registry doesn't grow unbounded.\n// All three modules are DOM-clean, so the node entry stays Node-loadable.\nexport { clearSession, getMetaEvents } from './state/debug-event-log';\nexport type { MetaEvent } from './state/debug-event-log';\nexport { buildTimelineEntries } from './state/persistence/build-timeline-entries';\nexport type { TurnSnapshotLike } from './state/persistence/build-timeline-entries';\n// `withFreshMetaSnapshot` matters to a headless consumer that stitches a STORED stream: the\n// newest stored `meta-snapshot` is frozen at the last config-signature change, so its context\n// and cost figures are as old as that. Pass a fresh snapshot of your own through this before\n// `assembleDebugLog`, or state in your own output that the totals are historical.\nexport { assembleDebugLog, withFreshMetaSnapshot } from './state/persistence/diagnostics';\nexport type { DebugLog, DiagnosticEntry } from './state/persistence/diagnostics';\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nvar ownKeys = function(o) {\n ownKeys = Object.getOwnPropertyNames || function (o) {\n var ar = [];\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\n return ar;\n };\n return ownKeys(o);\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __esDecorate,\n __runInitializers,\n __propKey,\n __setFunctionName,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n __rewriteRelativeImportExtension,\n};\n", "const noop = () => { };\n/**\n * Fan several `AbortSignal`s into one. The returned signal aborts as soon\n * as any input signal aborts, adopting that signal's `reason` \u2014 so callers can\n * distinguish, for example, a timeout (`TimeoutError`) from a user/lifecycle\n * cancellation (`AbortError`) by inspecting `signal.reason`. `undefined`\n * entries are ignored, letting callers pass optional signals directly.\n *\n * NOTE: the platform already provides exactly this \u2014 `AbortSignal.any([...])`\n * \u2014 but it is part of a newer spec than we target here. Our TypeScript config\n * is pinned to an older standard library (tsconfig `target: ES2015`,\n * `lib: [...ES2020]`), which predates `AbortSignal.any()`/`AbortSignal.timeout()`,\n * so those APIs are not in our typings (and have a narrower runtime-support\n * floor). This helper is the hand-rolled stand-in until the lib target is\n * raised, at which point this can be deleted in favour of `AbortSignal.any`.\n *\n * @example\n * const timeout = new AbortController();\n * const timer = setTimeout(\n * () => timeout.abort(new DOMException('Request timed out', 'TimeoutError')),\n * ms,\n * );\n * const { signal, dispose } = combineSignals([callerSignal, timeout.signal]);\n * try {\n * return await fetch(url, { signal });\n * } finally {\n * clearTimeout(timer);\n * dispose();\n * }\n */\nexport function combineSignals(signals) {\n const controller = new AbortController();\n const inputs = signals.filter((s) => s != null);\n // If any input is already aborted, adopt its reason immediately. Nothing to\n // wire up, so the disposer is a no-op.\n const preAborted = inputs.find((s) => s.aborted);\n if (preAborted) {\n controller.abort(preAborted.reason);\n return { signal: controller.signal, dispose: noop };\n }\n // `dispose` and `onAbort` reference each other; both are hoisted function\n // declarations so neither is read before it is initialised.\n function dispose() {\n for (const s of inputs) {\n s.removeEventListener('abort', onAbort);\n }\n }\n // `this` is the input signal the listener was attached to, so `this.reason`\n // is the reason of whichever signal aborted first.\n function onAbort() {\n controller.abort(this.reason);\n dispose();\n }\n for (const s of inputs) {\n s.addEventListener('abort', onAbort);\n }\n return { signal: controller.signal, dispose };\n}\n", "const LogLevels = {\n silent: Number.NEGATIVE_INFINITY,\n fatal: 0,\n error: 0,\n warn: 1,\n log: 2,\n info: 3,\n success: 3,\n fail: 3,\n ready: 3,\n start: 3,\n box: 3,\n debug: 4,\n trace: 5,\n verbose: Number.POSITIVE_INFINITY\n};\nconst LogTypes = {\n // Silent\n silent: {\n level: -1\n },\n // Level 0\n fatal: {\n level: LogLevels.fatal\n },\n error: {\n level: LogLevels.error\n },\n // Level 1\n warn: {\n level: LogLevels.warn\n },\n // Level 2\n log: {\n level: LogLevels.log\n },\n // Level 3\n info: {\n level: LogLevels.info\n },\n success: {\n level: LogLevels.success\n },\n fail: {\n level: LogLevels.fail\n },\n ready: {\n level: LogLevels.info\n },\n start: {\n level: LogLevels.info\n },\n box: {\n level: LogLevels.info\n },\n // Level 4\n debug: {\n level: LogLevels.debug\n },\n // Level 5\n trace: {\n level: LogLevels.trace\n },\n // Verbose\n verbose: {\n level: LogLevels.verbose\n }\n};\n\nfunction isPlainObject$1(value) {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {\n return false;\n }\n if (Symbol.iterator in value) {\n return false;\n }\n if (Symbol.toStringTag in value) {\n return Object.prototype.toString.call(value) === \"[object Module]\";\n }\n return true;\n}\n\nfunction _defu(baseObject, defaults, namespace = \".\", merger) {\n if (!isPlainObject$1(defaults)) {\n return _defu(baseObject, {}, namespace, merger);\n }\n const object = Object.assign({}, defaults);\n for (const key in baseObject) {\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = baseObject[key];\n if (value === null || value === void 0) {\n continue;\n }\n if (merger && merger(object, key, value, namespace)) {\n continue;\n }\n if (Array.isArray(value) && Array.isArray(object[key])) {\n object[key] = [...value, ...object[key]];\n } else if (isPlainObject$1(value) && isPlainObject$1(object[key])) {\n object[key] = _defu(\n value,\n object[key],\n (namespace ? `${namespace}.` : \"\") + key.toString(),\n merger\n );\n } else {\n object[key] = value;\n }\n }\n return object;\n}\nfunction createDefu(merger) {\n return (...arguments_) => (\n // eslint-disable-next-line unicorn/no-array-reduce\n arguments_.reduce((p, c) => _defu(p, c, \"\", merger), {})\n );\n}\nconst defu = createDefu();\n\nfunction isPlainObject(obj) {\n return Object.prototype.toString.call(obj) === \"[object Object]\";\n}\nfunction isLogObj(arg) {\n if (!isPlainObject(arg)) {\n return false;\n }\n if (!arg.message && !arg.args) {\n return false;\n }\n if (arg.stack) {\n return false;\n }\n return true;\n}\n\nlet paused = false;\nconst queue = [];\nclass Consola {\n options;\n _lastLog;\n _mockFn;\n /**\n * Creates an instance of Consola with specified options or defaults.\n *\n * @param {Partial<ConsolaOptions>} [options={}] - Configuration options for the Consola instance.\n */\n constructor(options = {}) {\n const types = options.types || LogTypes;\n this.options = defu(\n {\n ...options,\n defaults: { ...options.defaults },\n level: _normalizeLogLevel(options.level, types),\n reporters: [...options.reporters || []]\n },\n {\n types: LogTypes,\n throttle: 1e3,\n throttleMin: 5,\n formatOptions: {\n date: true,\n colors: false,\n compact: true\n }\n }\n );\n for (const type in types) {\n const defaults = {\n type,\n ...this.options.defaults,\n ...types[type]\n };\n this[type] = this._wrapLogFn(defaults);\n this[type].raw = this._wrapLogFn(\n defaults,\n true\n );\n }\n if (this.options.mockFn) {\n this.mockTypes();\n }\n this._lastLog = {};\n }\n /**\n * Gets the current log level of the Consola instance.\n *\n * @returns {number} The current log level.\n */\n get level() {\n return this.options.level;\n }\n /**\n * Sets the minimum log level that will be output by the instance.\n *\n * @param {number} level - The new log level to set.\n */\n set level(level) {\n this.options.level = _normalizeLogLevel(\n level,\n this.options.types,\n this.options.level\n );\n }\n /**\n * Displays a prompt to the user and returns the response.\n * Throw an error if `prompt` is not supported by the current configuration.\n *\n * @template T\n * @param {string} message - The message to display in the prompt.\n * @param {T} [opts] - Optional options for the prompt. See {@link PromptOptions}.\n * @returns {promise<T>} A promise that infer with the prompt options. See {@link PromptOptions}.\n */\n prompt(message, opts) {\n if (!this.options.prompt) {\n throw new Error(\"prompt is not supported!\");\n }\n return this.options.prompt(message, opts);\n }\n /**\n * Creates a new instance of Consola, inheriting options from the current instance, with possible overrides.\n *\n * @param {Partial<ConsolaOptions>} options - Optional overrides for the new instance. See {@link ConsolaOptions}.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n create(options) {\n const instance = new Consola({\n ...this.options,\n ...options\n });\n if (this._mockFn) {\n instance.mockTypes(this._mockFn);\n }\n return instance;\n }\n /**\n * Creates a new Consola instance with the specified default log object properties.\n *\n * @param {InputLogObject} defaults - Default properties to include in any log from the new instance. See {@link InputLogObject}.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n withDefaults(defaults) {\n return this.create({\n ...this.options,\n defaults: {\n ...this.options.defaults,\n ...defaults\n }\n });\n }\n /**\n * Creates a new Consola instance with a specified tag, which will be included in every log.\n *\n * @param {string} tag - The tag to include in each log of the new instance.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n withTag(tag) {\n return this.withDefaults({\n tag: this.options.defaults.tag ? this.options.defaults.tag + \":\" + tag : tag\n });\n }\n /**\n * Adds a custom reporter to the Consola instance.\n * Reporters will be called for each log message, depending on their implementation and log level.\n *\n * @param {ConsolaReporter} reporter - The reporter to add. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n addReporter(reporter) {\n this.options.reporters.push(reporter);\n return this;\n }\n /**\n * Removes a custom reporter from the Consola instance.\n * If no reporter is specified, all reporters will be removed.\n *\n * @param {ConsolaReporter} reporter - The reporter to remove. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n removeReporter(reporter) {\n if (reporter) {\n const i = this.options.reporters.indexOf(reporter);\n if (i !== -1) {\n return this.options.reporters.splice(i, 1);\n }\n } else {\n this.options.reporters.splice(0);\n }\n return this;\n }\n /**\n * Replaces all reporters of the Consola instance with the specified array of reporters.\n *\n * @param {ConsolaReporter[]} reporters - The new reporters to set. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n setReporters(reporters) {\n this.options.reporters = Array.isArray(reporters) ? reporters : [reporters];\n return this;\n }\n wrapAll() {\n this.wrapConsole();\n this.wrapStd();\n }\n restoreAll() {\n this.restoreConsole();\n this.restoreStd();\n }\n /**\n * Overrides console methods with Consola logging methods for consistent logging.\n */\n wrapConsole() {\n for (const type in this.options.types) {\n if (!console[\"__\" + type]) {\n console[\"__\" + type] = console[type];\n }\n console[type] = this[type].raw;\n }\n }\n /**\n * Restores the original console methods, removing Consola overrides.\n */\n restoreConsole() {\n for (const type in this.options.types) {\n if (console[\"__\" + type]) {\n console[type] = console[\"__\" + type];\n delete console[\"__\" + type];\n }\n }\n }\n /**\n * Overrides standard output and error streams to redirect them through Consola.\n */\n wrapStd() {\n this._wrapStream(this.options.stdout, \"log\");\n this._wrapStream(this.options.stderr, \"log\");\n }\n _wrapStream(stream, type) {\n if (!stream) {\n return;\n }\n if (!stream.__write) {\n stream.__write = stream.write;\n }\n stream.write = (data) => {\n this[type].raw(String(data).trim());\n };\n }\n /**\n * Restores the original standard output and error streams, removing the Consola redirection.\n */\n restoreStd() {\n this._restoreStream(this.options.stdout);\n this._restoreStream(this.options.stderr);\n }\n _restoreStream(stream) {\n if (!stream) {\n return;\n }\n if (stream.__write) {\n stream.write = stream.__write;\n delete stream.__write;\n }\n }\n /**\n * Pauses logging, queues incoming logs until resumed.\n */\n pauseLogs() {\n paused = true;\n }\n /**\n * Resumes logging, processing any queued logs.\n */\n resumeLogs() {\n paused = false;\n const _queue = queue.splice(0);\n for (const item of _queue) {\n item[0]._logFn(item[1], item[2]);\n }\n }\n /**\n * Replaces logging methods with mocks if a mock function is provided.\n *\n * @param {ConsolaOptions[\"mockFn\"]} mockFn - The function to use for mocking logging methods. See {@link ConsolaOptions[\"mockFn\"]}.\n */\n mockTypes(mockFn) {\n const _mockFn = mockFn || this.options.mockFn;\n this._mockFn = _mockFn;\n if (typeof _mockFn !== \"function\") {\n return;\n }\n for (const type in this.options.types) {\n this[type] = _mockFn(type, this.options.types[type]) || this[type];\n this[type].raw = this[type];\n }\n }\n _wrapLogFn(defaults, isRaw) {\n return (...args) => {\n if (paused) {\n queue.push([this, defaults, args, isRaw]);\n return;\n }\n return this._logFn(defaults, args, isRaw);\n };\n }\n _logFn(defaults, args, isRaw) {\n if ((defaults.level || 0) > this.level) {\n return false;\n }\n const logObj = {\n date: /* @__PURE__ */ new Date(),\n args: [],\n ...defaults,\n level: _normalizeLogLevel(defaults.level, this.options.types)\n };\n if (!isRaw && args.length === 1 && isLogObj(args[0])) {\n Object.assign(logObj, args[0]);\n } else {\n logObj.args = [...args];\n }\n if (logObj.message) {\n logObj.args.unshift(logObj.message);\n delete logObj.message;\n }\n if (logObj.additional) {\n if (!Array.isArray(logObj.additional)) {\n logObj.additional = logObj.additional.split(\"\\n\");\n }\n logObj.args.push(\"\\n\" + logObj.additional.join(\"\\n\"));\n delete logObj.additional;\n }\n logObj.type = typeof logObj.type === \"string\" ? logObj.type.toLowerCase() : \"log\";\n logObj.tag = typeof logObj.tag === \"string\" ? logObj.tag : \"\";\n const resolveLog = (newLog = false) => {\n const repeated = (this._lastLog.count || 0) - this.options.throttleMin;\n if (this._lastLog.object && repeated > 0) {\n const args2 = [...this._lastLog.object.args];\n if (repeated > 1) {\n args2.push(`(repeated ${repeated} times)`);\n }\n this._log({ ...this._lastLog.object, args: args2 });\n this._lastLog.count = 1;\n }\n if (newLog) {\n this._lastLog.object = logObj;\n this._log(logObj);\n }\n };\n clearTimeout(this._lastLog.timeout);\n const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0;\n this._lastLog.time = logObj.date;\n if (diffTime < this.options.throttle) {\n try {\n const serializedLog = JSON.stringify([\n logObj.type,\n logObj.tag,\n logObj.args\n ]);\n const isSameLog = this._lastLog.serialized === serializedLog;\n this._lastLog.serialized = serializedLog;\n if (isSameLog) {\n this._lastLog.count = (this._lastLog.count || 0) + 1;\n if (this._lastLog.count > this.options.throttleMin) {\n this._lastLog.timeout = setTimeout(\n resolveLog,\n this.options.throttle\n );\n return;\n }\n }\n } catch {\n }\n }\n resolveLog(true);\n }\n _log(logObj) {\n for (const reporter of this.options.reporters) {\n reporter.log(logObj, {\n options: this.options\n });\n }\n }\n}\nfunction _normalizeLogLevel(input, types = {}, defaultLevel = 3) {\n if (input === void 0) {\n return defaultLevel;\n }\n if (typeof input === \"number\") {\n return input;\n }\n if (types[input] && types[input].level !== void 0) {\n return types[input].level;\n }\n return defaultLevel;\n}\nConsola.prototype.add = Consola.prototype.addReporter;\nConsola.prototype.remove = Consola.prototype.removeReporter;\nConsola.prototype.clear = Consola.prototype.removeReporter;\nConsola.prototype.withScope = Consola.prototype.withTag;\nConsola.prototype.mock = Consola.prototype.mockTypes;\nConsola.prototype.pause = Consola.prototype.pauseLogs;\nConsola.prototype.resume = Consola.prototype.resumeLogs;\nfunction createConsola(options = {}) {\n return new Consola(options);\n}\n\nexport { Consola, LogLevels, LogTypes, createConsola };\n", "import { createConsola as createConsola$1 } from './core.mjs';\nexport { Consola, LogLevels, LogTypes } from './core.mjs';\n\nclass BrowserReporter {\n options;\n defaultColor;\n levelColorMap;\n typeColorMap;\n constructor(options) {\n this.options = { ...options };\n this.defaultColor = \"#7f8c8d\";\n this.levelColorMap = {\n 0: \"#c0392b\",\n // Red\n 1: \"#f39c12\",\n // Yellow\n 3: \"#00BCD4\"\n // Cyan\n };\n this.typeColorMap = {\n success: \"#2ecc71\"\n // Green\n };\n }\n _getLogFn(level) {\n if (level < 1) {\n return console.__error || console.error;\n }\n if (level === 1) {\n return console.__warn || console.warn;\n }\n return console.__log || console.log;\n }\n log(logObj) {\n const consoleLogFn = this._getLogFn(logObj.level);\n const type = logObj.type === \"log\" ? \"\" : logObj.type;\n const tag = logObj.tag || \"\";\n const color = this.typeColorMap[logObj.type] || this.levelColorMap[logObj.level] || this.defaultColor;\n const style = `\n background: ${color};\n border-radius: 0.5em;\n color: white;\n font-weight: bold;\n padding: 2px 0.5em;\n `;\n const badge = `%c${[tag, type].filter(Boolean).join(\":\")}`;\n if (typeof logObj.args[0] === \"string\") {\n consoleLogFn(\n `${badge}%c ${logObj.args[0]}`,\n style,\n // Empty string as style resets to default console style\n \"\",\n ...logObj.args.slice(1)\n );\n } else {\n consoleLogFn(badge, style, ...logObj.args);\n }\n }\n}\n\nfunction createConsola(options = {}) {\n const consola2 = createConsola$1({\n reporters: options.reporters || [new BrowserReporter({})],\n prompt(message, options2 = {}) {\n if (options2.type === \"confirm\") {\n return Promise.resolve(confirm(message));\n }\n return Promise.resolve(prompt(message));\n },\n ...options\n });\n return consola2;\n}\nconst consola = createConsola();\n\nexport { consola, createConsola, consola as default };\n", "import { createConsola as createConsolaBrowser } from 'consola/browser';\nimport { LogLevels, createConsola as createConsolaCore, } from 'consola/core';\n/**\n * Used to set the logging level.\n *\n * @example Explicitly set the level of an imported package beyond the current runtime level.\n * ```ts\n * import { LogLevel } from '@genesislcap/foundation-logger';\n * import { logger as myPackageLogger } from 'my-package';\n * myPackageLogger.level = LogLevel.Error;\n * ```\n *\n * @public\n */\nexport { LogLevels } from 'consola/core';\n/**\n * The default logger options.\n * @public\n */\nexport const defaultLoggerOptions = {\n level: LogLevels.debug,\n};\n/**\n * Creates a logger with the given name and options.\n *\n * @example Create a logger in my-package/utils.\n * ```ts\n * import { createLogger } from '@genesislcap/foundation-logger';\n * export const logger = createLogger('my-package');\n * ```\n *\n * @example Using the logger within my-package.\n * ```ts\n * import { logger } from '../utils';\n * logger.debug(`Data retrieved from ${resourceName}`);\n * logger.info(this.toggled ? 'On' : 'Off');\n * logger.warn('Not available in this browser.');\n * ```\n *\n * @example Explicitly set the level of an imported package.\n * ```ts\n * import { logger as commsLogger } from '@genesislcap/foundation-comms';\n * import { LogLevel } from '@genesislcap/foundation-logger';\n * commsLogger.level = LogLevel.Warn;\n * ```\n *\n * @param name - The name to give the logger.\n * @param options - The options to use when creating the logger.\n * @returns The resulting logger.\n * @public\n */\nexport function createLogger(name, options = defaultLoggerOptions) {\n const createConsola = typeof window !== 'undefined' ? createConsolaBrowser : createConsolaCore;\n const logger = createConsola().withTag(name);\n if ((options === null || options === void 0 ? void 0 : options.level) !== undefined)\n logger.level = options.level;\n const typedLogger = logger;\n typedLogger.deprecated = (symbol, instruction = 'Consult docs for better alternative.', removalVersionTarget) => {\n typedLogger.warn(`Deprecated symbol used '${symbol}'. ${instruction}`, `${removalVersionTarget ? `Will be removed in version ${removalVersionTarget}.` : ''}`);\n };\n return typedLogger;\n}\n", "import { createLogger } from '@genesislcap/foundation-logger';\nexport const logger = createLogger('foundation-ai');\n", "import { logger } from '../utils';\nconst CLAUSE_SCHEMA = {\n type: 'object',\n properties: {\n field: { type: 'string', description: 'Field name from available metadata' },\n operator: {\n type: 'string',\n enum: [\n 'contains',\n 'equals',\n 'startsWith',\n 'endsWith',\n 'greaterThan',\n 'lessThan',\n 'greaterThanOrEqual',\n 'lessThanOrEqual',\n 'notEqual',\n 'dateIsToday',\n 'dateIsAfter',\n 'dateIsBefore',\n 'dateIsEqual',\n 'dateIsGreaterEqual',\n 'dateIsLessEqual',\n 'dateTimeIsAfter',\n 'dateTimeIsBefore',\n 'dateTimeIsGreaterEqual',\n 'dateTimeIsLessEqual',\n ],\n },\n value: {\n type: ['string', 'number', 'boolean', 'null'],\n description: 'Value for the clause; null for dateIsToday',\n },\n },\n required: ['field', 'operator', 'value'],\n additionalProperties: false,\n};\n/**\n * Standard JSON Schema for criteria interpretation output.\n * Used by Chrome Prompt API (responseConstraint) and other providers.\n *\n * @beta\n */\nexport const CRITERIA_JSON_SCHEMA = {\n type: 'object',\n properties: {\n groups: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n logic: {\n type: 'string',\n enum: ['and', 'or'],\n description: 'How clauses within the group are combined',\n },\n negated: {\n type: 'boolean',\n default: false,\n description: 'If true, negate the entire group',\n },\n clauses: {\n type: 'array',\n items: CLAUSE_SCHEMA,\n },\n },\n required: ['logic', 'negated', 'clauses'],\n additionalProperties: false,\n },\n },\n },\n required: ['groups'],\n additionalProperties: false,\n};\n/**\n * OpenAI-specific response_format wrapper for structured output.\n *\n * @beta\n */\nexport const OPENAI_CRITERIA_RESPONSE_FORMAT = {\n type: 'json_schema',\n json_schema: {\n name: 'criteria_interpretation',\n strict: true,\n schema: CRITERIA_JSON_SCHEMA,\n },\n};\nconst DEFAULT_SYSTEM_PROMPT = `You are a criteria builder. Convert natural language into structured search criteria.\nReturn a JSON object with a \"groups\" array. Each group has: logic (\"and\" or \"or\"), optional negated (boolean), and clauses (array).\nEach clause has: field (string), operator (from enum), value (string|number|boolean|null).\n- When the user says \"or\" (e.g. \"quantity 100 or price > 50\"), use a group with logic \"or\" and multiple clauses.\n- When the user says \"not\" or \"except\", set negated: true on the group.\n- When the user says \"and\" or lists conditions without \"or\", use logic \"and\".\nUse dateIsToday with value null for \"today\" queries. Use yyyyMMdd for dates, yyyyMMdd-HH:mm for datetimes.`;\n/**\n * Builds the system prompt for criteria interpretation.\n *\n * @beta\n */\nexport function buildCriteriaSystemPrompt(fields = [], customInstructions) {\n const fieldList = fields\n .map((f) => {\n var _a, _b, _c, _d;\n return typeof f === 'string'\n ? f\n : ((_d = (_c = (_b = (_a = f === null || f === void 0 ? void 0 : f.NAME) !== null && _a !== void 0 ? _a : f === null || f === void 0 ? void 0 : f.name) !== null && _b !== void 0 ? _b : f === null || f === void 0 ? void 0 : f.field) !== null && _c !== void 0 ? _c : f === null || f === void 0 ? void 0 : f.label) !== null && _d !== void 0 ? _d : '');\n })\n .filter(Boolean)\n .join(', ');\n const basePrompt = customInstructions !== null && customInstructions !== void 0 ? customInstructions : DEFAULT_SYSTEM_PROMPT;\n const fieldsLine = `Available fields: ${fieldList || 'unknown - use common field names like NAME, ID, DATE, etc.'}`;\n return `${basePrompt}\\n${fieldsLine}`;\n}\n/**\n * Builds the user prompt for criteria interpretation.\n *\n * @beta\n */\nexport function buildCriteriaUserPrompt(input) {\n return `Convert to criteria: \"${input}\"`;\n}\n/**\n * Parses the raw response text into CriteriaInterpretationResult.\n *\n * @beta\n */\nexport function parseCriteriaResponse(text) {\n if (!(text === null || text === void 0 ? void 0 : text.trim())) {\n logger.debug('parseCriteriaResponse: empty or null input');\n return null;\n }\n try {\n const parsed = JSON.parse(text);\n if (!(parsed === null || parsed === void 0 ? void 0 : parsed.groups) || !Array.isArray(parsed.groups)) {\n logger.debug('parseCriteriaResponse: missing or invalid groups in response');\n return null;\n }\n return {\n groups: parsed.groups,\n };\n }\n catch (e) {\n logger.debug('parseCriteriaResponse: invalid JSON', e);\n return null;\n }\n}\n", "import { __asyncDelegator, __asyncGenerator, __asyncValues, __await, __awaiter } from \"tslib\";\nimport { buildCriteriaSystemPrompt, buildCriteriaUserPrompt, CRITERIA_JSON_SCHEMA, parseCriteriaResponse, } from '../interactions';\nimport { logger } from '../utils';\n/**\n * Anthropic Claude AI provider. Uses {@link AnthropicTransport} to handle requests.\n * Implements criteria interpretation and multi-turn chat.\n *\n * @beta\n */\nexport class AnthropicProvider {\n constructor(config, transport) {\n this.transport = transport;\n this.criteriaInstructions = config.criteriaInstructions;\n }\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n const config = this.transport.getConfig();\n return { provider: 'anthropic', model: config.model, contextLimit: config.contextLimit };\n });\n }\n interpretCriteria(input, context) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const fields = (_a = context === null || context === void 0 ? void 0 : context.fields) !== null && _a !== void 0 ? _a : [];\n const systemPrompt = buildCriteriaSystemPrompt(fields, this.criteriaInstructions);\n const userPrompt = buildCriteriaUserPrompt(input);\n try {\n const raw = yield this.transport.sendStructuredPrompt({\n systemPrompt,\n userPrompt,\n responseSchema: CRITERIA_JSON_SCHEMA,\n });\n return parseCriteriaResponse(raw);\n }\n catch (e) {\n logger.error('AnthropicProvider interpretCriteria failed:', e);\n return null;\n }\n });\n }\n prompt(message, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const response = yield this.transport.sendChatMessage([], message, options);\n return response.content;\n });\n }\n chat(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.transport.sendChatMessage(history, userMessage, options);\n });\n }\n streamChat(history, userMessage, options) {\n return __asyncGenerator(this, arguments, function* streamChat_1() {\n if ('streamChatMessage' in this.transport &&\n typeof this.transport.streamChatMessage === 'function') {\n yield __await(yield* __asyncDelegator(__asyncValues(this.transport.streamChatMessage(history, userMessage, options))));\n }\n else {\n const msg = yield __await(this.transport.sendChatMessage(history, userMessage, options));\n yield yield __await({ delta: msg.content, done: true, toolCalls: msg.toolCalls });\n }\n });\n }\n}\n", "import { __awaiter } from \"tslib\";\n/**\n * Default no-op AI provider. Used when no provider is configured.\n * Components should check for capability support and show \"Configure AI\" state when appropriate.\n *\n * @beta\n */\nexport class DefaultAIProvider {\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n return { provider: 'none', model: '' };\n });\n }\n interpretCriteria(_input, _context) {\n return __awaiter(this, void 0, void 0, function* () {\n return null;\n });\n }\n}\n", "import { __asyncDelegator, __asyncGenerator, __asyncValues, __await, __awaiter } from \"tslib\";\nimport { buildCriteriaSystemPrompt, buildCriteriaUserPrompt, CRITERIA_JSON_SCHEMA, parseCriteriaResponse, } from '../interactions';\nimport { logger } from '../utils';\n/**\n * Gemini AI provider. Uses {@link GeminiTransport} to handle requests.\n * Implements criteria interpretation and multi-turn chat.\n *\n * @beta\n */\nexport class GeminiProvider {\n constructor(config, transport) {\n this.transport = transport;\n this.criteriaInstructions = config.criteriaInstructions;\n }\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n const config = this.transport.getConfig();\n return { provider: 'gemini', model: config.model, contextLimit: config.contextLimit };\n });\n }\n interpretCriteria(input, context) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const fields = (_a = context === null || context === void 0 ? void 0 : context.fields) !== null && _a !== void 0 ? _a : [];\n const systemPrompt = buildCriteriaSystemPrompt(fields, this.criteriaInstructions);\n const userPrompt = buildCriteriaUserPrompt(input);\n try {\n const raw = yield this.transport.sendStructuredPrompt({\n systemPrompt,\n userPrompt,\n responseSchema: CRITERIA_JSON_SCHEMA,\n });\n return parseCriteriaResponse(raw);\n }\n catch (e) {\n logger.error('GeminiProvider interpretCriteria failed:', e);\n return null;\n }\n });\n }\n prompt(message, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const response = yield this.transport.sendChatMessage([], message, options);\n return response.content;\n });\n }\n chat(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.transport.sendChatMessage(history, userMessage, options);\n });\n }\n streamChat(history, userMessage, options) {\n return __asyncGenerator(this, arguments, function* streamChat_1() {\n if ('streamChatMessage' in this.transport &&\n typeof this.transport.streamChatMessage === 'function') {\n yield __await(yield* __asyncDelegator(__asyncValues(this.transport.streamChatMessage(history, userMessage, options))));\n }\n else {\n // Fallback: non-streaming chat exposed as a single chunk\n const msg = yield __await(this.transport.sendChatMessage(history, userMessage, options));\n yield yield __await({ delta: msg.content, done: true, toolCalls: msg.toolCalls });\n }\n });\n }\n}\n", "/**\n * The AI-spend budget wall (GENC-1464 workstream C/D).\n *\n * Lives in its own module rather than beside `ResponseTruncatedError` in\n * `anthropic-transport.ts` because it is raised from `post-with-retry.ts`, which\n * both transports import \u2014 homing it in a transport would close an import cycle\n * (transport \u2192 post-with-retry \u2192 transport) that the repo's `circular` check\n * rejects.\n */\n/** The proxy's machine-readable rejection code for an exhausted AI budget. */\nexport const BUDGET_EXCEEDED_CODE = 'BUDGET_EXCEEDED';\n/**\n * Display name for each concrete AI vendor: the **single source** every\n * transport's `vendorLabel` is read from, and the only place a vendor's name is\n * spelled for a user.\n *\n * This map is the hinge of the per-vendor budget model (GENC-1464). A wall is\n * attributed to a vendor by reverse-looking-up the label the refused transport\n * stamped on its {@link BudgetExhaustedError} \u2014 so a label that drifts from this\n * map (a literal typo, a casing change, a new vendor added with a hardcoded\n * string) silently degrades every wall from that transport to \"unattributable\"\n * and re-locks the whole session instead of just that vendor. It fails safe, but\n * the feature quietly stops working, which is why the transports read their label\n * from here rather than restating it.\n *\n * The map has **two kinds of entry**, and the difference matters:\n *\n * - The {@link BUDGETED_VENDORS} \u2014 `anthropic` and `gemini` \u2014 reach the model\n * through the ai-service proxy, are metered by it, and stamp their label on a\n * {@link BudgetExhaustedError}. For these the label is both an attribution key\n * and display copy.\n * - `chrome` and `openai` are **display-only**. `ChromeProvider` talks to the\n * on-device Prompt API and the proxy refuses `openai` outright, so neither can\n * be refused for budget or stamp a label \u2014 but both report a `provider` from\n * `getStatus()`, which puts them in the assistant's reachable set, which is\n * what the blocked banner names when it tells a walled user where they can\n * still go (\"Switch to Chrome to keep going.\"). Dropping either entry would\n * print the raw type there.\n *\n * `'none'` is excluded deliberately: it is the \"no provider configured\" sentinel,\n * not a vendor, and nothing can be refused by it \u2014 nor switched to.\n *\n * @beta\n */\nexport const VENDOR_LABELS = Object.freeze({\n anthropic: 'Anthropic',\n gemini: 'Gemini',\n openai: 'OpenAI',\n chrome: 'Chrome',\n});\n/**\n * The vendors whose spend the ai-service proxy meters \u2014 i.e. the only vendors\n * that can raise a {@link BudgetExhaustedError}, and therefore the only ones a\n * 402's `otherVendorAvailable: false` is a statement about.\n *\n * Deliberately narrower than the keys of {@link VENDOR_LABELS}, and it must stay\n * exactly the proxy's own list \u2014 `VENDORS` in ai-service's `utils/aiVendor.js`.\n * A vendor listed here that the proxy does not meter gets walled by the\n * `otherVendorAvailable: false` sweep on a verdict that says nothing about it,\n * and if it is reachable, `blocked` then derives true and locks a composer with\n * headroom left.\n *\n * Two vendors are excluded for that reason:\n * - `chrome` runs on-device \u2014 no pot to exhaust, and free.\n * - `openai` is **not budgeted by the proxy**. ai-service rejects it up front\n * with `400 UNSUPPORTED_PROVIDER` (`SUPPORTED_PROVIDERS` in `aiVendor.js`), no\n * `MODEL_PRICING` row names it, and `otherVendorAvailable` is computed over\n * Anthropic and Gemini alone. So it can never raise a 402, and a 402 is never\n * a statement about it.\n *\n * @beta\n */\nexport const BUDGETED_VENDORS = Object.freeze([\n 'anthropic',\n 'gemini',\n]);\n/**\n * Whether this vendor's spend is metered by the proxy \u2014 see\n * {@link BUDGETED_VENDORS}.\n *\n * A HOST-FACING helper with, deliberately, no internal caller: the library's\n * own consumers iterate {@link BUDGETED_VENDORS} directly (structural, cannot\n * drift), while a host writing its own budget pre-flight or status surface\n * needs the membership test in predicate form. Kept exported for that use \u2014\n * genesis-create's pre-flight is the shape of consumer it exists for.\n *\n * @beta\n */\nexport const isBudgetedVendor = (vendor) => vendor != null && BUDGETED_VENDORS.includes(vendor);\n/** Reverse index of {@link VENDOR_LABELS}, lower-cased, built once. */\nconst VENDOR_TYPE_BY_LABEL = new Map(Object.entries(VENDOR_LABELS).map(([type, label]) => [\n label.toLowerCase(),\n type,\n]));\n/**\n * The {@link AIProviderType} behind a vendor label, or `undefined` for a label\n * no vendor claims.\n *\n * Case-insensitive and whitespace-tolerant, because the label travels as free\n * text on the wire (the driver contract carries `vendorLabel`, not the type) and\n * an unrecognised label must degrade to \"unattributable\" rather than to a wrong\n * attribution \u2014 blocking the wrong vendor is worse than blocking none.\n *\n * @beta\n */\nexport function vendorTypeOfLabel(label) {\n if (typeof label !== 'string')\n return undefined;\n return VENDOR_TYPE_BY_LABEL.get(label.trim().toLowerCase());\n}\n/**\n * HTTP status the ai-service proxy rejects an over-budget request with, in both\n * the legacy JSON mode (the response status) and the NDJSON framed mode (the\n * `status` on the terminal `err` frame).\n *\n * Deliberately **absent** from every transport's `RETRYABLE_STATUSES`: the budget\n * does not refill on a backoff ladder, so retrying only delays the inevitable\n * five times over.\n */\nexport const BUDGET_EXCEEDED_STATUS = 402;\n/**\n * The single copy shown to a user whose AI budget is gone \u2014 the transcript bubble\n * the chat driver appends, and the default text of the assistant's blocked banner.\n *\n * Deliberately **vendor-neutral**: the same bundle ships to white-labelled\n * deployments where \"contact Genesis\" is simply wrong. A host that wants\n * branded wording overrides both surfaces \u2014 the banner via\n * `FoundationAiAssistant.setBlocked(true, reason)`, the transcript bubble via\n * `ChatDriverConfig.budgetExhaustedMessage` \u2014 so neither is stuck with this\n * default while the other is customised.\n *\n * @beta\n */\nexport const DEFAULT_BUDGET_EXHAUSTED_MESSAGE = \"You've reached your AI usage limit. Contact your administrator to raise it.\";\n/**\n * Thrown when the AI-spend budget for the caller (user, tenant, or project) is\n * exhausted and the ai-service proxy refuses the request outright \u2014 HTTP `402`\n * with `code: 'BUDGET_EXCEEDED'`, in either the legacy JSON or the NDJSON framed\n * mode.\n *\n * This is a **terminal, non-transient** condition, in the same family as\n * `ResponseTruncatedError`: no amount of retrying clears it, because nothing\n * about the request is wrong. The budget has to be raised out-of-band before any\n * further call can succeed, so both the transport retry ladder and the driver's\n * transient-retry catch step aside for it and the failure surfaces immediately\n * as the `'budget-exhausted'` `TurnFailureReason`.\n *\n * `budgetUsd`/`spentUsd` are populated from the rejection body when the proxy\n * supplies them (the workstream-C contract does); they are optional because a\n * plain-text or truncated 402 from an older proxy still has to classify.\n *\n * @beta\n */\nexport class BudgetExhaustedError extends Error {\n constructor(\n /** Vendor label of the transport that was refused (e.g. `'Anthropic'`). */\n vendorLabel, \n /** The configured spend cap in USD, when the proxy reported one. */\n budgetUsd, \n /** Spend already booked against that cap in USD, when the proxy reported it. */\n spentUsd, \n /** The proxy's human-readable rejection message, when present. */\n detail, \n /**\n * The fields the proxy reports about the wider budget picture. An object\n * rather than two more positional arguments: the four above are already the\n * limit of what reads at a call site, and these two are set together or not\n * at all.\n */\n extra) {\n super(`${vendorLabel} request refused: the AI usage budget is exhausted` +\n (budgetUsd != null\n ? ` (spent ${spentUsd != null ? `$${spentUsd}` : 'an unknown amount'} of a $${budgetUsd} budget)`\n : '') +\n (detail ? `: ${detail}` : '') +\n '. Retrying will not clear this \u2014 the budget must be raised.');\n this.vendorLabel = vendorLabel;\n this.budgetUsd = budgetUsd;\n this.spentUsd = spentUsd;\n this.detail = detail;\n this.name = 'BudgetExhaustedError';\n this.otherVendorAvailable = extra === null || extra === void 0 ? void 0 : extra.otherVendorAvailable;\n this.serverVendor = extra === null || extra === void 0 ? void 0 : extra.serverVendor;\n }\n}\n/**\n * True for a budget rejection in either wire mode: the contracted `402`, or the\n * `BUDGET_EXCEEDED` code under **any** status.\n *\n * Both keys are load-bearing, and they are not redundant:\n *\n * - `status` is the key the workstream-C contract guarantees (\"402 always\"), and\n * the only one a plain-text or unparseable rejection carries.\n * - `code` is the cheap defence against that contract drifting. Nothing stops a\n * proxy from mapping the refusal onto `403` or `429` \u2014 and `429` is in *both*\n * transports' `RETRYABLE_STATUSES`, so a status-only check would hand the user\n * the exact bug GENC-1464 exists to fix: five doomed requests and ~31s of backoff\n * before an opaque failure. A well-formed `{ t: 'err', status: 429, code:\n * 'BUDGET_EXCEEDED' }` frame is accepted by `readFramedBody` (it only rejects a\n * non-numeric status), so this is a reachable shape, not a hypothetical one.\n *\n * The false-positive cost is a proxy sending `code: 'BUDGET_EXCEEDED'` on a\n * genuinely retryable failure \u2014 a shape the contract does not permit.\n *\n * Internal to the transports (unlike `BudgetExhaustedError`, which hosts branch\n * on): deliberately **not** re-exported from the package index.\n *\n * @internal\n */\nexport const isBudgetRejection = (status, code) => status === BUDGET_EXCEEDED_STATUS || code === BUDGET_EXCEEDED_CODE;\n/**\n * Best-effort JSON parse of an error body \u2014 `undefined` rather than a throw.\n * Shared by every caller that has to classify a rejection body before it knows\n * whether the body is JSON at all.\n *\n * @internal\n */\nexport const parseJsonOrUndefined = (text) => {\n try {\n return JSON.parse(text);\n }\n catch (_a) {\n return undefined;\n }\n};\n/**\n * Read the `code` field off an already-parsed rejection body, ignoring anything\n * that is not a string. Pairs with {@link isBudgetRejection} at the legacy call\n * sites, which have a parsed body rather than a typed frame.\n *\n * @internal\n */\nexport const codeOf = (payload) => {\n const code = payload === null || payload === void 0 ? void 0 : payload.code;\n return typeof code === 'string' ? code : undefined;\n};\n/** Narrow an unknown JSON value to a number, ignoring anything else. */\nconst numberOrUndefined = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n/** Narrow an unknown JSON value to a boolean, ignoring anything else. */\nconst booleanOrUndefined = (value) => typeof value === 'boolean' ? value : undefined;\n/** Narrow an unknown JSON value to a non-empty string, ignoring anything else. */\nconst stringOrUndefined = (value) => typeof value === 'string' && value.trim() !== '' ? value : undefined;\n/**\n * Build a {@link BudgetExhaustedError} from a rejection payload of either shape:\n * the legacy body `{ error, code, budgetUsd, spentUsd, vendor,\n * otherVendorAvailable }` or the framed err frame's `details` (the same fields\n * minus `error`) plus its top-level `error`.\n *\n * The fields read off the wire, and why each is here:\n *\n * | field | used for |\n * | ---------------------- | ----------------------------------------------------- |\n * | `budgetUsd` | the cap in the banner's figures |\n * | `spentUsd` | the spend in the banner's figures |\n * | `error` | the proxy's human-readable detail |\n * | `vendor` | attribution when the transport's own label is unclaimed |\n * | `otherVendorAvailable` | whether \"switch vendor\" is honest advice at all |\n *\n * Tolerant by design \u2014 a `402` classifies even when the payload is missing,\n * unparseable, or carries none of these. Each field is narrowed independently,\n * so a proxy that sends `null` for a figure it does not know (which the\n * ai-service side now does, in preference to a misleading `0`) still yields the\n * vendor and the availability verdict.\n */\nexport function budgetExhaustedFrom(vendorLabel, payload, fallbackDetail) {\n var _a, _b, _c, _d;\n const body = (typeof payload === 'object' && payload !== null ? payload : {});\n // The framed shape nests everything but `error` under `details`; the legacy\n // body has it all at the top level. Read both so one helper serves both call\n // sites.\n const details = (typeof body.details === 'object' && body.details !== null ? body.details : {});\n const detail = typeof body.error === 'string' ? body.error : fallbackDetail;\n return new BudgetExhaustedError(vendorLabel, (_a = numberOrUndefined(body.budgetUsd)) !== null && _a !== void 0 ? _a : numberOrUndefined(details.budgetUsd), (_b = numberOrUndefined(body.spentUsd)) !== null && _b !== void 0 ? _b : numberOrUndefined(details.spentUsd), detail, {\n otherVendorAvailable: (_c = booleanOrUndefined(body.otherVendorAvailable)) !== null && _c !== void 0 ? _c : booleanOrUndefined(details.otherVendorAvailable),\n serverVendor: (_d = stringOrUndefined(body.vendor)) !== null && _d !== void 0 ? _d : stringOrUndefined(details.vendor),\n });\n}\n", "/**\n * The PROVIDER wall (GENC-1506) \u2014 the upstream vendor refusing this account, as opposed to the\n * ai-service proxy refusing this user's own spend budget (`budget-exhausted-error.ts`, GENC-1464).\n *\n * The two are constantly confused, so state the difference once: a\n * {@link BudgetExhaustedError} means *we* declined to spend more on the caller's behalf and an\n * administrator can raise the cap; a {@link ProviderRefusedError} means *Anthropic or Google*\n * declined to serve the request at all, and no amount of budget-raising in our own system changes\n * that. Both are terminal, neither is retryable, and they need different people to fix them.\n *\n * Lives in its own module for the same reason its sibling does: it is raised from\n * `post-with-retry.ts`, which both transports import, so homing it in a transport would close an\n * import cycle the repo's `circular` check rejects.\n *\n * ## Scope: Anthropic only, deliberately\n *\n * Gemini is **not** classified here yet (GENC-1506, Matt's call 2026-08-18). It is not an oversight\n * and it is not because Gemini cannot fail this way \u2014 it is because Gemini's failure shapes are\n * genuinely different and only partly observed:\n *\n * - Google's paid tiers refuse a spend cap with `429 RESOURCE_EXHAUSTED`, which is **the same status\n * and the same message text** as an ordinary rate limit, and `429` is in\n * `GeminiTransport.RETRYABLE_STATUSES`. A prose probe there would classify routine rate limiting as\n * terminal and break the retry ladder \u2014 the exact inverse of the Anthropic situation below.\n * - The discriminator that *would* work is structural \u2014 `details[].QuotaFailure.violations[].quotaId`\n * names the limit's scope (`\u2026PerMinute\u2026` is retryable, per-day or spend-scoped is not) \u2014 but only\n * the per-minute free-tier value has been observed. Guessing the others is what this module's\n * history says not to do.\n * - Google's Prepay balance hitting $0 stops every key on the billing account at once, and its error\n * shape is neither documented nor observed.\n *\n * So {@link providerRefusalOf} dispatches on vendor and answers `undefined` for anything that is not\n * Anthropic. Adding Gemini later is a new branch, not a rewrite \u2014 which is why the vendor is a\n * parameter rather than an assumption.\n *\n * @packageDocumentation\n */\nimport { VENDOR_LABELS } from './budget-exhausted-error';\n/**\n * The proxy's machine-readable code for \"the upstream vendor refused this account\".\n *\n * Deliberately distinct from `BUDGET_EXCEEDED`: the ai-service proxy stamps this when it relays a\n * provider refusal, so the client can tell a relayed upstream fault from the proxy's own budget\n * verdict without inspecting the body at all.\n *\n * Exported from the package index \u2014 unlike its `BUDGET_EXCEEDED_CODE` sibling, which is internal \u2014\n * because the SERVER side of the contract lives in another repo (genesis-create's ai-service stamps\n * this code onto its proxy responses). A hand-copied string literal there would drift on the first\n * rename, and the drift would be silent: the client would simply stop classifying.\n *\n * @beta\n */\nexport const PROVIDER_REFUSED_CODE = 'PROVIDER_REFUSED';\n/**\n * The single sentence shown to a user whose provider has refused \u2014 the transcript bubble the chat\n * driver appends, and the string ai-service reuses for its own generation surfaces.\n *\n * **It names no cause, and that is the whole design.** Three constraints shaped it, and a rewrite\n * has to clear all three:\n *\n * 1. **It must not sound like a cap.** The user can often see their remaining AI spend in the same\n * UI, so *allowance / limit / quota / budget / usage / credit / balance* risk a visible\n * self-contradiction: a message saying there is nothing left, next to a figure showing there is.\n * \"isn't related to your account **or your usage**\" goes further than avoiding the words \u2014 it\n * pre-empts the user checking that figure and concluding the message is wrong.\n * 2. **It must not imply we cannot pay our bills.** *Billing / payment / funds / top up* all read as\n * an unpaid invoice. Naming no cause means there is nothing to be embarrassed by and nothing for\n * the user to contradict.\n * 3. **It must not promise self-healing.** Clearing this needs a human to act out of band, so\n * \"currently\" rather than \"temporarily\", and \"so it can be restored\" positively signals that\n * someone must do something.\n *\n * It is also true of **both** {@link ProviderRefusalKind}s unchanged, which is what makes one\n * sentence for two kinds honest rather than a fudge: for an expired key the provider *is* refusing,\n * it *is* unrelated to the user's own account and usage, they *can* do nothing, and support *can*\n * restore it.\n *\n * Vendor-neutral and deployment-neutral on purpose \u2014 the same bundle ships to white-labelled\n * deployments where naming a vendor, or naming Genesis, would be wrong. A host that wants different\n * wording sets `ChatDriverConfig.providerRefusedMessage`.\n *\n * @beta\n */\nexport const DEFAULT_PROVIDER_REFUSED_MESSAGE = \"AI requests are currently being refused by the provider. This isn't related to your account or \" +\n 'your usage and needs no action from you \u2014 please contact your support team so it can be restored.';\n/**\n * Thrown when the upstream provider refuses the request because of the state of the **account**\n * rather than anything about the request \u2014 see {@link ProviderRefusalKind}.\n *\n * Terminal and non-transient, in the same family as `ResponseTruncatedError` and\n * `BudgetExhaustedError`: retrying cannot clear it, because nothing about the request is wrong. So\n * both the transport retry ladder and the driver's transient-retry catch step aside for it and the\n * failure surfaces immediately as the `'provider-refused'` `TurnFailureReason`.\n *\n * @beta\n */\nexport class ProviderRefusedError extends Error {\n constructor(\n /** Vendor label of the transport that was refused (e.g. `'Anthropic'`). */\n vendorLabel, \n /** Which kind of refusal \u2014 drives the log and the operator's fix, never the user's message. */\n kind, \n /**\n * The provider's own HTTP status, when known.\n *\n * Diagnostic only, and deliberately not part of the classification contract: the observed spend\n * refusals arrive as `400` (not the `402 billing_error` the docs describe), so a consumer that\n * branched on this would be encoding one snapshot of provider behaviour.\n */\n upstreamStatus, \n /** The provider's own `error.type` (e.g. `'invalid_request_error'`, `'authentication_error'`). */\n upstreamType, \n /** The provider's human-readable message, verbatim, for the log. Never shown to the user. */\n detail) {\n super(`${vendorLabel} refused the request (${kind})` +\n (upstreamStatus != null ? ` \u2014 HTTP ${upstreamStatus}` : '') +\n (upstreamType ? ` ${upstreamType}` : '') +\n (detail ? `: ${detail}` : '') +\n '. Retrying will not clear this \u2014 the provider account must be fixed.');\n this.vendorLabel = vendorLabel;\n this.kind = kind;\n this.upstreamStatus = upstreamStatus;\n this.upstreamType = upstreamType;\n this.detail = detail;\n this.name = 'ProviderRefusedError';\n }\n}\n/**\n * Phrases that identify a spend refusal hiding inside Anthropic's **generic**\n * `invalid_request_error` bucket.\n *\n * Prose matching is not a shortcut here, it is the only handle available, and that is a measured\n * fact rather than an assumption. Both refusals we have captured arrive as `400` +\n * `invalid_request_error` with **no distinct type, no dedicated header and nothing else structural**:\n *\n * | Captured 2026-08-18 | Message |\n * | --- | --- |\n * | Credit balance at zero | `Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.` |\n * | Workspace usage cap | `You have reached your specified workspace API usage limits. You will regain access on 2026-09-01 at 00:00 UTC.` |\n *\n * A classifier keyed only on the documented `402 billing_error` signal would have matched **neither**\n * and shipped a non-fix. That is why this list exists.\n *\n * **Independent signals, not whole sentences.** A sentence list would need a new entry every time a\n * member is reworded, and would silently stop matching in the meantime. `credit balance` and\n * `usage limit` are each confirmed against a capture above; `spend limit` and the `insufficient \u2026`\n * form are unobserved and included as cheap tolerance for the same family.\n *\n * **False positives are near-impossible**, for a reason that is easy to miss: on a refused account\n * the spend check runs *before* request validation (verified \u2014 a deliberately malformed request on a\n * dry key still returned the credit message), so a genuine schema `400` is only observable on a\n * healthy account, where its message quotes field paths and matches nothing here.\n *\n * Deletable the day Anthropic gives this family its own `error.type`.\n */\nconst ANTHROPIC_SPEND_PHRASES = Object.freeze([\n /credit balance/i,\n /usage limit/i,\n /spend limit/i,\n /insufficient (credit|funds|balance)/i,\n]);\n/** Anthropic `error.type` values that are an auth refusal, straight from the documented table. */\nconst ANTHROPIC_AUTH_TYPES = Object.freeze([\n 'authentication_error',\n 'permission_error',\n]);\n/**\n * The inner `{ type, message }` of an Anthropic error envelope, from wherever it is on the wire.\n *\n * Two positions, both load-bearing, because the same refusal reaches us in two shapes:\n * - **direct API and legacy JSON proxy** \u2014 the envelope IS the body:\n * `{ type: 'error', error: { type, message } }`;\n * - **NDJSON framed proxy** \u2014 the envelope is nested under the err frame's `details`, while the\n * frame's own top-level `error` is a *string* (the proxy's summary).\n *\n * So reading only the top level would classify nothing on the browser path, and reading only\n * `details` would classify nothing on the server path. Mirrors how `budgetExhaustedFrom` reads both.\n */\nfunction anthropicErrorBody(payload) {\n var _a;\n const outer = typeof payload === 'object' && payload !== null ? payload : {};\n // Framed: `details` holds the upstream envelope. Legacy/direct: the body itself does.\n for (const candidate of [\n outer.error,\n (_a = outer.details) === null || _a === void 0 ? void 0 : _a.error,\n ]) {\n if (typeof candidate === 'object' && candidate !== null) {\n const { type, message } = candidate;\n return {\n type: typeof type === 'string' ? type : undefined,\n message: typeof message === 'string' ? message : undefined,\n };\n }\n }\n return undefined;\n}\n/**\n * A `kind` the caller stated explicitly, from either wire position, or `undefined`.\n *\n * Both positions are read for the same reason `anthropicErrorBody` reads two: a JSON body carries its\n * fields at the top level, while an NDJSON err frame nests everything but `error` under `details`.\n */\nfunction statedKind(payload) {\n const outer = (typeof payload === 'object' && payload !== null ? payload : {});\n const nested = (typeof outer.details === 'object' && outer.details !== null ? outer.details : {});\n for (const candidate of [outer.kind, nested.kind]) {\n if (candidate === 'auth' || candidate === 'spend')\n return candidate;\n }\n return undefined;\n}\n/**\n * The kind implied by the provider envelope's `type` alone \u2014 no prose, no status.\n *\n * Vendor-agnostic on purpose, so the explicit-code path can reuse it: by the time the proxy has\n * stamped `PROVIDER_REFUSED` it has already decided this is a refusal, and all that is left is which\n * kind \u2014 a question the relayed envelope answers without any vendor dispatch.\n */\nfunction kindFromEnvelopeType(payload) {\n const body = anthropicErrorBody(payload);\n if (!(body === null || body === void 0 ? void 0 : body.type))\n return undefined;\n if (ANTHROPIC_AUTH_TYPES.includes(body.type))\n return 'auth';\n // The documented billing signal. Unobserved by us \u2014 every real spend refusal we captured came\n // through the generic bucket \u2014 but it is in the errors table, so honour it.\n if (body.type === 'billing_error')\n return 'spend';\n return undefined;\n}\n/**\n * Classify a rejection as a provider refusal, or `undefined` for anything else.\n *\n * **Every trigger is a POSITIVE signal \u2014 status alone never classifies.** That is what keeps this\n * from stealing the proxy's own `402 BUDGET_EXCEEDED`: a bare `402` with no provider envelope\n * carries nothing this function recognises, so it falls through to the budget classification exactly\n * as it did before this module existed. A `402` that *does* carry an Anthropic envelope is a relayed\n * upstream fault and is claimed here \u2014 which is the collision GENC-1506 set out to close, closed by\n * ordering and positive detection rather than by loosening the budget predicate.\n *\n * @param vendor - which vendor's transport was refused. Anything but `'anthropic'` returns\n * `undefined` today; see this module's header for why Gemini is deliberately absent.\n * @param code - the proxy's machine-readable code, when there is one (`err` frame or JSON body).\n * @param payload - the parsed rejection body, or the parsed `err` frame.\n */\nexport function providerRefusalOf(vendor, code, payload) {\n var _a, _b;\n // The proxy's explicit signal wins over any body inspection, in any status. It is the one route\n // that needs no vendor knowledge at all \u2014 the proxy has already done the classifying.\n //\n // The KIND, though, still has to be worked out rather than assumed. Three sources, in descending\n // authority, because a caller that troubled to state the kind knows more than we can infer:\n //\n // 1. a stated `kind`, in EITHER wire position \u2014 top level on a JSON body, under `details` on an\n // err frame, since the framed protocol carries rejection metadata there (the same split\n // `anthropicErrorBody` and `budgetExhaustedFrom` already straddle);\n // 2. the provider envelope's own type, which the proxy relays in `details` whether or not it\n // states a kind \u2014 this is what our own ai-service proxy actually sends today;\n // 3. `spend`, as the last resort.\n //\n // Reading only position 1 and defaulting the rest was a real mis-attribution rather than a\n // hypothetical: our proxy stamps this code with the Anthropic envelope in `details` and no\n // top-level `kind`, so an `authentication_error` was being reported as `spend` \u2014 sending an\n // operator to top up an account when the actual fix is to rotate a credential. The user-facing\n // copy is identical either way, which is exactly why nothing on screen would have caught it.\n if (code === PROVIDER_REFUSED_CODE) {\n return (_b = (_a = statedKind(payload)) !== null && _a !== void 0 ? _a : kindFromEnvelopeType(payload)) !== null && _b !== void 0 ? _b : 'spend';\n }\n if (vendor !== 'anthropic')\n return undefined;\n // Structural first: documented types, no prose, and cheaper than the phrase scan. `401`/`403` are\n // absent from every RETRYABLE_STATUSES, so claiming them changes what the user is told and what the\n // log records \u2014 never the retry behaviour.\n const structural = kindFromEnvelopeType(payload);\n if (structural)\n return structural;\n // The generic bucket, gated on the phrase list. Deliberately NOT gated on status as well: the\n // captures were all `400`, and pinning that would encode one snapshot of provider behaviour when\n // the type plus the phrase is already specific enough.\n const body = anthropicErrorBody(payload);\n if ((body === null || body === void 0 ? void 0 : body.type) === 'invalid_request_error' && body.message) {\n const message = body.message;\n if (ANTHROPIC_SPEND_PHRASES.some((phrase) => phrase.test(message)))\n return 'spend';\n }\n return undefined;\n}\n/**\n * Build a {@link ProviderRefusedError} from a classified rejection, pulling the provider's own\n * status/type/message across for the log.\n *\n * `upstreamStatus` is passed in rather than read from the payload because the two wire modes carry it\n * differently (HTTP status vs the err frame's `status`), and the caller is the only one that knows\n * which it is looking at.\n */\nexport function providerRefusedFrom(vendorLabel, kind, upstreamStatus, payload, fallbackDetail) {\n var _a;\n const body = anthropicErrorBody(payload);\n return new ProviderRefusedError(vendorLabel, kind, upstreamStatus, body === null || body === void 0 ? void 0 : body.type, (_a = body === null || body === void 0 ? void 0 : body.message) !== null && _a !== void 0 ? _a : fallbackDetail);\n}\n/**\n * The {@link AIProviderType} a vendor label belongs to, for the classification call above.\n *\n * A thin wrapper over the label map rather than a reuse of `vendorTypeOfLabel`: this one is called\n * with the transport's OWN label, which is always a literal from {@link VENDOR_LABELS}, so an exact\n * match is correct and the case-insensitive, whitespace-tolerant lookup that the wire-borne label\n * needs would be misleading precision here.\n */\nexport function vendorOfTransportLabel(vendorLabel) {\n const entry = Object.entries(VENDOR_LABELS).find(([, label]) => label === vendorLabel);\n return entry === null || entry === void 0 ? void 0 : entry[0];\n}\n", "/** @beta */\nexport const SUPPORTED_GEMINI_MODEL_IDS = [\n 'gemini-2.5-pro',\n 'gemini-2.5-flash',\n 'gemini-2.5-flash-lite',\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/** @beta */\nexport const SUPPORTED_ANTHROPIC_MODEL_IDS = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-opus-4-7',\n 'claude-sonnet-5',\n 'claude-sonnet-4-6',\n 'claude-haiku-4-5-20251001',\n];\n/**\n * Which vendor a model id belongs to, or `undefined` when no supported provider claims it.\n *\n * @remarks\n * Derived from {@link SUPPORTED_ANTHROPIC_MODEL_IDS} and {@link SUPPORTED_GEMINI_MODEL_IDS},\n * so it cannot drift from them the way a hand-maintained map does \u2014 adding a model to an\n * allowlist is enough to teach this too.\n *\n * Exists because callers hold a **model id**, not a vendor. A usage ledger reads a message's\n * `model` and then has to pick the matching pricing function \u2014 `anthropicTokenCost` vs\n * `geminiTokenCost` \u2014 whose usage records are deliberately not interchangeable, because the\n * two providers disagree about whether the prompt figure includes the cached part. Without\n * this, every such caller writes its own model\u2192vendor map, which is the same duplication that\n * exporting the pricing removes.\n *\n * Returns `undefined` rather than falling back to a default vendor so an unrecognised model\n * is a decision the caller has to make out loud. Silently defaulting is precisely how an\n * unlisted model gets priced at some other tier's rates \u2014 a consumer has already had Haiku\n * billed at Sonnet rates that way.\n *\n * Takes a plain `string`, not a union: the interesting callers are reading a model id back\n * off a stored message or a config file, where it is untrusted text.\n *\n * @beta\n */\nexport function vendorOfModel(modelId) {\n if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(modelId))\n return 'anthropic';\n if (SUPPORTED_GEMINI_MODEL_IDS.includes(modelId))\n return 'gemini';\n return undefined;\n}\n", "/**\n * Normalise an image MIME type to the spelling both vendors accept.\n *\n * Only `image/jpg` \u2192 `image/jpeg` today. That is a rename, not a guess: it is the same format\n * under a label neither API recognises \u2014 Anthropic documents `image/jpeg`, `image/png`,\n * `image/gif` and `image/webp`, and rejects `image/jpg` with a 400. The alias is common enough\n * to be worth absorbing (anything deriving a type from a `.jpg` extension produces it), and the\n * cost of not absorbing it is a failed turn the user is waiting on.\n *\n * Deliberately NOT a validator. A genuinely unsupported type (`image/bmp`, `image/svg+xml`)\n * passes through untouched so the vendor's own error names it, rather than this function\n * inventing a substitute or throwing on input a future model tier might accept.\n *\n * Lives here rather than inline in each transport because it is one rule that must hold for\n * both; copied into two files it drifts the first time only one is updated.\n */\nexport function normalizeImageMime(mimeType) {\n return mimeType === 'image/jpg' ? 'image/jpeg' : mimeType;\n}\n/**\n * Strip a leading `data:` URL prefix from a base64 image payload, returning the bare bytes both\n * vendors' image blocks expect.\n *\n * {@link ChatImageAttachment.data} is documented as bare base64, but the natural browser way to\n * produce it \u2014 `FileReader.readAsDataURL` \u2014 yields `data:image/png;base64,\u2026`, and handed in\n * verbatim that prefix is a 400 on both APIs. This absorbs that one mistake: a\n * `data:<mime>;base64,` preamble (any or no mime) is removed; anything already bare passes\n * through untouched. Anchored and `;base64,`-terminated so it only ever removes a real data-URL\n * header, never a slice of the payload (base64 contains no comma).\n *\n * Like {@link normalizeImageMime} it is a normaliser, not a validator \u2014 it does not check that\n * the remainder is valid base64, and lives here for the same reason: one rule both transports\n * must share.\n */\nexport function stripImageDataUrl(data) {\n return data.replace(/^data:[^,]*;base64,/, '');\n}\n", "/**\n * Normalized-temperature anchor. Values at or below it scale into\n * `[0, providerDefault]`; values above it scale into `[providerDefault, providerMax]`.\n * So a normalized `0.5` maps to each provider's own default temperature.\n */\nconst DEFAULT_ANCHOR = 0.5;\n/**\n * Translate a provider-agnostic, normalized temperature into a provider's\n * native range, anchored on the provider's own default so the normalized scale\n * means the same thing everywhere:\n *\n * - `0` \u2192 `0` (fully deterministic),\n * - `0.5` \u2192 the provider's default temperature,\n * - `1` \u2192 the provider's maximum.\n *\n * Values between the anchors interpolate linearly within each half, so `< 0.5`\n * is \"more focused than default\" and `> 0.5` is \"more random than default\" on\n * every provider \u2014 even though the providers' native ranges differ (Anthropic\n * default/max `1`/`1`, Gemini `1`/`2`). Where a provider's default equals its\n * max (Anthropic), the upper half is flat: it cannot go hotter than its default.\n *\n * The input is clamped to `[0, 1]` before scaling, so an out-of-range value can\n * never produce a native temperature the provider would reject.\n */\nexport function scaleTemperature(normalized, { defaultTemp, maxTemp }) {\n const t = Math.min(Math.max(normalized, 0), 1);\n return t <= DEFAULT_ANCHOR\n ? (t / DEFAULT_ANCHOR) * defaultTemp\n : defaultTemp + ((t - DEFAULT_ANCHOR) / (1 - DEFAULT_ANCHOR)) * (maxTemp - defaultTemp);\n}\n/**\n * Provider-agnostic, normalized sampling-temperature presets in `0`\u2013`1` space \u2014\n * named handles for the values most callers actually want, so intent reads\n * better than a bare magnitude. Each maps through `scaleTemperature` to the\n * active provider's native range, so the same preset means the same intent\n * whichever provider services the turn:\n *\n * - `ChatTemperature.Deterministic` (`0`) \u2014 greedy/argmax sampling.\n * - `ChatTemperature.Focused` (`0.25`) \u2014 low but not greedy; precise tool calls\n * and extraction work where you still want a little slack.\n * - `ChatTemperature.Balanced` (`0.5`) \u2014 the provider's own default.\n * - `ChatTemperature.Creative` (`0.75`) \u2014 hotter than default, short of the ceiling.\n * - `ChatTemperature.Maximum` (`1`) \u2014 the hottest the active provider allows.\n *\n * (On a provider whose default equals its max \u2014 Anthropic \u2014 `Creative` and\n * `Maximum` coincide; see `scaleTemperature`.)\n *\n * @beta\n */\nexport const ChatTemperature = {\n Deterministic: 0,\n Focused: 0.25,\n Balanced: 0.5,\n Creative: 0.75,\n Maximum: 1,\n};\n", "/**\n * Per-request cost pricing for the models this package can call.\n *\n * @remarks\n * Extracted from the two transports' private cost paths so a host that prices\n * requests of its own \u2014 a server proxy, a usage ledger, a benchmark \u2014 computes the\n * same numbers instead of hand-copying the rate tables. Duplicated tables drift:\n * an unlisted model silently prices at whatever the copy's fallback is, and a\n * missing multiplier misprices every cached request.\n *\n * **Typed over raw provider usage, deliberately.** These take the token counts a\n * provider response reports, NOT `ChatMessage`/`AggregateUsage`. Two reasons:\n *\n * 1. `ChatMessage.cacheWriteTokens` is a single total, but Anthropic bills cache\n * writes per TTL (5-minute at 1.25\u00D7, 1-hour at 2\u00D7). The split exists only in\n * the provider response, so pricing from a message cannot be exact.\n * 2. The path that actually needs to compute a cost is the one where no transport\n * stamped one \u2014 a proxied or server-side call holding a raw usage block.\n *\n * When a `ChatMessage` already carries `cost`, use that; it was computed here at\n * request time with information the message no longer has. Re-deriving a cost\n * from a message's token fields is wrong in the expensive direction, because\n * `inputTokens` is total prompt size *including* the cached part.\n *\n * **What this model cannot express, by construction.** Everything here is\n * *per-request*: a function of the tokens one call consumed. Caching priced by\n * **elapsed time** does not fit, and no additional bucket would make it fit \u2014\n * Gemini's explicit context caching, for instance, charges an hourly storage fee\n * that accrues while you are making no requests at all. Nothing to attribute it to.\n *\n * A provider whose caching is billed that way needs a **separate ledger entry**,\n * recorded against a cache's lifetime rather than against a request, and summed\n * alongside these figures rather than inside them. Do not fold it into\n * {@link TokenCostBreakdown} \u2014 a storage fee divided across whatever requests\n * happened to occur is an invented number, and it would make two runs with\n * identical token usage report different costs for reasons neither run caused.\n *\n * The vendors also differ in shape more than they differ in rates, which is why\n * there is a function per provider rather than one with a normalised record:\n * Anthropic charges a premium for the cache *write* and lets you choose the TTL;\n * Gemini's implicit caching has no write charge at all; a provider with automatic,\n * non-configurable caching has neither a write bucket nor a TTL to record. The\n * shared vocabulary is the RESULT ({@link TokenCost}), not the input.\n */\n/** One million \u2014 the unit every published rate is quoted in. */\nconst TOKENS_PER_MILLION = 1000000;\n// ---------------------------------------------------------------------------\n// Anthropic\n// ---------------------------------------------------------------------------\n/**\n * Standard tier pricing per million tokens \u2014\n * https://docs.claude.com/en/docs/about-claude/pricing\n *\n * @beta\n */\nconst ANTHROPIC_PRICING = {\n 'claude-haiku-4-5-20251001': { promptPerMillion: 1, candidatePerMillion: 5 },\n // Fable 5 \u2014 Anthropic's most capable widely-released model; priced above Opus tier.\n 'claude-fable-5': { promptPerMillion: 10, candidatePerMillion: 50 },\n // Opus 4.7 / 4.8 \u2014 same $5 / $25 per MTok. Stated per model rather than shared through a\n // fall-through, so neither is ever \"whatever was left over\".\n 'claude-opus-4-8': { promptPerMillion: 5, candidatePerMillion: 25 },\n 'claude-opus-4-7': { promptPerMillion: 5, candidatePerMillion: 25 },\n // Sonnet 5 is $2 / $10 \u2014 its OWN tier, and CHEAPER than the older Sonnet 4.6 below.\n //\n // This launched as an introductory rate through 2026-08-31, and an earlier version of this\n // table deliberately charged the $3 / $15 standard rate instead, on the reasoning that the\n // introductory period would lapse. Anthropic has since confirmed $2 / $10 as the permanent\n // standard price and cancelled the scheduled increase, so that reasoning is dead and the old\n // figure over-charged every Sonnet 5 request by 50%.\n // https://platform.claude.com/docs/en/about-claude/pricing#model-pricing\n 'claude-sonnet-5': { promptPerMillion: 2, candidatePerMillion: 10 },\n // Sonnet 4.6 remains on the older $3 / $15 Sonnet tier \u2014 the newer model is the cheaper one.\n 'claude-sonnet-4-6': { promptPerMillion: 3, candidatePerMillion: 15 },\n};\n/**\n * Standard tier pricing per million tokens \u2014\n * https://docs.claude.com/en/docs/about-claude/pricing\n *\n * @remarks\n * Backed by a total {@link https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type | Record}\n * over `AnthropicModelId` rather than a chain of checks with a default. That is the whole\n * point: adding a model to `SUPPORTED_ANTHROPIC_MODEL_IDS` without pricing it becomes a\n * COMPILE error instead of a silent charge at whatever the fall-through happened to be \u2014 the\n * exact failure this module's header warns about, and one a consumer has already been bitten\n * by. The Gemini half of this file has always had the guarantee; this half now matches.\n *\n * @beta\n */\nexport function anthropicRatesFor(model) {\n return ANTHROPIC_PRICING[model];\n}\n/**\n * Prompt-cache pricing multipliers, applied to the model's base input rate\n * (`promptPerMillion`) \u2014 https://docs.claude.com/en/docs/build-with-claude/prompt-caching\n * Reads bill at ~0.1\u00D7 base input; writes bill by TTL \u2014 5-minute at ~1.25\u00D7 and 1-hour at 2\u00D7.\n * Both write TTLs are reachable (`CachePolicy.ttl` is `'5m' | '1h'`), so each TTL bucket is\n * costed from the response's per-TTL `cache_creation` breakdown rather than assuming one rate.\n *\n * @beta\n */\nexport const ANTHROPIC_CACHE_READ_MULTIPLIER = 0.1;\n/** @beta */\nexport const ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER = 1.25;\n/** @beta */\nexport const ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER = 2;\n/**\n * Cost one Anthropic request.\n *\n * @beta\n */\nexport function anthropicTokenCost(model, usage) {\n const { promptPerMillion, candidatePerMillion } = anthropicRatesFor(model);\n const m = TOKENS_PER_MILLION;\n // Split the creation total into its 1-hour portion and the 5-minute remainder and\n // cost each at its own rate. All buckets are multiples of the same base input rate,\n // so summing them stays correct whether or not caching was active (every cache\n // field is 0 when it wasn't).\n const cacheWrite5mTokens = Math.max(0, usage.cacheWriteTokens - usage.cacheWrite1hTokens);\n const promptCost = (usage.uncachedInputTokens / m) * promptPerMillion;\n const cacheReadCost = (usage.cacheReadTokens / m) * promptPerMillion * ANTHROPIC_CACHE_READ_MULTIPLIER;\n const cacheWriteCost = (cacheWrite5mTokens / m) * promptPerMillion * ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER +\n (usage.cacheWrite1hTokens / m) * promptPerMillion * ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER;\n const candidateCost = (usage.outputTokens / m) * candidatePerMillion;\n // Net saving vs no caching: the cache-read tokens would have cost full input price\n // (we paid ~0.1\u00D7 of that), while the write premium is an upfront cost that pays back\n // on later reads \u2014 so the net dips negative on a write-heavy request and climbs\n // positive as reads accrue.\n const cacheReadFull = (usage.cacheReadTokens / m) * promptPerMillion;\n const cacheWriteFull = (usage.cacheWriteTokens / m) * promptPerMillion;\n return {\n costUsd: promptCost + cacheReadCost + cacheWriteCost + candidateCost,\n savedUsd: cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost),\n breakdown: {\n promptUsd: promptCost,\n cacheReadUsd: cacheReadCost,\n cacheWriteUsd: cacheWriteCost,\n candidateUsd: candidateCost,\n },\n };\n}\n// ---------------------------------------------------------------------------\n// Gemini\n// ---------------------------------------------------------------------------\n/**\n * Prompt size (tokens) at or below which the standard pricing tier applies.\n * Above it, Gemini's long-context tier kicks in. Google applies a single tier\n * to the whole request based on prompt size \u2014 it is not a marginal/blended rate.\n *\n * @beta\n */\nexport const GEMINI_LONG_CONTEXT_THRESHOLD = 200000;\n/**\n * Cached / context-cache input tokens bill at a flat ~10% of the model's normal input\n * rate \u2014 consistent across models (flash $0.30\u2192$0.03, flash-lite $0.10\u2192$0.01,\n * pro $1.25\u2192$0.125). Source: https://ai.google.dev/gemini-api/docs/pricing.\n * (Explicit context caching also has an hourly storage fee; implicit caching \u2014 what the\n * transport relies on \u2014 has none, so only this read discount applies. There is no write\n * premium on this provider, which is why its savings figure is never negative.)\n *\n * @beta\n */\nexport const GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;\n/**\n * Paid Standard tier rates (USD per million tokens) \u2014\n * https://ai.google.dev/gemini-api/docs/pricing\n */\nconst GEMINI_PRICING = {\n 'gemini-2.5-flash-lite': {\n kind: 'flat',\n rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 },\n },\n 'gemini-2.5-flash': { kind: 'flat', rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },\n 'gemini-2.5-pro': {\n kind: 'tiered',\n standard: { promptPerMillion: 1.25, candidatePerMillion: 10.0 },\n longContext: { promptPerMillion: 2.5, candidatePerMillion: 15.0 },\n },\n 'gemini-3.1-flash-lite': {\n kind: 'flat',\n rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 },\n },\n 'gemini-3.5-flash': { kind: 'flat', rate: { promptPerMillion: 1.5, candidatePerMillion: 9.0 } },\n 'gemini-3.1-pro-preview': {\n kind: 'tiered',\n standard: { promptPerMillion: 2.0, candidatePerMillion: 12.0 },\n longContext: { promptPerMillion: 4.0, candidatePerMillion: 18.0 },\n },\n};\n/**\n * Resolve the per-million-token rates for a model given the request's prompt size,\n * selecting the long-context tier for tiered models when the prompt exceeds\n * {@link GEMINI_LONG_CONTEXT_THRESHOLD}.\n *\n * @remarks\n * `promptTokens` must be the **full** prompt size, cached slice included \u2014 the tier\n * is chosen on what was sent, not on what was billed at full rate. A mostly-cached\n * long prompt is still a long prompt.\n *\n * Unlike Anthropic's, this accessor is not a pure function of the model, which is\n * why there is no single `ratesFor(model)` across both providers.\n *\n * @beta\n */\nexport function geminiRatesFor(model, promptTokens) {\n const pricing = GEMINI_PRICING[model];\n if (pricing.kind === 'flat') {\n return pricing.rate;\n }\n return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;\n}\n/**\n * Cost one Gemini request.\n *\n * @beta\n */\nexport function geminiTokenCost(model, usage) {\n // The pricing TIER is chosen on the full prompt size, BEFORE the cache split.\n const { promptPerMillion, candidatePerMillion } = geminiRatesFor(model, usage.promptTokens);\n const m = TOKENS_PER_MILLION;\n const uncachedPromptTokens = Math.max(0, usage.promptTokens - usage.cachedTokens);\n const promptCost = (uncachedPromptTokens / m) * promptPerMillion;\n const cacheReadCost = (usage.cachedTokens / m) * promptPerMillion * GEMINI_CACHED_INPUT_MULTIPLIER;\n // Thinking tokens bill at the output rate, and are incurred whenever the model\n // thinks (always, on 2.5 Pro).\n const candidateCost = ((usage.candidateTokens + usage.thoughtTokens) / m) * candidatePerMillion;\n return {\n costUsd: promptCost + cacheReadCost + candidateCost,\n // Implicit caching has no write premium, so this is always >= 0.\n savedUsd: (usage.cachedTokens / m) * promptPerMillion - cacheReadCost,\n breakdown: {\n promptUsd: promptCost,\n cacheReadUsd: cacheReadCost,\n cacheWriteUsd: 0,\n candidateUsd: candidateCost,\n },\n };\n}\n", "import { __rest } from \"tslib\";\nimport { logger } from './logger';\n/** Keys whose value is a *map* of name \u2192 schema. */\nconst SCHEMA_MAP_KEYS = ['properties', 'patternProperties', '$defs', 'definitions'];\n/** Keys whose value is an *array* of schemas. */\nconst SCHEMA_LIST_KEYS = ['anyOf', 'oneOf', 'allOf', 'prefixItems'];\n/** Keys whose value is a single schema (or, for `items`, optionally a tuple of them). */\nconst SCHEMA_VALUE_KEYS = [\n 'items',\n 'not',\n 'additionalProperties',\n 'propertyNames',\n 'contains',\n];\nconst isPlainObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);\n/** Structural deep clone for JSON-Schema-shaped values (JSON-serialisable by definition). */\nfunction cloneValue(value) {\n if (Array.isArray(value))\n return value.map(cloneValue);\n if (isPlainObject(value)) {\n const out = {};\n for (const [k, v] of Object.entries(value))\n out[k] = cloneValue(v);\n return out;\n }\n return value;\n}\n/**\n * Deep-clone `node`, recursing into every nested schema and applying `transform`\n * to each node bottom-up. `path` is a JSON Pointer, passed to `transform` so it\n * can report *where* a change was made.\n *\n * **Never mutates the input.** Tool definitions are routinely module-level\n * constants shared across every turn, so in-place adaptation would corrupt them\n * for all subsequent requests.\n *\n * Recursion is keyword-directed rather than structural: only the keys above hold\n * schemas. A blind walk would descend into `enum` (an array of *values*),\n * `required` (an array of *names*), or `type` (which may be an array of type\n * names) and corrupt them.\n */\nfunction mapChildSchemas(node, visit, path) {\n const out = {};\n for (const [key, value] of Object.entries(node)) {\n const here = `${path}/${key}`;\n if (SCHEMA_MAP_KEYS.includes(key) && isPlainObject(value)) {\n out[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [\n name,\n isPlainObject(child) ? visit(child, `${here}/${name}`) : cloneValue(child),\n ]));\n }\n else if (SCHEMA_LIST_KEYS.includes(key) && Array.isArray(value)) {\n out[key] = value.map((child, i) => isPlainObject(child) ? visit(child, `${here}/${i}`) : cloneValue(child));\n }\n else if (SCHEMA_VALUE_KEYS.includes(key)) {\n if (isPlainObject(value))\n out[key] = visit(value, here);\n else if (Array.isArray(value))\n // Legacy tuple form of `items`.\n out[key] = value.map((child, i) => isPlainObject(child) ? visit(child, `${here}/${i}`) : cloneValue(child));\n else\n out[key] = cloneValue(value);\n }\n else {\n out[key] = cloneValue(value);\n }\n }\n return out;\n}\nfunction mapSchema(node, transform, path = '') {\n return transform(mapChildSchemas(node, (child, childPath) => mapSchema(child, transform, childPath), path), path);\n}\n// \u2500\u2500 Anthropic: enforcement (F6) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * Keywords Anthropic rejects outright when a tool is compiled for enforcement,\n * and which can be dropped without changing what the rest of the schema means.\n * Measured against `claude-opus-4-8` \u2014 see `docs/tool-schemas.md`.\n *\n * `minItems` is absent because it is only rejected above 1; it is handled below.\n */\nconst UNENFORCEABLE_KEYWORDS = [\n 'minimum',\n 'maximum',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'maxItems',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n];\n/**\n * Keywords Anthropic rejects that **cannot** be dropped, because removing them\n * would leave a node that means something entirely different (`oneOf` and `not`\n * carry the node's whole meaning; deleting `oneOf` leaves `{}`, which matches\n * anything).\n *\n * These are deliberately left in place so the request fails loudly rather than\n * silently enforcing a weaker schema than the caller wrote.\n */\nconst UNDROPPABLE_KEYWORDS = ['oneOf', 'not'];\n/**\n * Adapt a tool's `parameters` for Anthropic's decode-time enforcement.\n *\n * Two changes, both required by the provider:\n *\n * 1. `additionalProperties: false` on every object node. Anthropic rejects an\n * enforced schema without it (`For 'object' type, 'additionalProperties' must\n * be explicitly set to false`) \u2014 a closed key set is what makes the object's\n * grammar finite.\n * 2. Keywords that enforcement cannot express are removed. Numeric bounds and\n * most array constraints are *rejected* by the provider, so leaving them in\n * fails the whole request; dropping them keeps everything else enforced.\n *\n * `required` is deliberately untouched: a subset, an empty list, and an absent\n * key are all accepted, and an omitted-but-present property is still constrained.\n *\n * Note what is **not** stripped: `maxLength`/`minLength` are accepted and\n * silently ignored, so they survive as documentation but guarantee nothing \u2014\n * validate lengths yourself. `pattern` and `format` *are* enforced (shape only,\n * in `format`'s case) and are cheaper to compile than an unconstrained string.\n */\nexport function toEnforcedAnthropicSchema(parameters) {\n const stripped = [];\n const overridden = [];\n const undroppable = [];\n const schema = mapSchema(parameters, (node, path) => {\n for (const keyword of UNENFORCEABLE_KEYWORDS) {\n if (keyword in node) {\n delete node[keyword];\n stripped.push(`${path}/${keyword}`);\n }\n }\n // Only values other than 0 and 1 are rejected.\n if (typeof node.minItems === 'number' && node.minItems > 1) {\n delete node.minItems;\n stripped.push(`${path}/minItems`);\n }\n for (const keyword of UNDROPPABLE_KEYWORDS) {\n if (keyword in node)\n undroppable.push(`${path}/${keyword}`);\n }\n // An object node must be closed. `additionalProperties: true` is a direct\n // contradiction of the caller's own enforcement request, so it is overridden\n // rather than honoured \u2014 but loudly, since it changes what the schema admits.\n //\n // `type` may be an ARRAY containing `'object'` (a nullable object), which has\n // to close exactly like the scalar spelling. Testing `properties` alone is not\n // enough: a *property-less* `{type: ['object','null']}` would slip through and\n // then differ from `{type: 'object'}` in what it admits, purely because it is\n // nullable.\n const isObjectNode = node.type === 'object' ||\n (Array.isArray(node.type) && node.type.includes('object')) ||\n isPlainObject(node.properties);\n if (isObjectNode) {\n if (node.additionalProperties !== false) {\n if (node.additionalProperties !== undefined) {\n overridden.push(`${path}/additionalProperties`);\n }\n node.additionalProperties = false;\n }\n }\n return node;\n });\n return { schema, stripped, overridden, undroppable };\n}\n/**\n * Adapt a tool's `parameters` for enforcement and log what could not be carried\n * across. Thin wrapper over {@link toEnforcedAnthropicSchema} for transport use.\n *\n * Named as a **verb** to keep it distinct from the pure transform it wraps: this\n * one logs and returns only the schema, so a caller that wants to inspect what was\n * stripped or tightened wants `toEnforcedAnthropicSchema` instead. An earlier name\n * differed from it by word order alone, which made the two easy to confuse on\n * autocomplete despite returning different things. PR #2449 review.\n */\nexport function enforceAnthropicToolSchema(parameters, toolName) {\n const { schema, stripped, overridden, undroppable } = toEnforcedAnthropicSchema(parameters);\n if (stripped.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" requested schema enforcement; these keywords cannot ` +\n `be enforced and were removed \u2014 validate them yourself: ${stripped.join(', ')}`);\n }\n if (overridden.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" requested schema enforcement, which requires closed ` +\n `objects; \\`additionalProperties\\` was set to false at: ${overridden.join(', ')}. The tool ` +\n `now accepts fewer inputs than its schema declared.`);\n }\n if (undroppable.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" uses schema keywords enforcement cannot express ` +\n `(${undroppable.join(', ')}). They cannot be removed without changing the schema's meaning, ` +\n `so the request will be rejected. Rewrite them or drop enforceSchema for this tool.`);\n }\n return schema;\n}\n// \u2500\u2500 Gemini: dialect translation (F7) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * Keywords Gemini's function-declaration schema has no field for. They are\n * unknown-field parse errors, not unsupported features, so they must be removed\n * whatever the caller wrote. Measured against `gemini-3.5-flash`.\n */\nconst GEMINI_UNSUPPORTED_KEYWORDS = [\n 'additionalProperties',\n 'examples',\n 'multipleOf',\n 'patternProperties',\n // Both spellings of the definitions block. `$defs` would also fall to the\n // `$`-prefix sweep below, but the draft-07 spelling has no `$` and would\n // otherwise survive inlining and 400 the request \u2014 so list the pair together.\n '$defs',\n 'definitions',\n];\n/** Resolve a local JSON Pointer (`#/$defs/Name`) against the document root. */\nfunction resolvePointer(root, ref) {\n if (!ref.startsWith('#/'))\n return undefined;\n let current = root;\n for (const segment of ref.slice(2).split('/')) {\n if (!isPlainObject(current))\n return undefined;\n current = current[segment.replace(/~1/g, '/').replace(/~0/g, '~')];\n }\n return isPlainObject(current) ? current : undefined;\n}\n/**\n * Inline every local `$ref` against the root's `$defs`/`definitions`, because\n * Gemini has no field for either.\n *\n * A `$ref` that cannot be inlined \u2014 a cycle, a typo'd pointer, or an external\n * (non-`#/\u2026`) one \u2014 is left in place and collected in `unresolved`. It then\n * survives to the wire on purpose: `toGeminiSchema` exempts `$ref` from its\n * `$`-prefix sweep, so Gemini rejects the declaration instead of accepting a node\n * that constrains nothing. The collected pointers are logged, so the developer\n * reads which ref is at fault rather than decoding a provider error about a field\n * they never wrote.\n */\nfunction inlineRefs(root, node, seen, unresolved) {\n // Substitute *before* descending, so refs nested inside a resolved target are\n // themselves resolved. `seen` carries down that branch only, so the same\n // definition may legitimately appear twice in sibling positions.\n //\n // Loops rather than substituting once, because a target may ITSELF be a `$ref`\n // (an alias chain `A \u2192 B \u2192 C`). Stopping after one hop leaves a trailing `$ref`\n // that the sweep then deletes, collapsing the property to `{}` \u2014 the silent case\n // described above. Every hop joins `visited`, so a chain that turns back on\n // itself terminates instead of expanding forever.\n let current = node;\n let visited = seen;\n let ref = typeof current.$ref === 'string' ? current.$ref : undefined;\n while (ref && !visited.has(ref)) {\n const target = resolvePointer(root, ref);\n if (!target)\n break;\n const { $ref: _dropped } = current, siblings = __rest(current, [\"$ref\"]);\n current = Object.assign(Object.assign({}, cloneValue(target)), siblings);\n visited = new Set([...visited, ref]);\n ref = typeof current.$ref === 'string' ? current.$ref : undefined;\n }\n if (typeof current.$ref === 'string')\n unresolved.push(current.$ref);\n return mapChildSchemas(current, (child) => inlineRefs(root, child, visited, unresolved), '');\n}\n/**\n * Translate a JSON Schema into the OpenAPI 3.0 subset Gemini's function\n * declarations (and `responseSchema`) actually parse.\n *\n * This runs **unconditionally**, independently of any enforcement opt-in: Gemini\n * constrains tool arguments by default, so the only question here is whether the\n * declaration is *accepted at all*. Left untranslated, a schema with any nullable\n * column is a hard `400 Unknown name \"type\"` before the model runs.\n *\n * | JSON Schema | Gemini |\n * | --- | --- |\n * | `{\"type\": [\"integer\",\"null\"]}` | `{\"type\": \"integer\", \"nullable\": true}` |\n * | `{\"anyOf\": [{...}, {\"type\":\"null\"}]}` | the non-null branch, `nullable: true` |\n * | `{\"const\": \"X\"}` | `{\"enum\": [\"X\"]}` |\n * | `additionalProperties`, `examples`, `multipleOf` | removed |\n * | `$defs` / `$ref` | inlined, alias chains walked out |\n * | a `$ref` that cannot be inlined | **kept**, so the provider rejects it |\n * | any other `$`-prefixed keyword | removed |\n *\n * A type union that is not simply \"T or null\" (e.g. `[\"string\",\"integer\"]`) has\n * no OpenAPI equivalent and is left alone, so the provider rejects it rather\n * than us silently picking a branch.\n */\nexport function toGeminiSchema(parameters) {\n const unresolved = [];\n const inlined = inlineRefs(parameters, parameters, new Set(), unresolved);\n if (unresolved.length) {\n logger.warn(`GeminiTransport: these \\`$ref\\` pointers could not be inlined \u2014 a cycle, a typo, or an ` +\n `external ref: ${[...new Set(unresolved)].join(', ')}. They are left in the schema, so ` +\n `Gemini will reject this declaration; that is deliberate, because dropping them would ` +\n `send a node that constrains nothing.`);\n }\n const translated = mapSchema(inlined, (node) => {\n // `type: [T, \"null\"]` \u2192 `type: T, nullable: true`\n if (Array.isArray(node.type)) {\n const types = node.type.filter((t) => t !== 'null');\n if (types.length === 1 && node.type.length !== types.length) {\n node.type = types[0];\n node.nullable = true;\n }\n }\n // `anyOf: [X, {type:\"null\"}]` \u2192 X with `nullable: true`\n if (Array.isArray(node.anyOf)) {\n const branches = node.anyOf.filter(isPlainObject);\n const nonNull = branches.filter((b) => b.type !== 'null');\n if (branches.length === 2 && nonNull.length === 1) {\n const { anyOf: _dropped } = node, siblings = __rest(node, [\"anyOf\"]);\n return Object.assign(Object.assign(Object.assign({}, nonNull[0]), siblings), { nullable: true });\n }\n }\n if ('const' in node) {\n node.enum = [node.const];\n delete node.const;\n }\n for (const keyword of GEMINI_UNSUPPORTED_KEYWORDS)\n delete node[keyword];\n // Anything else `$`-prefixed (`$schema`, `$comment`, `$id`) is an unknown field\n // to Gemini and is dropped. `$ref` is deliberately EXEMPT: one that survives\n // inlining is a cycle, a typo, or an external pointer, and deleting it would\n // leave `{}` \u2014 a node Gemini accepts and does not constrain, which is the\n // silent widening this whole module exists to avoid. Left in place, the\n // declaration is rejected outright. Same choice as the genuine multi-type union\n // above: a schema that cannot be translated faithfully must fail rather than\n // quietly admit anything. PR #2449 review.\n for (const key of Object.keys(node)) {\n if (key.startsWith('$') && key !== '$ref')\n delete node[key];\n }\n return node;\n });\n return translated;\n}\n", "/**\n * Resolve the authoritative reason behind an abort-shaped rejection.\n *\n * Chromium/Firefox reject an aborted fetch/body read with the signal's\n * `reason`, but older WebKit rejects with a generic `AbortError` \u2014 which would\n * send a transport timeout down a caller's user-cancel path. Node and jsdom\n * test environments can raise the same shape as a plain `Error` rather than a\n * `DOMException`, so both are accepted (gated on the exact abort names).\n *\n * When `error` is abort-shaped the CALLER signal wins a same-tick tie: if the\n * user hits Stop in the same tick a stall/timeout fires, their intent takes\n * precedence, so the turn still routes to the user-cancel path and keeps its\n * \"Stopped.\" marker (first-cancel-wins, matching the pre-refactor behaviour).\n * A pure timeout \u2014 caller not aborted \u2014 still yields the timeout signal's\n * tagged `TimeoutError`, which is the WebKit fix. Anything not abort-shaped\n * passes through untouched.\n */\nexport function authoritativeAbortReason(error, timeoutSignal, callerSignal) {\n const abortShaped = (error instanceof DOMException || error instanceof Error) &&\n (error.name === 'AbortError' || error.name === 'TimeoutError');\n if (!abortShaped)\n return error;\n if (callerSignal === null || callerSignal === void 0 ? void 0 : callerSignal.aborted)\n return callerSignal.reason;\n if (timeoutSignal.aborted)\n return timeoutSignal.reason;\n return error;\n}\n", "/**\n * A `setTimeout`-based delay that rejects as soon as `signal` aborts, with the\n * signal's reason \u2014 so retry backoffs unwind immediately on a caller cancel or\n * dispose instead of waiting out the full wait. Resolves normally when `ms`\n * elapses first (the abort listener is detached, so a long-lived signal reused\n * across many delays does not accumulate dead listeners).\n */\nexport function abortableDelay(ms, signal) {\n return new Promise((resolve, reject) => {\n const abortReason = () => { var _a; return (_a = signal === null || signal === void 0 ? void 0 : signal.reason) !== null && _a !== void 0 ? _a : new DOMException('The operation was aborted.', 'AbortError'); };\n if (signal === null || signal === void 0 ? void 0 : signal.aborted) {\n reject(abortReason());\n return;\n }\n const onAbort = () => {\n clearTimeout(timer);\n reject(abortReason());\n };\n const timer = setTimeout(() => {\n signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n", "/**\n * Shared reader for the ai-service proxy's NDJSON heartbeat protocol (v1),\n * used by the server-proxied transports (Anthropic, Gemini). The proxy streams\n * `ping` frames while the upstream call runs and ends the body with exactly one\n * terminal `ok`/`err` frame, one JSON object per LF-terminated line.\n */\nimport { __awaiter } from \"tslib\";\n/** Cap on how much of a malformed proxy frame is quoted in the error message. */\nconst MALFORMED_FRAME_PREVIEW_CHARS = 120;\n/**\n * Read an NDJSON heartbeat body to its terminal frame. Buffers partial lines\n * across chunks, tolerates blank lines, and skips unknown frame types \u2014 pings\n * matter only as activity, which `onChunk` reports to the caller's stall\n * timer. An abort (stall timer or caller signal) rejects the pending `read()`\n * with the abort reason, which propagates to the caller's finally cleanup.\n * `vendorLabel` (e.g. `'Anthropic'`) prefixes the protocol-violation messages.\n *\n * `stallTimeout` (ms) arms a client-side backstop: the proxy's own pings re-arm\n * the caller's inactivity timer, so a proxy whose upstream has wedged but which\n * keeps pinging would never trip it. Each ping stamps `sinceLastEventMs` (time\n * since the last upstream event); when that exceeds `stallTimeout` we treat it\n * as a stall and throw the tagged `TimeoutError`, independent of the proxy\n * noticing its own stall. `<= 0` disables the backstop (inactivity detection off).\n */\nexport function readFramedBody(stream, onChunk, vendorLabel, stallTimeout) {\n return __awaiter(this, void 0, void 0, function* () {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n const malformedFrame = (line) => new Error(`${vendorLabel} proxy sent a malformed frame: ${line.slice(0, MALFORMED_FRAME_PREVIEW_CHARS)}`);\n const parseLine = (line) => {\n if (!line)\n return undefined;\n let parsed;\n try {\n parsed = JSON.parse(line);\n }\n catch (_a) {\n throw malformedFrame(line);\n }\n // JSON.parse also accepts null/scalars/arrays \u2014 a frame must be an object\n // (dereferencing `.t` on null would otherwise throw a raw TypeError).\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw malformedFrame(line);\n }\n const frame = parsed;\n if (frame.t === 'ok') {\n if (frame.body == null) {\n throw new Error(`${vendorLabel} proxy sent an ok frame without a body`);\n }\n return frame;\n }\n if (frame.t === 'err') {\n // The cast below promises a numeric status; hold the proxy to it rather\n // than letting `undefined` leak into the retry/status checks downstream.\n if (typeof frame.status !== 'number') {\n throw new Error(`${vendorLabel} proxy sent an err frame without a numeric status`);\n }\n return frame;\n }\n if (frame.t === 'ping') {\n // Client-side stall backstop: the proxy stamps how long its upstream has\n // been silent. Its pings keep the caller's inactivity timer alive, so\n // this is the only signal that catches a wedged upstream behind a proxy\n // that is itself still healthy. Surface the same tagged TimeoutError a\n // local inactivity fire would.\n if (stallTimeout > 0 &&\n typeof frame.sinceLastEventMs === 'number' &&\n frame.sinceLastEventMs > stallTimeout) {\n throw new DOMException(`${vendorLabel} request stalled: proxy reported ${frame.sinceLastEventMs}ms since the last upstream event (exceeds ${stallTimeout}ms)`, 'TimeoutError');\n }\n return undefined;\n }\n return undefined; // unknown frame types (forward compat)\n };\n try {\n for (;;) {\n // oxlint-disable-next-line no-await-in-loop -- sequential stream reads\n const { done, value } = yield reader.read();\n if (done)\n break;\n onChunk();\n buffer += decoder.decode(value, { stream: true });\n let newline = buffer.indexOf('\\n');\n while (newline !== -1) {\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n const frame = parseLine(line);\n if (frame)\n return frame;\n newline = buffer.indexOf('\\n');\n }\n }\n // Tolerate a final terminal frame missing its LF.\n const frame = parseLine((buffer + decoder.decode()).trim());\n if (frame)\n return frame;\n throw new Error(`${vendorLabel} proxy stream ended without a terminal frame`);\n }\n finally {\n // Stop the stream on early return, error, or abort; cancel rejects on an\n // already-errored stream, which is fine to ignore.\n void reader.cancel().catch(() => { });\n }\n });\n}\n", "/**\n * Server-supplied retry hints for the shared `postWithRetry` ladder (GENC-1506).\n *\n * ## Why this exists\n *\n * The ladder was `base * 2^attempt` \u2014 1s, 2s, 4s, 8s, 16s, **31s in total** \u2014 and it read neither the\n * HTTP `Retry-After` header nor Google's in-body `RetryInfo`. Measured against a real rate-limited\n * Gemini key (2026-08-18), the provider asked for **53s**:\n *\n * ```jsonc\n * {\"error\":{\"code\":429,\"status\":\"RESOURCE_EXHAUSTED\",\n * \"message\":\"\u2026 Please retry in 53.59713199s.\",\n * \"details\":[{\"@type\":\"type.googleapis.com/google.rpc.RetryInfo\",\"retryDelay\":\"53s\"}]}}\n * ```\n *\n * So a **legitimate** rate limit burned all five retries inside the window the provider had told us to\n * wait, then failed opaquely \u2014 every attempt after the first guaranteed to fail, and the user waiting\n * 31s to be told nothing useful. Honouring the hint turns five doomed requests into one that works.\n *\n * ## Scope note\n *\n * This is deliberately vendor-neutral and applies to **healthy traffic**, not just refusals. It is the\n * one part of GENC-1506 that changes timing on a path that is working: some failures that used to give\n * up after 31s will now wait longer before succeeding or failing. That is the correct behaviour and it\n * is what the server asked for, but it is why the ladder keeps its own tests and its own line in the\n * release notes rather than riding along silently inside a fix about error messages.\n *\n * @packageDocumentation\n */\n/**\n * Ceiling on a server-requested wait, per attempt.\n *\n * A hint is *advice from a remote party*, so it needs a bound: without one, a mistaken or hostile\n * `Retry-After: 86400` parks a turn for a day with no way out but a caller abort. 60s sits comfortably\n * above the largest value observed (53s) while keeping the worst case survivable.\n *\n * This caps each wait, and it is the ONLY per-attempt bound \u2014 the earlier claim that the exponential\n * ladder bounds a pathological sequence was simply wrong, because `resolveBackoffMs` takes the LARGER\n * of the two and the ladder tops out at `baseMs * 2 ** 4` (16s at the 1s base every transport uses). A\n * 60s hint therefore wins on every attempt and the ladder never contributes. That is what\n * {@link MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS} is for.\n */\nexport const MAX_SERVER_REQUESTED_BACKOFF_MS = 60000;\n/**\n * Ceiling on the server-requested wait across a WHOLE retry sequence.\n *\n * Without it the per-attempt cap is no real bound: five capped waits is five minutes, and nothing is\n * watching during them \u2014 the attempt's own timeout is cleared before each backoff, so a provider (or a\n * proxy in front of one) answering `Retry-After: 3600` five times parks the turn for the full five\n * minutes with a caller abort as the only way out.\n *\n * 120s is chosen so the case this module was written for still works untouched: the measured Gemini\n * hint was 53s, and two of those fit inside the budget with headroom. Past it we stop honouring hints\n * and fall back to the ladder, so a sequence of maximal 60s hints now totals ~151s (120s of honoured\n * excess plus the ladder's own 31s) rather than 300s.\n *\n * What it budgets is the EXCESS over the wait the ladder would have taken anyway \u2014 see\n * {@link serverBackoffSpentMs}. Budgeting the raw hint instead would let the ladder's own growth eat\n * the allowance late in a sequence, declining hints on the grounds of time we were always going to\n * spend.\n */\nexport const MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS = 120000;\n/** Anthropic's explicit retry verdict, which its own SDK honours. */\nconst SHOULD_RETRY_HEADER = 'x-should-retry';\n/** Both hint formats are expressed in seconds; every internal wait is in ms. */\nconst MS_PER_SECOND = 1000;\n/**\n * `true` only when the server has **explicitly** said not to retry.\n *\n * Absent means \"no opinion\" and must never be read as `true` \u2014 that asymmetry is measured, not\n * cautious: the captured Anthropic `401` carries no `x-should-retry` at all, while the captured\n * spend-refusal `400` carries `false`. Treating absence as a refusal to retry would silently disable\n * the ladder for every provider that does not send the header, Google included.\n */\nexport function shouldNotRetry(headers) {\n var _a;\n const value = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, SHOULD_RETRY_HEADER);\n return typeof value === 'string' && value.trim().toLowerCase() === 'false';\n}\n/**\n * The `Retry-After` header in ms, or `undefined`.\n *\n * Both documented forms are accepted \u2014 delta-seconds (`Retry-After: 53`) and an HTTP-date\n * (`Retry-After: Wed, 21 Oct 2026 07:28:00 GMT`) \u2014 because a proxy or CDN in front of the provider may\n * rewrite one into the other, and a silently unparsed hint is indistinguishable from no hint at all.\n * A date already in the past clamps to 0 rather than going negative.\n */\nexport function retryAfterMs(headers) {\n var _a;\n const raw = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, 'retry-after');\n if (typeof raw !== 'string' || raw.trim() === '')\n return undefined;\n const seconds = Number(raw.trim());\n if (Number.isFinite(seconds))\n return Math.max(0, seconds * MS_PER_SECOND);\n const at = Date.parse(raw);\n if (Number.isNaN(at))\n return undefined;\n return Math.max(0, at - Date.now());\n}\n/**\n * Google's `google.rpc.RetryInfo.retryDelay` in ms, or `undefined`.\n *\n * Read from **two positions**, for the same reason the refusal classifier reads two: on the direct API\n * the body is Google's own (`{ error: { details: [...] } }`), while through the NDJSON framed proxy that\n * body is nested under the err frame's `details`. Reading one position only would honour the hint on\n * exactly one of the two paths.\n *\n * Matched on an `@type` **suffix** rather than the full URL: the type prefix is a Google-owned constant\n * that has no reason to change, but suffix-matching costs nothing and survives it if it does.\n */\nexport function retryInfoMs(payload) {\n const outer = typeof payload === 'object' && payload !== null ? payload : {};\n const framed = typeof outer.details === 'object' && outer.details !== null\n ? outer.details\n : undefined;\n for (const holder of [outer.error, framed === null || framed === void 0 ? void 0 : framed.error]) {\n const details = holder === null || holder === void 0 ? void 0 : holder.details;\n if (!Array.isArray(details))\n continue;\n for (const entry of details) {\n const type = entry === null || entry === void 0 ? void 0 : entry['@type'];\n if (typeof type !== 'string' || !type.endsWith('google.rpc.RetryInfo'))\n continue;\n const delay = entry === null || entry === void 0 ? void 0 : entry.retryDelay;\n // Protobuf Duration as JSON: a decimal number of seconds with an `s` suffix (\"53s\", \"1.5s\").\n if (typeof delay !== 'string')\n continue;\n const seconds = Number(delay.replace(/s$/, ''));\n if (Number.isFinite(seconds) && seconds >= 0)\n return seconds * MS_PER_SECOND;\n }\n }\n return undefined;\n}\n/**\n * How long to wait before the next attempt: never less than our own ladder, never less than the\n * server asked, never more than the ceiling.\n *\n * `max` rather than \"prefer the server's value\" is the point \u2014 a server asking for *less* than our\n * backoff must not be able to talk us into hammering it, which a naive \"honour the hint\" would do on\n * `Retry-After: 0`.\n *\n * @param attempt - zero-based attempt index, as the ladder counts them.\n * @param baseMs - the transport's backoff base; the ladder is `baseMs * 2^attempt`.\n * @param serverMs - the server's requested delay, when it supplied one.\n */\nexport function resolveBackoffMs(attempt, baseMs, serverMs, serverAllowanceMs = Number.POSITIVE_INFINITY) {\n const ladder = baseMs * Math.pow(2, attempt);\n if (serverMs == null || !Number.isFinite(serverMs))\n return ladder;\n // Three ceilings, all of which have to hold: what the server asked, the per-attempt cap, and\n // whatever is left of the sequence budget. An exhausted allowance clamps to 0, so the `max` below\n // returns the bare ladder and the sequence degrades to its pre-GENC-1506 behaviour rather than\n // stopping \u2014 a hint we decline to honour is not a reason to stop retrying.\n const honoured = Math.min(serverMs, MAX_SERVER_REQUESTED_BACKOFF_MS, Math.max(0, serverAllowanceMs));\n return Math.max(ladder, honoured);\n}\n/**\n * How much of the sequence budget a resolved wait consumed.\n *\n * Only the part attributable to the server counts: a wait the ladder would have taken anyway is not\n * the server's doing, so it must not eat the allowance \u2014 otherwise a long ladder late in a sequence\n * would exhaust the budget without a single hint having been honoured.\n */\nexport function serverBackoffSpentMs(resolvedMs, ladderMs) {\n return Math.max(0, resolvedMs - ladderMs);\n}\n", "import { __awaiter } from \"tslib\";\nimport { authoritativeAbortReason } from '../utils/abort-reason';\nimport { abortableDelay } from '../utils/abortable-delay';\nimport { combineSignals } from '../utils/combine-signals';\nimport { logger } from '../utils/logger';\nimport { budgetExhaustedFrom, codeOf, isBudgetRejection, parseJsonOrUndefined, } from './budget-exhausted-error';\nimport { readFramedBody } from './ndjson-frames';\nimport { providerRefusalOf, providerRefusedFrom, vendorOfTransportLabel } from './provider-refused';\nimport { MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS, resolveBackoffMs, retryAfterMs, retryInfoMs, serverBackoffSpentMs, shouldNotRetry, } from './retry-hints';\nconst MAX_RETRIES = 5;\n/**\n * POST with the shared retry ladder, wall-clock timeout, framed-mode stall\n * detection and abort-reason preservation. Returns the terminal `ok` frame body\n * (framed proxy) or the parsed JSON (legacy proxy / direct API) as `unknown` \u2014\n * the caller casts. Throws a tagged `TimeoutError` on a stall (local inactivity,\n * the proxy's `sinceLastEventMs` backstop, or an `UPSTREAM_STALLED` frame), the\n * caller's reason on a caller abort, or a plain `Error` otherwise.\n */\nexport function postWithRetry(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c, _d, _e, _f, _g;\n const { url, headers, body, credentials, vendorLabel, retryableStatuses, timeout, stallTimeout, backoffBaseMs, signal, } = options;\n // The vendor behind this transport's label, resolved once \u2014 the refusal classifier dispatches on\n // it, and it is the only vendor knowledge this envelope needs (GENC-1506).\n const vendor = vendorOfTransportLabel(vendorLabel);\n // Total time this sequence has spent waiting BEYOND its own ladder because a server asked it to.\n // The per-attempt cap alone is not a bound on the sequence \u2014 five capped waits is five minutes, with\n // no timer running through any of them \u2014 so the allowance is tracked here and spent down across\n // attempts. Per-call state, deliberately: a budget shared between concurrent requests would make one\n // request's hints silently shorten another's.\n let serverBackoffSpent = 0;\n // Exponential backoff between retries: base, 2\u00D7, 4\u00D7, 8\u00D7, 16\u00D7 \u2014 raised to whatever the server asked\n // for when it asked for more (GENC-1506; see `retry-hints`). Abortable on the CALLER signal only \u2014\n // the timeout is cleared before each backoff, so a caller cancel mid-wait unwinds immediately while\n // a timeout does not.\n const backoff = (attempt, serverMs) => {\n const ladderMs = backoffBaseMs * Math.pow(2, attempt);\n const allowanceMs = MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS - serverBackoffSpent;\n const waitMs = resolveBackoffMs(attempt, backoffBaseMs, serverMs, allowanceMs);\n serverBackoffSpent += serverBackoffSpentMs(waitMs, ladderMs);\n if (serverMs != null && waitMs > ladderMs) {\n // Logged because an honoured hint is otherwise indistinguishable from a hang: a silent 53s\n // pause in a log is the sort of thing someone spends an afternoon on.\n logger.warn(`${vendorLabel}Transport: honouring the server's requested retry delay (${Math.round(waitMs)}ms, asked ${Math.round(serverMs)}ms)`);\n }\n else if (serverMs != null && serverMs > ladderMs) {\n // The hint was declined, which is worth its own line: the wait about to happen is shorter than\n // the server asked for, and without this the log looks like the hint was never sent.\n logger.warn(`${vendorLabel}Transport: declining the server's requested retry delay (asked ${Math.round(serverMs)}ms; the ${MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS}ms sequence allowance is spent) \u2014 using the ladder's ${Math.round(waitMs)}ms`);\n }\n return abortableDelay(waitMs, signal);\n };\n // Sequential retries are intentional \u2014 each attempt depends on the previous response.\n /* oxlint-disable no-await-in-loop -- intentional sequential retries with backoff */\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {\n const timeoutController = new AbortController();\n // Which phase the request reached before the clock fired. A bare \"timed out\"\n // cannot distinguish \"the service never answered at all\" from \"it answered,\n // then produced no body\" \u2014 and those have completely different owners\n // (network/gateway vs the service itself). `fetch` resolves on HEADERS, so\n // the phase is knowable here and is the single most useful fact when the\n // only evidence available is a client-side log.\n // `performance.now()` (monotonic), not `Date.now()`: an NTP step or suspend/resume mid-request\n // would otherwise land a nonsense duration in the very message someone is reading to diagnose\n // a hang. Only differences are used, so the arbitrary time origin is irrelevant.\n const startedAt = performance.now();\n let headersAt;\n let responseCtype;\n const timedOutMessage = () => {\n const waited = Math.round(performance.now() - startedAt);\n if (headersAt === undefined) {\n return `${vendorLabel} request timed out after ${waited}ms \u2014 no response headers (the service never answered; nothing was received to stall on)`;\n }\n return `${vendorLabel} request timed out after ${waited}ms \u2014 headers arrived in ${Math.round(headersAt - startedAt)}ms (content-type: ${responseCtype !== null && responseCtype !== void 0 ? responseCtype : 'unknown'}) but no body followed`;\n };\n // Wall clock for connect/headers (and the whole body on the legacy JSON\n // path). The framed path swaps it for the inactivity timer below once the\n // heartbeat body starts streaming.\n let timeoutId = setTimeout(() => timeoutController.abort(new DOMException(timedOutMessage(), 'TimeoutError')), timeout);\n // Re-armed on every received chunk. With proxy pings every 5s it only fires\n // when the proxy/network actually dies \u2014 a framed body that keeps streaming\n // has no wall cap (max_tokens bounds generation; the proxy watches upstream).\n // A non-positive stallTimeout disables inactivity detection: leave the wall\n // clock armed as the only cap (and the sinceLastEventMs backstop stays off).\n const rearmStallTimer = () => {\n if (stallTimeout <= 0)\n return;\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => timeoutController.abort(new DOMException(`${vendorLabel} request stalled (no data for ${stallTimeout}ms)`, 'TimeoutError')), stallTimeout);\n };\n // Combine so BOTH the local timeout and an optional caller signal can abort\n // the fetch. A plain `signal ?? timeoutController.signal` would silently\n // disarm the timeout whenever a caller signal was supplied. The tagged\n // `TimeoutError` lets callers distinguish a timeout from a caller-initiated\n // cancellation by inspecting the abort reason.\n const { signal: combinedSignal, dispose } = combineSignals([signal, timeoutController.signal]);\n // The finally guards the WHOLE attempt \u2014 body reads included. Disarming on\n // headers alone left `response.json()` with no deadline and no caller abort.\n try {\n const response = yield fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: combinedSignal,\n credentials,\n });\n // Headers are in \u2014 record the phase so a later timeout can say so. Cheap and\n // unconditional: the value is only read when the clock actually fires.\n headersAt = performance.now();\n // Defensive: `headers` is optional on the Response-likes callers and tests supply, and a\n // diagnostic must never be the thing that breaks the request it is describing.\n responseCtype = (_c = (_b = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, 'content-type')) !== null && _c !== void 0 ? _c : undefined;\n if (!response.ok) {\n // One read of the error body per failing attempt \u2014 it feeds BOTH the\n // budget classification and the thrown message, and the response is\n // discarded either way. Note this means a retryable attempt now reads\n // the (small, proxy-authored) error body before backing off. That is the\n // price of the classification winning over the ladder in this branch as\n // well as the framed one; the attempt's wall-clock timer is still armed\n // and the read runs on the fetch's combined signal, so a pathological\n // non-terminating body times out rather than hanging.\n //\n // That timeout is a real behaviour change for a RETRYABLE status, and the\n // accepted cost of the symmetry: a 503 used to reach the ladder without\n // the body being touched, so a non-terminating one still backed off and\n // retried. Now the abort propagates out of `postWithRetry` instead.\n // Acceptable because these bodies are proxy-authored and small \u2014 if that\n // ever stops being true, read the body only when the status is\n // non-retryable or already budget-shaped.\n const errText = yield response.text();\n const parsed = parseJsonOrUndefined(errText);\n // The PROVIDER wall (GENC-1506) is classified BEFORE the budget wall, and the order is\n // load-bearing rather than arbitrary. `isBudgetRejection` treats a bare `402` as our own\n // budget verdict, and `402` is also Anthropic's documented `billing_error` status \u2014 so a\n // relayed upstream billing failure would otherwise be reported as the user's own spend cap,\n // locking their composer and sending them to an administrator to raise a limit that has\n // headroom. Every trigger in `providerRefusalOf` is a POSITIVE signal, so a bare `402` with\n // no provider envelope still falls through to the budget branch exactly as it always did.\n const refusal = providerRefusalOf(vendor, codeOf(parsed), parsed);\n if (refusal) {\n throw providerRefusedFrom(vendorLabel, refusal, response.status, parsed, errText || undefined);\n }\n // The budget wall (GENC-1464) wins over ANY status-based retry \u2014 the same\n // rule the framed branch below applies, now symmetric. It must be\n // classified BEFORE the ladder, not after it: 402 is absent from every\n // RETRYABLE_STATUSES today, but a proxy that maps the refusal onto a\n // retryable status (or a future set that includes 402) would otherwise\n // cost five doomed requests and ~31s of backoff before an opaque error \u2014\n // exactly the bug this classification exists to remove. Parsing is\n // best-effort: an unparseable or plain-text 402 still classifies, just\n // without the budget/spent figures.\n if (isBudgetRejection(response.status, codeOf(parsed))) {\n throw budgetExhaustedFrom(vendorLabel, parsed, errText || undefined);\n }\n // An explicit `x-should-retry: false` outranks our own retryable-status set (GENC-1506).\n // The provider knows things the status does not \u2014 a 429 it will keep refusing, say \u2014 and\n // Anthropic's own SDK honours this header. Absent means \"no opinion\", never `false`.\n const refusedRetry = shouldNotRetry(response.headers);\n if (retryableStatuses.includes(response.status) && !refusedRetry && attempt < MAX_RETRIES) {\n logger.warn(`${vendorLabel}Transport: retryable status ${response.status}, retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);\n clearTimeout(timeoutId); // this attempt is over \u2014 don't let its timer tick through the backoff\n // `||` not `??`: `retryAfterMs` returns 0 \u2014 not undefined \u2014 for `Retry-After: 0` and for an\n // HTTP-date already in the past, and a 0 carries nothing the ladder does not already have.\n // With `??` such a response would take the 0 and never read the in-body hint beside it.\n yield backoff(attempt, retryAfterMs(response.headers) || retryInfoMs(parsed));\n continue;\n }\n throw new Error(`${vendorLabel} request error ${response.status}: ${errText}`);\n }\n // The proxy streams NDJSON heartbeat frames when it supports them; an old\n // proxy ignores our Accept header and returns plain JSON, so branch on\n // what actually came back.\n if (((_e = (_d = response.headers) === null || _d === void 0 ? void 0 : _d.get('content-type')) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('application/x-ndjson')) &&\n response.body) {\n rearmStallTimer();\n const frame = yield readFramedBody(response.body, rearmStallTimer, vendorLabel, stallTimeout);\n if (frame.t === 'ok')\n return frame.body;\n // Classify a stall by `code` BEFORE the retryable-status ladder: a stall\n // paired with a retryable status must surface as the non-retried\n // TimeoutError, not get retried 5\u00D7 as that status.\n if (frame.code === 'UPSTREAM_STALLED') {\n // The proxy watchdog saw no upstream data \u2014 same tagged shape as a\n // local stall, so the driver's TimeoutError branch handles both.\n throw new DOMException(`${vendorLabel} request stalled: ${(_f = frame.error) !== null && _f !== void 0 ? _f : 'no upstream data'}`, 'TimeoutError');\n }\n // The budget wall, framed (GENC-1464) \u2014 the in-band twin of the 402 above,\n // through the same predicate, keyed on status OR code. Classified before\n // the retryable ladder for the same reason UPSTREAM_STALLED is: the\n // classification must win over any status-based retry. That ordering is\n // no longer unique to this branch \u2014 the legacy branch above now applies\n // the identical rule, so the two read as one policy rather than two.\n // The PROVIDER wall, framed (GENC-1506) \u2014 the in-band twin of the classification in the\n // legacy branch above, ahead of the budget wall for the same reason: the proxy relays an\n // upstream `402` faithfully, so a `billing_error` would otherwise be reported as the user's\n // own spend cap. On this path the upstream envelope rides in the frame's `details` while the\n // frame's own `error` is the proxy's summary string \u2014 `providerRefusalOf` reads both\n // positions, so the same classification serves the browser and the server.\n const framedRefusal = providerRefusalOf(vendor, frame.code, frame);\n if (framedRefusal) {\n throw providerRefusedFrom(vendorLabel, framedRefusal, frame.status, frame, frame.error);\n }\n if (isBudgetRejection(frame.status, frame.code)) {\n throw budgetExhaustedFrom(vendorLabel, frame);\n }\n // An in-band retryable status joins the same attempt/backoff ladder as\n // its HTTP-status equivalent (shared attempt counter). No `x-should-retry` to consult here \u2014\n // in framed mode the HTTP response is the proxy's own 200, so its headers say nothing about\n // the upstream attempt; the in-body `RetryInfo` is the only hint that survives the hop.\n if (retryableStatuses.includes(frame.status) && attempt < MAX_RETRIES) {\n logger.warn(`${vendorLabel}Transport: retryable status ${frame.status} (err frame), retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);\n clearTimeout(timeoutId); // disarm the stall timer \u2014 the stream is done, only the backoff remains\n yield backoff(attempt, retryInfoMs(frame));\n continue;\n }\n throw new Error(`${vendorLabel} request error ${frame.status}: ${(_g = frame.error) !== null && _g !== void 0 ? _g : JSON.stringify(frame.details)}`);\n }\n return (yield response.json());\n }\n catch (e) {\n // Some engines reject an aborted read with a generic AbortError instead of\n // the signal's reason \u2014 rethrow the authoritative one so a timeout stays a\n // tagged TimeoutError rather than looking like a user cancel.\n throw authoritativeAbortReason(e, timeoutController.signal, signal);\n }\n finally {\n clearTimeout(timeoutId);\n dispose();\n }\n }\n /* oxlint-enable no-await-in-loop */\n throw new Error(`${vendorLabel} request failed: max retries exceeded`);\n });\n}\n", "import { __awaiter } from \"tslib\";\nimport { SUPPORTED_ANTHROPIC_MODEL_IDS, } from '../types';\nimport { normalizeImageMime, stripImageDataUrl } from '../utils/image-mime';\nimport { logger } from '../utils/logger';\nimport { scaleTemperature } from '../utils/temperature';\nimport { anthropicTokenCost } from '../utils/token-cost';\nimport { enforceAnthropicToolSchema } from '../utils/tool-schema';\nimport { VENDOR_LABELS } from './budget-exhausted-error';\nimport { postWithRetry } from './post-with-retry';\nconst ANTHROPIC_DIRECT_URL = 'https://api.anthropic.com/v1/messages';\nconst ANTHROPIC_API_VERSION = '2023-06-01';\nconst DEFAULT_MODEL = 'claude-haiku-4-5-20251001';\nconst DEFAULT_TIMEOUT = 300000; // healthy >200s generations observed at 128k max_tokens; wall clock is a last resort\nconst DEFAULT_STALL_TIMEOUT = 30000; // inactivity window on the framed proxy path; pings arrive every 5s\nconst DEFAULT_MAX_TOKENS = 4096;\n/** Anthropic's native default + ceiling temperature \u2014 https://docs.claude.com/en/api/messages */\nconst ANTHROPIC_DEFAULT_TEMPERATURE = 1;\nconst ANTHROPIC_MAX_TEMPERATURE = 1;\n/**\n * Map a provider-agnostic {@link ChatToolChoice} to Anthropic's `tool_choice`.\n * Returns undefined for the default (`'auto'`) so the request omits the field.\n */\nfunction toAnthropicToolChoice(choice) {\n if (!choice || choice === 'auto')\n return undefined;\n if (choice === 'required')\n return { type: 'any' };\n if (choice === 'none')\n return { type: 'none' };\n return { type: 'tool', name: choice.tool };\n}\n/**\n * Maximum input context window (tokens) per supported Claude model.\n * Source: https://docs.claude.com/en/docs/about-claude/models/overview\n */\nconst ANTHROPIC_CONTEXT_LIMITS = {\n 'claude-fable-5': 1000000,\n 'claude-opus-4-8': 1000000,\n 'claude-opus-4-7': 1000000,\n 'claude-sonnet-5': 1000000,\n 'claude-sonnet-4-6': 1000000,\n 'claude-haiku-4-5-20251001': 200000,\n};\n/**\n * Tool name used to coerce JSON-schema output from the model when the caller\n * provided a `responseSchema`. The transport forces `tool_choice` to this tool\n * and surfaces the `input` field as the structured response.\n */\nconst STRUCTURED_OUTPUT_TOOL_NAME = 'emit_structured_response';\n/** Beta flag enabling the server-side `fallbacks` request parameter (refusal rescue). */\nconst SERVER_SIDE_FALLBACK_BETA = 'server-side-fallback-2026-06-01';\nfunction assertSupportedAnthropicModel(model) {\n if (!SUPPORTED_ANTHROPIC_MODEL_IDS.includes(model)) {\n throw new Error(`AnthropicTransport: unsupported model \"${model}\". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(', ')}.`);\n }\n}\n/**\n * Models that reject non-default sampling parameters (`temperature`/`top_p`/`top_k`) with a 400 \u2014\n * the Opus 4.7+ / Sonnet 5 / Fable 5 generation. Sonnet 4.6 and Haiku 4.5 still accept them.\n */\nfunction rejectsSamplingParams(model) {\n return (model === 'claude-fable-5' ||\n model === 'claude-opus-4-8' ||\n model === 'claude-opus-4-7' ||\n model === 'claude-sonnet-5');\n}\n/**\n * Whether the model enforces structured output natively via decode-time `output_config.format`\n * (json_schema). True for Fable 5, Opus 4.8, Sonnet 5, and Haiku 4.5; false for Opus 4.7 and\n * Sonnet 4.6, which fall back to the forced-tool approach on the one-shot path. `output_config`\n * composes with a live `tools` array, so no tool-vs-schema gating is needed on this provider.\n */\nfunction supportsNativeStructuredOutput(model) {\n return (model === 'claude-fable-5' ||\n model === 'claude-opus-4-8' ||\n model === 'claude-sonnet-5' ||\n model === 'claude-haiku-4-5-20251001');\n}\n/**\n * Whether a model accepts `thinking: {type:'adaptive'}` at all. Everything from the 4.6\n * generation on does; Haiku 4.5 does not, and asking for it there is a 400 rather than a\n * no-op \u2014 so a caller's `'auto'` degrades to the model default instead of failing the turn.\n */\nfunction supportsAdaptiveThinking(model) {\n return model !== 'claude-haiku-4-5-20251001';\n}\n/**\n * Models that think **unconditionally** \u2014 `{type:'disabled'}` is a 400, not a no-op. The same\n * constraint exists on the other provider (Gemini 2.5 Pro), so this is a property of flagship\n * reasoning models rather than an Anthropic quirk; see `ChatThinkingPolicy`.\n */\nfunction thinkingIsMandatory(model) {\n return model === 'claude-fable-5';\n}\n/**\n * Extended-thinking posture for a request, given the model and the caller's\n * {@link ChatThinkingPolicy} for this turn.\n *\n * **`policy === undefined` is the per-model default, and is a distinct third state** \u2014 not a\n * synonym for either value. It reproduces exactly what this function returned before the option\n * existed, so an agent that leaves `thinkingPolicy` unset (or whose resolver returns `undefined`\n * on a given turn) is priced and behaves identically to before:\n *\n * - Sonnet 5 and Fable 5 \u2192 adaptive thinking with `display:'summarized'`, regardless of\n * `tool_choice`. First-party has no forced-tool-vs-thinking restriction (that's Bedrock-only),\n * and \"adaptive\" self-regulates (the model thinks little on trivial turns on its own), so there\n * is no reason to special-case forced tool calls. `display:'summarized'` means the reasoning\n * summary is always returned \u2014 billed regardless, with the host's toggle deciding only\n * *visibility*. Hiding the steps saves no money; `'off'` is what saves money.\n * - Every other model (Opus 4.8/4.7, Sonnet 4.6, Haiku) \u2192 `thinking` omitted, so it runs WITHOUT\n * thinking on the chat path (their adaptive thinking is opt-in). The older \"forced tool +\n * thinking is incompatible\" restriction therefore never applies to them \u2014 you cannot hit it\n * when thinking is off.\n *\n * An explicit policy overrides that default, **clamped to what the model can actually honour**\n * so a policy can never turn a turn into a 400:\n *\n * - `'off'` on a mandatory-thinking model (Fable 5) \u2192 left at its default. Requesting `disabled`\n * there is a 400; the caller is told once via {@link AnthropicTransport} rather than losing\n * the turn.\n * - `'auto'` on a model without adaptive support (Haiku) \u2192 omitted, i.e. its default.\n *\n * `'off'` is expressed as an *omission* on models that already default to no thinking, rather\n * than an explicit `{type:'disabled'}`: the two are equivalent on the wire there, and omitting\n * keeps the request identical to the one those models have always received.\n */\nfunction anthropicThinking(model, policy) {\n const defaultsToThinking = model === 'claude-sonnet-5' || thinkingIsMandatory(model);\n const adaptive = { type: 'adaptive', display: 'summarized' };\n if (policy === 'off') {\n // Cannot be turned off \u2014 keep the model's default rather than 400 the turn.\n if (thinkingIsMandatory(model))\n return adaptive;\n // Already off by default: omitting and disabling are the same request.\n return defaultsToThinking ? { type: 'disabled' } : undefined;\n }\n if (policy === 'auto') {\n return supportsAdaptiveThinking(model) ? adaptive : undefined;\n }\n // A graded level asks for reasoning DEPTH, which on Anthropic is `output_config.effort`\n // riding alongside adaptive thinking (see `anthropicEffort`). Asking for a depth on a model\n // with no adaptive support leaves it at its default rather than 400ing the turn.\n if (policy !== undefined) {\n return supportsAdaptiveThinking(model) ? adaptive : undefined;\n }\n // policy === undefined \u2192 the per-model default, unchanged.\n return defaultsToThinking ? adaptive : undefined;\n}\n/**\n * Whether the model accepts `output_config.effort`.\n *\n * An allow-list, and deliberately the same generation {@link supportsNativeStructuredOutput}\n * treats as new, minus Haiku: `effort` and `format` share the one `output_config` container, so\n * the two gates must agree on which models understand it. `output_config` arrived with the\n * Fable 5 / Opus 4.8 / Sonnet 5 generation \u2014 Opus 4.7 and Sonnet 4.6 predate it and 400 on a\n * field inside it, so a graded policy is dropped for them (they run their default posture, with a\n * one-time warning from {@link AnthropicTransport}) rather than forwarded into a failed turn.\n *\n * Haiku 4.5 is the lone asymmetry with `supportsNativeStructuredOutput`, which lists it: Haiku\n * took `output_config.format` but not `.effort`, and has no adaptive thinking for effort to ride\n * on anyway (`anthropicEffort` also gates on {@link supportsAdaptiveThinking}). An allow-list is\n * the safe default for a \"send-it-and-400\" parameter \u2014 a newly added model gets no `effort` until\n * it is confirmed to accept it.\n */\nfunction supportsEffort(model) {\n return model === 'claude-fable-5' || model === 'claude-opus-4-8' || model === 'claude-sonnet-5';\n}\n/**\n * `output_config.effort` for a graded policy.\n *\n * An exhaustive `Record`, not a condition chain: adding a member to {@link ChatThinkingLevel}\n * then fails to compile here instead of silently falling through to the model default, which is\n * the failure mode this mapping is most likely to acquire.\n *\n * `'minimal'` clamps UP to `low` \u2014 Anthropic's ladder starts there. `xhigh` is deliberately\n * unreachable; see {@link ChatThinkingPolicy}.\n */\nconst ANTHROPIC_EFFORT = {\n minimal: 'low',\n low: 'low',\n medium: 'medium',\n high: 'high',\n max: 'max',\n};\nfunction anthropicEffort(model, policy) {\n if (policy === undefined || policy === 'auto' || policy === 'off')\n return undefined;\n if (!supportsEffort(model) || !supportsAdaptiveThinking(model))\n return undefined;\n return ANTHROPIC_EFFORT[policy];\n}\n/**\n * Key under which this transport stashes its round-trip state on a tool call's\n * provider-neutral `providerMetadata` bag. Private to AnthropicTransport.\n */\nconst ANTHROPIC_PROVIDER_KEY = 'anthropic';\n/**\n * Thrown when a response was cut off at the output-token limit (Anthropic\n * `stop_reason: 'max_tokens'`, Gemini `finishReason: 'MAX_TOKENS'`) in a way\n * that leaves nothing safe to keep. Both transports raise it when the truncated\n * turn carries tool calls: the model ran out of its output-token budget\n * mid-stream, so the cut-off call's arguments are incomplete or untrustworthy\n * (e.g. a `vfs_write` whose `content` never finished serializing) \u2014 rather than\n * hand a corrupt tool call to the caller, which silently runs with missing args\n * and tends to be retried into an identical wall, the failure is loud and\n * diagnosable. The Gemini transport also raises it when truncation leaves no\n * usable answer text (a blank or thinking-only response), which would otherwise\n * be misclassified \u2014 and pointlessly retried \u2014 as an \"empty\" response.\n *\n * It is deterministic: re-issuing the same request hits the same cap. The remedy\n * is to raise the provider's `maxTokens` where configurable (see\n * {@link AnthropicAIConfig.maxTokens}) or to split the work into smaller\n * outputs \u2014 not to retry verbatim.\n *\n * Shared by both transports; it lives here with the transport that introduced it.\n *\n * @beta\n */\nexport class ResponseTruncatedError extends Error {\n constructor(\n /** The model that produced the truncated response. */\n model, \n /**\n * The `max_tokens` cap the request was sent with, when the transport sends\n * one (Anthropic). Undefined when no explicit cap was requested and the\n * model's own output-token limit applied instead (Gemini).\n */\n maxTokens, \n /** Output tokens generated before truncation, when the usage block is present. */\n outputTokens, \n /** Names of the tool call(s) on the truncated turn (the last is the cut-off one). */\n toolNames) {\n super(`Response truncated at ${maxTokens != null ? `the max_tokens cap (${maxTokens})` : \"the model's output-token limit\"} for model ${model}` +\n (toolNames.length > 0 ? ` while emitting tool call(s): ${toolNames.join(', ')}` : '') +\n '. The output exceeds the per-response limit \u2014 raise the provider maxTokens (where configurable) or split the work into smaller outputs.');\n this.model = model;\n this.maxTokens = maxTokens;\n this.outputTokens = outputTokens;\n this.toolNames = toolNames;\n this.name = 'ResponseTruncatedError';\n }\n}\n/**\n * Transport for Anthropic Claude. Calls the Messages API directly when `apiKey`\n * is provided, otherwise falls back to a server-proxy endpoint (if `serverEndpoint`\n * is configured).\n *\n * Implements `AITransport` (structured prompt via tool-forcing) and `ChatTransport`\n * (multi-turn chat).\n *\n * @beta\n */\nexport class AnthropicTransport {\n /**\n * Warn once when a requested policy is silently clamped, in EITHER direction \u2014 which is what\n * `ChatThinkingPolicy` promises callers. Both directions cost the caller something they asked\n * for and would otherwise get no signal about: `'off'` on a model that always thinks keeps\n * billing reasoning as output, and `'auto'` on a model without adaptive support means an agent\n * that asked to reason quietly does not. (Gemini's twin deliberately stays silent on `'auto'`,\n * but only because dynamic thinking is already the default there; Haiku defaults to none, so\n * the same silence would hide a real difference.)\n */\n warnIfThinkingUnclampable(policy) {\n if (this.warnedThinkingClamped)\n return;\n const message = this.clampWarning(policy);\n if (!message)\n return;\n this.warnedThinkingClamped = true;\n logger.warn(message);\n }\n /**\n * The warning for a policy this model cannot honour, or `undefined` when it can.\n *\n * An exhaustive `switch` with a `never` check rather than a condition chain: a new\n * {@link ChatThinkingPolicy} member must be considered HERE or the build fails. The condition\n * chain this replaced would have let every graded level clamp in silence, which is the one\n * outcome the type's own docs promise callers never happens.\n */\n clampWarning(policy) {\n switch (policy) {\n case undefined:\n return undefined;\n case 'off':\n return thinkingIsMandatory(this.model)\n ? `AnthropicTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} always thinks and rejects an explicit disable. Reasoning tokens are still billed as output; switch model if you need them gone.`\n : undefined;\n case 'auto':\n return supportsAdaptiveThinking(this.model)\n ? undefined\n : `AnthropicTransport: thinkingPolicy 'auto' ignored \u2014 ${this.model} does not support adaptive thinking, so this turn runs without reasoning. Use a Sonnet or Opus tier if the agent needs it.`;\n case 'minimal':\n case 'low':\n case 'medium':\n case 'high':\n case 'max':\n if (!supportsAdaptiveThinking(this.model) || !supportsEffort(this.model)) {\n return `AnthropicTransport: thinkingPolicy '${policy}' ignored \u2014 ${this.model} predates output_config.effort, so this turn runs at its default posture. Use Opus 4.8, Sonnet 5, or Fable 5 to set reasoning depth.`;\n }\n // A clamp WITHIN the supported ladder is documented on the type (Anthropic has no\n // 'minimal'), costs nothing, and would be noise on every turn of a vision loop.\n return undefined;\n default: {\n const exhaustive = policy;\n return exhaustive;\n }\n }\n }\n constructor(config = {}) {\n var _a, _b, _c, _d;\n /**\n * Estimated USD cost accumulated across every successful request on this\n * transport instance. Convenience accessor for non-chat consumers\n * (telemetry, debug overlays). The main chat UI sums per-message `cost`\n * fields instead so its session total stays attributed to chat turns only.\n */\n this.lifetimeCostUsd = 0;\n /**\n * Estimated USD saved by prompt caching vs paying full input price, accumulated across\n * every request. Net of cache-write premiums, so it can be briefly negative before reads\n * accrue. Surfaced alongside `getLifetimeCost`.\n */\n this.lifetimeSavingsUsd = 0;\n /**\n * Whether we have already told the caller their `thinkingPolicy: 'off'` cannot be honoured\n * on this model. Latched, because it would otherwise fire on every turn of a tool loop.\n */\n this.warnedThinkingClamped = false;\n /**\n * Serving-model ids already reported as unrecognised. Per-id rather than a single flag, so a\n * second unknown model is still announced. See {@link AnthropicTransport.servingModel}.\n */\n this.warnedUnknownServingModels = new Set();\n const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL;\n assertSupportedAnthropicModel(model);\n this.model = model;\n if (model === 'claude-sonnet-5') {\n logger.warn('AnthropicTransport: using claude-sonnet-5 \u2014 standard Sonnet tier, higher cost than Haiku, and adaptive thinking runs by default so reasoning tokens add to output cost. Use for stronger reasoning or agent tasks.');\n }\n else if (model === 'claude-sonnet-4-6') {\n logger.warn('AnthropicTransport: using claude-sonnet-4-6 \u2014 higher cost than Haiku; use for stronger reasoning or agent tasks.');\n }\n else if (model === 'claude-opus-4-7' || model === 'claude-opus-4-8') {\n logger.warn(`AnthropicTransport: using ${model} \u2014 significantly higher cost; reserve for tasks where Sonnet reliability is insufficient.`);\n }\n else if (model === 'claude-fable-5') {\n logger.warn('AnthropicTransport: using claude-fable-5 \u2014 Anthropic\\'s most capable model, priced above Opus tier ($10 / $50 per MTok) with thinking always on. Reserve for the hardest reasoning/long-horizon work. Requires \u226530-day data retention (unavailable under ZDR) and may return stop_reason \"refusal\"; pair with an Opus 4.8 fallback.');\n }\n this.timeout = (_b = config.timeout) !== null && _b !== void 0 ? _b : DEFAULT_TIMEOUT;\n this.stallTimeout = (_c = config.stallTimeout) !== null && _c !== void 0 ? _c : DEFAULT_STALL_TIMEOUT;\n this.apiKey = config.apiKey;\n this.serverEndpoint = config.serverEndpoint;\n this.maxTokens = (_d = config.maxTokens) !== null && _d !== void 0 ? _d : DEFAULT_MAX_TOKENS;\n }\n getConfig() {\n return {\n provider: 'anthropic',\n model: this.model,\n contextLimit: ANTHROPIC_CONTEXT_LIMITS[this.model],\n };\n }\n /** Estimated USD cost accumulated across every successful request on this transport instance. */\n getLifetimeCost() {\n return this.lifetimeCostUsd;\n }\n /** Estimated USD saved by prompt caching (net of write premiums) across this instance. */\n getLifetimeSavings() {\n return this.lifetimeSavingsUsd;\n }\n /** Reset the lifetime cost + savings counters. Intended for chat-clear / new-session flows. */\n resetLifetimeCost() {\n this.lifetimeCostUsd = 0;\n this.lifetimeSavingsUsd = 0;\n }\n // \u2500\u2500 AITransport (structured prompt) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendStructuredPrompt(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n const { systemPrompt, userPrompt, responseSchema } = options;\n const messages = [{ role: 'user', content: userPrompt }];\n const body = {\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n };\n if (systemPrompt)\n body.system = systemPrompt;\n // Prefer native decode-time enforcement (`output_config.format`) where the model supports it \u2014\n // the answer comes back as ordinary text conforming to the schema. On models without native\n // support (Opus 4.7, Sonnet 4.6), fall back to the legacy pattern: a tool whose `input_schema`\n // is the schema, forced via `tool_choice`, with the structured payload read from its `tool_use`.\n const useNative = responseSchema != null && supportsNativeStructuredOutput(this.model);\n const useForcedTool = responseSchema != null && !useNative;\n if (useNative) {\n body.output_config = Object.assign(Object.assign({}, body.output_config), { format: { type: 'json_schema', schema: responseSchema } });\n }\n else if (useForcedTool) {\n body.tools = [\n {\n name: STRUCTURED_OUTPUT_TOOL_NAME,\n description: 'Emit the structured response that matches the required schema.',\n input_schema: responseSchema,\n },\n ];\n body.tool_choice = { type: 'tool', name: STRUCTURED_OUTPUT_TOOL_NAME };\n }\n // Sonnet 5 runs adaptive thinking by default; disable it for one-shot prompts \u2014 the reasoning\n // would be billed but discarded. Fable 5 runs thinking unconditionally (cannot be disabled \u2014 a\n // 400), so it is left on; its summary is simply unused here. Not routed through\n // `anthropicThinking`: this path wants the summary suppressed rather than returned, so a\n // clamped Fable 5 must keep omitting the field rather than opting into `display:'summarized'`.\n if (this.model === 'claude-sonnet-5')\n body.thinking = { type: 'disabled' };\n const response = yield this.post(body);\n if (useForcedTool) {\n const toolUse = ((_a = response.content) !== null && _a !== void 0 ? _a : []).find((b) => b.type === 'tool_use' && b.name === STRUCTURED_OUTPUT_TOOL_NAME);\n return toolUse ? JSON.stringify((_b = toolUse.input) !== null && _b !== void 0 ? _b : {}) : '';\n }\n // Native structured output and plain prompts both return the answer as text.\n return ((_c = response.content) !== null && _c !== void 0 ? _c : [])\n .filter((b) => b.type === 'text')\n .map((b) => b.text)\n .join('');\n });\n }\n // \u2500\u2500 ChatTransport (multi-turn chat) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendChatMessage(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c, _d, _e;\n // The models this request could actually be served by \u2014 the configured one plus any\n // fallback target. Needed when replaying reasoning: a signature is only valid for the\n // model that produced it, so stored blocks are replayed only when their producer is\n // still reachable on THIS request. See `reasoningToReplay`.\n const reachableModels = new Set([\n this.model,\n ...((_a = options === null || options === void 0 ? void 0 : options.fallbacks) !== null && _a !== void 0 ? _a : []).map((f) => f.model),\n ]);\n const messages = this.toAnthropicMessages(history, userMessage, options === null || options === void 0 ? void 0 : options.attachments, reachableModels);\n const body = {\n model: this.model,\n // Per-turn override wins over the instance default; see ChatRequestOptions.maxTokens.\n max_tokens: (_b = options === null || options === void 0 ? void 0 : options.maxTokens) !== null && _b !== void 0 ? _b : this.maxTokens,\n messages,\n };\n if (options === null || options === void 0 ? void 0 : options.systemPrompt)\n body.system = options.systemPrompt;\n if ((_c = options === null || options === void 0 ? void 0 : options.tools) === null || _c === void 0 ? void 0 : _c.length) {\n // `enforceSchema` is a per-tool opt-in, and the provider compiles per tool:\n // an unenforced tool is never compiled and costs nothing against the\n // compilation limits, so marking one tool in a large surface is legitimate.\n // Enforcement additionally requires `additionalProperties: false` on every\n // object node, which the adapter adds (see `enforceAnthropicToolSchema` in\n // `utils/tool-schema.ts` for what it strips and what it tightens).\n body.tools = options.tools.map((t) => (Object.assign({ name: t.name, description: t.description, input_schema: t.enforceSchema\n ? enforceAnthropicToolSchema(t.parameters, t.name)\n : t.parameters }, (t.enforceSchema ? { strict: true } : {}))));\n }\n // Map the requested tool-call mode to Anthropic's tool_choice \u2014 only\n // meaningful when tools exist. `'required'`/`{ tool }` force a tool call so\n // a turn can only end via one (e.g. a sub-agent's completion tool).\n if ((_d = body.tools) === null || _d === void 0 ? void 0 : _d.length) {\n const toolChoice = toAnthropicToolChoice(options === null || options === void 0 ? void 0 : options.toolChoice);\n if (toolChoice)\n body.tool_choice = toolChoice;\n }\n // Extended thinking. Adaptive regardless of `tool_choice` \u2014 first-party has no\n // forced-tool-vs-thinking restriction (that's Bedrock-only) and adaptive self-regulates on\n // mechanical turns. The per-turn `thinkingPolicy` overrides the per-model default; an\n // undefined policy reproduces it exactly (see `anthropicThinking`).\n this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n const thinking = anthropicThinking(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n if (thinking)\n body.thinking = thinking;\n // Reasoning DEPTH rides in `output_config.effort`, a different field from `thinking`.\n // MERGED, never assigned: structured output writes `format` into the same object further\n // down, and either write clobbering the other is silent \u2014 the request stays valid, it just\n // quietly stops doing one of the two things it was asked to do.\n const effort = anthropicEffort(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n if (effort)\n body.output_config = Object.assign(Object.assign({}, body.output_config), { effort });\n // Normalized [0,1] temperature \u2192 Anthropic's native range, anchored so 0.5 maps to its default.\n // (Default == max here, so the upper half is flat.) Skipped in two cases:\n //\n // - models that reject sampling params outright (Opus 4.7+ / Sonnet 5 / Fable 5), where\n // sending `temperature` is a 400 whether or not thinking is on;\n // - ANY model with thinking enabled, because temperature is incompatible with thinking on\n // the models that still accept sampling params. Sonnet 4.6 is the live case: it takes a\n // temperature happily until `thinkingPolicy: 'auto'` turns thinking on, at which point\n // `{ thinkingPolicy: 'auto', temperature: 0 }` \u2014 an entirely reasonable agent config \u2014\n // becomes an invalid request. The thinking posture wins; temperature is dropped.\n const thinkingEnabled = (thinking === null || thinking === void 0 ? void 0 : thinking.type) === 'adaptive';\n if ((options === null || options === void 0 ? void 0 : options.temperature) != null && !rejectsSamplingParams(this.model) && !thinkingEnabled) {\n body.temperature = scaleTemperature(options.temperature, {\n defaultTemp: ANTHROPIC_DEFAULT_TEMPERATURE,\n maxTemp: ANTHROPIC_MAX_TEMPERATURE,\n });\n }\n // Structured output: constrain the final text answer to the caller's JSON schema via\n // decode-time `output_config.format`. Composes with a live `tools` array \u2014 the model still\n // calls tools through the turn and conforms its closing answer to the schema. Applied only on\n // models that support it natively; elsewhere the schema is dropped here (the caller keeps a\n // prompt-instruction + validator fallback). No beta header needed.\n if ((options === null || options === void 0 ? void 0 : options.responseSchema) && supportsNativeStructuredOutput(this.model)) {\n body.output_config = Object.assign(Object.assign({}, body.output_config), { format: { type: 'json_schema', schema: options.responseSchema } });\n }\n // Refusal fallback chain (e.g. Fable 5 \u2192 Opus 4.8). Sent as the server-side `fallbacks`\n // param; `post` adds the required beta header when this is present. A refused turn is\n // re-run on the next model in one round trip.\n if ((_e = options === null || options === void 0 ? void 0 : options.fallbacks) === null || _e === void 0 ? void 0 : _e.length) {\n body.fallbacks = options.fallbacks.map((f) => f.maxTokens != null ? { model: f.model, max_tokens: f.maxTokens } : { model: f.model });\n }\n // Place prompt-cache breakpoints per the resolved policy (no-op for `'default'`/absent).\n if (options === null || options === void 0 ? void 0 : options.cachePolicy) {\n this.applyCacheControl(body, options.cachePolicy);\n }\n // Inject never-stored tail context AFTER the cache breakpoints, so this per-turn volatile\n // block stays outside the cached prefix. The caller has already framed it.\n if (options === null || options === void 0 ? void 0 : options.tailContext) {\n this.appendTailContext(body, options.tailContext);\n }\n const response = yield this.post(body, options === null || options === void 0 ? void 0 : options.signal);\n return this.fromAnthropicResponse(response, body.max_tokens);\n });\n }\n /**\n * Place prompt-cache breakpoints on the outgoing request per the resolved {@link CachePolicy}.\n * A breakpoint is `cache_control: {type:'ephemeral'}` on a content block / tool / system block;\n * the API caches the byte-exact prefix up to it. Below a model's minimum cacheable prefix the\n * marker is silently ignored (no error), so placing one is always safe.\n *\n * Render order is tools \u2192 system \u2192 messages, so a breakpoint's cached prefix covers everything\n * before it:\n * - `'tools'` \u2014 last tool (caches the tool block; survives a later system-prompt change).\n * - `'prompt'` \u2014 system block (caches tools + system); falls back to the last tool when there\n * is no system prompt.\n * - `'history'` \u2014 last stored message block (caches tools + system + the whole stored history),\n * keeping the system-tier breakpoint as a cheaper fallback. The injected, never-stored tail\n * context (if any) sits after this and is intentionally left uncached.\n */\n applyCacheControl(body, policy) {\n var _a, _b;\n if (policy.scope === 'default')\n return;\n const cacheControl = policy.ttl === '1h' ? { type: 'ephemeral', ttl: '1h' } : { type: 'ephemeral' };\n if (policy.scope === 'tools') {\n if ((_a = body.tools) === null || _a === void 0 ? void 0 : _a.length) {\n body.tools[body.tools.length - 1].cache_control = cacheControl;\n }\n return;\n }\n // 'prompt' and 'history' both cache through the system prompt. A breakpoint on the (single)\n // system block caches tools + system together; with no system prompt, fall back to the last\n // tool \u2014 the furthest stable prefix available.\n if (typeof body.system === 'string' && body.system.length > 0) {\n body.system = [{ type: 'text', text: body.system, cache_control: cacheControl }];\n }\n else if ((_b = body.tools) === null || _b === void 0 ? void 0 : _b.length) {\n body.tools[body.tools.length - 1].cache_control = cacheControl;\n }\n if (policy.scope === 'history') {\n const lastMessage = body.messages[body.messages.length - 1];\n if (lastMessage && Array.isArray(lastMessage.content) && lastMessage.content.length > 0) {\n lastMessage.content[lastMessage.content.length - 1].cache_control = cacheControl;\n }\n }\n }\n /**\n * Append never-stored tail context (already framed by the caller) as the final block of the\n * outbound messages. Called AFTER `applyCacheControl`, so any `'history'` breakpoint sits\n * on the last *stored* block and this per-turn volatile block stays outside the cached prefix.\n * At a model-call the last message is user-role; if not (defensive), start a fresh user turn.\n */\n appendTailContext(body, tailContext) {\n const block = { type: 'text', text: tailContext };\n const lastMessage = body.messages[body.messages.length - 1];\n if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'user' && Array.isArray(lastMessage.content)) {\n lastMessage.content.push(block);\n }\n else {\n body.messages.push({ role: 'user', content: [block] });\n }\n }\n /**\n * Logs the per-call cost breakdown, accumulates the lifetime running total,\n * and returns the per-call total so the caller can attach it to the response\n * message.\n */\n logTokenUsage(model, promptTokens, candidateTokens, cacheReadTokens, cacheCreationTokens, cacheCreation1hTokens) {\n // The arithmetic and the rate table live in `utils/token-cost` so a host pricing\n // its own requests \u2014 a server proxy, a usage ledger \u2014 uses the same numbers\n // instead of a hand-copied table that drifts. This method keeps only what is\n // instance-scoped: the lifetime accumulators and the log.\n const { costUsd, savedUsd, breakdown } = anthropicTokenCost(model, {\n uncachedInputTokens: promptTokens,\n outputTokens: candidateTokens,\n cacheReadTokens,\n cacheWriteTokens: cacheCreationTokens,\n cacheWrite1hTokens: cacheCreation1hTokens,\n });\n this.lifetimeCostUsd += costUsd;\n this.lifetimeSavingsUsd += savedUsd;\n const dp = AnthropicTransport.COST_DECIMAL_PLACES;\n console.log(`--- Anthropic Token Usage (${model}) ---`);\n console.log(`Prompt Tokens: ${promptTokens} ($${breakdown.promptUsd.toFixed(dp)})`);\n console.log(`Cache Read: ${cacheReadTokens} ($${breakdown.cacheReadUsd.toFixed(dp)})`);\n console.log(`Cache Write: ${cacheCreationTokens} ($${breakdown.cacheWriteUsd.toFixed(dp)})`);\n console.log(`Candidate Tokens: ${candidateTokens} ($${breakdown.candidateUsd.toFixed(dp)})`);\n console.log(`Total Cost: $${costUsd.toFixed(dp)}`);\n console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);\n console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);\n console.log('--------------------------');\n return costUsd;\n }\n /**\n * Convert the internal `ChatMessage[]` history into Anthropic's message format.\n *\n * Anthropic alternates strictly `user` / `assistant`. Tool calls are emitted by\n * the assistant as `tool_use` blocks; the corresponding `tool_result` blocks\n * must appear in the *next* user message and reference the tool by `tool_use_id`.\n * Consecutive same-role turns are merged by the API but we merge here to keep\n * the payload tidy.\n */\n toAnthropicMessages(history, userMessage, attachments, reachableModels = new Set([this.model])) {\n var _a, _b, _c, _d;\n const messages = [];\n const pushBlock = (role, block) => {\n const last = messages[messages.length - 1];\n if (last && last.role === role && Array.isArray(last.content)) {\n last.content.push(block);\n return;\n }\n messages.push({ role, content: [block] });\n };\n /**\n * Split attachments by kind. Images are emitted BEFORE the accompanying text (the order\n * Anthropic's vision guidance specifies); text attachments keep their existing position\n * AFTER it, so a turn with no images produces a byte-identical request to before.\n *\n * Branches on `kind`, never on `mimeType` \u2014 see {@link ChatImageAttachment}.\n */\n const splitAttachments = (atts) => {\n const images = [];\n const texts = [];\n for (const att of atts) {\n if (att.kind === 'image') {\n images.push({\n type: 'image',\n source: {\n type: 'base64',\n media_type: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n });\n }\n else {\n texts.push({ type: 'text', text: `[File: ${att.name}]\\n${att.content}` });\n }\n }\n return { images, texts };\n };\n for (const msg of history) {\n if (msg.role === 'system' ||\n msg.role === 'system-event' ||\n msg.role === 'synthetic-user' ||\n msg.role === 'compacted-summary' ||\n msg.category === 'reasoning' ||\n msg.category === 'narration' ||\n msg.thinking // legacy pre-split sessions\n )\n continue;\n if (msg.toolResult) {\n const resultImages = (_a = msg.toolResult.attachments) !== null && _a !== void 0 ? _a : [];\n pushBlock('user', {\n type: 'tool_result',\n tool_use_id: msg.toolResult.toolCallId,\n // Bare string when there are no images \u2014 the historical shape, byte for byte.\n content: resultImages.length\n ? [\n // Text block only when there IS text. A handler can return an image with no\n // caption (`{ content: '', attachments: [img] }` \u2014 the mainline vision-agent\n // \"just look at this\" shape), and Anthropic 400s an empty text block, live and on\n // replay. Guarded like every user-turn path; the array is then image-only.\n ...(msg.toolResult.content\n ? [{ type: 'text', text: msg.toolResult.content }]\n : []),\n ...resultImages.map((att) => ({\n type: 'image',\n source: {\n type: 'base64',\n media_type: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n })),\n ]\n : msg.toolResult.content,\n });\n continue;\n }\n if ((_b = msg.toolCalls) === null || _b === void 0 ? void 0 : _b.length) {\n // Reasoning first, then text, then the calls \u2014 the order the model produced them,\n // which is the order the API validates. A tool-use loop is one assistant turn, so\n // resuming it requires the thinking that led to the call to still be present and\n // byte-identical. Replayed from the first call's stashed blocks (see\n // `AnthropicToolCallState`), never rebuilt from the display summary.\n for (const block of this.reasoningToReplay(msg.toolCalls[0], reachableModels)) {\n pushBlock('assistant', block);\n }\n if (msg.content) {\n pushBlock('assistant', { type: 'text', text: msg.content });\n }\n for (const tc of msg.toolCalls) {\n pushBlock('assistant', {\n type: 'tool_use',\n id: tc.id,\n name: tc.name,\n input: (_c = tc.args) !== null && _c !== void 0 ? _c : {},\n });\n }\n continue;\n }\n const role = msg.role === 'user' ? 'user' : 'assistant';\n if (role === 'user' && ((_d = msg.attachments) === null || _d === void 0 ? void 0 : _d.length)) {\n const { images, texts } = splitAttachments(msg.attachments);\n for (const image of images)\n pushBlock(role, image);\n // Guarded like the live turn below: an image-only message has empty `content`, and\n // Anthropic 400s an empty text block. Unguarded, such a turn succeeded when sent and\n // then failed on REPLAY \u2014 the nastiest shape of this bug, and \"image, no caption\" is\n // mainline input for a vision agent.\n if (msg.content)\n pushBlock(role, { type: 'text', text: msg.content });\n for (const text of texts)\n pushBlock(role, text);\n }\n else if (msg.content) {\n pushBlock(role, { type: 'text', text: msg.content });\n }\n }\n if (userMessage || (attachments === null || attachments === void 0 ? void 0 : attachments.length)) {\n const { images, texts } = splitAttachments(attachments !== null && attachments !== void 0 ? attachments : []);\n for (const image of images)\n pushBlock('user', image);\n if (userMessage) {\n pushBlock('user', { type: 'text', text: userMessage });\n }\n for (const text of texts)\n pushBlock('user', text);\n }\n return messages;\n }\n /**\n * The blocks to replay ahead of a tool call \u2014 fallback boundaries then reasoning, or none.\n *\n * A `signature` is only valid for the model that produced it, so reasoning captured under a\n * *different* model is normally dropped: an agent that varies `provider` by state can switch\n * models mid-loop, and replaying the old model's signatures would send blocks the new one\n * cannot verify.\n *\n * Two ways the producer can be the model that will validate:\n *\n * 1. **It is the model we are asking for.** `state.model === this.model` \u2014 the ordinary case.\n * 2. **Sticky routing will send this conversation back to it.** After a conversation falls\n * back, later requests carrying `fallbacks` go straight to the model that served, without\n * re-running the one that declined. That is what makes a fallback producer's reasoning\n * replayable at all (Fable 5 configured, Opus 4.8 serving \u2014 the pairing this transport's\n * own constructor warning recommends). But it holds only while the conversation continues\n * under the SAME request configuration, which is why `requestedModel` is compared rather\n * than just checking the chain for the producer.\n *\n * That second condition is deliberately narrow. Chain membership alone is too weak: a\n * fallback target is only *contingently* the server, so an agent that switches `provider` to\n * a model whose own chain happens to contain the old producer would replay foreign\n * signatures to whichever model actually answers. Requiring the requested model to be\n * unchanged separates \"this conversation is still going\" from \"we are somewhere else now\".\n *\n * State captured before `requestedModel` existed falls back to condition 1 alone, which is\n * the conservative branch \u2014 it can drop reasoning, never misdirect it.\n *\n * Boundaries themselves are always echoed: keeping them in place is the documented rule, and\n * with no thinking blocks around them they are inert rather than harmful.\n */\n reasoningToReplay(firstCall, reachableModels) {\n var _a, _b, _c;\n const state = (_a = firstCall.providerMetadata) === null || _a === void 0 ? void 0 : _a[ANTHROPIC_PROVIDER_KEY];\n if (!state)\n return [];\n const boundaries = (_b = state.fallbacks) !== null && _b !== void 0 ? _b : [];\n const stickyToProducer = state.requestedModel === this.model && reachableModels.has(state.model);\n const vouched = state.model === this.model || stickyToProducer;\n return [...boundaries, ...(vouched ? ((_c = state.reasoning) !== null && _c !== void 0 ? _c : []) : [])];\n }\n /**\n * The model that actually served this response.\n *\n * A server-side `fallbacks` chain re-runs a declined request on another model and\n * names it in the response's top-level `model`. Pricing must follow that, not the\n * model we asked for: a Fable 5 request served by Opus 4.8 costed at Fable's\n * $10/$50 instead of $5/$25 doubles that part of the bill.\n *\n * An unrecognised model id is NOT priced at a guessed rate \u2014 that is precisely how\n * a consumer ended up billing Haiku at Sonnet rates. It warns and falls back to the\n * configured model, which is at least a figure someone chose.\n */\n servingModel(response) {\n const served = response.model;\n if (!served || served === this.model)\n return this.model;\n if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(served)) {\n return served;\n }\n // Latched per id: this is reached once per response AND once per fallback-chain attempt, so\n // an unrecognised model would otherwise repeat on every iteration of every turn for the\n // session's life \u2014 burying the one message the operator needs at exactly the moment cost\n // reporting has gone wrong. Keyed by id so a second unknown model still gets its own line.\n if (!this.warnedUnknownServingModels.has(served)) {\n this.warnedUnknownServingModels.add(served);\n logger.warn(`AnthropicTransport: response was served by \"${served}\", which is not a known model \u2014 ` +\n `pricing it at the configured \"${this.model}\" rate instead of guessing. The reported ` +\n `cost for this request may be wrong; add the model to SUPPORTED_ANTHROPIC_MODEL_IDS.`);\n }\n return this.model;\n }\n /**\n * Whether a fallback-chain attempt is a refusal that was **not billed**.\n *\n * Anthropic does not charge for a refusal that arrives before any output: the token counts\n * still appear in `usage`, but they are not on the bill. Pricing them anyway turns the\n * fallback undercount this reducer was written to fix into an overcount \u2014 the documented\n * example declines with `input_tokens: 535, output_tokens: 0`, which is real money at\n * Fable 5's prompt rate.\n *\n * A **mid-output** refusal *is* billed for the input and whatever it streamed, so output\n * tokens are the discriminator rather than the refusal itself.\n *\n * Declined attempts appear as `type: 'message'`; the attempt that served the turn is\n * `type: 'fallback_message'`. The serving entry is normally billable \u2014 except when every\n * model in the chain declined, where the last entry is both the serving one and a refusal,\n * which `lastAndRefused` covers.\n *\n * Also called for a response with no chain at all, as `isUnbilledRefusal({}, usage, refused)`:\n * a direct request that was declined has no `iterations` array, and the same rule applies to\n * it. That is in fact the common case \u2014 `iterations` only appears when `fallbacks` was\n * configured.\n */\n isUnbilledRefusal(attempt, usage, lastAndRefused) {\n var _a;\n if (((_a = usage.output_tokens) !== null && _a !== void 0 ? _a : 0) > 0)\n return false;\n return attempt.type === 'message' || lastAndRefused;\n }\n /** Cost one attempt's usage block at `model`'s rates, logging and banking it. */\n costAttempt(model, usage) {\n var _a, _b, _c, _d, _e, _f;\n const cacheRead = (_a = usage.cache_read_input_tokens) !== null && _a !== void 0 ? _a : 0;\n // 1-hour writes bill at 2\u00D7 vs 1.25\u00D7 for 5-min, so read the per-TTL breakdown when present\n // and let the cost path split the buckets. Fall back to the flat total (treated as 5-min)\n // when the breakdown is absent.\n const breakdown = usage.cache_creation;\n const cacheCreation1h = (_b = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _b !== void 0 ? _b : 0;\n const cacheCreation = (_c = usage.cache_creation_input_tokens) !== null && _c !== void 0 ? _c : (breakdown ? ((_d = breakdown.ephemeral_5m_input_tokens) !== null && _d !== void 0 ? _d : 0) + cacheCreation1h : 0);\n return this.logTokenUsage(model, (_e = usage.input_tokens) !== null && _e !== void 0 ? _e : 0, (_f = usage.output_tokens) !== null && _f !== void 0 ? _f : 0, cacheRead, cacheCreation, cacheCreation1h);\n }\n fromAnthropicResponse(response, \n /** The cap ACTUALLY sent this turn \u2014 a per-turn `maxTokens` overrides the instance one. */\n effectiveMaxTokens = this.maxTokens) {\n var _a, _b, _c, _d, _e, _f, _g;\n let inputTokens;\n let outputTokens;\n let cacheReadTokens;\n let cacheWriteTokens;\n let cost;\n const servingModel = this.servingModel(response);\n if (response.usage) {\n const uncachedInput = (_a = response.usage.input_tokens) !== null && _a !== void 0 ? _a : 0;\n const cacheRead = (_b = response.usage.cache_read_input_tokens) !== null && _b !== void 0 ? _b : 0;\n const breakdown = response.usage.cache_creation;\n const cacheCreation1h = (_c = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _c !== void 0 ? _c : 0;\n const cacheCreation = (_d = response.usage.cache_creation_input_tokens) !== null && _d !== void 0 ? _d : (breakdown ? ((_e = breakdown.ephemeral_5m_input_tokens) !== null && _e !== void 0 ? _e : 0) + cacheCreation1h : 0);\n // Top-level `usage` describes only the attempt that produced this message. When a\n // fallback chain ran, the ATTEMPTS BEFORE IT were billed too \u2014 a mid-output decline\n // bills for what it streamed \u2014 and they may have run on a different model at a\n // different rate. Cost each attempt at its own model and sum; the token fields\n // below still describe the serving attempt, which is what the message's content is.\n const attempts = response.usage.iterations;\n if (attempts === null || attempts === void 0 ? void 0 : attempts.length) {\n const refused = response.stop_reason === 'refusal';\n cost = attempts.reduce((total, attempt, index) => {\n var _a;\n const usage = (_a = attempt.usage) !== null && _a !== void 0 ? _a : attempt;\n if (this.isUnbilledRefusal(attempt, usage, index === attempts.length - 1 && refused)) {\n return total;\n }\n // An omitted `model` means the attempt ran on the model we ASKED for \u2014 which on a\n // chain turn is precisely not the one that served it. Defaulting to `servingModel`\n // here would price a declining Fable 5 attempt at Opus 4.8's $5/$25 instead of\n // $10/$50: half its real cost, in the same silent-undercount direction this reducer\n // exists to fix.\n const model = attempt.model ? this.servingModel({ model: attempt.model }) : this.model;\n return total + this.costAttempt(model, usage);\n }, 0);\n }\n else if (this.isUnbilledRefusal({}, response.usage, response.stop_reason === 'refusal')) {\n // A refusal with no chain behind it \u2014 the model was called directly, declined before\n // producing anything, and was not charged. The `iterations` branch above only sees\n // this when `fallbacks` was configured; most refusals arrive here instead, so pricing\n // this path is the difference between an occasional phantom charge and a routine one.\n cost = 0;\n }\n else {\n cost = this.costAttempt(servingModel, response.usage);\n }\n // Report TOTAL prompt size (uncached + cache read + cache write) so `inputTokens` means\n // \"prompt tokens\" consistently whether or not caching was active \u2014 matching Gemini's\n // `promptTokenCount`, which already includes cached tokens. Cost (above) reflects the\n // cache discount; this field is the size, not the bill.\n inputTokens = uncachedInput + cacheRead + cacheCreation;\n // The two cache buckets BREAK DOWN the prompt total above rather than adding\n // to it, so a consumer derives uncached input by subtracting them. Reported\n // even when zero: \"this provider measured the split and it was 0\" is distinct\n // from \"this provider reports no split at all\" (undefined).\n cacheReadTokens = cacheRead;\n cacheWriteTokens = cacheCreation;\n if (response.usage.output_tokens != null) {\n outputTokens = response.usage.output_tokens;\n }\n }\n const blocks = (_f = response.content) !== null && _f !== void 0 ? _f : [];\n const toolCalls = [];\n const thoughtParts = [];\n const textParts = [];\n // Raw reasoning blocks, kept verbatim for wire replay. Distinct from `thoughtParts`,\n // which is the readable text for display \u2014 that copy is lossy (no signature) and must\n // never be what goes back to the API.\n const reasoningBlocks = [];\n // A server-side fallback splits the turn: everything before the LAST `fallback` block was\n // produced by a model that then declined. Its reasoning and client tool calls must be\n // dropped when echoing the turn \u2014 they belong to a model that is no longer answering, and\n // their signatures are not valid for the one that is. Replaying blocks from both sides of\n // the boundary is a rejected request, not a degraded one. Absent a fallback (the normal\n // case) this is -1, so every block counts as post-boundary and nothing changes.\n const fallbackIndex = blocks.map((b) => b.type).lastIndexOf('fallback');\n const fallbackBlocks = blocks.filter((b) => b.type === 'fallback');\n for (const [index, block] of blocks.entries()) {\n const postBoundary = index > fallbackIndex;\n if (block.type === 'tool_use') {\n // A pre-boundary client tool call was abandoned with the declined attempt; echoing it\n // would ask the serving model to own a call it never made.\n if (postBoundary) {\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: (_g = block.input) !== null && _g !== void 0 ? _g : {},\n });\n }\n }\n else if (block.type === 'thinking') {\n if (postBoundary)\n reasoningBlocks.push(block);\n thoughtParts.push(block.thinking);\n }\n else if (block.type === 'redacted_thinking') {\n // No readable text by design \u2014 replayable but never displayable.\n if (postBoundary)\n reasoningBlocks.push(block);\n }\n else if (block.type === 'text') {\n textParts.push(block.text);\n }\n }\n // Attach the turn's reasoning to the FIRST tool call, which is where it is replayed\n // from: the blocks precede the whole `tool_use` group in the assistant message, not\n // each call individually. Stored only when a tool call exists \u2014 without one the turn\n // ends and there is nothing to resume, so the blocks have no further wire role. The\n // boundary marker travels with them so it can be re-emitted in position, which is what\n // the API validates the surrounding thinking blocks against.\n if (toolCalls.length > 0 && (reasoningBlocks.length > 0 || fallbackBlocks.length > 0)) {\n const state = {\n reasoning: reasoningBlocks,\n model: servingModel,\n requestedModel: this.model,\n };\n if (fallbackBlocks.length > 0)\n state.fallbacks = fallbackBlocks;\n toolCalls[0].providerMetadata = Object.assign(Object.assign({}, toolCalls[0].providerMetadata), { [ANTHROPIC_PROVIDER_KEY]: state });\n }\n // A `max_tokens` stop means the response was cut off mid-stream. For a turn\n // carrying tool calls this is fatal: the final tool call's argument JSON was\n // truncated before it closed, so its args are incomplete and the call cannot\n // be run. Raise rather than return a corrupt tool call (which would run with\n // missing args and get retried into the same wall). Usage/cost is already\n // logged above, so the spent tokens are still accounted for on this instance.\n if (response.stop_reason === 'max_tokens' && toolCalls.length > 0) {\n throw new ResponseTruncatedError(this.model, effectiveMaxTokens, outputTokens, toolCalls.map((tc) => tc.name));\n }\n // Reasoning (extended-thinking summary) and answer/narration travel in separate channels:\n // `content` is the answer text, `reasoning` is the summary. The driver splits them into\n // separate category-tagged messages. (Previously `thoughtParts.join('') || textParts.join('')`\n // put reasoning in `content` and DROPPED the answer text whenever thinking was present.)\n const reasoning = thoughtParts.join('') || undefined;\n const base = toolCalls.length > 0\n ? { role: 'assistant', content: textParts.join(''), reasoning, toolCalls }\n : { role: 'assistant', content: textParts.join(''), reasoning };\n if (inputTokens != null)\n base.inputTokens = inputTokens;\n if (outputTokens != null)\n base.outputTokens = outputTokens;\n if (cacheReadTokens != null)\n base.cacheReadTokens = cacheReadTokens;\n if (cacheWriteTokens != null)\n base.cacheWriteTokens = cacheWriteTokens;\n if (cost != null)\n base.cost = cost;\n // The model that actually answered \u2014 which is NOT the configured one when a\n // fallback chain served the request. Stamped here rather than left to the driver,\n // which only knows what was asked for; a usage ledger attributing spend to the\n // requested model would misattribute every fallback-served turn.\n base.model = servingModel;\n // Surface a non-standard stop reason for observability and parity with the\n // Gemini transport's `responseMeta.finishReason`. A text-only `max_tokens`\n // stop yields partial-but-legible content, so it is returned (not raised) with\n // the truncation flagged \u2014 the caller can decide what to do with it.\n if (response.stop_reason === 'max_tokens') {\n base.responseMeta = { finishReason: 'max_tokens' };\n }\n // A `refusal` stop means safety classifiers declined the request (Fable 5 and other\n // recent models). Content is empty (pre-output) or partial (mid-stream) \u2014 return it\n // rather than crash on an assumed non-empty block, and flag the reason so the driver\n // (or a server-side `fallbacks` chain) can respond deterministically instead of\n // retrying into the same wall. Usage/cost is already logged above.\n if (response.stop_reason === 'refusal') {\n base.responseMeta = { finishReason: 'refusal' };\n }\n return base;\n }\n buildEndpoint() {\n if (this.apiKey) {\n return {\n url: ANTHROPIC_DIRECT_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': ANTHROPIC_API_VERSION,\n // Anthropic blocks browser-origin requests by default. This header is the\n // documented opt-in (equivalent to the SDK's `dangerouslyAllowBrowser`).\n 'anthropic-dangerous-direct-browser-access': 'true',\n },\n credentials: 'omit',\n };\n }\n if (this.serverEndpoint) {\n return {\n url: this.serverEndpoint,\n // Opt in to the proxy's NDJSON heartbeat framing. An old proxy ignores\n // this and returns plain JSON \u2014 see the Content-Type branch in `post`.\n headers: { 'Content-Type': 'application/json', Accept: 'application/x-ndjson' },\n credentials: 'include',\n };\n }\n throw new Error('AnthropicTransport: no API key or server endpoint configured. ' +\n 'Set ANTHROPIC_API_KEY in your .env or pass apiKey/serverEndpoint in AnthropicAIConfig.');\n }\n post(body, signal) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const { url, headers, credentials } = this.buildEndpoint();\n // The server-side `fallbacks` param is gated behind a beta flag; add it per-request only\n // when a fallback chain is set (the param without the header is a 400, and vice-versa is fine).\n const requestHeaders = ((_a = body.fallbacks) === null || _a === void 0 ? void 0 : _a.length)\n ? Object.assign(Object.assign({}, headers), { 'anthropic-beta': [headers['anthropic-beta'], SERVER_SIDE_FALLBACK_BETA]\n .filter(Boolean)\n .join(',') }) : headers;\n return (yield postWithRetry({\n url,\n headers: requestHeaders,\n body,\n credentials,\n vendorLabel: VENDOR_LABELS.anthropic,\n retryableStatuses: AnthropicTransport.RETRYABLE_STATUSES,\n timeout: this.timeout,\n stallTimeout: this.stallTimeout,\n backoffBaseMs: AnthropicTransport.BACKOFF_BASE_MS,\n signal,\n }));\n });\n }\n}\n// \u2500\u2500 Private helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nAnthropicTransport.TOKENS_PER_MILLION = 1000000;\nAnthropicTransport.COST_DECIMAL_PLACES = 6;\nAnthropicTransport.RATE_LIMIT_STATUS = 429;\nAnthropicTransport.SERVICE_UNAVAILABLE_STATUS = 503;\nAnthropicTransport.OVERLOADED_STATUS = 529;\nAnthropicTransport.RETRYABLE_STATUSES = [\n AnthropicTransport.RATE_LIMIT_STATUS,\n AnthropicTransport.SERVICE_UNAVAILABLE_STATUS,\n AnthropicTransport.OVERLOADED_STATUS,\n];\n// Base backoff for the shared retry ladder (1s, 2s, 4s, 8s, 16s).\nAnthropicTransport.BACKOFF_BASE_MS = 1000;\n", "// \u2500\u2500 MALFORMED_FUNCTION_CALL repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Gemini occasionally returns `finishReason: \"MALFORMED_FUNCTION_CALL\"` when it\n// has actually produced a complete, correct tool call but serialised it as a\n// Python statement instead of the API's structured format, e.g.\n//\n// print(default_api.vfs_edit(new_string = \"\u2026\", old_string = \"\u2026\", path = \"\u2026\", replace_all = true))\n//\n// The intended call is fully present in `candidates[0].finishMessage`. Rather\n// than throw and burn a ChatDriver retry (a full re-roll that may regenerate\n// something worse, or malform again), we parse the call back out and hand it to\n// the transport as a normal structured tool call \u2014 unwrapping a wrong envelope,\n// not guessing. The parser is deliberately fail-closed: on ANY ambiguity it\n// returns null and the transport falls back to throwing\n// `MalformedFunctionCallError`, leaving today's retry behaviour unchanged. It\n// never returns a half-parsed call.\nconst MALFORMED_CALL_ANCHOR = 'default_api.';\nconst PRINT_WRAPPER_RE = /print\\(\\s*$/;\nconst UNICODE_ESCAPE_DIGITS = 4;\nconst HEX_ESCAPE_DIGITS = 2;\nconst HEX_RADIX = 16;\n/**\n * Recursive-descent scanner for a single Python-style `default_api.<tool>(...)`\n * call. Walks the string character by character so that delimiters (commas,\n * parens, quotes, brackets, newlines) appearing *inside* string-literal\n * arguments don't prematurely terminate parsing. Throws on the first unexpected\n * token; callers treat any throw as \"not confidently parseable\".\n */\nclass MalformedFunctionCallParser {\n constructor(src) {\n this.src = src;\n this.pos = 0;\n }\n parse() {\n const anchor = this.src.indexOf(MALFORMED_CALL_ANCHOR);\n if (anchor === -1)\n this.bail();\n // Tolerate an enclosing `print(` wrapper (the observed Python form) or a\n // bare call. Any other preamble (e.g. \"Malformed function call: \") is\n // ignored \u2014 we only anchor on `default_api.`.\n const wrapped = PRINT_WRAPPER_RE.test(this.src.slice(0, anchor));\n this.pos = anchor;\n const call = this.parseCall();\n this.skipWhitespace();\n if (wrapped) {\n this.expect(')');\n this.skipWhitespace();\n }\n // Strict: nothing may follow the call. In particular a second\n // `default_api.` (batched calls) bails rather than silently dropping work.\n if (this.pos !== this.src.length)\n this.bail();\n return call;\n }\n parseCall() {\n this.expectLiteral(MALFORMED_CALL_ANCHOR);\n const name = this.readIdentifier();\n this.expect('(');\n const args = this.parseKwargs();\n this.expect(')');\n return { name, args };\n }\n parseKwargs() {\n const args = {};\n for (;;) {\n this.skipWhitespace();\n // Empty arg list, or a tolerated trailing comma before the closing paren.\n if (this.peek() === ')')\n break;\n const key = this.readIdentifier();\n this.skipWhitespace();\n this.expect('=');\n this.skipWhitespace();\n const value = this.parseValue();\n if (Object.prototype.hasOwnProperty.call(args, key))\n this.bail();\n args[key] = value;\n this.skipWhitespace();\n const next = this.peek();\n if (next === ',') {\n this.pos += 1;\n continue;\n }\n if (next === ')')\n break;\n this.bail();\n }\n return args;\n }\n parseValue() {\n const ch = this.peek();\n if (ch === '\"' || ch === \"'\")\n return this.readString();\n if (ch === '-' || ch === '+' || this.isDigit(ch))\n return this.readNumber();\n if (/[A-Za-z]/.test(ch))\n return this.readBareword();\n // Unhandled value form (e.g. a list `[\u2026]` or dict `{\u2026}`) \u2014 bail.\n return this.bail();\n }\n readString() {\n const quote = this.src[this.pos];\n this.pos += 1; // opening quote\n let out = '';\n for (;;) {\n if (this.pos >= this.src.length)\n this.bail(); // unterminated \u2192 truncation guard\n const c = this.src[this.pos];\n this.pos += 1;\n if (c === quote)\n return out; // closing quote\n if (c === '\\\\') {\n out += this.readEscape();\n continue;\n }\n out += c;\n }\n }\n readEscape() {\n if (this.pos >= this.src.length)\n this.bail();\n const e = this.src[this.pos];\n this.pos += 1;\n switch (e) {\n case 'n':\n return '\\n';\n case 't':\n return '\\t';\n case 'r':\n return '\\r';\n case 'b':\n return '\\b';\n case 'f':\n return '\\f';\n case '\\\\':\n return '\\\\';\n case '\"':\n return '\"';\n case \"'\":\n return \"'\";\n case '/':\n return '/';\n case 'u':\n return this.readHexCodepoint(UNICODE_ESCAPE_DIGITS);\n case 'x':\n return this.readHexCodepoint(HEX_ESCAPE_DIGITS);\n default:\n // Unknown escape \u2014 refuse rather than risk a silent mis-decode.\n return this.bail();\n }\n }\n readHexCodepoint(digits) {\n const hex = this.src.slice(this.pos, this.pos + digits);\n if (hex.length !== digits || !/^[0-9a-fA-F]+$/.test(hex))\n this.bail();\n this.pos += digits;\n return String.fromCharCode(parseInt(hex, HEX_RADIX));\n }\n readNumber() {\n const start = this.pos;\n if (this.peek() === '-' || this.peek() === '+')\n this.pos += 1;\n while (this.pos < this.src.length && /[0-9.eE+-]/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n const value = Number(this.src.slice(start, this.pos));\n if (!Number.isFinite(value))\n this.bail();\n return value;\n }\n readBareword() {\n const word = this.readIdentifier();\n switch (word) {\n case 'true':\n case 'True':\n return true;\n case 'false':\n case 'False':\n return false;\n // Python serialises an omitted/optional kwarg as `None` (and sometimes a\n // JSON-ish `null`); decode both to `null` rather than bailing the whole call.\n case 'null':\n case 'None':\n return null;\n default:\n return this.bail();\n }\n }\n readIdentifier() {\n const start = this.pos;\n if (!/[A-Za-z_]/.test(this.peek()))\n this.bail();\n while (this.pos < this.src.length && /[A-Za-z0-9_]/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n return this.src.slice(start, this.pos);\n }\n isDigit(ch) {\n return ch >= '0' && ch <= '9';\n }\n peek() {\n return this.pos < this.src.length ? this.src[this.pos] : '';\n }\n skipWhitespace() {\n while (this.pos < this.src.length && /\\s/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n }\n expect(ch) {\n if (this.src[this.pos] !== ch)\n this.bail();\n this.pos += 1;\n }\n expectLiteral(literal) {\n if (this.src.slice(this.pos, this.pos + literal.length) !== literal)\n this.bail();\n this.pos += literal.length;\n }\n bail() {\n throw new Error('MalformedFunctionCallParser: unexpected token');\n }\n}\n/**\n * Attempts to recover a structured tool call from a Gemini\n * `MALFORMED_FUNCTION_CALL` `finishMessage`. Returns the parsed call only when\n * it parses cleanly AND its tool name is one of the offered tools; otherwise\n * returns null so the caller can fall back to the existing retry path.\n */\nexport function repairMalformedFunctionCall(finishMessage, offeredToolNames) {\n if (!finishMessage)\n return null;\n let call;\n try {\n call = new MalformedFunctionCallParser(finishMessage).parse();\n }\n catch (_a) {\n return null;\n }\n if (!offeredToolNames.has(call.name))\n return null;\n return call;\n}\n", "import { __awaiter } from \"tslib\";\nimport { SUPPORTED_GEMINI_MODEL_IDS, } from '../types';\nimport { normalizeImageMime, stripImageDataUrl } from '../utils/image-mime';\nimport { logger } from '../utils/logger';\nimport { scaleTemperature } from '../utils/temperature';\nimport { geminiTokenCost } from '../utils/token-cost';\nimport { toGeminiSchema } from '../utils/tool-schema';\nimport { ResponseTruncatedError } from './anthropic-transport';\nimport { VENDOR_LABELS } from './budget-exhausted-error';\nimport { repairMalformedFunctionCall } from './gemini-malformed-call';\nimport { postWithRetry } from './post-with-retry';\nconst GEMINI_DIRECT_URL = (model) => `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;\nconst DEFAULT_MODEL = 'gemini-2.5-flash-lite';\nconst DEFAULT_TIMEOUT = 300000; // healthy >200s generations observed at 128k max_tokens; wall clock is a last resort\nconst DEFAULT_STALL_TIMEOUT = 30000; // inactivity window on the framed proxy path; pings arrive every 5s\n/**\n * Maximum input context window (tokens) per supported Gemini model.\n * Source: https://ai.google.dev/gemini-api/docs/models\n */\nconst GEMINI_CONTEXT_LIMITS = {\n 'gemini-2.5-pro': 1048576,\n 'gemini-2.5-flash': 1048576,\n 'gemini-2.5-flash-lite': 1048576,\n 'gemini-3.5-flash': 1048576,\n 'gemini-3.1-flash-lite': 1048576,\n 'gemini-3.1-pro-preview': 1048576,\n};\n/** Gemini's native default + ceiling temperature \u2014 https://ai.google.dev/gemini-api/docs */\nconst GEMINI_DEFAULT_TEMPERATURE = 1;\nconst GEMINI_MAX_TEMPERATURE = 2;\n/**\n * Map a provider-agnostic {@link ChatToolChoice} to Gemini's `toolConfig`.\n * Returns undefined for the default (`'auto'`) so the request omits the field.\n */\nfunction toGeminiToolConfig(choice) {\n if (!choice || choice === 'auto')\n return undefined;\n if (choice === 'required')\n return { functionCallingConfig: { mode: 'ANY' } };\n if (choice === 'none')\n return { functionCallingConfig: { mode: 'NONE' } };\n return { functionCallingConfig: { mode: 'ANY', allowedFunctionNames: [choice.tool] } };\n}\nfunction assertSupportedGeminiModel(model) {\n if (!SUPPORTED_GEMINI_MODEL_IDS.includes(model)) {\n throw new Error(`GeminiTransport: unsupported model \"${model}\". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(', ')}.`);\n }\n}\n/**\n * Per-model warnings emitted on construction. flash-lite tiers are the cheap\n * default and warn-free; higher-cost, frontier, and preview models flag their\n * trade-offs so callers don't pick them by accident.\n */\nconst GEMINI_MODEL_WARNINGS = {\n 'gemini-2.5-flash': 'GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.',\n 'gemini-2.5-pro': 'GeminiTransport: using gemini-2.5-pro \u2014 significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.',\n 'gemini-3.5-flash': 'GeminiTransport: using gemini-3.5-flash \u2014 frontier model, materially higher cost than flash-lite; use for harder reasoning or agent tasks.',\n 'gemini-3.1-pro-preview': 'GeminiTransport: using gemini-3.1-pro-preview \u2014 PREVIEW model (no stability guarantee, may be withdrawn) with significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.',\n};\n/**\n * Gemini's `thinkingConfig` for a turn, given the model and the caller's\n * {@link ChatThinkingPolicy}.\n *\n * `includeThoughts` is about what is **returned**, not what is billed, and stays on for every\n * posture that thinks \u2014 a thinking-only turn would otherwise surface as blank, and the thought\n * summary is what `logTokenUsage` reconciles its thinking-token accounting against.\n *\n * `thinkingBudget` is the posture itself: `0` off, `-1` model-decides. **Omitting it is the third\n * state** and is what an undefined policy sends \u2014 the model's own default, exactly the request\n * shape this transport issued before the option existed.\n *\n * Only the flash tiers can actually be turned off. `gemini-2.5-pro` always thinks (its minimum\n * budget is 128; `0` is rejected), which is the same constraint Anthropic's Fable 5 has \u2014 so a\n * clamp here is the norm across providers, not a Gemini quirk. The 3.x tiers moved to a\n * `thinkingLevel` enum instead of a numeric budget, and a graded {@link ChatThinkingPolicy} now\n * maps onto it (GENC-1508) \u2014 the \"wire it through once per-tier support is confirmed\" this\n * comment used to defer. The 2.5 tiers keep the budget dialect and ignore graded levels rather\n * than being sent an enum they do not take: a clamp costs money, but a guess costs a 400 on a\n * turn the user is waiting for.\n */\nconst GEMINI_THINKING_DISABLEABLE = [\n 'gemini-2.5-flash',\n 'gemini-2.5-flash-lite',\n];\n/** Tiers that accept `generationConfig.mediaResolution`. Gemini 3 only, like `thinkingLevel`. */\nconst GEMINI_MEDIA_RESOLUTION_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/** The tiers that take `thinkingConfig.thinkingLevel` rather than a numeric `thinkingBudget`. */\nconst GEMINI_THINKING_LEVEL_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/**\n * Graded policy \u2192 Gemini `thinkingLevel`. Exhaustive `Record` for the same reason as the\n * Anthropic table: a new level must be mapped here or the build fails.\n *\n * `'max'` clamps DOWN to `high` \u2014 Gemini's ladder stops there. See {@link ChatThinkingPolicy}.\n */\nconst GEMINI_THINKING_LEVEL = {\n minimal: 'minimal',\n low: 'low',\n medium: 'medium',\n high: 'high',\n max: 'high',\n};\n/**\n * Tiers that accept only the coarse `low` / `high` pair rather than the full four-level enum.\n *\n * Currently EVERY `thinkingLevel` tier. The Gemini 3 line did not ship `minimal` and `medium`\n * across every tier at once, and this file's own doctrine is that an unverified enum value is\n * worse than a coarser one \u2014 \"a clamp costs money, but a guess costs a 400 on a turn the user is\n * waiting for\". `low`/`high` are the pair confirmed across the line, so the fine levels fold onto\n * their nearer neighbour here rather than being forwarded on faith to a tier that may 400 on\n * them. Remove a tier from this list once its support for the full enum has been OBSERVED, not\n * assumed \u2014 `GEMINI_THINKING_LEVEL`'s finer mapping then takes effect for it immediately.\n */\nconst GEMINI_COARSE_LEVEL_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\nconst GEMINI_COARSE_LEVEL = {\n minimal: 'low',\n low: 'low',\n medium: 'high',\n high: 'high',\n};\nconst isGradedLevel = (p) => p !== undefined && p !== 'auto' && p !== 'off';\nfunction geminiThinkingConfig(model, policy) {\n if (isGradedLevel(policy) && GEMINI_THINKING_LEVEL_TIERS.includes(model)) {\n const level = GEMINI_THINKING_LEVEL[policy];\n return {\n includeThoughts: true,\n thinkingLevel: GEMINI_COARSE_LEVEL_TIERS.includes(model) ? GEMINI_COARSE_LEVEL[level] : level,\n };\n }\n if (policy === 'off' && GEMINI_THINKING_DISABLEABLE.includes(model)) {\n // No reasoning to return once there is none to bill for.\n return { includeThoughts: false, thinkingBudget: 0 };\n }\n if (policy === 'auto' && GEMINI_THINKING_DISABLEABLE.includes(model)) {\n return { includeThoughts: true, thinkingBudget: -1 };\n }\n // Undefined policy, or a model whose posture we cannot safely set: the default.\n return { includeThoughts: true };\n}\n/**\n * Token accepted by the Gemini 3 API in place of a real `thoughtSignature` to\n * skip signature validation. Used when replaying a tool call whose signature\n * belongs to a different model (a mid-execution model switch) or was never\n * captured: the step's first function call still needs *a* signature to pass\n * validation, but a foreign signature can't be honoured.\n * Source: https://ai.google.dev/gemini-api/docs/thought-signatures\n */\nconst SKIP_SIGNATURE = 'skip_thought_signature_validator';\n/**\n * Key under which this transport stashes its round-trip state on a tool call's\n * provider-neutral `providerMetadata` bag. Private to GeminiTransport.\n */\nconst GEMINI_PROVIDER_KEY = 'gemini';\n/**\n * Split attachments into image parts and text parts.\n *\n * Images are emitted BEFORE the accompanying text part; text attachments keep their existing\n * position AFTER it, so a turn carrying no images serialises byte-identically to before this\n * existed. Branches on `kind`, never on `mimeType` \u2014 the composer's `readAsText` path can\n * produce an image mime with text content (see `ChatImageAttachment`).\n */\nfunction splitAttachmentParts(atts) {\n const imageParts = [];\n const textParts = [];\n for (const att of atts) {\n if (att.kind === 'image') {\n imageParts.push({\n inlineData: {\n mimeType: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n });\n }\n else {\n textParts.push({ text: `[File: ${att.name}]\\n${att.content}` });\n }\n }\n return { imageParts, textParts };\n}\n/**\n * Thrown when Gemini returns a `MALFORMED_FUNCTION_CALL` finish reason,\n * typically because the model tried to batch multiple tool calls using\n * Python-style syntax instead of the proper API format.\n *\n * @beta\n */\nexport class MalformedFunctionCallError extends Error {\n constructor(finishMessage) {\n super('Gemini returned MALFORMED_FUNCTION_CALL');\n this.finishMessage = finishMessage;\n this.name = 'MalformedFunctionCallError';\n }\n}\n/**\n * Transport for Gemini. Calls the Gemini REST API directly when `apiKey` is\n * provided, otherwise falls back to a server-proxy endpoint (if `serverEndpoint`\n * is configured).\n *\n * Implements `AITransport` (structured prompt) and `ChatTransport` (multi-turn chat).\n *\n * @beta\n */\nexport class GeminiTransport {\n /**\n * Warn once when a requested policy cannot be honoured on this model \u2014 a *cost* decision the\n * caller made that the wire silently reversed, so they hear about it, but only once, not per\n * turn. Two shapes reach here (the Anthropic twin warns on the same two):\n *\n * - `'off'` on a tier that can't disable thinking \u2014 only the flash tiers accept a zero thinking\n * budget; everything else keeps paying for reasoning it was told to stop. (`'auto'` is NOT this\n * case: it is already what an omitted budget produces on every model here, so warning it was\n * \"ignored\" would be false and would spend the one warning the genuine cases need.)\n * - A graded depth (`minimal`\u2026`max`) on a 2.5 tier \u2014 those speak the numeric-budget dialect,\n * not the Gemini 3 `thinkingLevel` enum, so the level is dropped and the turn runs at the\n * default posture. Without this, a caller asking for `high` on `gemini-2.5-pro` and quietly\n * getting the default is left to wonder why.\n */\n warnIfThinkingUnclampable(policy) {\n if (this.warnedThinkingClamped) {\n return;\n }\n if (policy === 'off' && !GEMINI_THINKING_DISABLEABLE.includes(this.model)) {\n this.warnedThinkingClamped = true;\n logger.warn(`GeminiTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} runs its default thinking posture and takes no budget we can safely set. Reasoning tokens are still billed at the candidate rate; use a flash tier if you need them gone.`);\n return;\n }\n if (isGradedLevel(policy) && !GEMINI_THINKING_LEVEL_TIERS.includes(this.model)) {\n this.warnedThinkingClamped = true;\n logger.warn(`GeminiTransport: thinkingPolicy '${policy}' ignored \u2014 ${this.model} takes a numeric thinking budget, not the graded 'thinkingLevel' the Gemini 3 tiers use, so this turn runs at its default reasoning posture. Use a Gemini 3 tier to set reasoning depth.`);\n }\n }\n constructor(config = {}) {\n var _a, _b, _c;\n /**\n * Estimated USD cost accumulated across every successful request on this\n * transport instance. Convenience accessor for non-chat consumers\n * (telemetry, debug overlays). The main chat UI sums per-message `cost`\n * fields instead so its session total stays attributed to chat turns only.\n */\n this.lifetimeCostUsd = 0;\n /**\n * Estimated USD saved by context caching vs paying full input price, accumulated across\n * every request. Gemini implicit caching has no write premium, so this is always \u2265 0.\n * Surfaced alongside `getLifetimeCost`.\n */\n this.lifetimeSavingsUsd = 0;\n /**\n * Whether we have already told the caller their `thinkingPolicy` cannot be honoured on this\n * model. Latched, because it would otherwise fire on every turn of a tool loop.\n */\n this.warnedThinkingClamped = false;\n const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL;\n assertSupportedGeminiModel(model);\n this.model = model;\n const warning = GEMINI_MODEL_WARNINGS[model];\n if (warning) {\n logger.warn(warning);\n }\n this.timeout = (_b = config.timeout) !== null && _b !== void 0 ? _b : DEFAULT_TIMEOUT;\n this.stallTimeout = (_c = config.stallTimeout) !== null && _c !== void 0 ? _c : DEFAULT_STALL_TIMEOUT;\n this.apiKey = config.apiKey;\n this.serverEndpoint = config.serverEndpoint;\n }\n getConfig() {\n return {\n provider: 'gemini',\n model: this.model,\n contextLimit: GEMINI_CONTEXT_LIMITS[this.model],\n };\n }\n /** Estimated USD cost accumulated across every successful request on this transport instance. */\n getLifetimeCost() {\n return this.lifetimeCostUsd;\n }\n /** Estimated USD saved by context caching across this instance (implicit caching \u2192 always \u2265 0). */\n getLifetimeSavings() {\n return this.lifetimeSavingsUsd;\n }\n /** Reset the lifetime cost + savings counters. Intended for chat-clear / new-session flows. */\n resetLifetimeCost() {\n this.lifetimeCostUsd = 0;\n this.lifetimeSavingsUsd = 0;\n }\n // \u2500\u2500 AITransport (structured prompt) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendStructuredPrompt(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const { systemPrompt, userPrompt, responseSchema } = options;\n const contents = [];\n if (systemPrompt) {\n contents.push({ role: 'user', parts: [{ text: systemPrompt }] });\n contents.push({ role: 'model', parts: [{ text: 'Understood.' }] });\n }\n contents.push({ role: 'user', parts: [{ text: userPrompt }] });\n const response = yield this.post({ model: this.model, contents, responseSchema });\n return (_a = response === null || response === void 0 ? void 0 : response.content) !== null && _a !== void 0 ? _a : '';\n });\n }\n // \u2500\u2500 ChatTransport (multi-turn chat) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendChatMessage(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n // NOTE: `options.cachePolicy` is intentionally NOT read here. Gemini 2.5+ does *implicit*\n // caching automatically and always-on \u2014 it caches as much of the stable request prefix as it\n // can on every call, regardless of the policy's `scope` (including `'default'`). We issue no\n // explicit `cachedContent`, so there is no request-side field to set; the only lever is\n // keeping the prefix byte-stable (a consumer concern). The cached tokens that come back are\n // priced in `logTokenUsage` via `cachedContentTokenCount`. See `CachePolicy` docs.\n const contents = this.toGeminiContents(history, userMessage, options === null || options === void 0 ? void 0 : options.attachments);\n // Never-stored tail context as a trailing user content (after the stable prefix). Verified\n // valid even directly after a functionResponse content. The caller has already framed it.\n if (options === null || options === void 0 ? void 0 : options.tailContext) {\n contents.push({ role: 'user', parts: [{ text: options.tailContext }] });\n }\n // Gemini's function declarations are an OpenAPI 3.0 subset, not JSON Schema,\n // so the canonical dialect is translated on the way out. This is unconditional\n // and unrelated to `ChatToolDefinition.enforceSchema`: Gemini already\n // constrains arguments by default, and the only question here is whether the\n // declaration parses at all. Untranslated, any nullable column is a hard 400.\n const tools = ((_a = options === null || options === void 0 ? void 0 : options.tools) === null || _a === void 0 ? void 0 : _a.length)\n ? [\n {\n functionDeclarations: options.tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: toGeminiSchema(t.parameters),\n })),\n },\n ]\n : undefined;\n const systemInstruction = (options === null || options === void 0 ? void 0 : options.systemPrompt)\n ? { role: 'system', parts: [{ text: options.systemPrompt }] }\n : undefined;\n // Map the requested tool-call mode to Gemini's toolConfig \u2014 only meaningful\n // when functions are declared. NOTE: forcing (`ANY` / allowedFunctionNames)\n // can make the model batch calls in Python-ish syntax \u2192\n // `MALFORMED_FUNCTION_CALL`, which `fromGeminiResponse` repairs in place when\n // it can confidently parse the call (see `repairMalformedFunctionCall`),\n // falling back to the caller's retry otherwise.\n const toolConfig = tools ? toGeminiToolConfig(options === null || options === void 0 ? void 0 : options.toolChoice) : undefined;\n // Thinking posture for this turn. By default (no `thinkingPolicy`) this asks only for thought\n // summaries, so the model's official reasoning is returned and a thinking-only turn surfaces\n // *something* rather than going silently blank \u2014 see `logTokenUsage` for the thinking-token\n // accounting it lets us capture. A policy adds an explicit `thinkingBudget` where the model\n // supports one; Gemini 2.5 Pro always thinks regardless. See `geminiThinkingConfig`.\n this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n const generationConfig = { thinkingConfig: geminiThinkingConfig(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy) };\n // Per-turn output ceiling; see ChatRequestOptions.maxTokens for why the instance default\n // is not enough. Omitted when unset, so an unchanged caller sends an unchanged body.\n if ((options === null || options === void 0 ? void 0 : options.maxTokens) != null) {\n generationConfig.maxOutputTokens = options.maxTokens;\n }\n // Image fidelity, from the FIRST image attachment that states a preference. Gemini bills\n // image tokens by resolution, so this is a real cost lever \u2014 and it is the one thing on\n // ChatImageAttachment that Anthropic has no equivalent for, where the only lever is the\n // pixels you send. Deliberately not synthesised into an Anthropic knob.\n const resolutionHint = [\n ...((_b = options === null || options === void 0 ? void 0 : options.attachments) !== null && _b !== void 0 ? _b : []),\n ...history.flatMap((m) => { var _a; return (_a = m.attachments) !== null && _a !== void 0 ? _a : []; }),\n // Tool-result images too: `ChatToolResult.attachments` is typed ChatImageAttachment[], so\n // `detail` is offerable there, and a render handed back by a tool is the whole point of\n // the tool-result image path. Omitting this source made the field silently inert there.\n ...history.flatMap((m) => { var _a, _b; return (_b = (_a = m.toolResult) === null || _a === void 0 ? void 0 : _a.attachments) !== null && _b !== void 0 ? _b : []; }),\n ].find((att) => att.kind === 'image' && att.detail);\n // Gated by tier for the same reason thinkingLevel is: a clamp costs money, a guess costs a\n // 400. Note it is per-REQUEST, so the first stated preference governs every image in the\n // turn \u2014 there is no per-image control on the wire.\n if ((resolutionHint === null || resolutionHint === void 0 ? void 0 : resolutionHint.kind) === 'image' &&\n resolutionHint.detail &&\n GEMINI_MEDIA_RESOLUTION_TIERS.includes(this.model)) {\n generationConfig.mediaResolution = `MEDIA_RESOLUTION_${resolutionHint.detail.toUpperCase()}`;\n }\n // Normalized [0,1] temperature \u2192 Gemini's native range, anchored so 0.5\n // maps to its default (native 1) and 1 to its ceiling (native 2).\n if ((options === null || options === void 0 ? void 0 : options.temperature) != null) {\n generationConfig.temperature = scaleTemperature(options.temperature, {\n defaultTemp: GEMINI_DEFAULT_TEMPERATURE,\n maxTemp: GEMINI_MAX_TEMPERATURE,\n });\n }\n // Names of the tools offered this turn \u2014 used to validate a repaired\n // malformed call against the real tool surface before accepting it.\n const offeredToolNames = new Set(((_c = options === null || options === void 0 ? void 0 : options.tools) !== null && _c !== void 0 ? _c : []).map((t) => t.name));\n // Structured output (native JSON mode). Gemini 3 can combine it with function calling;\n // Gemini 2.x cannot, so on 2.x apply the schema only on a pure structured turn (no tools) and\n // otherwise drop it (the caller keeps a prompt-instruction + validator fallback). Passed as a\n // top-level `responseSchema` that `toDirectPayload` maps to `generationConfig.responseMimeType`\n // + `responseSchema` on the direct path (the proxy forwards it).\n const schemaCoexistsWithTools = this.model.startsWith('gemini-3');\n const applyResponseSchema = (options === null || options === void 0 ? void 0 : options.responseSchema) != null && (!tools || schemaCoexistsWithTools);\n const response = yield this.post(Object.assign({ model: this.model, contents,\n tools,\n systemInstruction,\n toolConfig,\n generationConfig }, (applyResponseSchema\n ? { responseSchema: toGeminiSchema(options.responseSchema) }\n : {})), options === null || options === void 0 ? void 0 : options.signal);\n return this.fromGeminiResponse(response, offeredToolNames, generationConfig.maxOutputTokens);\n });\n }\n /**\n * Logs the per-call cost breakdown, accumulates the lifetime running total,\n * and returns the per-call total so the caller can attach it to the response\n * message.\n */\n logTokenUsage(promptTokens, candidateTokens, thoughtTokens, cachedTokens) {\n // The arithmetic, the rate table and the long-context tiering rule live in\n // `utils/token-cost` so a host pricing its own requests uses the same numbers\n // instead of a hand-copied table that drifts. This method keeps only what is\n // instance-scoped: the lifetime accumulators and the log.\n const { costUsd, savedUsd, breakdown } = geminiTokenCost(this.model, {\n promptTokens,\n candidateTokens,\n thoughtTokens,\n cachedTokens,\n });\n this.lifetimeCostUsd += costUsd;\n this.lifetimeSavingsUsd += savedUsd;\n const dp = GeminiTransport.COST_DECIMAL_PLACES;\n console.log(`--- Gemini Token Usage (${this.model}) ---`);\n console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${breakdown.promptUsd.toFixed(dp)} + $${breakdown.cacheReadUsd.toFixed(dp)})`);\n console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${breakdown.candidateUsd.toFixed(dp)})`);\n console.log(`Total Cost: $${costUsd.toFixed(dp)}`);\n console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);\n console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);\n console.log('--------------------------');\n return costUsd;\n }\n toGeminiContents(history, userMessage, attachments) {\n var _a, _b, _c, _d;\n const contents = [];\n // Gemini requires functionResponse.name to match the original functionCall.name.\n // Our internal IDs are UUIDs, so build a lookup from ID \u2192 function name as we go.\n const toolCallNameById = new Map();\n for (const msg of history) {\n if (msg.role === 'system' ||\n msg.role === 'system-event' ||\n msg.role === 'synthetic-user' ||\n msg.role === 'compacted-summary' ||\n msg.category === 'reasoning' ||\n msg.category === 'narration' ||\n msg.thinking // legacy pre-split sessions\n )\n continue;\n const role = msg.role === 'user' ? 'user' : 'model';\n if (msg.toolResult) {\n const fnName = (_a = toolCallNameById.get(msg.toolResult.toolCallId)) !== null && _a !== void 0 ? _a : msg.toolResult.toolCallId;\n contents.push({\n role: 'user',\n parts: [\n {\n functionResponse: {\n name: fnName,\n response: { content: msg.toolResult.content },\n },\n },\n ],\n });\n // Images ride in their OWN following user content rather than inside\n // `functionResponse.response`. That field is a protobuf Struct and per-tier support for\n // media nested in it is unverified; a separate content is plainly legal and costs an\n // extra content entry. Only emitted when the tool actually returned images, so a\n // result without them is byte-identical to before.\n const resultImages = (_b = msg.toolResult.attachments) !== null && _b !== void 0 ? _b : [];\n if (resultImages.length) {\n contents.push({\n role: 'user',\n parts: resultImages.map((att) => ({\n inlineData: { mimeType: normalizeImageMime(att.mimeType), data: att.data },\n })),\n });\n }\n }\n else if ((_c = msg.toolCalls) === null || _c === void 0 ? void 0 : _c.length) {\n for (const tc of msg.toolCalls) {\n toolCallNameById.set(tc.id, tc.name);\n }\n contents.push({\n role: 'model',\n parts: msg.toolCalls.map((tc, i) => {\n var _a;\n const part = { functionCall: { name: tc.name, args: tc.args } };\n const state = (_a = tc.providerMetadata) === null || _a === void 0 ? void 0 : _a[GEMINI_PROVIDER_KEY];\n // A signature is only valid for the model that produced it. Replay\n // the real one only when the producing model matches this request's\n // model; on a mid-execution model switch (or when none was captured)\n // put the skip token on the step's first call so validation passes.\n // Parallel sibling calls (i > 0) carry no signature, matching what\n // Gemini emits.\n const sig = (state === null || state === void 0 ? void 0 : state.model) === this.model ? state.thoughtSignature : undefined;\n if (sig) {\n part.thoughtSignature = sig;\n }\n else if (i === 0) {\n part.thoughtSignature = SKIP_SIGNATURE;\n }\n return part;\n }),\n });\n }\n else if (role === 'user' && ((_d = msg.attachments) === null || _d === void 0 ? void 0 : _d.length)) {\n const { imageParts, textParts } = splitAttachmentParts(msg.attachments);\n // Empty text parts are dropped, not sent \u2014 see the Anthropic twin. An image-only\n // message has no caption to carry.\n contents.push({\n role: 'user',\n parts: [...imageParts, ...(msg.content ? [{ text: msg.content }] : []), ...textParts],\n });\n }\n else {\n contents.push({ role, parts: [{ text: msg.content }] });\n }\n }\n const { imageParts, textParts } = splitAttachmentParts(attachments !== null && attachments !== void 0 ? attachments : []);\n if (userMessage || imageParts.length || textParts.length) {\n contents.push({\n role: 'user',\n parts: [...imageParts, ...(userMessage ? [{ text: userMessage }] : []), ...textParts],\n });\n }\n return contents;\n }\n /**\n * Map Gemini's `usageMetadata` onto the provider-agnostic usage fields, pricing\n * the call as a side effect (`logTokenUsage`). Returns an empty object when the\n * response carries no usage \u2014 every field is optional, so an absent count stays\n * `undefined` rather than being reported as a measured 0.\n *\n * Split out of `fromGeminiResponse` because it is self-contained bookkeeping\n * that reads better alone \u2014 and because folding it inline pushed that method\n * past the complexity ceiling.\n */\n usageFromGemini(usageMetadata) {\n var _a, _b, _c, _d, _e, _f;\n if (!usageMetadata)\n return {};\n const usage = usageMetadata;\n const cost = this.logTokenUsage((_a = usage.promptTokenCount) !== null && _a !== void 0 ? _a : 0, (_b = usage.candidatesTokenCount) !== null && _b !== void 0 ? _b : 0, (_c = usage.thoughtsTokenCount) !== null && _c !== void 0 ? _c : 0, (_d = usage.cachedContentTokenCount) !== null && _d !== void 0 ? _d : 0);\n return {\n inputTokens: usage.promptTokenCount,\n // Thinking tokens are generated output, billed at the candidate rate, but\n // reported in a field disjoint from `candidatesTokenCount`. Fold them into the\n // provider-agnostic `outputTokens` so it reflects the true generated total \u2014\n // matching Anthropic, whose `output_tokens` already includes them. Left\n // `undefined` only when the provider reported neither count.\n outputTokens: usage.candidatesTokenCount != null || usage.thoughtsTokenCount != null\n ? ((_e = usage.candidatesTokenCount) !== null && _e !== void 0 ? _e : 0) + ((_f = usage.thoughtsTokenCount) !== null && _f !== void 0 ? _f : 0)\n : undefined,\n thoughtsTokens: usage.thoughtsTokenCount,\n // Gemini reports cache HITS only \u2014 implicit caching bills no separate write, so\n // `cacheWriteTokens` is left unset rather than 0 (there is no write bucket to\n // measure, which is not the same as measuring 0). Already counted inside\n // `promptTokenCount`, so this breaks that total down rather than adding to it.\n cacheReadTokens: usage.cachedContentTokenCount,\n cost,\n };\n }\n fromGeminiResponse(response, offeredToolNames = new Set(), \n /**\n * The per-turn cap actually sent, when one was. Left `undefined` on the default path so a\n * truncation still reports \"the model's output-token limit\" \u2014 which is the truth when no\n * `maxOutputTokens` was set, and a lie the moment one is.\n */\n effectiveMaxTokens) {\n var _a, _b, _c, _d;\n const { inputTokens, outputTokens, thoughtsTokens, cacheReadTokens, cost } = this.usageFromGemini(response.usageMetadata);\n const candidates = response === null || response === void 0 ? void 0 : response.candidates;\n const firstCandidate = candidates === null || candidates === void 0 ? void 0 : candidates[0];\n const parts = (_b = (_a = firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.content) === null || _a === void 0 ? void 0 : _a.parts) !== null && _b !== void 0 ? _b : [];\n const toolCalls = [];\n const thoughtParts = [];\n const textParts = [];\n for (const part of parts) {\n if (part.functionCall) {\n // Stash the reasoning signature (and the producing model) so it can be\n // replayed on the next request \u2014 Gemini 3 requires the first function\n // call of each step to carry its signature or the request 400s. The\n // API only returns a signature on the first of a set of parallel calls.\n const state = { model: this.model };\n if (part.thoughtSignature) {\n state.thoughtSignature = part.thoughtSignature;\n }\n toolCalls.push({\n id: crypto.randomUUID(),\n name: part.functionCall.name,\n args: (_c = part.functionCall.args) !== null && _c !== void 0 ? _c : {},\n providerMetadata: { [GEMINI_PROVIDER_KEY]: state },\n });\n }\n else if (part.thought && part.text) {\n thoughtParts.push(part.text);\n }\n else if (part.text) {\n textParts.push(part.text);\n }\n }\n // Gemini sometimes flags MALFORMED_FUNCTION_CALL when it produced a complete\n // tool call but serialised it as a Python statement. Recover it in place\n // when we can parse it with full confidence (its `parts` are empty in this\n // case, so the repaired call flows through the normal token/cost handling\n // below); otherwise throw so the ChatDriver retry takes over.\n if ((firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.finishReason) === 'MALFORMED_FUNCTION_CALL') {\n const repaired = repairMalformedFunctionCall(firstCandidate.finishMessage, offeredToolNames);\n if (!repaired) {\n throw new MalformedFunctionCallError(firstCandidate.finishMessage);\n }\n toolCalls.push({ id: crypto.randomUUID(), name: repaired.name, args: repaired.args });\n }\n // The model's official thinking (thought-summary parts, returned because we set\n // `thinkingConfig.includeThoughts`) travels in its OWN channel, distinct from the answer /\n // tool-call narration: `content` carries the answer text, `reasoning` carries the summary. The\n // driver splits them into separate category-tagged messages (reasoning vs narration) so each has\n // its own visibility toggle and log category. Final answers surface only the answer text; the\n // reasoning summary rides `reasoning` and is deliberately not promoted to be the answer.\n const reasoning = thoughtParts.join('');\n const narration = textParts.join('');\n const base = toolCalls.length > 0\n ? { role: 'assistant', content: narration, reasoning: reasoning || undefined, toolCalls }\n : { role: 'assistant', content: narration, reasoning: reasoning || undefined };\n // Blank / non-STOP finishes are the recurring failure mode (especially empty\n // STOP on 2.5 Pro). Log the full shape so the cause is legible from the\n // breakdown rather than inferred. MALFORMED is excluded \u2014 it has its own\n // repair/throw path above.\n const finishReason = firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.finishReason;\n const isBlank = toolCalls.length === 0 && !reasoning && !narration;\n if (isBlank ||\n (finishReason && finishReason !== 'STOP' && finishReason !== 'MALFORMED_FUNCTION_CALL')) {\n this.logAbnormalResponse(response, {\n finishReason,\n functionCallParts: toolCalls.length,\n thoughtParts: thoughtParts.length,\n textParts: textParts.length,\n });\n }\n this.guardMaxTokensTruncation(finishReason, toolCalls, narration, outputTokens, effectiveMaxTokens);\n if (inputTokens != null)\n base.inputTokens = inputTokens;\n if (outputTokens != null)\n base.outputTokens = outputTokens;\n if (cacheReadTokens != null)\n base.cacheReadTokens = cacheReadTokens;\n if (cost != null)\n base.cost = cost;\n // Surface the provider diagnostic on the message so the driver can fold it\n // into the debug-log meta events (the console log above is dev-only). Only\n // when there's signal \u2014 a finish reason, thinking tokens, or a block reason.\n const blockReason = (_d = response.promptFeedback) === null || _d === void 0 ? void 0 : _d.blockReason;\n if (finishReason != null || thoughtsTokens != null || blockReason != null) {\n base.responseMeta = {\n finishReason,\n thoughtsTokens,\n parts: {\n functionCall: toolCalls.length,\n thought: thoughtParts.length,\n text: textParts.length,\n },\n blockReason,\n };\n }\n return base;\n }\n /**\n * Raises {@link ResponseTruncatedError} when a `MAX_TOKENS` finish left nothing\n * safe to keep. A MAX_TOKENS finish means generation was cut off at the\n * output-token limit (no explicit cap is requested, so this is the model's own\n * output ceiling \u2014 which thinking tokens share). Truncation is DETERMINISTIC:\n * re-issuing the identical request hits the same limit, so it must not fall\n * through to the caller's empty-response retry. Mirrors the Anthropic\n * transport's contract: with tool calls the cut-off call's args can't be\n * trusted, and with no usable answer text (blank or thinking-only) there is\n * nothing to keep either \u2014 the typed truncation error is raised for both.\n * Partial answer TEXT is instead returned by `fromGeminiResponse`, flagged via\n * `responseMeta.finishReason`, for the caller to decide. Usage/cost is logged\n * before this check runs, so the spent tokens stay accounted for.\n */\n guardMaxTokensTruncation(finishReason, toolCalls, narration, outputTokens, \n /** The per-turn cap sent, when one was \u2014 so the error names the cap it actually hit. */\n effectiveMaxTokens) {\n if (finishReason !== 'MAX_TOKENS')\n return;\n // A truncated text-only answer is partial but legible \u2014 keep it (the driver's\n // emptiness rule is `!content.trim()`, so whitespace-only does NOT count).\n if (toolCalls.length === 0 && narration.trim() !== '')\n return;\n throw new ResponseTruncatedError(this.model, effectiveMaxTokens, outputTokens, toolCalls.map((tc) => tc.name));\n }\n /**\n * Log the full shape of a blank or non-STOP response so its cause is legible\n * without re-deriving it: a thinking-only STOP (substantial `thoughtsTokenCount`,\n * ~0 `candidatesTokenCount`) vs a content block (`SAFETY` / `RECITATION`) vs a\n * token cap (`MAX_TOKENS`) vs a prompt-level block (top-level\n * `promptFeedback.blockReason`). On 2.5 Pro \u2014 which always thinks \u2014 a blank\n * STOP carrying substantial thought tokens is the \"thought, then stopped\n * without answering\" signature.\n */\n logAbnormalResponse(response, parsed) {\n var _a, _b, _c;\n const usage = ((_a = response.usageMetadata) !== null && _a !== void 0 ? _a : {});\n const candidate = (_c = (_b = response.candidates) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : {};\n logger.warn('GeminiTransport: blank/non-STOP response', {\n model: this.model,\n finishReason: parsed.finishReason,\n finishMessage: candidate.finishMessage,\n parts: {\n total: parsed.functionCallParts + parsed.thoughtParts + parsed.textParts,\n functionCall: parsed.functionCallParts,\n thought: parsed.thoughtParts,\n text: parsed.textParts,\n },\n usage: {\n promptTokenCount: usage.promptTokenCount,\n candidatesTokenCount: usage.candidatesTokenCount,\n thoughtsTokenCount: usage.thoughtsTokenCount,\n totalTokenCount: usage.totalTokenCount,\n },\n promptFeedback: response.promptFeedback,\n safetyRatings: candidate.safetyRatings,\n citationMetadata: candidate.citationMetadata,\n });\n }\n buildEndpoint(body) {\n if (this.apiKey) {\n return {\n url: `${GEMINI_DIRECT_URL(this.model)}?key=${this.apiKey}`,\n payload: this.toDirectPayload(body),\n headers: { 'Content-Type': 'application/json' },\n credentials: 'omit',\n };\n }\n if (this.serverEndpoint) {\n return {\n url: this.serverEndpoint,\n payload: body,\n // Opt in to the proxy's NDJSON heartbeat framing. An old proxy ignores\n // this and returns plain JSON \u2014 see the Content-Type branch in `post`.\n headers: { 'Content-Type': 'application/json', Accept: 'application/x-ndjson' },\n credentials: 'include',\n };\n }\n throw new Error('GeminiTransport: no API key or server endpoint configured. ' +\n 'Set GEMINI_API_KEY in your .env or pass apiKey/serverEndpoint in GeminiAIConfig.');\n }\n post(body, signal) {\n return __awaiter(this, void 0, void 0, function* () {\n const { url, payload, headers, credentials } = this.buildEndpoint(body);\n return (yield postWithRetry({\n url,\n headers,\n body: payload,\n credentials,\n vendorLabel: VENDOR_LABELS.gemini,\n retryableStatuses: GeminiTransport.RETRYABLE_STATUSES,\n timeout: this.timeout,\n stallTimeout: this.stallTimeout,\n backoffBaseMs: GeminiTransport.BACKOFF_BASE_MS,\n signal,\n }));\n });\n }\n toDirectPayload(body) {\n const payload = Object.assign({}, body);\n delete payload.model;\n if (payload.responseSchema) {\n payload.generationConfig = Object.assign(Object.assign({}, payload.generationConfig), { responseMimeType: 'application/json', responseSchema: payload.responseSchema });\n delete payload.responseSchema;\n }\n return payload;\n }\n}\n// \u2500\u2500 Private helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nGeminiTransport.TOKENS_PER_MILLION = 1000000;\nGeminiTransport.COST_DECIMAL_PLACES = 6;\nGeminiTransport.RATE_LIMIT_STATUS = 429;\nGeminiTransport.SERVICE_UNAVAILABLE_STATUS = 503;\n/**\n * 502 BAD_GATEWAY is a cleanly transient fault from an intermediate proxy or load\n * balancer fronting the API \u2014 back off and retry it alongside 429/503.\n *\n * Deliberately NOT retried: 500 INTERNAL and 504 DEADLINE_EXCEEDED. Google documents\n * both as also carrying a deterministic cause (\"input context is too long\" / \"prompt\n * too large to process in time\"); re-issuing the identical request just re-hits the\n * same wall and burns the whole backoff ladder \u2014 the same deterministic-retry trap\n * this transport avoids for MAX_TOKENS, and especially wasteful on the large-context\n * agent path. They fail fast instead.\n */\nGeminiTransport.BAD_GATEWAY_STATUS = 502;\nGeminiTransport.RETRYABLE_STATUSES = [\n GeminiTransport.RATE_LIMIT_STATUS,\n GeminiTransport.SERVICE_UNAVAILABLE_STATUS,\n GeminiTransport.BAD_GATEWAY_STATUS,\n];\n// Base backoff for the shared retry ladder (1s, 2s, 4s, 8s, 16s).\nGeminiTransport.BACKOFF_BASE_MS = 1000;\n", "import { __awaiter } from \"tslib\";\nimport { AnthropicProvider } from './providers/anthropic-provider';\nimport { ChromeProvider } from './providers/chrome-provider';\nimport { DefaultAIProvider } from './providers/default-provider';\nimport { GeminiProvider } from './providers/gemini-provider';\nimport { OpenAIProvider } from './providers/openai-provider';\nimport { AnthropicTransport } from './transports/anthropic-transport';\nimport { ChromePromptTransport } from './transports/chrome-prompt-transport';\nimport { GeminiTransport } from './transports/gemini-transport';\nimport { ServerOpenAITransport } from './transports/server-openai-transport';\nimport { SUPPORTED_ANTHROPIC_MODEL_IDS, SUPPORTED_GEMINI_MODEL_IDS, } from './types';\nimport { logger } from './utils';\nimport { isAIFeatureEnabled } from './utils/feature-flags';\nfunction isChromeConfig(config) {\n return 'providerType' in config && config.providerType === 'chrome';\n}\nfunction isGeminiConfig(config) {\n return 'providerType' in config && config.providerType === 'gemini';\n}\nfunction isAnthropicConfig(config) {\n return 'providerType' in config && config.providerType === 'anthropic';\n}\nfunction isServerAIConfig(config) {\n return !!config.provider;\n}\n/**\n * Creates an AIProvider from config.\n * Uses ChromeProvider when providerType is 'chrome'.\n * Uses OpenAIProvider with ServerOpenAITransport when provider is set (server-only).\n * Otherwise returns DefaultAIProvider.\n * When the AI feature flag is disabled (?feature.ai), always returns DefaultAIProvider.\n *\n * @beta\n */\nexport function createAIProvider(config) {\n if (!isAIFeatureEnabled()) {\n logger.warn('createAIProvider: AI feature flag disabled, using DefaultAIProvider');\n return new DefaultAIProvider();\n }\n if (config && isChromeConfig(config)) {\n logger.debug('createAIProvider: using ChromeProvider');\n return new ChromeProvider(config);\n }\n if (config && isGeminiConfig(config)) {\n logger.debug('createAIProvider: using GeminiProvider');\n const transport = new GeminiTransport({\n model: config.model,\n timeout: config.timeout,\n stallTimeout: config.stallTimeout,\n serverEndpoint: config.serverEndpoint,\n apiKey: config.apiKey,\n });\n return new GeminiProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n if (config && isAnthropicConfig(config)) {\n logger.debug('createAIProvider: using AnthropicProvider');\n const transport = new AnthropicTransport({\n model: config.model,\n timeout: config.timeout,\n stallTimeout: config.stallTimeout,\n serverEndpoint: config.serverEndpoint,\n apiKey: config.apiKey,\n maxTokens: config.maxTokens,\n });\n return new AnthropicProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n if (config && isServerAIConfig(config)) {\n if (config.provider !== 'openai') {\n logger.warn('createAIProvider: only openai server provider supported for now, using default');\n return new DefaultAIProvider();\n }\n logger.debug('createAIProvider: using OpenAIProvider (server proxy)');\n const transport = new ServerOpenAITransport({\n model: config.model,\n timeout: config.timeout,\n });\n return new OpenAIProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n logger.debug('createAIProvider: using DefaultAIProvider');\n return new DefaultAIProvider();\n}\n/**\n * Resolves AI config, optionally preferring Chrome when available.\n * Use before registering AIProvider. Server URL is derived from API_HOST.\n * Returns null when the AI feature flag is disabled (?feature.ai).\n *\n * @beta\n */\nexport function resolveAIConfig() {\n return __awaiter(this, arguments, void 0, function* (options = {}) {\n if (!isAIFeatureEnabled()) {\n logger.warn('resolveAIConfig: AI feature flag disabled');\n return null;\n }\n const { provider = 'openai', model, preferChrome = true } = options;\n if (preferChrome) {\n const transport = new ChromePromptTransport();\n const availability = yield transport.getAvailability();\n if (availability === 'available' ||\n availability === 'downloadable' ||\n availability === 'downloading') {\n return { providerType: 'chrome' };\n }\n logger.warn('resolveAIConfig: Chrome not available', availability);\n }\n if (provider === 'gemini') {\n const geminiModel = model !== null && model !== void 0 ? model : 'gemini-2.5-flash-lite';\n if (!SUPPORTED_GEMINI_MODEL_IDS.includes(geminiModel)) {\n throw new Error(`resolveAIConfig: unsupported Gemini model \"${geminiModel}\". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(', ')}.`);\n }\n return { providerType: 'gemini', model: geminiModel };\n }\n if (provider === 'anthropic') {\n const anthropicModel = model !== null && model !== void 0 ? model : 'claude-haiku-4-5-20251001';\n if (!SUPPORTED_ANTHROPIC_MODEL_IDS.includes(anthropicModel)) {\n throw new Error(`resolveAIConfig: unsupported Anthropic model \"${anthropicModel}\". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(', ')}.`);\n }\n return { providerType: 'anthropic', model: anthropicModel };\n }\n return { provider, model: model !== null && model !== void 0 ? model : 'gpt-4o-mini' };\n });\n}\n/**\n * Feature-detects an {@link ObservableAIProviderRegistry}. Returns `true` when\n * `r` exposes a `subscribe` method \u2014 i.e. it can notify on runtime changes \u2014\n * and `false` for the immutable built-ins.\n *\n * @beta\n */\nexport function isObservableAIProviderRegistry(r) {\n return typeof r.subscribe === 'function';\n}\n/**\n * Built-in fallback registry. Resolved by the DI container when no host has\n * registered an {@link (AIProviderRegistry:interface)}. Holds a single\n * `DefaultAIProvider` (no-op) under the name `'default'`, preserving the\n * \"no host registration \u2192 assistant inert\" behavior.\n *\n * @internal\n */\nexport class EmptyAIProviderRegistry {\n constructor() {\n this.noopProvider = new DefaultAIProvider();\n }\n get(name) {\n return name === EmptyAIProviderRegistry.DEFAULT_NAME ? this.noopProvider : undefined;\n }\n default() {\n return this.noopProvider;\n }\n defaultName() {\n return EmptyAIProviderRegistry.DEFAULT_NAME;\n }\n names() {\n return [EmptyAIProviderRegistry.DEFAULT_NAME];\n }\n getStatus(name) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n if (name !== undefined && name !== EmptyAIProviderRegistry.DEFAULT_NAME)\n return null;\n return (_c = (yield ((_b = (_a = this.noopProvider).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : null;\n });\n }\n listStatuses() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n const status = (_c = (yield ((_b = (_a = this.noopProvider).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : null;\n return [{ name: EmptyAIProviderRegistry.DEFAULT_NAME, isDefault: true, status }];\n });\n }\n}\nEmptyAIProviderRegistry.DEFAULT_NAME = 'default';\n/**\n * Map-backed registry built by {@link registerAIProviders}. Preserves the\n * insertion order of `providers` for {@link (AIProviderRegistry:interface).names}\n * and {@link (AIProviderRegistry:interface).listStatuses}.\n *\n * Mutable and observable: a host that holds a reference can rebind names,\n * change the default, or atomically replace the whole mapping at runtime via\n * {@link MutableAIProviderRegistry.set}, {@link MutableAIProviderRegistry.setDefault}\n * and {@link MutableAIProviderRegistry.update}, and subscribe to be told when\n * any of those happen. This is the substrate for runtime provider switching:\n * the DI token resolves one stable instance, and consumers re-resolve their\n * cached providers when {@link MutableAIProviderRegistry.subscribe | subscribe}\n * fires. A registry that is never mutated behaves identically to an immutable\n * one, so existing single-registration callers are unaffected.\n *\n * @beta\n */\nexport class MutableAIProviderRegistry {\n constructor(providers, defaultName) {\n this.listeners = new Set();\n // Defensive copy so external mutation of the caller's Map can't desync the\n // registry from its own invariants. Validate the copy we will actually keep.\n const next = new Map(providers);\n MutableAIProviderRegistry.assertValidMapping(next, defaultName);\n this.providers = next;\n this._defaultName = defaultName;\n }\n /**\n * The mapping invariant shared by construction and\n * {@link MutableAIProviderRegistry.update}: at least one provider, and the\n * resolved default name must be one of the keys. Throws\n * with the same messages from both call sites. Validates the finalized map, so\n * callers normalize/copy and resolve the default name first, then validate.\n */\n static assertValidMapping(providers, defaultName) {\n if (providers.size === 0) {\n throw new Error('MutableAIProviderRegistry: at least one provider is required.');\n }\n if (!providers.has(defaultName)) {\n throw new Error(`MutableAIProviderRegistry: default name \"${defaultName}\" not present in providers.`);\n }\n }\n get(name) {\n return this.providers.get(name);\n }\n default() {\n // Construction and every mutator guarantee this lookup succeeds.\n return this.providers.get(this._defaultName);\n }\n defaultName() {\n return this._defaultName;\n }\n names() {\n return [...this.providers.keys()];\n }\n getStatus(name) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n const provider = name === undefined ? this.default() : this.providers.get(name);\n if (!provider)\n return null;\n return (_b = (yield ((_a = provider.getStatus) === null || _a === void 0 ? void 0 : _a.call(provider)))) !== null && _b !== void 0 ? _b : null;\n });\n }\n listStatuses() {\n return __awaiter(this, void 0, void 0, function* () {\n const entries = [...this.providers.entries()];\n return Promise.all(entries.map((_a) => __awaiter(this, [_a], void 0, function* ([name, provider]) {\n var _b, _c;\n return ({\n name,\n isDefault: name === this._defaultName,\n status: (_c = (yield ((_b = provider.getStatus) === null || _b === void 0 ? void 0 : _b.call(provider)))) !== null && _c !== void 0 ? _c : null,\n });\n })));\n });\n }\n /**\n * Rebind (or add) a single name. Rebinding an existing name preserves its\n * position in `names()`; a new name is appended. Notifies subscribers.\n */\n set(name, provider) {\n this.providers.set(name, provider);\n this.notify();\n }\n /**\n * Change the default provider. Throws if `name` is not currently registered.\n * Notifies subscribers.\n */\n setDefault(name) {\n if (!this.providers.has(name)) {\n throw new Error(`MutableAIProviderRegistry: cannot set default to \"${name}\" \u2014 not present in providers.`);\n }\n this._defaultName = name;\n this.notify();\n }\n /**\n * Atomically replace the whole mapping (and optionally the default) in one\n * step, then notify subscribers once. Applies the same validation as the\n * constructor: an empty mapping throws, and the resolved default must be\n * present. When `options.default` is omitted the current default name is\n * retained (and must still exist in the new mapping).\n */\n update(providers, options = {}) {\n var _a;\n const next = providers instanceof Map ? new Map(providers) : new Map(Object.entries(providers));\n const nextDefault = (_a = options.default) !== null && _a !== void 0 ? _a : this._defaultName;\n MutableAIProviderRegistry.assertValidMapping(next, nextDefault);\n this.providers = next;\n this._defaultName = nextDefault;\n this.notify();\n }\n subscribe(listener) {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n /**\n * Fire every listener once. Iterates a snapshot so a listener that\n * unsubscribes (or subscribes) during notification doesn't perturb the\n * in-flight iteration.\n */\n notify() {\n for (const listener of Array.from(this.listeners))\n listener();\n }\n}\n", "import type { AgenticActivityEvents } from './ai-activity-channel';\n\n/**\n * Configuration for {@link AgenticActivityBus}.\n *\n * @beta\n */\nexport interface AgenticActivityBusConfig {\n /** Events that should also be forwarded via BroadcastChannel to other tabs. */\n crossTabEvents?: (keyof AgenticActivityEvents)[];\n /** BroadcastChannel name. Only used when crossTabEvents is non-empty. */\n channelName?: string;\n /**\n * Lazy alternative to {@link AgenticActivityBusConfig.channelName}: called the first\n * time a cross-tab channel is actually needed, in a browser only. Deferring the name\n * computation keeps side effects (e.g. `sessionStorage` reads) out of module-eval and\n * off the non-browser path. Ignored if `channelName` is also set.\n */\n channelNameFactory?: () => string;\n}\n\ntype AnyHandler = (detail: any) => void;\n\n/**\n * Minimal activity-bus surface the drivers depend on. `ChatDriver`/`OrchestratingDriver`\n * only ever *publish* \u2014 accepting this narrow interface (rather than importing the module\n * singleton) lets a headless/server or unit-test host omit the bus entirely, so no live\n * `BroadcastChannel` is ever opened on that path. See {@link NOOP_ACTIVITY_BUS}.\n *\n * @beta\n */\nexport interface ActivityBus {\n publish<K extends keyof AgenticActivityEvents>(type: K, detail: AgenticActivityEvents[K]): void;\n}\n\n/**\n * No-op {@link ActivityBus}. The default when no bus is injected (Node, tests, headless\n * server use) \u2014 publishing goes nowhere and nothing is left open to tear down.\n *\n * @beta\n */\nexport const NOOP_ACTIVITY_BUS: ActivityBus = { publish: () => {} };\n\n/**\n * Typed in-process event bus for AI assistant activity events.\n *\n * Dispatches events synchronously to all local subscribers in the same JS module instance\n * (i.e. the same browser tab). Events listed in `crossTabEvents` are additionally forwarded\n * via a shared `BroadcastChannel` so that other tabs on the same origin receive them.\n *\n * @remarks\n * The pre-instantiated {@link agenticActivityBus} singleton covers all platform use cases.\n * App developers can extend the event map using TypeScript declaration merging on\n * {@link AgenticActivityEvents} and subscribe/publish custom events without any platform changes.\n *\n * @beta\n */\nexport class AgenticActivityBus {\n private readonly subscribers = new Map<string, Set<AnyHandler>>();\n private readonly crossTabEvents: Set<string>;\n private readonly channelNameFactory?: () => string;\n private channel?: BroadcastChannel;\n private channelInitialised = false;\n\n /**\n * @param config - Optional configuration. Omit to create an in-memory-only bus.\n * @beta\n */\n constructor(config?: AgenticActivityBusConfig) {\n this.crossTabEvents = new Set(config?.crossTabEvents ?? []);\n this.channelNameFactory =\n config?.channelName != null ? () => config.channelName! : config?.channelNameFactory;\n }\n\n /**\n * Lazily open the cross-tab `BroadcastChannel` on first use. Deferred (rather than\n * created in the constructor) so that importing this module, or constructing the bus\n * off-browser (Node, tests, headless server), never opens a live channel or reads\n * `sessionStorage` \u2014 both would keep a Node event loop alive and hang the process.\n * Cross-tab forwarding is inherently browser-only, so channel creation is gated on a\n * browser environment; elsewhere the bus stays purely in-process.\n */\n private ensureChannel(): void {\n if (this.channelInitialised) return;\n this.channelInitialised = true;\n const inBrowser = typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined';\n if (this.crossTabEvents.size === 0 || !this.channelNameFactory || !inBrowser) return;\n this.channel = new BroadcastChannel(this.channelNameFactory());\n this.channel.onmessage = (ev) => {\n const { type, detail } = (ev.data ?? {}) as { type?: string; detail?: unknown };\n if (type) this.notifyLocal(type, detail);\n };\n }\n\n /**\n * Subscribe to an event. Returns an unsubscribe function \u2014 call it in\n * `disconnectedCallback` to avoid memory leaks.\n *\n * @beta\n */\n subscribe<K extends keyof AgenticActivityEvents>(\n type: K,\n handler: (detail: AgenticActivityEvents[K]) => void,\n ): () => void {\n // Open the cross-tab channel (browser only) so this subscriber receives events\n // forwarded from other tabs; no-op off-browser.\n this.ensureChannel();\n let handlers = this.subscribers.get(type as string);\n if (!handlers) {\n handlers = new Set();\n this.subscribers.set(type as string, handlers);\n }\n const h = handler as AnyHandler;\n handlers.add(h);\n return () => handlers!.delete(h);\n }\n\n /**\n * Publish an event to all local subscribers and, if configured, to other tabs\n * via BroadcastChannel.\n *\n * @beta\n */\n publish<K extends keyof AgenticActivityEvents>(type: K, detail: AgenticActivityEvents[K]): void {\n this.notifyLocal(type as string, detail);\n if (this.crossTabEvents.has(type as string)) {\n this.ensureChannel();\n this.channel?.postMessage({ type, detail });\n }\n }\n\n /**\n * Add an event type to the cross-tab forwarding set at runtime.\n * Must be called before the first {@link AgenticActivityBus.publish} of that event type.\n *\n * @beta\n */\n addCrossTabEvent(type: keyof AgenticActivityEvents): void {\n this.crossTabEvents.add(type as string);\n }\n\n /**\n * Close the underlying BroadcastChannel. Call once on application teardown if needed.\n *\n * @beta\n */\n close(): void {\n this.channel?.close();\n this.channel = undefined;\n }\n\n private notifyLocal(type: string, detail: unknown): void {\n this.subscribers.get(type)?.forEach((handler) => handler(detail));\n }\n}\n\n/**\n * Returns a `BroadcastChannel` name that is scoped to the current tab and any popout windows\n * it opens, while remaining isolated from unrelated tabs on the same origin.\n *\n * **How it works:**\n * A UUID is generated once and stored in `sessionStorage`. `sessionStorage` persists across\n * page refreshes (so the channel name stays stable after an F5), but is cleared when the tab\n * is closed. Crucially, when a page opens a child window via `window.open()`, the browser\n * initialises the new window's `sessionStorage` as a copy of the opener's \u2014 so the child\n * inherits the same UUID and therefore the same channel name.\n *\n * Result:\n * - **Same tab + its `window.open()` popouts** share one channel \u2192 events flow as intended.\n * - **Independent tabs** (opened from the address bar, bookmarks, or links) each get a fresh\n * `sessionStorage` and therefore a distinct channel \u2192 no cross-talk between unrelated app\n * instances on the same origin.\n */\nfunction getTabScopedChannelName(base: string): string {\n // Belt-and-braces: this only runs in a browser (see `ensureChannel`), but guard anyway\n // so a direct call off-browser never throws a `sessionStorage is not defined` ReferenceError.\n if (typeof sessionStorage === 'undefined') return `${base}-nostorage`;\n const key = `${base}-tab-id`;\n let id = sessionStorage.getItem(key);\n if (!id) {\n id = crypto.randomUUID();\n sessionStorage.setItem(key, id);\n }\n return `${base}-${id}`;\n}\n\n/**\n * Pre-instantiated singleton event bus for AI assistant activity.\n *\n * - `halo-start` / `halo-stop` are forwarded via a tab-scoped `BroadcastChannel` so that\n * popout windows opened from this tab show halo animations, while remaining isolated from\n * unrelated tabs on the same origin (tab-scoped channel name).\n * - `tool-loop-start` / `tool-loop-end` are cross-tab for the same reason: they describe the\n * assistant's lifecycle (a turn beginning / ending), and the most common subscribers\n * (workspace transitions, post-turn deferred recomputation, UI gates tied to the assistant\n * being idle) need the event regardless of whether the user is interacting with the chat\n * in the main tab or a popout window. Tab-local-only telemetry can subscribe and filter.\n * - `chat-popout` / `chat-popin` are in-memory only \u2014 they must only affect the tab where the\n * user clicked.\n *\n * @beta\n */\nexport const agenticActivityBus = new AgenticActivityBus({\n crossTabEvents: ['halo-start', 'halo-stop', 'tool-loop-start', 'tool-loop-end'],\n // Lazy: the tab-scoped name (and its `sessionStorage` read) is computed on first\n // cross-tab use in a browser, not at module-eval \u2014 so importing this module is\n // side-effect-free and Node/test-safe.\n channelNameFactory: () => getTabScopedChannelName('foundation-ai-activity'),\n});\n", "import type { AIProvider, AIProviderRegistry } from '@genesislcap/foundation-ai';\nimport type { AgentConfig } from './config';\n\n/**\n * Resolve a provider name against the registry and assert it implements\n * `chat()` \u2014 the capability the chat tool-loop depends on. Throws with a\n * message naming the agent so misconfigured agents are easy to track down.\n *\n * Used by both the up-front static walk in `OrchestratingDriver` and by\n * `ChatDriver`'s per-turn resolver for function-form `provider` values.\n *\n * @internal\n */\nexport function resolveChatProvider(\n registry: AIProviderRegistry,\n providerName: string,\n agentName: string,\n): AIProvider {\n const provider = registry.get(providerName);\n if (!provider) {\n const available = registry.names().join(', ') || '(none)';\n throw new Error(\n `Agent \"${agentName}\" references unknown provider \"${providerName}\". Registered: ${available}`,\n );\n }\n if (!provider.chat) {\n throw new Error(\n `Agent \"${agentName}\" resolved to provider \"${providerName}\" which does not implement chat().`,\n );\n }\n return provider;\n}\n\n/**\n * Walk an agent tree (including nested `subAgents`) and validate every static\n * `provider: string` against the registry. Function-form `provider` values are\n * deferred \u2014 they validate on first resolution inside the driver.\n *\n * Throws on the first failure, with the same message shape produced by\n * {@link resolveChatProvider}.\n *\n * @internal\n */\nexport function validateStaticAgentProviders(\n agents: AgentConfig[],\n registry: AIProviderRegistry,\n): void {\n const visited = new Set<AgentConfig>();\n const walk = (agent: AgentConfig): void => {\n if (visited.has(agent)) return;\n visited.add(agent);\n if (typeof agent.provider === 'string') {\n resolveChatProvider(registry, agent.provider, agent.name);\n }\n for (const sub of agent.subAgents ?? []) walk(sub);\n };\n for (const root of agents) walk(root);\n}\n", "/**\n * Module-level append-only timeline of meta/lifecycle events, keyed by session\n * identity (the same `stateKey` space used by the driver registry and the\n * session store).\n *\n * Why a module registry rather than the redux store or the driver:\n * - **Survives the pop-in/pop-out element churn.** A single session can be\n * emitted from up to two element instances (an `expand` bubble + a `collapse`\n * panel) sharing one driver; keying by `stateKey` unifies them into one\n * timeline.\n * - **Survives driver rebuilds.** The driver is torn down and recreated when the\n * host swaps the agents array (see `agentsChanged` / `deleteDriver`), so a\n * driver-owned buffer would lose the timeline mid-session. The `stateKey`\n * outlives the driver.\n * - **Stays out of redux reactivity.** These appends never drive the UI, so\n * there's no reason to pay immutable-reducer cost or flood the Redux DevTools\n * action log with debug noise.\n *\n * Surfaced in `getDebugLog().timeline`, merged chronologically with messages and\n * turn snapshots. Ring-buffered \u2014 the oldest non-`high` events are evicted first\n * while `high`-importance failure events are retained \u2014 so a long-lived session\n * stays bounded in normal use without ever dropping a failure signal.\n *\n * @internal\n */\n\nimport type { TurnFailureReason } from '@genesislcap/foundation-ai';\n\n/**\n * Catalogue of meta event names. This is the documented surface \u2014 extend it as\n * new events are wired in (Tier 2/3 lifecycle, interaction, provider events).\n */\nexport type MetaEventType =\n // Element lifecycle + window placement\n | 'assistant.connected'\n | 'assistant.disconnected'\n | 'assistant.popout'\n | 'assistant.popin'\n // Driver lifecycle / wiring\n | 'driver.created'\n | 'driver.wired'\n | 'driver.unwired'\n // Turn lifecycle\n | 'state.changed'\n | 'turn.start'\n | 'turn.end'\n | 'turn.retry'\n | 'turn.error'\n | 'tool.failed'\n | 'tool.unresolved'\n | 'subagent.started'\n | 'subagent.completed'\n | 'subagent.failed'\n // Routing / providers\n | 'agent.handoff'\n | 'agent.pinned'\n | 'agent.unpinned'\n | 'provider.selected'\n // Blocking interactions\n | 'interaction.requested'\n | 'interaction.resolved'\n // External / unified diagnostics (GENC-1461) \u2014 an out-of-band engine's log folded into this session\n | 'external-diagnostics.folded'\n // Context / cost\n | 'context.updated'\n | 'context.threshold-crossed'\n | 'context.compacted'\n | 'context.condensed'\n // UI + input\n | 'panel.toggled'\n | 'attachment.added'\n | 'file.read-failed'\n | 'suggestions.failed'\n // Session lifecycle (GENC-1351)\n | 'session.cleared'\n | 'session.switched'\n | 'session.switch-deferred'\n | 'persistence.toggled'\n | 'persistence.saved'\n | 'persistence.save-failed'\n | 'persistence.suppressed'\n | 'persistence.not-resumable'\n | 'persistence.restored'\n | 'persistence.restore-orphan';\n\n/**\n * How much a reader should care about an event \u2014 lets a consumer (or an AI\n * agent) filter the timeline: skip `low` UI/bookkeeping noise, skim `normal`\n * session flow, or jump straight to `high` problem/limit signals when triaging.\n */\nexport type MetaEventImportance = 'high' | 'normal' | 'low';\n\n/**\n * Importance is intrinsic to the event *type*, not the instance, so it's\n * defined once here and stamped automatically by {@link recordMetaEvent} \u2014 call\n * sites never pass it. The `Record` is exhaustive: adding a `MetaEventType`\n * without a level here is a compile error.\n *\n * - `high` \u2014 failures and hard limits you almost always want to see.\n * - `normal` \u2014 meaningful session flow you read to follow what happened.\n * - `low` \u2014 frequent UI / bookkeeping noise, usually safe to skip.\n */\nexport const META_EVENT_IMPORTANCE: Record<MetaEventType, MetaEventImportance> = {\n 'turn.error': 'high',\n 'tool.failed': 'high',\n 'subagent.failed': 'high',\n 'file.read-failed': 'high',\n 'suggestions.failed': 'high',\n 'context.threshold-crossed': 'high',\n 'context.compacted': 'high',\n 'persistence.restore-orphan': 'high',\n // A save that did not land is silent data loss in progress: the transcript on screen\n // is no longer backed by the store, and every later turn widens the gap. GENC-1511.\n 'persistence.save-failed': 'high',\n\n 'assistant.connected': 'normal',\n 'assistant.disconnected': 'normal',\n 'assistant.popout': 'normal',\n 'assistant.popin': 'normal',\n 'driver.created': 'normal',\n 'state.changed': 'normal',\n 'turn.start': 'normal',\n 'turn.end': 'normal',\n 'turn.retry': 'normal',\n 'tool.unresolved': 'normal',\n 'subagent.started': 'normal',\n 'subagent.completed': 'normal',\n 'agent.handoff': 'normal',\n 'agent.pinned': 'normal',\n 'agent.unpinned': 'normal',\n 'provider.selected': 'normal',\n 'interaction.requested': 'normal',\n 'interaction.resolved': 'normal',\n 'external-diagnostics.folded': 'normal',\n 'session.cleared': 'normal',\n 'session.switched': 'low',\n 'session.switch-deferred': 'low',\n 'persistence.restored': 'normal',\n 'persistence.suppressed': 'normal',\n 'persistence.not-resumable': 'normal',\n\n 'driver.wired': 'low',\n 'driver.unwired': 'low',\n 'context.updated': 'low',\n 'context.condensed': 'low',\n 'panel.toggled': 'low',\n 'persistence.toggled': 'low',\n 'persistence.saved': 'low',\n 'attachment.added': 'low',\n};\n\n/** One entry in the meta-event timeline. */\nexport interface MetaEvent {\n /** Monotonic counter across the session's lifetime (does not reset on driver rebuild). */\n index: number;\n /** ISO timestamp, matching the format used elsewhere in the debug log. */\n timestamp: string;\n /** Event name \u2014 see {@link MetaEventType}. */\n type: MetaEventType;\n /** How much to care about this event \u2014 see {@link META_EVENT_IMPORTANCE}. */\n importance: MetaEventImportance;\n /** Optional structured payload. */\n detail?: Record<string, unknown>;\n}\n\n/**\n * Soft ring-buffer cap. Once exceeded, the oldest *non-`high`* event is evicted;\n * `high`-importance events (failures and hard limits) are never dropped \u2014 they're\n * the whole reason the log exists. So a buffer dominated by `high` events is\n * allowed to float above this cap rather than lose a failure signal; in normal\n * use the frequent `low`/`normal` events keep it near the cap. Entries are cheap.\n */\nconst DEFAULT_MAX_META_EVENTS = 800;\n\ninterface MetaEventBuffer {\n events: MetaEvent[];\n /** Next index to assign \u2014 kept separate from `events.length` so it stays monotonic after eviction. */\n next: number;\n}\n\nconst registry = new Map<string, MetaEventBuffer>();\n\n/**\n * Append a meta event to the timeline for `key`. Once the buffer exceeds\n * {@link DEFAULT_MAX_META_EVENTS}, evicts the oldest *non-`high`* event;\n * `high`-importance events are never evicted. An empty `key` is bucketed under\n * `''`, matching how drivers/stores handle an absent session identity, so\n * callers never need to guard.\n */\nexport function recordMetaEvent(\n key: string,\n type: MetaEventType,\n detail?: Record<string, unknown>,\n): void {\n let buffer = registry.get(key);\n if (!buffer) {\n buffer = { events: [], next: 0 };\n registry.set(key, buffer);\n }\n buffer.events.push({\n index: buffer.next,\n timestamp: new Date().toISOString(),\n type,\n importance: META_EVENT_IMPORTANCE[type],\n detail,\n });\n buffer.next += 1;\n if (buffer.events.length > DEFAULT_MAX_META_EVENTS) {\n // Drop the oldest event that isn't `high` importance. `high` events\n // (failures/limits) are retained even past the cap \u2014 losing a failure\n // signal is worse than briefly exceeding the buffer size. If every retained\n // event is `high` (all-failures session), nothing is evicted and the buffer\n // grows; in practice frequent `low`/`normal` events keep it bounded.\n const evictAt = buffer.events.findIndex((e) => e.importance !== 'high');\n if (evictAt !== -1) {\n buffer.events.splice(evictAt, 1);\n }\n }\n}\n\n/**\n * Why a turn failed or was retried \u2014 stamped as `detail.reason` on `turn.error`\n * and `turn.retry` events, and (since PTC-0) surfaced at the driver's loop\n * boundary via {@link ChatDriverResult.failureReason}. Re-exported from\n * `@genesislcap/foundation-ai` \u2014 where it lives alongside `ChatDriverResult` so\n * the boundary field and this log surface can never drift apart \u2014 under its\n * historical name so existing importers are unaffected. Enumerated so the set\n * stays in sync with the README and call sites can't drift to ad-hoc strings.\n */\nexport type { TurnFailureReason };\n\n/**\n * Record a turn-ending failure (`turn.error`, importance `high`). The `reason`\n * is typed so the high-importance triage surface stays consistent; pass any\n * diagnostic specifics (attempt counts, offending tool names, etc.) in `detail`.\n */\nexport function recordTurnError(\n key: string,\n reason: TurnFailureReason,\n detail?: Record<string, unknown>,\n): void {\n recordMetaEvent(key, 'turn.error', { reason, ...detail });\n}\n\n/**\n * Record a recoverable retry *within* a turn (`turn.retry`, importance `normal`)\n * \u2014 e.g. one malformed/empty attempt that will be retried, as distinct from the\n * final attempt that bails out as a `turn.error`. Include `attempt`/`maxAttempts`\n * in `detail` so the timeline shows which try this was.\n */\nexport function recordTurnRetry(\n key: string,\n reason: TurnFailureReason,\n detail?: Record<string, unknown>,\n): void {\n recordMetaEvent(key, 'turn.retry', { reason, ...detail });\n}\n\n/** Returns the meta-event timeline for `key`, or an empty array if none recorded. */\nexport function getMetaEvents(key: string): ReadonlyArray<MetaEvent> {\n return registry.get(key)?.events ?? [];\n}\n\n/**\n * Merge pre-built meta events into the timeline for `targetKey`, **preserving each\n * event's original `timestamp`** (so it interleaves chronologically on export)\n * while re-indexing onto the target buffer's monotonic counter. Used to fold a\n * sub-agent's harvested events into the parent session \u2014 see\n * `ChatDriver.invokeSubAgent`. Unlike {@link recordMetaEvent} it does not stamp a\n * fresh timestamp; the same non-`high` eviction policy is applied once after the\n * batch so the buffer stays bounded.\n */\nexport function mergeMetaEvents(targetKey: string, events: readonly MetaEvent[]): void {\n if (events.length === 0) return;\n let buffer = registry.get(targetKey);\n if (!buffer) {\n buffer = { events: [], next: 0 };\n registry.set(targetKey, buffer);\n }\n for (const event of events) {\n buffer.events.push({ ...event, index: buffer.next });\n buffer.next += 1;\n }\n // Evict oldest non-`high` events until back under the cap \u2014 same policy as\n // recordMetaEvent; `high` events (failures/limits) are never dropped. Single\n // pass: take the overflow count, then drop that many of the oldest non-`high`\n // events in order (if there aren't enough non-`high`, the buffer floats above\n // the cap rather than losing a failure signal).\n let toEvict = buffer.events.length - DEFAULT_MAX_META_EVENTS;\n if (toEvict > 0) {\n buffer.events = buffer.events.filter((e) => {\n if (toEvict > 0 && e.importance !== 'high') {\n toEvict -= 1;\n return false;\n }\n return true;\n });\n }\n}\n\n/**\n * Drop the entire timeline for `key`. Used to discard a sub-agent's transient\n * per-invocation session once its events have been harvested into the parent, so\n * the module registry doesn't accumulate one orphaned bucket per sub-agent run.\n */\nexport function clearSession(key: string): void {\n registry.delete(key);\n}\n\n/**\n * Human/agent-facing guide emitted as the first key of the exported debug log,\n * so whoever opens the JSON (often an AI agent) knows how to read it without\n * reverse-engineering the shape. Kept here next to the event catalogue it\n * describes \u2014 but proximity alone demonstrably did NOT keep the two in sync\n * (`refusal` was missing from both reason lists for a whole release), so\n * `debug-event-log.test.ts` now asserts that every `TurnFailureReason` and every\n * `SubAgentFailureReason` is named here, and fails the build when one is added\n * without a matching sentence. Enumerations below read as exhaustive and WILL be\n * trusted by an agent reading the JSON \u2014 keep them so.\n */\nexport const DEBUG_LOG_README: readonly string[] = [\n 'This is an exported debug log for the Genesis AI assistant. Read it top-to-bottom.',\n \"`sessionUsage` is what this session spent: `costUsd` (USD, provider-reported per request and summed, cache discounts already applied) plus the four TOKEN BUCKETS \u2014 `uncachedInputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `outputTokens`. Those four are disjoint and safe to add up for a total-tokens figure; the per-message fields further down are NOT (see kind:'message'). Each bucket bills at a different rate \u2014 cache reads a fraction of uncached input, cache writes a premium, output highest \u2014 so a big token count against a small cost means the prompt was mostly cache hits, not a missing charge. It covers sub-agent turns and spend a compaction banked, so for the CONVERSATION it is the authoritative total: prefer it over re-summing the timeline, which can be short by whatever the ring buffers evicted. The same figures appear under `meta.context`. It is as current as the snapshot it came from: the assistant's own download stamps a fresh one, but a log stitched by another tool can carry an older one \u2014 compare `meta.timestamp` with the last timeline entry, and if it is well behind, read these totals as historical and fall back to summing the timeline. One scope caveat: it is derived from the transcript, so it excludes billed calls that produced no message (a blank or refused attempt that was retried \u2014 see kind:'turn'.`usage`). Summing the turns can therefore come out HIGHER than this, and the difference is exactly that discarded spend, not a double-count.\",\n \"What 'session' means for those figures: the CURRENT conversation under this session key (a host-supplied per-project id, or the element id + header title when the host supplies none) \u2014 which is not necessarily everything in `timeline`. It is re-derived from the live transcript, so it spans page loads only when the chat is being remembered, and a Clear resets it to zero. `timeline` is append-only regardless: it keeps every page load and the pre-Clear conversation, with the session.cleared event as the boundary. So on a long-lived log, read these totals as the latest conversation's and the earlier sections as history \u2014 not as a total of the whole file.\",\n '`timeline` is the entire session as one array, already sorted chronologically by `timestamp` (ISO 8601). Every entry has a `kind`.',\n 'Timestamps are millisecond-resolution; entries that share the same millisecond are ordered by a fixed kind rank (event, then turn, then message), which is a heuristic and may not reflect exact causal order within that millisecond \u2014 e.g. a user message and the turn it triggered, or a final assistant message and its turn.end event, can appear in either order depending on whether they landed in the same millisecond. Read the logical structure of a turn rather than over-interpreting the micro-ordering of co-timestamped entries of different kinds.',\n \"kind:'message' \u2014 the conversation. `role` is user/assistant/tool/system-event/synthetic-user; `agentName` says which agent produced it; `toolCalls`/`toolResult`/`interaction` carry tool and widget activity; `inputTokens`/`outputTokens`/`cost` are per-message LLM usage, where `inputTokens` is the WHOLE prompt for that request and `cacheReadTokens`/`cacheWriteTokens` BREAK IT DOWN rather than add to it \u2014 uncached input is `inputTokens` minus those two, and adding the cache fields to `inputTokens` counts the prompt twice. The cache fields are absent on providers that report no cache split (Gemini reports reads only, since implicit caching bills no write) and on messages persisted before they existed, so read them as 0 when missing. Each bucket bills at a different rate \u2014 cache reads a fraction of uncached input, cache writes a premium, output highest \u2014 so a large token count at a small cost means the prompt was mostly cache hits. `externalCostUsd` is any non-LLM cost a widget reported for its own external service calls (folded into the session cost total alongside `cost`). On model-produced assistant messages, `model` is the concrete model id that generated it (e.g. 'gemini-2.5-flash-lite') and `providerName` is the registry slot it resolved under (e.g. a tier name like 'high'/'low', or the default); together they attribute the message \u2014 and any tool calls it carries \u2014 to an exact model even across a mid-session vendor/tier switch, where one slot name can map to different models before and after the switch. Both are undefined on any entry that is NOT an LLM response: non-assistant roles (user/tool/system-event) and 'synthetic-user' echoes; assistant interaction/widget entries (empty content carrying an `interaction` \u2014 a rendered widget, not a model turn); driver-authored assistant fallbacks (the timeout, repeated-malformed-call, and empty-response apology messages); and messages restored from a session persisted before these fields existed. One partial case: on a genuine model turn whose provider exposes no `getStatus` (or reports no model), `providerName` is still set but `model` alone is undefined. A 'synthetic-user' message is a display-only echo of an interaction outcome (e.g. the answer a widget reported): it renders on the user's side of the chat and `agentName` is the agent that created it, but it is never sent to the LLM \u2014 so it has no matching 'turn' and the model learns the outcome only from the corresponding tool result.\",\n \"Sub-agent messages appear inline. When a tool delegates to a sub-agent (via `requestSubAgent`), the sub-agent's whole conversation \u2014 its own assistant/tool messages, each with their own `content`/`thinking`/`toolCalls`/`toolResult` and per-message `model`/`providerName`/`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheWriteTokens`/`cost` \u2014 is hoisted into the timeline as ordinary kind:'message' entries, interleaved by timestamp right after the tool call that spawned them (so you read the delegation top-to-bottom). A hoisted entry is marked: `subAgentDepth` is its delegation depth (1 for a sub-agent, 2 for a sub-agent's sub-agent, \u2026), `subAgentOf` is the id of the parent tool call that spawned it (correlates it back even when two sub-agents run in one parent turn), `subAgentName` is the sub-agent's own name, and `agentName` is rewritten to a `\\\"<parent> \u203A <sub-agent>\\\"` breadcrumb (composing when nested, e.g. `\\\"UI Builder \u203A Planner \u203A Grounding\\\"`). The sub-agent's per-LLM-call snapshots also surface as kind:'turn' entries with an N-M `turnIndex`, and subagent.started/completed (or subagent.failed) events bracket the run. Per-message `cost` on hoisted entries is already part of the session total (it is summed from the un-flattened history), so summing the top-level timeline does NOT double-count.\",\n \"kind:'turn' \u2014 one LLM call. `turnIndex` is a string: a top-level turn is the bare counter ('0', '1', \u2026); a sub-agent's turns are numbered under the parent turn that activated them ('3-1', '3-2', \u2026, and a nested sub-agent contributes '3-2-1', \u2026), and `agentName` names the agent that ran the turn. `systemPrompt` and `toolNames` are what the model saw. A systemPrompt of '<repeated \u2014 identical to turn N>' was byte-identical to turn N and de-duplicated; the full prompt is shown whenever it changes (often because a stateful agent advanced), so prompt evolution is visible.\",\n \"kind:'turn'.`model`/`providerName`/`provider` \u2014 which model ran that call: the concrete model id, the registry slot it resolved under (a tier name like 'high'/'low', or the default), and the vendor. Recorded per CALL, so an agent whose `provider` selector varies by state \u2014 a flow that plans on a high tier and executes on a low one \u2014 has every step attributed, including calls that produced no message. `model` is the SERVING model where the provider reports one, so a turn answered by a server-side fallback names the model that answered rather than the one requested; it always matches the `model` on the message that call produced. Absent when the provider exposes no `getStatus` and the transport stamped nothing.\",\n \"kind:'turn'.`usage` \u2014 what that ONE call cost, in the same four-bucket + `costUsd` shape as `sessionUsage`. Absent while a call is in flight and on providers that report no usage. This is the SAME money as the message the call produced, not extra money: never add turn usage to message usage, and read a turn plus its message as one charge. Its distinct value is the calls that produced NO message \u2014 a blank or refused response is billed and then discarded before the retry, so the turn entry is the only record of that spend, and a turn with `usage` but no message after it is exactly that. `costUsd: 0` alongside a nonzero token count means the provider reported no price, not that the call was free.\",\n \"kind:'turn'.`agentSnapshot` \u2014 the active agent's own view of its internal state, captured at that turn. An agent opts into this by exposing a `getDebugSnapshot()` that returns JSON-serializable per-state info; stateful/flow agents wire it automatically, so you can watch a flow advance turn-by-turn (e.g. current step, cursor, collected fields, pending changes). Absent for agents that don't expose one.\",\n \"kind:'event' \u2014 a meta/lifecycle event. `type` names it (see below); `detail` carries structured data. `detail.placement` is the emitting UI instance: 'bubble' (collapsed), 'panel' (popped-out), or 'standalone'.\",\n \"Each 'event' also has an `importance`: 'high' (failures/limits \u2014 turn.error, tool.failed, subagent.failed, file.read-failed, suggestions.failed, context.threshold-crossed), 'normal' (session flow \u2014 connects, turns, retries, handoffs, agent/provider changes, interactions, sub-agent start/complete), or 'low' (skippable UI/bookkeeping noise \u2014 panel.toggled, attachment.added, driver.wired/unwired, context.updated, context.condensed). To skim, ignore importance:'low'; to triage a failure, filter to importance:'high' then read the nearby messages and turns. A 'high' turn.error is often preceded by one or more 'normal' turn.retry events for the same reason \u2014 read them together to see how many attempts were made before bailing. 'message' and 'turn' entries carry no importance \u2014 they are the substance, always read them.\",\n 'Event types: assistant.connected/disconnected (mount + placement + whether the session was created or restored), assistant.popout/popin (window placement), driver.created/wired/unwired (which driver is live and why it stops/starts responding across a popout), state.changed (idle\u2194loading), turn.start/turn.end (turn boundary; turn.end carries durationMs), turn.retry (a recoverable in-turn retry \u2014 detail.reason plus attempt/maxAttempts; for malformed calls also finishMessage; for empty responses also the provider finishReason + thoughtsTokens + parts breakdown), turn.error (a turn failed or hit a guardrail \u2014 detail.reason is one of exception/malformed-function-call/empty-response/unknown-tool-limit/max-iterations/response-truncated/refusal/budget-exhausted/provider-refused, plus reason-specific diagnostics: attempts (for empty-response also finishReason + thoughtsTokens + a parts breakdown, distinguishing a thinking-only STOP from a truly empty turn), finishMessage, for response-truncated the model + maxTokens + outputTokens + tools, unknownTools (split into staleTools \u2014 real earlier this activation but retired by the current state or hidden behind an open exclusive fold \u2014 and hallucinatedTools \u2014 never advertised) + availableTools, iterations + limit, for budget-exhausted the budgetUsd + spentUsd figures reported by the proxy plus the resolved vendor, for provider-refused the kind (spend|auth) plus the upstream status and error type \u2014 the vendor refusing the ACCOUNT rather than us refusing to spend, so the remedy is a top-up or a key rotation rather than a raised cap, and the kind is the only place that distinction survives because the user-facing copy is deliberately cause-free, or name + message for exceptions), tool.failed (a tool threw), tool.unresolved (the model called a tool that could not be dispatched \u2014 detail.kind is folded/fold-hidden/stale/unknown, plus tool + agent and, for the counted kinds, the consecutive streak; the recurring lead-up to an unknown-tool-limit turn.error), subagent.started/completed/failed (the lifecycle of a `requestSubAgent` delegation \u2014 detail.agent names the sub-agent; these bracket the sub-agent turns that appear as kind:turn entries with an N-M `turnIndex`; subagent.failed also carries detail.reason, one of max_iterations/malformed_tool_call/empty_response/unknown_tool_limit/timeout/response_truncated/refusal/budget_exhausted/provider_refused; budget_exhausted and provider_refused are both terminal for the PARENT turn too \u2014 the parent stops rather than calling the model again into the same wall), agent.handoff (routing; from=null is the initial activation), agent.pinned/unpinned (forced routing), provider.selected (the resolved provider for the upcoming turns \u2014 detail.provider is the registry SLOT/tier name, detail.model the concrete model behind it and detail.vendor its vendor; emitted only when the slot CHANGES, so read the per-turn `model` for the model of any given call rather than assuming the nearest event still applies), interaction.requested/resolved (blocking user widgets \u2014 explain quiet gaps; note that when a sub-agent opens a widget, detail.agent \u2014 and the agentName on the interaction message \u2014 is the HOST agent that owns the widget, NOT the sub-agent that asked, because widgets render and resolve on the host driver), context.updated/threshold-crossed (token + cost), context.condensed (a stale tool payload was collapsed out of the model-bound history by a `condenseWhen` declaration on the tool \u2014 detail.tool + toolCallId, target args|response, trigger (superseded:<key> or age:<n>), stubLen, and an estimated tokensSaved; stored history and this log keep the FULL payload, so the model-visible slice at any point is the full history minus the condensations recorded up to then), panel.toggled, attachment.added, file.read-failed, suggestions.failed.',\n 'Sub-agent meta events: a sub-agent\\'s own turn.retry/turn.error/tool.failed/tool.unresolved events are merged into this same timeline, tagged with `detail.subAgent` \u2014 a `\"<parent> \u203A <sub-agent>\"` breadcrumb that composes when nested (e.g. `\"UI Builder \u203A Planner \u203A Grounding\"`) \u2014 and interleaved by their original timestamps within the subagent.started\u2192completed/failed bracket. These are the per-attempt/per-failure signals that do NOT appear among the sub-agent\\'s (hoisted) messages: a malformed/empty attempt that gets retried produces no message, and the stale-vs-hallucinated split and streak counts live only on the event. A sub-agent\\'s high-volume, message-derivable events (turn.start/turn.end, provider.selected, context.updated) are intentionally NOT merged \u2014 read its hoisted messages for model/tokens/cost and turn-by-turn activity, and the bracketing subagent.* events for the run\\'s span.',\n \"`meta` holds context captured at export time: agentSummary (full agent configs), context (active model, contextTokens/contextLimit/contextUsagePercent for the last call, and the session totals \u2014 sessionCostUsd, sessionTokensConsumed, and the four-bucket sessionUsage lifted to the top of this log), activeDebugSnapshot (the active agent's `getDebugSnapshot()` taken fresh at export \u2014 reflects state NOW, which may have advanced beyond the last turn's agentSnapshot), debug (optional host-supplied debug state), host, and the export timestamp.\",\n 'Note the two different scopes in `meta.context`: `contextTokens` is the prompt size of the LAST call (against `contextLimit`, the model context window), while `sessionUsage`/`sessionTokensConsumed` are cumulative BILLED throughput. Every turn resends the conversation, so the cumulative figure counts each turn\u2019s prompt again in the next turn\u2019s and is expected to dwarf the context size \u2014 that is not double-counting.',\n 'To debug a failure: find the last turn.error or tool.failed, then read upward for the user message, the turn(s), and the agent/provider/state events that led into it.',\n];\n\n/**\n * Removes all entries. Exposed for test isolation only \u2014 not part of the\n * public API.\n *\n * @internal\n */\nexport function clearMetaEventRegistry(): void {\n registry.clear();\n}\n", "import { createLogger } from '@genesislcap/foundation-logger';\n\nexport const logger = createLogger('ai-assistant');\n", "import type { InteractionContext } from '../types/interaction-context';\nimport { logger } from '../utils/logger';\n\n/**\n * A created {@link InteractionContext} plus the host-only `dispose` handle. The\n * driver keeps the handle (so it can tear the context down on resolve/evict) and\n * hands only `context` to the widget \u2014 widgets must not dispose their own context.\n *\n * @internal\n */\nexport interface InteractionContextHandle {\n readonly context: InteractionContext;\n /**\n * Run every registered `onDispose` callback once (in registration order), then\n * clear listeners. Idempotent. Called by the driver from `resolveInteraction`\n * and on driver teardown \u2014 never on element unmount.\n */\n dispose(): void;\n}\n\n/**\n * Create a live, per-interaction context (GENC-1390). Framework-agnostic: the\n * `subscribe`/`notify` pair is a plain observer set, not FAST reactivity. See\n * {@link InteractionContext} for the lifetime/semantics contract.\n *\n * @internal\n */\nexport function createInteractionContext(interactionId: string): InteractionContextHandle {\n const state: Record<string, unknown> = {};\n const onceCache = new Map<string, unknown>();\n const listeners = new Set<() => void>();\n const disposers = new Set<() => void>();\n let disposed = false;\n\n const context: InteractionContext = {\n interactionId,\n state,\n once<T>(key: string, factory: () => T): T | null {\n if (onceCache.has(key)) return onceCache.get(key) as T;\n // Interaction already ended (resolve/timeout/evict): refuse to run the factory.\n // A resource created here would leak \u2014 dispose has already run every `onDispose`\n // and won't run again. Return null so a stray late call (e.g. an async callback\n // that lands after a `timeoutMs` timeout) degrades instead of crashing or leaking.\n if (disposed) {\n logger.warn(\n `InteractionContext.once(\"${key}\") called after dispose; not creating a resource on an ended interaction.`,\n );\n return null;\n }\n const value = factory();\n onceCache.set(key, value);\n return value;\n },\n notify(): void {\n // A Set tolerates a listener unsubscribing mid-walk (matches\n // interaction-panel-session's forEach); a throwing subscriber must not stop the rest.\n for (const listener of listeners) {\n try {\n listener();\n } catch (e) {\n logger.error('InteractionContext subscriber threw during notify()', e);\n }\n }\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n onDispose(fn: () => void): void {\n // Late registration after the interaction already ended: run immediately so\n // callers never leak a resource by registering a beat too late.\n if (disposed) {\n fn();\n return;\n }\n disposers.add(fn);\n },\n };\n\n return {\n context,\n dispose(): void {\n if (disposed) return;\n disposed = true;\n for (const fn of disposers) {\n try {\n fn();\n } catch (e) {\n logger.error('InteractionContext onDispose callback threw', e);\n }\n }\n disposers.clear();\n listeners.clear();\n // Release memoised `once` values (sockets, timers, service handles) for GC \u2014 the resources\n // themselves are closed via their `onDispose`, but drop the references too.\n onceCache.clear();\n },\n };\n}\n", "import type { ChatMessage, CondensePolicy, CondenseTrigger } from '@genesislcap/foundation-ai';\n\n/**\n * Tool-context condensation: collapse stale tool payloads out of the history\n * sent to the model, while leaving stored history untouched.\n *\n * The driver owns the registry (tool handlers populate it via `condenseWhen`)\n * and the cadence (this runs before every provider call). This module owns the\n * pure application: given the registry + the current loop iteration, produce a\n * rewritten copy of the history with stale args/results replaced by stubs. Kept\n * pure (no driver/session state, no logging) so it unit-tests in isolation \u2014\n * the one-time `context.condensed` signal is delivered via an `onCondensed`\n * callback rather than reaching into the debug-event log directly.\n *\n * @packageDocumentation\n */\n\n/**\n * Below this serialized size a tool payload isn't worth condensing \u2014 the stub\n * would save little and cost a breadcrumb. A driver-level floor so the public\n * `condenseWhen` API needs no per-policy threshold field.\n */\nexport const CONDENSE_MIN_CHARS = 1000;\n\n/** Key the collapsed args are stored under \u2014 a tool-call's args must stay a Record. */\nexport const CONDENSED_ARGS_KEY = 'condensed';\n\n/**\n * Rough chars-per-token divisor for the `tokensSaved` estimate. No tokenizer is\n * available in this stack; ~4 chars/token is the usual English approximation.\n */\nconst APPROX_CHARS_PER_TOKEN = 4;\n\n/**\n * A `condenseWhen` policy registered against a tool-call id, with its age clock\n * and report-once flags. The driver holds these in a `Map<toolCallId, \u2026>`;\n * {@link applyCondensation} reads them and flips the `reported*` flags so the\n * `context.condensed` signal fires once per payload, not once per provider call.\n */\nexport interface RegisteredCondensePolicy {\n policy: CondensePolicy;\n /**\n * Monotonic model-call sequence (`modelCallSeq`) when `condenseWhen` was called\n * \u2014 the origin of the age clock. Driver-lifetime and NOT reset per turn, so age\n * is measured consistently across turn boundaries (the field name is historical;\n * it is not the per-turn loop iteration).\n */\n iteration: number;\n /** Turn (`sendMessage`) sequence when the call was made \u2014 the `turnEnd` clock. */\n turn: number;\n /** Agent-activation sequence when the call was made \u2014 the `agentEnd` clock. */\n activation: number;\n /** App-controlled phase epoch when the call was made \u2014 the `phaseEnd` clock. */\n phaseEpoch: number;\n /** `context.condensed` already emitted for the args payload (fire-once). */\n reportedArgs?: boolean;\n /** `context.condensed` already emitted for the response payload (fire-once). */\n reportedResponse?: boolean;\n /**\n * The first trigger to fire for this call, latched on the pass it fired.\n *\n * \"Fired\", not \"collapsed\": it is written during trigger resolution, before the\n * per-payload size floor is applied, so an entry whose payloads are all below the floor\n * can latch without anything ever rendering. That is deliberate and safe \u2014 both payloads\n * of a call resolve off the same clocks in the same pass, so they can never disagree\n * about which trigger fired, and a payload's size is fixed for the life of the call\n * (condensation never touches stored history), so a below-floor payload can never later\n * become a large one under a stale reason.\n *\n * Trigger resolution picks the first LISTED trigger that is *currently* true, so without\n * this it re-evaluates on every provider call and can change after the collapse: with the\n * usual `on: [{superseded}, {agentEnd}]`, a payload collapsed at `agentEnd` silently\n * re-resolves to `superseded` as soon as a newer call on the same key lands. Any stub that\n * embeds the reason (`pointer` does) is then rewritten \u2014 an in-place history mutation that\n * invalidates the prompt cache from that position a second time, for a payload that had\n * already collapsed. Latching keeps the rendered stub stable, which is sound because a\n * collapse is monotonic and never reverts, so the first trigger to fire is the correct\n * one to keep.\n */\n firedTrigger?: CondenseTrigger;\n}\n\n/**\n * The driver's live state at the moment of a provider call \u2014 the clocks every\n * trigger is evaluated against. Passed by the driver; kept as an interface so the\n * transform stays a pure function of (history, policies, clocks).\n */\nexport interface CondenseContext {\n /** Monotonic model-call sequence now \u2014 the `age` clock. */\n modelCall: number;\n /** Monotonic turn (`sendMessage`) sequence now \u2014 the `turnEnd` clock. */\n turn: number;\n /** Whether the agent activation that made a call has since ended \u2014 the `agentEnd` clock. */\n activationEnded: (activation: number) => boolean;\n /**\n * Whether a later phase epoch is current than the one a call was made in \u2014 the\n * `phaseEnd` clock. True once `endPhase()` has been called since the call.\n */\n phaseEnded: (phaseEpoch: number) => boolean;\n /**\n * Collapse in batches of this many model-calls instead of continuously. A positive\n * integer; decimals are floored and anything below `1` becomes `1`. Omit (or `1`) to\n * collapse as soon as a trigger fires, which is the historical behaviour.\n *\n * Condensation rewrites a payload *in place*, so the model-bound history is not\n * append-only and every prompt-cache entry written before the rewrite is invalidated\n * from that position on. Collapsing the moment each trigger fires therefore breaks the\n * cache on nearly every call of a re-read loop \u2014 the case condensation exists to\n * contain. Batching holds the collapse set still between boundaries so the prefix is\n * append-only in between, trading up to `batchCalls` calls' worth of extra context for\n * one cache break per batch instead of one per call.\n *\n * `agentEnd` and `phaseEnd` are exempt and still collapse as they fire: they mark a\n * discontinuity that invalidates the cached prefix anyway, so deferring them would hold\n * stale payloads longer for nothing.\n */\n batchCalls?: number;\n}\n\n/**\n * Structured detail for a `context.condensed` meta-event. The index signature\n * lets it satisfy `recordMetaEvent`'s `Record<string, unknown>` detail param\n * while the named fields stay strictly typed.\n */\nexport interface CondensedEventDetail {\n [key: string]: unknown;\n /** Tool-loop iteration the collapsed call was made on. */\n turn: number;\n toolCallId: string;\n tool: string;\n target: 'args' | 'response';\n /** Human-readable trigger, e.g. `superseded:Foo.tsx` or `age:3`. */\n trigger: string;\n /** Length of the replacement stub. */\n stubLen: number;\n /** Estimated input tokens saved this collapse (char/4 \u2014 no tokenizer in-stack). */\n tokensSaved: number;\n}\n\n/** Short human-readable reason for the stub text, per fired trigger. */\nfunction triggerReason(trigger: CondenseTrigger): string {\n switch (trigger.kind) {\n case 'age':\n return 'aged out';\n case 'turnEnd':\n return 'turn ended';\n case 'agentEnd':\n return 'agent finished';\n case 'phaseEnd':\n return 'phase ended';\n default:\n return 'superseded';\n }\n}\n\n/**\n * Framework-generated stub, shared by `pointer` and `drop`. Names the tool, the superseded key\n * (the only surviving identifier once args are elided \u2014 the model cannot otherwise tell WHICH\n * file a collapsed `vfs_write` wrote) and the original size.\n *\n * `restorable` is the ONLY difference between the two modes: `pointer` promises that re-calling\n * reproduces the content and is valid solely for idempotent tools; `drop` makes no such promise\n * and must not carry the clause. Identifying information is not what separates them \u2014 a stub too\n * bare to say what the call did is how GENC-1494 started.\n */\nfunction condenseStub(\n target: 'args' | 'response',\n tool: string,\n trigger: CondenseTrigger,\n origLen: number,\n restorable: boolean,\n /**\n * Images elided alongside the text. Reported separately because the model reads this stub as\n * fact: folding base64 bytes into the char count would tell it a 15KB render was \"~15447\n * chars\" of prose. One variable cannot be both the size FLOOR (bytes, correctly) and a\n * model-facing description (characters).\n */\n imageCount = 0,\n): string {\n const what = target === 'args' ? 'args' : 'result';\n const key = trigger.kind === 'superseded' ? ` ${trigger.by}` : '';\n const restore = restorable ? '; re-call to restore' : '';\n const images = imageCount > 0 ? ` + ${imageCount} image${imageCount === 1 ? '' : 's'}` : '';\n return `[${tool}${key} \u2014 ${what} elided, ~${origLen} chars${images} (${triggerReason(trigger)})${restore}]`;\n}\n\n/** Stable label for the `context.condensed` meta-event's `trigger` field. */\nfunction triggerLabel(trigger: CondenseTrigger): string {\n switch (trigger.kind) {\n case 'age':\n return `age:${trigger.turns}`;\n case 'superseded':\n return `superseded:${trigger.by}`;\n default:\n return trigger.kind; // 'turnEnd' | 'agentEnd' | 'phaseEnd'\n }\n}\n\nfunction estimateTokensSaved(origLen: number, stubLen: number): number {\n return Math.max(0, Math.ceil((origLen - stubLen) / APPROX_CHARS_PER_TOKEN));\n}\n\n/**\n * Whether a trigger marks a genuine discontinuity rather than firing continuously, and so is\n * exempt from batching.\n *\n * `agentEnd` advances only when the active agent's name changes (or a sub-agent completes /\n * the agent is released), which swaps the system prompt and tool definitions \u2014 those render\n * before the messages, so the cached prefix is invalidated at that point regardless. `phaseEnd`\n * is the app declaring the same kind of boundary explicitly, and falls back to `agentEnd`.\n * Deferring either to the next batch would buy no cache and only hold stale payloads longer.\n *\n * The rest fire continuously (`superseded`, `age`) or at a point where the history is otherwise\n * append-only (`turnEnd` \u2014 a new turn appends a user message, leaving the previous entry live),\n * so batching them is exactly where the cache is won.\n */\nfunction marksDiscontinuity(kind: CondenseTrigger['kind']): boolean {\n return kind === 'agentEnd' || kind === 'phaseEnd';\n}\n\n/**\n * Collapse stale tool payloads (declared via `condenseWhen`) out of the\n * model-bound history. Pure over the `history` array \u2014 it emits new message\n * objects and never mutates the input messages (mirroring the agent-masking\n * transform). It DOES, however, write two latches onto the matching `policies`\n * entry the first time a payload collapses, both because the collapse itself\n * re-runs before every provider call: the `reported*` flag (the report-once gate\n * that keeps `onCondensed` firing once per (tool call, payload)) and\n * `firedTrigger` (which pins the reason so a reason-bearing stub is rendered\n * once and never rewritten).\n *\n * Triggers (a policy may list several via `on: Trigger[]` \u2014 the FIRST to fire\n * collapses the payload; all are monotonic, so the collapse never reverts):\n * - `superseded` \u2014 among all registered calls sharing a `by` key, the LAST in\n * history order survives; every earlier one's targeted payload collapses. A\n * re-call with the same key becomes the new survivor and re-arms the rest.\n * - `age` \u2014 the result is first visible one model-call after the call, so `turns`\n * is how many model-calls may see the full result before it collapses\n * (fires when `modelCall \u2212 callModelCall > turns`): `turns: 1` is seen once,\n * then collapses. The clock is monotonic across turns.\n * - `turnEnd` \u2014 collapses once the turn (`sendMessage`) that made the call has\n * ended (fires when `turn > callTurn`): full for the rest of that request,\n * gone on every later one.\n * - `agentEnd` \u2014 collapses once the agent activation that made the call has ended\n * (a swap to another agent, or `releaseAgent`/`completeSubAgent`): kept across\n * all of the agent's turns, dropped when its flow finishes.\n * - `phaseEnd` \u2014 collapses once the app advances its phase epoch via `endPhase()`\n * after the call (a sub-`agentEnd` boundary the author declares), OR at\n * `agentEnd` as a backstop if no boundary is ever declared.\n *\n * The tool-call/result envelope is never removed (providers reject orphaned\n * calls/results) \u2014 only the args object or the result content is replaced.\n *\n * @param history - The to-model history copy to rewrite (not mutated).\n * @param policies - The driver's registry, keyed by tool-call id. Its entries'\n * `reported*` flags are flipped as payloads first collapse.\n * @param ctx - The driver's live clocks (model-call / turn / agent-activation).\n * @param onCondensed - Invoked once per payload at its full\u2192stub transition.\n */\nexport function applyCondensation(\n history: ChatMessage[],\n policies: Map<string, RegisteredCondensePolicy>,\n ctx: CondenseContext,\n onCondensed: (detail: CondensedEventDetail) => void,\n): ChatMessage[] {\n if (policies.size === 0) return history;\n\n const triggersOf = (entry: RegisteredCondensePolicy): CondenseTrigger[] =>\n Array.isArray(entry.policy.on) ? entry.policy.on : [entry.policy.on];\n\n // One pass: resolve supersession survivors and a toolCallId \u2192 tool-name\n // lookup. For each `superseded` key the LAST call in history order survives.\n // The name lookup lets a tool message (which carries only an id) name its tool\n // in stubs and events.\n // Batch boundary: the collapse set is resolved as of this model-call and stays put\n // until the next boundary, so the prefix is append-only in between. `batchCalls` of 1\n // (the default) makes this `ctx.modelCall` \u2014 i.e. no batching.\n const batchCalls = Math.max(1, Math.floor(ctx.batchCalls ?? 1));\n const asOf =\n batchCalls === 1 ? ctx.modelCall : Math.floor(ctx.modelCall / batchCalls) * batchCalls;\n // A call made after the boundary is invisible to this pass in BOTH directions: it\n // cannot supersede an older call (which would collapse the older payload early), and\n // it cannot itself collapse (which would elide the very result just fetched). Unbatched,\n // the boundary is the live clock and this gate is off entirely \u2014 a call registered on\n // the current model-call is still eligible, as it always was.\n const withinBatch = (entry: RegisteredCondensePolicy): boolean =>\n batchCalls === 1 || entry.iteration <= asOf;\n\n const latestByKey = new Map<string, string>();\n const nameById = new Map<string, string>();\n for (const msg of history) {\n if (!msg.toolCalls?.length) continue;\n for (const tc of msg.toolCalls) {\n nameById.set(tc.id, tc.name);\n const entry = policies.get(tc.id);\n if (!entry || !withinBatch(entry)) continue;\n for (const t of triggersOf(entry)) {\n if (t.kind === 'superseded') latestByKey.set(t.by, tc.id);\n }\n }\n }\n\n const triggerFires = (\n toolCallId: string,\n entry: RegisteredCondensePolicy,\n trig: CondenseTrigger,\n ): boolean => {\n switch (trig.kind) {\n // Result first visible one model-call after the call, so collapse one call\n // past the last allowed view: turns:1 \u2192 seen once, then gone. Monotonic\n // clock, so this holds across turn boundaries too.\n case 'age':\n return asOf - entry.iteration > trig.turns;\n case 'turnEnd':\n return ctx.turn > entry.turn;\n case 'agentEnd':\n return ctx.activationEnded(entry.activation);\n // Fires when the app advanced the phase epoch since the call \u2014 OR, as a\n // backstop, when the whole activation has ended, so a phase boundary that\n // is never declared still collapses at `agentEnd` rather than never.\n case 'phaseEnd':\n return ctx.phaseEnded(entry.phaseEpoch) || ctx.activationEnded(entry.activation);\n default:\n return latestByKey.get(trig.by) !== toolCallId; // superseded by a newer call\n }\n };\n\n // The first listed trigger that fires \u2014 drives the collapse, the stub reason,\n // and the event label. `undefined` means the payload stays full.\n //\n // Latched on first fire (see `firedTrigger`): re-resolving on every pass lets the reason\n // change under a payload that has already collapsed, which rewrites any reason-bearing stub\n // and costs a second cache break. Both payloads of a call share the latch \u2014 they are\n // evaluated in the same pass off the same clocks, so they never disagree about which\n // trigger fired; only the size floor decides whether each one renders.\n const firstFired = (\n toolCallId: string,\n entry: RegisteredCondensePolicy,\n ): CondenseTrigger | undefined => {\n if (entry.firedTrigger) return entry.firedTrigger;\n const fired = triggersOf(entry).find(\n (t) =>\n (marksDiscontinuity(t.kind) || withinBatch(entry)) && triggerFires(toolCallId, entry, t),\n );\n if (fired) entry.firedTrigger = fired;\n return fired;\n };\n\n return history.map((msg) => {\n // Tool-call ARGS live on the assistant message.\n if (msg.toolCalls?.length) {\n let changed = false;\n const toolCalls = msg.toolCalls.map((tc) => {\n const entry = policies.get(tc.id);\n if (!entry?.policy.args) return tc;\n const fired = firstFired(tc.id, entry);\n if (!fired) return tc;\n const origLen = JSON.stringify(tc.args ?? {}).length;\n if (origLen < CONDENSE_MIN_CHARS) return tc;\n changed = true;\n const result = entry.policy.args;\n // Args must stay a Record, so every mode stashes its stub under a single key.\n // Spread `tc` so providerMetadata (e.g. the Gemini reasoning signature that must\n // round-trip) and UI fields survive.\n //\n // GENC-1494: `drop` used to collapse args to a bare `{}`. That is indistinguishable\n // from a call the model made with NO arguments, and the model reads its own history\n // as fact: a ui-builder run saw its elided `vfs_write` calls as `vfs_write {}` beside\n // a live `{\"status\":\"buffered\",\"path\":\"\u2026\"}` result, concluded it was calling the tool\n // without content, and burned two hours re-writing files that were already correct.\n // A bare marker is not enough either \u2014 it still fails to say WHICH file the call\n // wrote, since `path` went with the args. So `drop` renders the same identifying stub\n // as `pointer`, minus only the restore promise it cannot honour.\n const args: Record<string, unknown> = {\n [CONDENSED_ARGS_KEY]:\n result === 'drop' || result === 'pointer'\n ? condenseStub('args', tc.name, fired, origLen, result === 'pointer')\n : result.replaceWith,\n };\n if (!entry.reportedArgs) {\n entry.reportedArgs = true;\n const stubLen = JSON.stringify(args).length;\n onCondensed({\n turn: entry.iteration,\n toolCallId: tc.id,\n tool: tc.name,\n target: 'args',\n trigger: triggerLabel(fired),\n stubLen,\n tokensSaved: estimateTokensSaved(origLen, stubLen),\n });\n }\n return { ...tc, args };\n });\n return changed ? { ...msg, toolCalls } : msg;\n }\n\n // The tool RESULT lives on the tool message.\n if (msg.toolResult) {\n const entry = policies.get(msg.toolResult.toolCallId);\n // Defensive `?? 0` for restored/malformed history \u2014 `content` is typed\n // `string`, but a 0-length payload is simply below the floor and skipped.\n //\n // Attachment bytes COUNT toward the floor (GENC-1508). An image-bearing result is\n // typically a few words of text \u2014 \"rendered the mockup\" \u2014 plus ~15KB of base64, so\n // sizing on `content` alone leaves it permanently under CONDENSE_MIN_CHARS and the\n // image rides every subsequent turn. That is the exact payload condensation exists\n // to shed, so it must be what is measured.\n const textLen = msg.toolResult.content?.length ?? 0;\n const images = msg.toolResult.attachments ?? [];\n // Bytes gate the FLOOR (an image result is a few words of text plus ~15KB of base64, so\n // sizing on text alone would never condense it); `textLen` and the image count are what\n // the model is told. See condenseStub.\n const origLen = textLen + images.reduce((n, att) => n + (att.data?.length ?? 0), 0);\n const fired = entry?.policy.response\n ? firstFired(msg.toolResult.toolCallId, entry)\n : undefined;\n if (entry && fired && origLen >= CONDENSE_MIN_CHARS) {\n const tool = nameById.get(msg.toolResult.toolCallId) ?? msg.toolResult.toolCallId;\n const result = entry.policy.response!; // `fired` is only set when response is declared\n // Kept non-empty \u2014 Anthropic rejects empty tool_result content.\n const content =\n result === 'drop' || result === 'pointer'\n ? condenseStub('response', tool, fired, textLen, result === 'pointer', images.length)\n : result.replaceWith;\n if (!entry.reportedResponse) {\n entry.reportedResponse = true;\n onCondensed({\n turn: entry.iteration,\n toolCallId: msg.toolResult.toolCallId,\n tool,\n target: 'response',\n trigger: triggerLabel(fired),\n stubLen: content.length,\n tokensSaved: estimateTokensSaved(origLen, content.length),\n });\n }\n // `attachments` is dropped, not spread through: the stub says the payload was\n // elided, and leaving the images attached would make that a lie AND shed none of\n // the bytes the condensation was performed to shed.\n const { attachments: _elided, ...restOfResult } = msg.toolResult;\n return { ...msg, toolResult: { ...restOfResult, content } };\n }\n }\n\n return msg;\n });\n}\n", "import type { ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * Masks the tool-specific payload of a single message \u2014 clears tool call args\n * and replaces tool result content with a placeholder. Used when passing history\n * to an agent that should not see another agent's implementation detail.\n */\nfunction maskToolPayload(msg: ChatMessage): ChatMessage {\n if (msg.toolCalls?.length) {\n return { ...msg, toolCalls: msg.toolCalls.map((tc) => ({ ...tc, args: {} })) };\n }\n if (msg.toolResult) {\n // `attachments` is dropped, not spread through. Masking exists to keep another agent's\n // payload out of this one's context, and an image is the largest payload there is \u2014 spreading\n // it would stub the prose while still shipping the render, defeating the mask for exactly the\n // case it matters most. `applyHistoryCap` masks everything past the cap for sub-agent context,\n // so without this every older image rides every sub-agent turn under an \"omitted\" label.\n const { attachments: _masked, ...restOfResult } = msg.toolResult;\n return {\n ...msg,\n toolResult: { ...restOfResult, content: \"[other agent's tool result omitted]\" },\n };\n }\n return msg;\n}\n\n/**\n * Prepares history for the LLM only: masks tool call args and results from other\n * agents so the active specialist is not confused by tools it does not have.\n * Canonical history in `ChatDriver` stays unmasked for UI and logging.\n */\nexport function transformHistoryForAgent(history: ChatMessage[], agentName: string): ChatMessage[] {\n return history.map((msg) => {\n if (!msg.agentName || msg.agentName === agentName) return msg;\n return maskToolPayload(msg);\n });\n}\n\n/**\n * Applies a history cap for sub-agent context: the last `cap` messages are passed\n * verbatim; older messages have their tool payloads masked.\n */\nexport function applyHistoryCap(history: readonly ChatMessage[], cap: number): ChatMessage[] {\n const cutoff = history.length - cap;\n return history.map((msg, i) => (i < cutoff ? maskToolPayload(msg) : msg));\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Compaction (GENC-1351 \u00A75.7) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Recent messages kept verbatim when compacting; everything earlier is summarized. */\nexport const COMPACT_KEEP_RECENT_MESSAGES = 4;\n\n/** Don't bother compacting unless at least this many messages would be summarized. */\nexport const COMPACT_MIN_MESSAGES_TO_COMPACT = 4;\n\n/**\n * Index at which the verbatim tail begins \u2014 everything before it gets summarized.\n * The tail starts on a clean turn boundary (a `user` message): a user message\n * never appears between a `tool_use` and its `tool_result`, so cutting there\n * guarantees the summarized region is tool-pair-balanced (compaction only runs\n * when idle, so history is turn-complete). Returns `null` when there is nothing\n * worth compacting (too short, or no earlier user boundary) \u2014 e.g. a freshly\n * restored session whose only user turn is the current one.\n */\nexport function findCompactionCut(history: readonly ChatMessage[]): number | null {\n if (history.length < COMPACT_KEEP_RECENT_MESSAGES + COMPACT_MIN_MESSAGES_TO_COMPACT) {\n return null;\n }\n const target = history.length - COMPACT_KEEP_RECENT_MESSAGES;\n for (let i = target; i > 0; i -= 1) {\n if (history[i].role === 'user') {\n return i >= COMPACT_MIN_MESSAGES_TO_COMPACT ? i : null;\n }\n }\n return null;\n}\n\n/** One-line rendering of a message for the summarizer transcript. */\nfunction renderMessageForSummary(m: ChatMessage): string {\n switch (m.role) {\n case 'compacted-summary':\n return `[Earlier summary] ${m.content}`;\n case 'user':\n return m.content ? `User: ${m.content}` : '';\n case 'assistant': {\n // Reasoning (\"Thinking\") and narration (\"Working\") are display-only assistant splits\n // (GENC-1410) with no tool calls of their own \u2014 fold them into the summary too, labelled\n // the same as the UI so the summarizer knows they were internal, not a final answer.\n if (m.category === 'reasoning') {\n return m.content ? `Thinking: ${m.content}` : '';\n }\n if (m.category === 'narration') {\n return m.content ? `Working: ${m.content}` : '';\n }\n if (m.toolCalls?.length) {\n const calls = m.toolCalls.map((t) => t.name).join(', ');\n return m.content\n ? `Assistant: ${m.content} (called: ${calls})`\n : `Assistant called: ${calls}`;\n }\n return m.content ? `Assistant: ${m.content}` : '';\n }\n case 'tool':\n return m.toolResult ? `Tool result: ${m.toolResult.content}` : '';\n default:\n return ''; // system-event / synthetic-user \u2014 not part of the model transcript\n }\n}\n\n/**\n * Build the one-shot summarizer prompt for a run of older messages (used with\n * `AIProvider.prompt`). Mirrors the `<conversation_history>` block convention\n * that suggestions use. Any existing `compacted-summary` at the head is folded\n * in (rendered as prior-summary context), so rolling re-compaction produces one\n * combined summary.\n */\nexport function buildCompactionSummaryPrompt(toCompact: readonly ChatMessage[]): {\n systemPrompt: string;\n userMessage: string;\n} {\n const transcript = toCompact.map(renderMessageForSummary).filter(Boolean).join('\\n');\n const systemPrompt =\n 'You compress a conversation transcript into a concise summary that lets an AI ' +\n 'assistant continue the conversation seamlessly. Preserve key facts, decisions, ' +\n 'what the user wants, entity names and IDs, and any unresolved threads. Write ' +\n 'plain prose. Never roleplay or continue the conversation.';\n const userMessage =\n `<conversation_history>\\n${transcript}\\n</conversation_history>\\n\\n` +\n 'Summarize the conversation above so it can be dropped from context while ' +\n 'preserving everything needed to continue. Output only the summary prose.';\n return { systemPrompt, userMessage };\n}\n\n/**\n * Normalize history for a provider request (GENC-1351 \u00A75.7): translate each\n * `compacted-summary` message into a `user` message that wraps its summary in a\n * `<conversation_summary>` block, so the raw display-only role never reaches a\n * transport. Other roles pass through untouched. Pure \u2014 returns a new array.\n *\n * Applied at the request-build chokepoint *before* per-agent masking, so the\n * guarantee holds for every provider/transport regardless of any optional\n * per-agent history transform.\n */\nexport function normalizeForProvider(history: readonly ChatMessage[]): ChatMessage[] {\n return history.map((m) => {\n if (m.role !== 'compacted-summary') return m;\n return {\n ...m,\n role: 'user',\n content:\n `<conversation_summary>\\n${m.content}\\n</conversation_summary>\\n\\n` +\n 'The above summarizes earlier parts of this conversation that were compacted. ' +\n 'Continue naturally from it.',\n compaction: undefined,\n };\n });\n}\n\n/** Human-facing divider label for a `compacted-summary` message. */\nexport function compactionDividerLabel(m: ChatMessage): string {\n const n = m.compaction?.compactedCount ?? 0;\n return `Compacted ${n} earlier message${n === 1 ? '' : 's'}`;\n}\n", "import type { AggregateUsage, ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * Zeroed {@link AggregateUsage}. A factory, not a shared const, because callers\n * accumulate into the returned object.\n *\n * @beta\n */\nexport function emptyUsage(): AggregateUsage {\n return {\n costUsd: 0,\n uncachedInputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n outputTokens: 0,\n };\n}\n\n/**\n * Total tokens processed \u2014 the four buckets added up. Safe to sum because the\n * buckets are disjoint (see {@link AggregateUsage}); the equivalent sum over\n * per-message fields would double-count the prompt.\n *\n * Bear in mind what this number is: because every turn resends the conversation,\n * a turn's prompt is counted again in the next turn's. It is billed throughput,\n * NOT the count of distinct tokens in the conversation, so it grows\n * super-linearly with turn count and is expected to dwarf the context size.\n *\n * @beta\n */\nexport function totalTokens(usage: AggregateUsage): number {\n return (\n usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens + usage.outputTokens\n );\n}\n\n/**\n * `a + b`, per bucket, as a new object.\n *\n * Used to lay a row's banked (pre-transcript) spend over what the live transcript\n * proves. Pure rather than in-place because both operands are live state a caller\n * must not mutate.\n *\n * @beta\n */\nexport function addUsage(a: AggregateUsage, b: AggregateUsage): AggregateUsage {\n return {\n costUsd: a.costUsd + b.costUsd,\n uncachedInputTokens: a.uncachedInputTokens + b.uncachedInputTokens,\n cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,\n cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,\n outputTokens: a.outputTokens + b.outputTokens,\n };\n}\n\n/**\n * The four buckets plus USD for ONE message \u2014 the per-message fields projected into\n * the disjoint, addable shape, or `undefined` when the message reports no usage at\n * all (a user turn, a display-only reasoning/narration split, a provider that\n * reports none).\n *\n * Shallow by design: it does NOT recurse into `toolCalls[].subAgentTrace` and does\n * NOT count `compaction.rolledUpUsage`, so it answers \"what did this one request\n * cost\" rather than \"what did this message and everything under it cost\". Use\n * {@link sumUsage} for the latter \u2014 passing a whole transcript through this one\n * message at a time would silently drop both.\n *\n * `costUsd` folds in `externalCostUsd` (non-LLM spend a widget reported), matching\n * `sumUsage`. It is `0` when the provider priced nothing, which is NOT a claim that\n * the call was free \u2014 see {@link AggregateUsage}; `UsageRow.costUsd` is the\n * shape that keeps unpriced distinguishable, and is the right tool for a ledger.\n *\n * @beta\n */\nexport function messageUsage(m: ChatMessage): AggregateUsage | undefined {\n if (\n m.cost == null &&\n m.externalCostUsd == null &&\n m.inputTokens == null &&\n m.outputTokens == null &&\n m.cacheReadTokens == null &&\n m.cacheWriteTokens == null\n ) {\n return undefined;\n }\n const cacheReadTokens = m.cacheReadTokens ?? 0;\n const cacheWriteTokens = m.cacheWriteTokens ?? 0;\n return {\n costUsd: (m.cost ?? 0) + (m.externalCostUsd ?? 0),\n // The uncached REMAINDER, clamped \u2014 the same arithmetic `accumulate` below applies,\n // for the same reasons. The two are deliberately separate implementations (that walk\n // mutates one accumulator rather than allocating per message) and must agree;\n // `sum-usage.test.ts` pins them together.\n uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),\n cacheReadTokens,\n cacheWriteTokens,\n outputTokens: m.outputTokens ?? 0,\n };\n}\n\n/**\n * Sum cost and per-bucket token usage across a message list.\n *\n * One walk produces everything a usage display needs, replacing separate cost and\n * token passes over the same (potentially deep) transcript. Recurses into each\n * tool call's `subAgentTrace`, so LLM work a sub-agent did \u2014 possibly on another\n * provider at other rates \u2014 lands in the total; the driver embeds a whole\n * sub-agent conversation in the parent's tool result, so this is the only place\n * that spend is visible.\n *\n * Splitting the prompt into buckets is the point: `cost` already has the cache\n * discount applied, but a single token total cannot show that a session was cheap\n * because most of its prompt was a cache hit. The three input buckets are derived\n * from the per-message fields, where `inputTokens` is the whole prompt and the\n * cache fields break it down \u2014 so uncached input is the remainder, never an\n * addition.\n *\n * Also counts `compaction.rolledUpUsage`: compaction destroys the messages it\n * summarises, and without their banked usage every total re-derived from the\n * transcript would drop by whatever those turns had already spent.\n *\n * Returns a zeroed total when no message carries usage \u2014 providers that report\n * none (e.g. Chrome built-in) are skipped silently rather than guessed at.\n *\n * @remarks\n * This sums the WHOLE array, which is the right answer only when the array is the\n * whole of the work being billed. A driver whose conversation **continues across\n * rounds** opens its history with turns an earlier round already paid for, so\n * summing it again bills them twice \u2014 and the session total then grows\n * quadratically in the number of rounds while every individual figure in it stays\n * correct. Nothing about the result looks wrong, which is why it is called out\n * here rather than left to the caller to notice.\n *\n * Do NOT solve this with a \"sum from this message onwards\" marker. Compaction\n * *replaces* the messages it summarises \u2014 and compaction is one of this function's\n * own call sites \u2014 so the marker message can be absent from history by the time\n * the sum runs, leaving the caller to either fail or silently sum everything,\n * which is the double-count the marker was meant to prevent.\n *\n * Instead hold a **banked baseline**: spend that predates the current transcript,\n * carried as a value, with `usage = banked + live` composed via {@link addUsage}.\n * `resolveBankedUsage` in `utils/cost-session-history.ts` is the worked form, and\n * the shape of its signature is the load-bearing part. It separates three cases:\n *\n * 1. no prior record \u2014 a genuine first round, so nothing is banked;\n * 2. prior record, and the live transcript already accounts for it (a restored\n * session) \u2014 carry the prior record's own banked figure forward;\n * 3. prior record, and the transcript starts empty \u2014 bank the prior record's\n * whole total, because nothing in the transcript can re-derive it.\n *\n * Case 1 and case 3 take the same arithmetic and mean opposite things, so the\n * prior record must be a **required** input with no zero-defaulting path: a\n * caller who carries a transcript and forgets its baseline reports the entire\n * prior conversation as this round's spend. Distinguishing 2 from 3 is a separate\n * decision, and getting it wrong is destructive in the other direction \u2014 it\n * rewrites a total down to the current page-load and drops earlier spend.\n *\n * @beta\n */\nexport function sumUsage(messages: readonly ChatMessage[]): AggregateUsage {\n const total = emptyUsage();\n accumulate(messages, total);\n return total;\n}\n\n/** Add `from` into `into`, in place. */\nfunction addInto(into: AggregateUsage, from: AggregateUsage): void {\n into.costUsd += from.costUsd;\n into.uncachedInputTokens += from.uncachedInputTokens;\n into.cacheReadTokens += from.cacheReadTokens;\n into.cacheWriteTokens += from.cacheWriteTokens;\n into.outputTokens += from.outputTokens;\n}\n\n/**\n * Walk `messages`, accumulating into `into`. Mutates a single accumulator rather\n * than merging returned objects \u2014 this runs on every transcript change, so the\n * per-message allocation is worth avoiding.\n */\nfunction accumulate(messages: readonly ChatMessage[], into: AggregateUsage): void {\n for (const m of messages) {\n // Provider/LLM cost plus any non-LLM cost a widget reported for its own\n // external service calls. Both are real spend on this session.\n if (m.cost != null) into.costUsd += m.cost;\n if (m.externalCostUsd != null) into.costUsd += m.externalCostUsd;\n\n const cacheRead = m.cacheReadTokens ?? 0;\n const cacheWrite = m.cacheWriteTokens ?? 0;\n into.cacheReadTokens += cacheRead;\n into.cacheWriteTokens += cacheWrite;\n // The uncached remainder of the prompt. Clamped at zero so malformed or\n // hand-edited history whose buckets exceed the prompt total can't drive the\n // session total negative \u2014 a wrong-but-plausible number is worse than a\n // conservative one here, since this feeds a cost display.\n into.uncachedInputTokens += Math.max(0, (m.inputTokens ?? 0) - cacheRead - cacheWrite);\n into.outputTokens += m.outputTokens ?? 0;\n\n // Spend banked by a compaction on this summary's behalf. NOTE: deliberately\n // not `compaction.tokensBefore` \u2014 that is a one-turn context-window reading,\n // not cumulative spend, and counting it here would inflate the total.\n const rolled = m.compaction?.rolledUpUsage;\n if (rolled) addInto(into, rolled);\n\n for (const tc of m.toolCalls ?? []) {\n if (tc.subAgentTrace) accumulate(tc.subAgentTrace, into);\n }\n }\n}\n", "import type { ChatToolDefinition, ChatToolHandlers } from '@genesislcap/foundation-ai';\n\n/**\n * Symbol used to attach ToolFold metadata to a facade handler function.\n * The ChatDriver inspects this to detect fold facades at runtime.\n *\n * @internal\n */\nexport const TOOL_FOLD_SYMBOL = Symbol('toolFold');\n\n/**\n * Internal metadata for a tool fold. Attached to the facade handler via TOOL_FOLD_SYMBOL.\n *\n * @internal\n */\nexport interface ToolFold {\n /** Facade tool name. */\n name: string;\n /** Description shown to the model. */\n description: string;\n /** Optional guidance injected in the fold-open response. */\n usageNotes?: string;\n /** Tool definitions inside this fold. */\n tools: ChatToolDefinition[];\n /** Handlers for the inner tools (keyed by tool name). */\n handlers: ChatToolHandlers;\n /**\n * When true (default), all other tools are removed when this fold opens \u2014\n * the model can only see this fold's tools until it closes.\n * When false, sibling tools remain alongside the inner tools.\n */\n exclusive: boolean;\n}\n\n/**\n * The value returned by `createToolFold`.\n *\n * @beta\n */\nexport interface ToolFoldResult {\n /**\n * The facade tool definition. Add this to your agent's `toolDefinitions`.\n * It is a regular `ChatToolDefinition` with an empty parameter schema.\n */\n definition: ChatToolDefinition;\n /**\n * The facade handler \u2014 a single-entry map keyed by the fold name.\n * Spread this into your agent's `toolHandlers`.\n * Inner tool handlers are NOT included here \u2014 they are encapsulated inside\n * the fold metadata and installed by the driver only when the fold opens.\n */\n handler: ChatToolHandlers;\n}\n\n/**\n * Creates a tool fold \u2014 a facade that hides a group of related tools behind a single\n * named entry, revealing them progressively when the model invokes the facade.\n *\n * The `tools` and `handlers` parameters accept the exact same types as `AgentConfig.toolDefinitions`\n * and `AgentConfig.toolHandlers`, so existing tool creation functions can be passed in unchanged.\n *\n * @example\n * ```typescript\n * const tradingTools = createToolFold({\n * name: 'trading_tools',\n * tools: createTradesToolDefinitions(),\n * handlers: createTradesToolHandlers(connect),\n * });\n *\n * const agent: AgentConfig = {\n * name: 'Trades',\n * systemPrompt: '...',\n * toolDefinitions: [getCurrentDateDef, tradingTools.definition],\n * toolHandlers: { get_current_date: handler, ...tradingTools.handler },\n * };\n * ```\n *\n * @example Nesting folds\n * ```typescript\n * const insertFold = createToolFold({\n * name: 'trade_insertion',\n * tools: [validateDef, insertDef],\n * handlers: { validate_trade: vHandler, insert_trade: iHandler },\n * });\n *\n * const tradingFold = createToolFold({\n * name: 'trading_tools',\n * tools: [searchDef, insertFold.definition],\n * handlers: { search_trades: sHandler, ...insertFold.handler },\n * });\n * ```\n *\n * @beta\n */\nexport function createToolFold(config: {\n /** Facade tool name \u2014 used as the tool name the model calls to open this fold. */\n name: string;\n /**\n * Description shown to the model for the facade tool.\n * If omitted, auto-generated from the inner tool names:\n * \"Contains: tool_a, tool_b. Invoke to access these tools.\"\n */\n description?: string;\n /**\n * Optional usage guidance injected into the fold-open response message.\n * Not included in the facade description \u2014 only visible once the fold is open.\n */\n usageNotes?: string;\n /** Inner tool definitions. Same type as `AgentConfig.toolDefinitions`. */\n tools: ChatToolDefinition[];\n /** Inner tool handlers. Same type as `AgentConfig.toolHandlers`. */\n handlers: ChatToolHandlers;\n /**\n * When true (default), all other tools are removed when this fold opens.\n * When false, sibling tools remain available alongside the inner tools.\n */\n exclusive?: boolean;\n}): ToolFoldResult {\n const description =\n config.description ??\n `Contains: ${config.tools.map((t) => t.name).join(', ')}. Invoke to access these tools.`;\n\n const fold: ToolFold = {\n name: config.name,\n description,\n usageNotes: config.usageNotes,\n tools: config.tools,\n handlers: config.handlers,\n exclusive: config.exclusive ?? true,\n };\n\n const definition: ChatToolDefinition = {\n name: config.name,\n description,\n parameters: { type: 'object', properties: {} },\n };\n\n // The facade handler body is never actually called \u2014 the driver intercepts it\n // via TOOL_FOLD_SYMBOL before dispatch. The body is a no-op fallback.\n const facadeHandler = async (): Promise<string> => `Fold: ${config.name}`;\n (facadeHandler as any)[TOOL_FOLD_SYMBOL] = fold;\n\n return {\n definition,\n handler: {\n [config.name]: facadeHandler,\n },\n };\n}\n\n/**\n * A tool entry in the expanded debug tree.\n * Folds are represented as nodes with a `tools` array; regular tools have none.\n *\n * @beta\n */\nexport interface ToolTreeNode extends ChatToolDefinition {\n /** Present when this tool is a fold \u2014 contains its inner tools recursively expanded. */\n tools?: ToolTreeNode[];\n}\n\n/**\n * Expands a flat list of tool definitions into a nested tree by resolving fold\n * metadata from the corresponding handlers. Use this for debug output so the\n * full tool hierarchy is visible rather than just the top-level facade names.\n *\n * @beta\n */\nexport function expandToolTree(\n definitions: ChatToolDefinition[],\n handlers: ChatToolHandlers,\n): ToolTreeNode[] {\n return definitions.map((def) => {\n const handler = handlers[def.name];\n const fold: ToolFold | undefined = handler ? (handler as any)[TOOL_FOLD_SYMBOL] : undefined;\n if (fold) {\n return { ...def, tools: expandToolTree(fold.tools, fold.handlers) };\n }\n return { ...def };\n });\n}\n", "import type {\n AggregateUsage,\n AIProvider,\n AIProviderRegistry,\n AIProviderType,\n CachePolicy,\n ChatAttachment,\n ChatDriverResult,\n ChatFallback,\n ChatImageAttachment,\n ChatMessage,\n ChatRequestOptions,\n ChatThinkingPolicy,\n ChatToolCall,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n CondensePolicy,\n CondenseTrigger,\n InteractionRequestOptions,\n InteractionResult,\n SubAgentFailureReason,\n SubAgentRequestOptions,\n TurnFailureReason,\n} from '@genesislcap/foundation-ai';\nimport {\n BudgetExhaustedError,\n DEFAULT_BUDGET_EXHAUSTED_MESSAGE,\n DEFAULT_PROVIDER_REFUSED_MESSAGE,\n ProviderRefusedError,\n isObservableAIProviderRegistry,\n MalformedFunctionCallError,\n ResponseTruncatedError,\n vendorTypeOfLabel,\n} from '@genesislcap/foundation-ai';\nimport { type ActivityBus, NOOP_ACTIVITY_BUS } from '../../channel/ai-activity-bus';\nimport type {\n AgentConfig,\n CachePolicyInput,\n ProviderInput,\n ResponseSchemaInput,\n SystemPromptContext,\n SystemPromptInput,\n TailContextInput,\n TemperatureInput,\n ThinkingPolicyInput,\n ToolChoiceInput,\n ToolDefinitionsInput,\n ToolHandlersInput,\n UnresolvedToolInput,\n} from '../../config/config';\nimport { resolveChatProvider } from '../../config/validate-providers';\nimport {\n clearSession,\n getMetaEvents,\n type MetaEvent,\n mergeMetaEvents,\n type MetaEventType,\n recordMetaEvent,\n recordTurnError,\n recordTurnRetry,\n} from '../../state/debug-event-log';\nimport {\n createInteractionContext,\n type InteractionContextHandle,\n} from '../../state/interaction-context';\nimport type { DiagnosticEntry } from '../../state/persistence/diagnostics';\nimport type { InteractionContext } from '../../types/interaction-context';\nimport { applyCondensation, type RegisteredCondensePolicy } from '../../utils/condense-history';\nimport {\n applyHistoryCap,\n buildCompactionSummaryPrompt,\n findCompactionCut,\n normalizeForProvider,\n} from '../../utils/history-transform';\nimport { logger } from '../../utils/logger';\nimport { messageUsage, sumUsage } from '../../utils/sum-usage';\nimport { TOOL_FOLD_SYMBOL, type ToolFold } from '../../utils/tool-fold';\nimport type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';\n\n/**\n * The `budget` payload carried on a `'budget-exhausted'` {@link ChatDriverResult}.\n * Derived from the type rather than restated so the two cannot drift.\n */\ntype BudgetDetail = NonNullable<Extract<ChatDriverResult, { reason: 'done' }>['budget']>;\n/** The `providerRefused` payload on a `'provider-refused'` {@link ChatDriverResult} (GENC-1506). */\ntype ProviderRefusedDetail = NonNullable<\n Extract<ChatDriverResult, { reason: 'done' }>['providerRefused']\n>;\n\n/**\n * Lift the reportable facts off a {@link BudgetExhaustedError}, or `undefined`\n * when it carries none.\n *\n * \"None\" means **no figures AND no attributable vendor** \u2014 not merely no\n * figures. Dropping the whole object on a figure-less 402 also dropped\n * `vendorLabel`, which is the authoritative attribution source, and left the\n * element's latch falling back to the driver's last-resolved provider, i.e. the\n * PREVIOUS turn's vendor. A turn-1 Gemini call followed by a turn-2 classifier\n * refused by Anthropic with a figure-less 402 then walled *Gemini* and advised\n * switching to the vendor that had actually run out. Three live shapes reach\n * here with no figures \u2014 a bare gateway 402, a code-only body, and the framed\n * err frame whose figures are `null` (which the proxy now prefers over a\n * misleading `0`, so this path is getting more common, not less).\n *\n * The figures alone still decide whether banner copy is composed \u2014 see\n * `formatBlockedReason`, which returns `undefined` for a figure-less budget so a\n * host-set explanation survives the latch.\n */\n/**\n * The images on a tool handler's return, or `undefined` if it did not return any.\n *\n * Deliberately strict: `attachments` must be a non-empty array in which EVERY entry carries\n * `kind: 'image'`. A handler returning an ordinary object that happens to have an\n * `attachments` key therefore still JSON-stringifies exactly as it did before, and a\n * half-populated array fails the check rather than silently sending some of the images.\n */\nconst toolResultImages = (result: unknown): ChatImageAttachment[] | undefined => {\n if (!result || typeof result !== 'object') return undefined;\n const candidate = (result as { attachments?: unknown }).attachments;\n if (!Array.isArray(candidate) || candidate.length === 0) return undefined;\n const allImages = candidate.every(\n (att) => !!att && typeof att === 'object' && (att as { kind?: unknown }).kind === 'image',\n );\n return allImages ? (candidate as ChatImageAttachment[]) : undefined;\n};\n\n/**\n * Lift the reportable facts off a {@link ProviderRefusedError} (GENC-1506).\n *\n * Unlike `budgetDetailOf` this is total \u2014 it always returns a detail. The budget version can answer\n * `undefined` because its payload is figures the proxy may not have sent; here every field either\n * comes from the transport that was refused (`vendorLabel`, `kind`) or is plainly optional, so there\n * is no \"nothing worth reporting\" case to model.\n */\nconst providerRefusedDetailOf = (e: ProviderRefusedError): ProviderRefusedDetail => ({\n vendorLabel: e.vendorLabel,\n kind: e.kind,\n ...(e.upstreamStatus != null ? { upstreamStatus: e.upstreamStatus } : {}),\n ...(e.upstreamType ? { upstreamType: e.upstreamType } : {}),\n});\n\nconst budgetDetailOf = (e: BudgetExhaustedError): BudgetDetail | undefined => {\n // The typed vendor is derived from the LABEL, not from `lastResolvedProvider`:\n // the label comes from the transport that was actually refused, whereas the\n // last-resolved provider is stale on the classification seam (an orchestrated\n // turn classifies against the registry default, which this driver may never\n // have resolved). The proxy's own `vendor` is the fallback for a transport\n // whose static label no vendor claims (a multiplexing or white-labelled\n // gateway). Omitted rather than set to `undefined` when neither resolves, so\n // \"we know the vendor\" stays testable by presence alone.\n const vendor = vendorTypeOfLabel(e.vendorLabel) ?? vendorTypeOfLabel(e.serverVendor);\n if (e.budgetUsd == null && e.spentUsd == null && !vendor) return undefined;\n return {\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n vendorLabel: e.vendorLabel,\n ...(vendor ? { vendor } : {}),\n // Server-known truth the client cannot re-derive, so it rides all the way to\n // the banner rather than being re-guessed there from registry membership.\n ...(e.otherVendorAvailable != null ? { otherVendorAvailable: e.otherVendorAvailable } : {}),\n };\n};\n\nconst DEFAULT_MAX_TOOL_ITERATIONS = 50;\nconst DEFAULT_MAX_FOLD_OPERATIONS = 5;\n// TODO: dedup system prompts in-memory to allow raising this cap much higher.\n// Each TurnSnapshot stores the full resolved `systemPrompt`, so the buffer's\n// memory cost scales with cap \u00D7 prompt size \u2014 a stable agent repeats a multi-KB\n// prompt every turn. `getDebugLog` already dedups identical consecutive prompts\n// at export time (`<repeated \u2014 identical to turn N>`); applying the same dedup\n// at capture time (store the prompt only when it changes, back-reference\n// otherwise) would make snapshots nearly as cheap as meta events and let this\n// cap reach thousands for full-session capture without the memory blowup.\nconst DEFAULT_MAX_TURN_SNAPSHOTS = 400;\nconst DEFAULT_MAX_UNKNOWN_TOOL_CALLS = 5;\n// Stale tools (advertised in an earlier state, retired now) and fold-hidden tools are\n// self-correcting \u2014 the model drops them once guided \u2014 so they get a higher loop-protection\n// ceiling than hallucinated names: a few legitimate stale calls across state transitions must\n// not prematurely end the turn. Still bounded so a genuinely stuck loop terminates.\nconst MAX_STALE_TOOL_CALLS = DEFAULT_MAX_UNKNOWN_TOOL_CALLS * 2;\n// Gemini in particular emits short bursts of MALFORMED_FUNCTION_CALL; allow more CONSECUTIVE\n// retries. These counters reset on any productive response, so this is a consecutive-failure\n// ceiling, not a per-turn total.\nconst MAX_MALFORMED_RETRIES = 5;\nconst MAX_EMPTY_RESPONSE_RETRIES = 3;\n// Transient throws while building the per-turn tool surface or calling the provider retry the\n// SAME iteration up to this many times before propagating, rather than tearing down the turn.\nconst MAX_SETUP_TRANSPORT_RETRIES = 3;\nconst SUGGESTIONS_HISTORY_WINDOW = 8;\n\n/**\n * Sub-agent meta events worth folding into the parent's debug timeline: the\n * per-attempt and per-failure signals that do NOT otherwise surface in the\n * sub-agent's (now hoisted) messages \u2014 a retried-away malformed/empty attempt\n * produces no message, and the stale-vs-hallucinated/streak diagnostics live only\n * on the event. High-volume, message-derivable events (turn.start/turn.end,\n * provider.selected, context.updated) are intentionally excluded: read the\n * sub-agent's hoisted messages for model/tokens/cost and turn-by-turn activity.\n * See `ChatDriver.invokeSubAgent`.\n */\nconst HARVESTED_SUBAGENT_EVENTS: ReadonlySet<MetaEventType> = new Set([\n 'turn.retry',\n 'turn.error',\n 'tool.failed',\n 'tool.unresolved',\n]);\n\n/** Name reserved for the cross-agent handoff tool \u2014 injected by OrchestratingDriver. */\nexport const REQUEST_CONTINUATION_TOOL = 'request_continuation';\n\n/** Paired in history for each `request_continuation` so tool_calls stay balanced for the provider. */\nconst HANDOFF_TOOL_RESULT_PLACEHOLDER =\n 'Handoff to another specialist \u2014 routing continues on the next turn.';\n\n/**\n * Event emitted when the chat history is updated (new message appended).\n *\n * @beta\n */\nexport type ChatHistoryUpdatedEvent = CustomEvent<ReadonlyArray<ChatMessage>>;\n\n/**\n * One captured frame of what the LLM saw on a single tool-loop iteration.\n * The driver records these as a ring buffer (cap: configurable via\n * `chatConfig.agent.maxTurnSnapshots`, default 400) so the export log can show,\n * per turn: which agent was active, the resolved system prompt, the tool names\n * visible to the LLM, and any agent-supplied debug snapshot (e.g. machine\n * state for stateful agents).\n *\n * @beta\n */\nexport interface TurnSnapshot {\n /**\n * Turn identifier, always a string. A driver's own turns are the bare counter\n * (`\"0\"`, `\"1\"`, \u2026 \u2014 monotonic, does not reset on agent swap). Turns forwarded\n * up from a sub-agent are re-labelled under the parent turn that activated them\n * \u2014 a sub-agent invoked on parent turn 5 contributes `\"5-1\"`, `\"5-2\"`, \u2026, and a\n * nested sub-agent on `\"5-2\"` contributes `\"5-2-1\"`, \u2026. See\n * `forwardSubAgentSnapshots`.\n */\n turnIndex: string;\n /** ISO timestamp captured just before the LLM call. */\n timestamp: string;\n /** Name of the agent active when this LLM call ran. */\n agentName?: string;\n /**\n * The agent's resolved system prompt sent to the LLM, verbatim. NOTE: this is\n * now the *bare* prompt \u2014 the fold-surface suffix and the malformed/empty retry\n * nudge no longer mutate it (they kept it byte-unstable and busted prompt\n * caching), so they moved to {@link TurnSnapshot.tailContext}. To reconstruct\n * exactly what the model saw, read both fields.\n */\n systemPrompt?: string;\n /**\n * The framed `<system-reminder>` tail appended to the final user turn for this\n * call, verbatim \u2014 never part of stored history, so this snapshot is the only\n * record of it. Carries the framework's volatile additions (fold suffix, retry\n * nudge) and the agent's per-turn `tailContext` (e.g. current file spec, live\n * diagnostics). Undefined when the tail was empty (the normal case).\n */\n tailContext?: string;\n /** Tool names sent to the LLM, in order \u2014 definitions are static per name so names alone suffice. */\n toolNames: string[];\n /**\n * Normalized `0`\u2013`1` sampling temperature in effect for this call, if the\n * agent (or its current state) configured one. Undefined \u2192 provider/model\n * default. Mirrors the value resolved from `BaseAgentConfig.temperature`.\n */\n temperature?: number;\n /**\n * Tool-call mode actually sent to the provider this call \u2014 the effective\n * value, including the sub-agent `'required'` default. Undefined \u2192 `'auto'`.\n * Mirrors the value resolved from `BaseAgentConfig.toolChoice`.\n */\n toolChoice?: ChatToolChoice;\n /**\n * Per-turn display label resolved from the agent's `displayName`, e.g.\n * \"Guided Booking (Counterparties)\". `agentName` stays as the canonical\n * identity used for routing/filtering.\n */\n agentLabel?: string;\n /** Agent-supplied snapshot \u2014 machine state/context for stateful agents, undefined otherwise. */\n agentSnapshot?: unknown;\n /**\n * Concrete model that ran this call (e.g. `'claude-sonnet-4-6'`) \u2014 the serving model\n * where the provider reports one, else the model the resolved tier was configured\n * with. Undefined when the provider exposes no `getStatus` and the transport stamped\n * nothing.\n *\n * Recorded per call, so an agent whose `provider` selector varies by state (a tier\n * switch between steps of a flow) has each step attributed to the model that actually\n * ran it \u2014 without the reader having to join the turn to the message after it, which\n * is impossible for a call that produced no message.\n */\n model?: string;\n /**\n * Registry slot the provider resolved under for this call \u2014 a tier name like\n * `'high'`/`'low'`, or the registry default's name. Kept alongside {@link\n * TurnSnapshot.model} because they answer different questions: the slot is what the\n * agent asked for, the model is what served it, and repointing a slot at a new model\n * mid-session is only visible when both are recorded.\n */\n providerName?: string;\n /** Vendor behind the resolved slot (`'anthropic'`, `'gemini'`, \u2026), when the provider reports it. */\n provider?: AIProviderType;\n /**\n * What this one LLM call cost \u2014 the four disjoint token buckets plus USD, derived\n * from the response's usage by `messageUsage`. Back-filled when the response lands\n * (the rest of the snapshot is captured *before* the call), so it is `undefined`\n * while the call is in flight, on providers that report no usage, and on a call that\n * threw rather than returning \u2014 a malformed-call/truncation/402 error carries no usage\n * block, so any tokens the provider billed for it are not recoverable here.\n *\n * A snapshot is one **model call**, not one user turn: every tool-loop iteration and\n * every retried attempt records its own. That makes this the only record of spend on\n * an attempt that produced no message \u2014 a blank or refused response is billed and\n * then discarded (see the empty-response retries), so summing the transcript alone\n * under-reports the turn.\n *\n * For a call that DID produce a message, this is the same money as that message's\n * `cost`/token fields, not additional money \u2014 never add turn usage to message usage.\n */\n usage?: AggregateUsage;\n}\n\ninterface FoldStackFrame {\n foldName: string;\n previousDefinitions: ChatToolDefinition[];\n previousHandlers: ChatToolHandlers;\n}\n\n/**\n * Construction-time configuration for {@link ChatDriver}. Everything except the provider\n * registry is optional \u2014 most fields are also settable per-agent via `applyAgent`, so a\n * bare `new ChatDriver(registry)` is valid. Mirrors the `(registry, options)` shape of\n * `OrchestratingDriver`.\n *\n * @beta\n */\nexport interface ChatDriverConfig {\n /** Initial tool handlers (static map or per-turn factory). Default `{}`. */\n toolHandlers?: ToolHandlersInput;\n /** Initial tool definitions (static array or per-turn factory). Default `[]`. */\n toolDefinitions?: ToolDefinitionsInput;\n /** Initial system prompt (string or per-turn resolver). */\n systemPrompt?: SystemPromptInput;\n /** Primer history prepended to the conversation. */\n primerHistory?: ChatMessage[];\n /** Hard cap on tool-loop iterations. Default `50`. */\n maxToolIterations?: number;\n /** Hard cap on fold operations. Default `5`. */\n maxFoldOperations?: number;\n /**\n * Collapse `condenseWhen` payloads in batches of this many model-calls rather than as\n * soon as each trigger fires. A positive integer; decimals are floored and anything\n * below `1` becomes `1`. Default `1` \u2014 collapse immediately, the historical behaviour.\n *\n * Condensation rewrites history in place, so collapsing continuously breaks the\n * provider's prompt cache on nearly every call of a re-read loop. Raising this trades\n * up to that many calls' worth of extra context for one cache break per batch.\n */\n condenseBatchCalls?: number;\n /** Ring-buffer size for per-turn snapshots. Default `400`. */\n maxTurnSnapshots?: number;\n /** Session identity used to file meta events onto the shared debug-log timeline. */\n sessionKey?: string;\n /**\n * Activity bus for lifecycle/halo/tool-loop events. Injected by the browser host\n * (the shared cross-tab singleton); omitted off-browser (Node, tests, headless), where\n * it defaults to {@link NOOP_ACTIVITY_BUS} so no `BroadcastChannel` is ever opened.\n */\n activityBus?: ActivityBus;\n /**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464),\n * used VERBATIM \u2014 set it only to own the copy entirely (white-labelling).\n * When unset, the driver composes the bubble per wall: the neutral\n * `DEFAULT_BUDGET_EXHAUSTED_MESSAGE`, upgraded with \"switch to another AI\n * provider\" advice only when the 402's `otherVendorAvailable` positively says\n * another metered vendor still has headroom \u2014 the same rule the blocked\n * banner applies, so the two surfaces can no longer contradict each other.\n *\n * The assistant element already lets a host override the blocked **banner**\n * via `setBlocked(true, reason)`; without this the transcript **bubble** stayed\n * on the default, so a white-labelled host got its own copy in the banner and\n * the shipped default directly below it. Passing the same effective copy here\n * keeps the two surfaces saying one thing.\n *\n * Deliberately a driver-config field rather than something read off a chat\n * config: `ChatDriver` has no `chatConfig` and is used standalone (see\n * `chat-driver-node`), so threading one in would be a much larger and less\n * reversible change.\n */\n budgetExhaustedMessage?: string;\n\n /**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account\n * (GENC-1506) \u2014 see `DEFAULT_PROVIDER_REFUSED_MESSAGE`.\n *\n * Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend\n * cap a host administrator can raise, this is the vendor declining to serve us at all. A host that\n * white-labels one will usually want to white-label both, but conflating them into one field would\n * force identical copy on two situations with different remedies.\n *\n * Rarely needed: unlike the budget default, the shipped sentence names no vendor and no Genesis, so\n * it is already safe for a white-labelled deployment.\n */\n providerRefusedMessage?: string;\n}\n\n/**\n * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop.\n * Owned by `FoundationAiAssistant` \u2014 created in `connectedCallback`, torn down in `disconnectedCallback`.\n *\n * Dispatches `'history-updated'` events on itself so the owning element can observe changes.\n *\n * @fires history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`\n *\n * @beta\n */\nexport class ChatDriver extends EventTarget implements AiDriver {\n private history: ChatMessage[] = [];\n private busy = false;\n /** Epoch ms when the current turn loop began \u2014 drives the `turn.end` duration. */\n private turnStartedAt = 0;\n private pendingInteractions = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (reason?: any) => void;\n /** Present when the call requested a chat-input override. */\n overrideId?: string;\n /** Present when the call set `timeoutMs`; cleared on resolution. */\n timeoutHandle?: ReturnType<typeof setTimeout>;\n }\n >();\n /**\n * Live per-interaction contexts (GENC-1390), keyed by interactionId. Created in\n * `requestInteraction` alongside the pending entry, disposed + removed in\n * `resolveInteraction`. Non-serialisable (sockets, timers, subscriber sets), so\n * they live here on the driver \u2014 not on the DOM, not in the persisted store \u2014 and\n * therefore survive the element remounts (layout reflow/drag, transcript\n * re-render) that this feature exists to make harmless. At most one is live at a\n * time (see the one-interaction-at-a-time guard in `requestInteraction`).\n */\n private interactionContexts = new Map<string, InteractionContextHandle>();\n\n private systemPrompt?: SystemPromptInput;\n /**\n * Resolved tool definitions visible to the LLM. Folds mutate this in place\n * (push/pop on open/close). When `toolDefinitionsFactory` is set, this is\n * overwritten each tool-loop iteration with the factory's output.\n */\n private toolDefinitions: ChatToolDefinition[];\n /**\n * Optional dynamic-tools source. When set, called each tool-loop iteration\n * to recompute `toolDefinitions` before the LLM call. `defineStatefulAgent`\n * forbids folds when this is set, so the fold-mutation path is unreachable\n * in that case.\n */\n private toolDefinitionsFactory?: (\n ctx: SystemPromptContext,\n ) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>;\n /**\n * Resolved tool handler map used for dispatch. When `toolHandlersFactory` is\n * set, this is overwritten each tool-loop iteration with the factory's output\n * \u2014 keeping it in lockstep with `toolDefinitions` so handlers don't have to\n * defend themselves against being dispatched in states where their tool\n * isn't advertised. Folds mutate this in place; `defineStatefulAgent`\n * forbids folds when a factory is set, so the fold-mutation path is\n * unreachable in that case.\n */\n private toolHandlers: ChatToolHandlers;\n /**\n * Optional per-turn handler-map source. Mirrors `toolDefinitionsFactory` so\n * the LLM-visible tools and the dispatchable handlers can be narrowed in\n * lockstep. Resolved each tool-loop iteration before the LLM call.\n */\n private toolHandlersFactory?: (\n ctx: SystemPromptContext,\n ) => ChatToolHandlers | Promise<ChatToolHandlers>;\n private primerHistory?: ChatMessage[];\n private activeAgentName?: string;\n /**\n * Per-turn display label resolved from the agent's `displayName`. Stamped\n * onto outgoing messages and turn snapshots for UX; `activeAgentName` stays\n * stable for routing/history-transform identity matching.\n */\n private activeAgentLabel?: string;\n private displayName?: SystemPromptInput;\n /**\n * When set, `requestInteraction` delegates to this callback instead of using\n * this driver's own pending map. Wired by `invokeSubAgent` so a sub-agent's\n * widget renders in \u2014 and resolves through \u2014 the parent (ultimately the\n * root) driver, where the main UI is listening.\n */\n private hostInteractionRequester?: <T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ) => Promise<T>;\n /**\n * When set (e.g. by OrchestratingDriver), applied only to the conversation slice\n * sent to the model \u2014 stored `history` stays unchanged for UI and logging.\n */\n private providerHistoryTransform?: (history: ChatMessage[]) => ChatMessage[];\n /**\n * Tool-declared condensation policies, keyed by tool-call id. Populated by\n * `condenseWhen` (first-wins per call); read by `applyCondensation` before each\n * provider call to collapse stale payloads from the model-bound history only.\n * Accumulates across agents on a shared driver (a superseded read collapses no\n * matter which agent made it) and is never cleared \u2014 it dies with the driver.\n */\n private readonly condensePolicies = new Map<string, RegisteredCondensePolicy>();\n /**\n * Monotonic model-call counter for the driver's whole lifetime \u2014 the age clock\n * for `condenseWhen({ on: { kind: 'age' } })`. The per-`sendMessage` `iterations`\n * loop counter resets to 0 every turn, so it can only measure age WITHIN a\n * single turn; this never resets, so `age` counts model-calls since the result\n * appeared across turn boundaries (each short turn still advances it \u2265 1).\n * Bumped once per tool-loop iteration (provider call).\n */\n private modelCallSeq = 0;\n /**\n * Monotonic turn counter \u2014 the `turnEnd` clock. Bumped once per `sendMessage`\n * (a user turn; NOT per handoff continuation, which is the same request), never\n * reset. `turnEnd` collapses a payload once `turnSeq` exceeds the turn it was\n * created in.\n */\n private turnSeq = 0;\n /**\n * Monotonic agent-activation counter \u2014 the `agentEnd` clock. Advances when the\n * active flow ends: a swap to a different-named agent (`applyAgent`) OR an\n * explicit `releaseAgent` / `completeSubAgent`. A stateful agent re-resolving\n * the same name across turns keeps one activation. `agentEnd` fires for a\n * payload once a LATER activation is current (`callActivation < currentActivation`)\n * \u2014 so a re-run of a released agent gets a fresh activation and is NOT\n * collapsed until IT ends.\n */\n private currentActivation = 0;\n /**\n * Monotonic phase-epoch counter \u2014 the `phaseEnd` clock. Advanced by the\n * handler-context `endPhase()` (an app-declared phase boundary within one\n * activation), never reset. Unlike `currentActivation` it is NOT tied to agent\n * swaps or releases \u2014 it ticks only when the agent itself declares a phase\n * done. `phaseEnd` fires for a payload once a LATER epoch is current\n * (`callPhaseEpoch < currentPhaseEpoch`), with an `agentEnd` backstop.\n */\n private currentPhaseEpoch = 0;\n\n /** Stack of fold frames \u2014 grows when a fold opens, shrinks when it closes. */\n private foldStack: FoldStackFrame[] = [];\n /** Consecutive fold open/close ops without a real tool call. Reset on real tool execution. */\n private consecutiveFoldOps = 0;\n /** Consecutive unknown-tool calls without a real tool call. Reset on real tool execution. */\n private consecutiveUnknownToolCalls = 0;\n /**\n * Distinct unknown-tool names seen in the current consecutive streak \u2014 stamped\n * onto the `unknown-tool-limit` turn.error so a triager knows which tools were\n * hallucinated. Reset alongside `consecutiveUnknownToolCalls`.\n */\n private readonly recentUnknownToolNames = new Set<string>();\n /**\n * Union of every tool name advertised at any point during the current agent\n * activation. Lets the unknown-tool path tell a *stale* call (a real tool from\n * an earlier state, now retired \u2014 or one an open exclusive fold is hiding)\n * apart from a *hallucinated* one. Reset on agent swap in `applyAgent`.\n */\n private readonly everSeenToolNames = new Set<string>();\n /**\n * Subset of the current unknown-tool streak that was stale (previously\n * available) rather than hallucinated \u2014 surfaced separately on the\n * `unknown-tool-limit` turn.error so triage can tell a state/prompt-design\n * problem from a model that's inventing tools. Reset alongside\n * `recentUnknownToolNames`.\n */\n private readonly recentStaleToolNames = new Set<string>();\n private readonly maxFoldOperations: number;\n\n /** Sub-agents declared on the active agent config, keyed by name. */\n private subAgentsMap: Map<string, AgentConfig> = new Map();\n /**\n * Set by `completeSubAgent` inside a sub-agent tool handler. Checked at the\n * same point in the loop as `REQUEST_CONTINUATION_TOOL` \u2014 after tool results\n * are appended \u2014 so the exit path mirrors the system-call pattern.\n * `undefined` means the loop has not been stopped early.\n */\n private subAgentCompletion: { result: unknown } | undefined;\n /**\n * True when this driver runs as a child sub-agent (created by a parent\n * driver's `invokeSubAgent`). Sub-agents force tool use every turn so a turn\n * can only end via their completion tool, and on any non-completion exit they\n * record a typed `SubAgentFailureReason` instead of appending a\n * user-facing message \u2014 the parent decides how to surface the failure.\n */\n private isSubAgent = false;\n /**\n * Set when a sub-agent's tool loop ends without `completeSubAgent` being\n * called. Read by the parent's `invokeSubAgent` to build the `{ ok: false }`\n * branch of `requestSubAgent`. Only ever set when `isSubAgent` is true.\n *\n * `budget` rides along on a `'budget_exhausted'` failure so the parent inherits\n * the child's ATTRIBUTION, not just the fact of a wall \u2014 see\n * `budgetWallDetail`.\n */\n private subAgentFailure:\n | {\n reason: SubAgentFailureReason;\n budget?: BudgetDetail;\n /**\n * The refusing vendor and kind, when a child hit the PROVIDER wall (GENC-1506).\n *\n * Carried for the same reason `budget` is: the child is a **separate driver instance**, so\n * nothing it sets on itself is visible to the parent. Without this the parent could report\n * `provider-refused` but not say which vendor or which kind \u2014 losing the only signal that\n * distinguishes \"top up the account\" from \"rotate the key\", since the user copy is cause-free.\n */\n providerRefused?: ProviderRefusedDetail;\n }\n | undefined;\n /**\n * Set by `releaseAgent` inside a top-level tool handler \u2014 typically a stateful\n * agent's terminal-state handler signalling that its flow is complete and the\n * auto-pin lock can release. Checked by the orchestrator after `sendMessage`\n * returns; the orchestrator fires `onDeactivate` and clears the pin.\n *\n * Reset at the start of each `sendMessage` so a release from a previous turn\n * doesn't leak forward.\n */\n private agentReleaseRequested = false;\n /**\n * Ring buffer of per-LLM-call snapshots. Cap is configurable via\n * `chatConfig.agent.maxTurnSnapshots`; older entries drop off as new ones\n * arrive. See {@link TurnSnapshot} for the captured shape.\n */\n private turnSnapshots: TurnSnapshot[] = [];\n /**\n * `turn` + `message` diagnostic-log entries harvested from an out-of-band source (a resolved\n * interaction whose widget returned `InteractionResult.diagnostics` \u2014 e.g. a server-side\n * ChatDriver's debug log). `event` entries are NOT kept here \u2014 they're folded into the session's\n * meta-event registry via `mergeMetaEvents` (see `resolveInteraction`) so they inherit fresh host\n * indices, and reach the log through `getMetaEvents`. Append-only; the host folds these into its\n * debug log alongside this driver's own timeline. Not cleared here \u2014 it lives with the driver\n * instance, like `turnSnapshots`, so a new chat (fresh driver) starts empty while a compaction\n * (same instance) keeps it. (GENC-1461.)\n */\n private readonly externalDiagnostics: DiagnosticEntry[] = [];\n /**\n * Monotonic count of external-diagnostics batches harvested this driver-lifetime. Namespaces each\n * batch's re-keyed `turn` entries so distinct server generations in one chat session can't collide\n * on `turnIndex` in the forward-capture persister (which dedups turns by that key). (GENC-1461.)\n */\n private externalDiagnosticsBatches = 0;\n /** Monotonic counter that survives agent swaps \u2014 useful for cross-referencing with history. */\n private globalTurnIndex = 0;\n /** Captured from `applyAgent` so we don't store the whole `AgentConfig`. */\n private debugSnapshotter?: () => unknown;\n private readonly maxTurnSnapshots: number;\n\n /**\n * Aborted by `dispose()` on driver teardown (e.g. an agent-config swap).\n * Threaded into every provider call as `ChatRequestOptions.signal`, so a\n * disposed driver's in-flight LLM request is cancelled instead of running on\n * to completion or the transport timeout. Also passed to prompt/tool\n * factories via `SystemPromptContext.signal`.\n */\n private readonly lifecycleController = new AbortController();\n\n /**\n * Per-turn abort controller, reset at the start of every turn by `beginTurn`.\n * Aborted by `cancel()` (user stop) and chained to `lifecycleController` so a\n * driver dispose also ends the current turn. Its signal \u2014 not the lifecycle\n * one \u2014 is what reaches the provider call, so a turn can be cancelled without\n * bricking the driver for the next message.\n */\n private turnController = new AbortController();\n /** True when the current turn was stopped via `cancel()` (vs a dispose). Drives the \"Stopped.\" marker. */\n private turnCancelled = false;\n /** Detaches the lifecycle\u2192turn abort link at turn end; set by `beginTurn`. */\n private unlinkLifecycleFromTurn?: () => void;\n\n /**\n * Active agent's provider selector (static name or per-turn resolver).\n * `undefined` means \"use the registry default\".\n */\n private activeProviderInput?: ProviderInput;\n /**\n * Active agent's temperature selector (static number or per-turn resolver),\n * normalized to `0`\u2013`1`. `undefined` means \"use the provider/model default\".\n */\n private activeTemperatureInput?: TemperatureInput;\n /**\n * Active agent's tool-call mode selector (static value or per-turn resolver).\n * `undefined` falls back to the per-turn default (sub-agents force a tool\n * call; top-level turns are `'auto'`).\n */\n private activeToolChoiceInput?: ToolChoiceInput;\n /**\n * Active agent's prompt-cache policy selector (static value or per-turn resolver).\n * `undefined` requests no caching (equivalent to `{ scope: 'default' }`).\n */\n private activeCachePolicyInput?: CachePolicyInput;\n /**\n * Active agent's extended-thinking selector (static value or per-turn resolver). `undefined` \u2014\n * unset, or returned by the resolver \u2014 leaves the model on its own default posture, which is\n * neither uniformly on nor off, so an agent that never sets this is unaffected by the option.\n */\n private activeThinkingPolicyInput?: ThinkingPolicyInput;\n /**\n * Active agent's tail-context selector (static value or per-turn resolver). The driver frames\n * the resolved string in a `<system-reminder>` marker and injects it at the message tail.\n */\n private activeTailContextInput?: TailContextInput;\n /**\n * Active agent's structured-output schema selector (static value or per-turn resolver).\n * When it resolves to a schema, the model's final answer is constrained to it this turn.\n */\n private activeResponseSchemaInput?: ResponseSchemaInput;\n /**\n * Active agent's refusal-fallback chain (static). Passed through to the provider so a refused\n * turn (e.g. Fable 5) is re-run on the next model server-side.\n */\n private activeFallbacks?: ChatFallback[];\n /**\n * Active agent's unresolved-tool hook, captured from `applyAgent`. Consulted\n * only when a tool call cannot be dispatched (a stale or hallucinated name);\n * `undefined` keeps the framework's default messages. See\n * `resolveUnresolvedToolContent`.\n */\n private activeOnUnresolvedTool?: UnresolvedToolInput;\n /**\n * Caches validated provider lookups per name within the current agent. Cleared\n * by `applyAgent` so each new agent's static/function-resolved names are\n * validated fresh.\n */\n private resolvedProviderCache = new Map<string, AIProvider>();\n /** Last successfully resolved provider name \u2014 drives `getActiveProviderName`. */\n private lastResolvedProviderName?: string;\n /** Last dispatched `provider-changed` name; avoids duplicate events on stable turns. */\n private lastDispatchedProviderName?: string;\n /**\n * Concrete model id of the provider resolved for the current turn, read from\n * its `getStatus()` and stamped onto the resulting assistant message so the\n * debug log carries per-message model lineage. Re-resolved each turn in\n * `resolveProviderForTurn`.\n */\n private lastResolvedModel?: string;\n /**\n * Vendor id from the provider's `getStatus()` for the current turn (e.g.\n * `'anthropic'`, `'gemini'`). Stamped onto assistant messages alongside\n * `lastResolvedModel`.\n */\n private lastResolvedProvider?: AIProviderType;\n /**\n * Memoised `name \u2192 getStatus()` lookups, so per-turn resolution doesn't\n * re-await `getStatus()` every turn. Cleared (with `resolvedProviderCache`) on\n * an observable-registry change, so a model swapped behind a stable name is\n * picked up on the next turn.\n */\n private resolvedStatusCache = new Map<string, { model?: string; provider?: AIProviderType }>();\n /**\n * Unsubscribe handle for the provider-registry change listener (only set when\n * the injected registry is observable). Called in `dispose` so the long-lived\n * registry doesn't retain this driver \u2014 see the constructor and the sub-agent\n * teardown in `runSubAgent`.\n */\n private unsubscribeRegistry?: () => void;\n\n /** Hard cap on tool-loop iterations. */\n private readonly maxToolIterations: number;\n /** Model-calls per condensation batch; `1` collapses as soon as a trigger fires. */\n private readonly condenseBatchCalls: number;\n /** Session identity used to file meta events onto the shared debug-log timeline. */\n private readonly sessionKey: string;\n /** Injected activity bus; defaults to a no-op off-browser (Node/tests/headless). */\n private readonly activityBus: ActivityBus;\n /**\n * Host override for the budget-wall transcript copy, used verbatim \u2014 see\n * `ChatDriverConfig.budgetExhaustedMessage`. `undefined` means no override,\n * and the bubble is composed per wall by {@link ChatDriver.budgetExhaustedBubble}.\n */\n private readonly budgetExhaustedMessageOverride?: string;\n\n /**\n * Host override for the provider-refusal sentence, from\n * `ChatDriverConfig.providerRefusedMessage`. `undefined` means no override, so the shipped default\n * is used verbatim.\n */\n private readonly providerRefusedMessageOverride?: string;\n\n /**\n * A provider refusal was observed this turn, so the tool loop must not call the model again\n * (GENC-1506).\n *\n * Exists for the SUB-AGENT path only, exactly like `budgetExhaustedThisTurn`: this driver's own\n * refusal returns straight out of the catch, whereas a child's refusal reaches the parent as a tool\n * result, and without this flag the loop would issue another call into the same wall \u2014 N batched\n * children costing N doomed calls plus a doomed parent one.\n */\n private providerRefusedThisTurn = false;\n\n /** The refusal detail latched off a sub-agent's failure, for the parent's own result. */\n private providerRefusedDetail?: ProviderRefusedDetail;\n /**\n * Set the moment a budget wall is observed anywhere in this turn \u2014 this\n * driver's own 402, or a sub-agent's (which surfaces here only as a\n * `'budget_exhausted'` tool result). Read at the top of the tool loop to end\n * the turn before issuing another model call that would hit the same wall.\n * Reset per turn alongside the other per-turn counters.\n */\n private budgetExhaustedThisTurn = false;\n /**\n * The refusing vendor's own attribution for the wall `budgetExhaustedThisTurn`\n * records, when it was knowable. Kept SEPARATE from the flag rather than\n * replacing it: a figure-less 402 from a transport no vendor claims yields no\n * detail at all (`budgetDetailOf` returns `undefined`), and folding the two\n * would make that case stop ending the turn.\n *\n * It matters most for a sub-agent's wall. The child can sit on a different\n * vendor from its parent \u2014 `applyAgent` reads `config.provider` \u2014 so without\n * this the parent's short-circuit reports `lastResolvedProvider`, i.e. the one\n * vendor that did NOT refuse. Under a mixed registry that walls Gemini because\n * an Anthropic child 402'd, and if those are the only two reachable vendors the\n * host then derives `blocked` and locks a composer that still had headroom.\n */\n private budgetWallDetail?: BudgetDetail;\n /**\n * Whether this turn's budget wall came from a SUB-AGENT rather than this\n * driver's own request. Decides whether `lastResolvedProvider` is a valid\n * attribution fallback: for an own wall it is the refusing vendor, for a\n * child's wall it is the parent's vendor \u2014 the one known NOT to have refused.\n * Reset per turn alongside `budgetWallDetail`.\n */\n private budgetWallViaSubAgent = false;\n\n constructor(\n private readonly providerRegistry: AIProviderRegistry,\n config: ChatDriverConfig = {},\n ) {\n super();\n const {\n toolHandlers = {},\n toolDefinitions = [],\n systemPrompt,\n primerHistory,\n maxToolIterations = DEFAULT_MAX_TOOL_ITERATIONS,\n maxFoldOperations = DEFAULT_MAX_FOLD_OPERATIONS,\n condenseBatchCalls = 1,\n maxTurnSnapshots = DEFAULT_MAX_TURN_SNAPSHOTS,\n sessionKey = '',\n activityBus = NOOP_ACTIVITY_BUS,\n budgetExhaustedMessage,\n providerRefusedMessage,\n } = config;\n this.maxToolIterations = maxToolIterations;\n this.condenseBatchCalls = condenseBatchCalls;\n this.sessionKey = sessionKey;\n this.activityBus = activityBus;\n this.budgetExhaustedMessageOverride = budgetExhaustedMessage;\n this.providerRefusedMessageOverride = providerRefusedMessage;\n if (typeof toolHandlers === 'function') {\n this.toolHandlersFactory = toolHandlers;\n this.toolHandlers = {};\n } else {\n this.toolHandlersFactory = undefined;\n this.toolHandlers = toolHandlers;\n }\n if (typeof toolDefinitions === 'function') {\n this.toolDefinitionsFactory = toolDefinitions;\n this.toolDefinitions = [];\n } else {\n this.toolDefinitionsFactory = undefined;\n this.toolDefinitions = toolDefinitions;\n }\n this.systemPrompt = systemPrompt;\n this.primerHistory = primerHistory;\n this.maxFoldOperations = maxFoldOperations;\n this.maxTurnSnapshots = maxTurnSnapshots;\n // Runtime provider switching: when the host registered an observable\n // registry, drop our memoised provider lookups whenever its mapping/default\n // changes so the next turn re-resolves against the new providers. Resetting\n // `lastDispatchedProviderName` forces the next `resolveProviderForTurn` to\n // re-emit `provider-changed` even when the resolved *name* is unchanged\n // (e.g. a tier name like 'high' kept, but the vendor underneath swapped) \u2014\n // that's what lets status UI refresh on a same-name switch. Feature-detect\n // means immutable/empty registries are a no-op. Child sub-agent drivers get\n // the same registry and so subscribe here too; each cleans up in `dispose`.\n if (isObservableAIProviderRegistry(this.providerRegistry)) {\n this.unsubscribeRegistry = this.providerRegistry.subscribe(() => {\n this.resolvedProviderCache.clear();\n this.resolvedStatusCache.clear();\n this.lastResolvedProviderName = undefined;\n this.lastResolvedModel = undefined;\n this.lastResolvedProvider = undefined;\n this.lastDispatchedProviderName = undefined;\n });\n }\n }\n\n /**\n * Tear down the driver: aborts the lifecycle signal so any in-flight provider\n * request (and prompt/tool factories awaiting it) cancels instead of running\n * on to completion or the transport timeout. Called by the host on driver\n * swap and by `OrchestratingDriver.dispose()`. Idempotent.\n *\n * Deliberately does NOT settle `pendingInteractions` here: dispose is never\n * reached while one is pending. The only host-level dispose is the agent-swap\n * rebuild, which is guarded by `isBusy()` \u2014 a pending interaction keeps the\n * tool loop suspended (`busy === true`), so the swap is deferred until the\n * widget resolves. Sub-agent child disposes always have an empty pending map\n * (widgets park on the parent via `setHostInteractionRequester`). A pending\n * interaction is instead settled by `resolveInteraction` (user response or\n * timeout), which also stamps history and reverts the chat-input override.\n */\n dispose(): void {\n this.lifecycleController.abort(new DOMException('AI assistant driver disposed', 'AbortError'));\n // Drop any live interaction contexts (GENC-1390). Normally empty at teardown\n // (a context is created and destroyed with its pending interaction, and dispose\n // is not reached mid-interaction); disposed defensively so a stray context can\n // never leak an open socket/timer.\n for (const handle of this.interactionContexts.values()) handle.dispose();\n this.interactionContexts.clear();\n // Detach from the provider registry so the long-lived registry doesn't pin\n // this driver (and its closure) after teardown. Guard-cleared so a second\n // dispose is a no-op, matching this method's idempotent contract.\n this.unsubscribeRegistry?.();\n this.unsubscribeRegistry = undefined;\n }\n\n /**\n * Stop the current turn (user \"stop\" button). Aborts the in-flight provider\n * request immediately; if a tool is mid-execution it runs to completion and\n * the loop bails at the next boundary (tools are atomic). No-op when idle.\n * The driver stays usable for the next message.\n */\n cancel(): void {\n if (!this.busy) return;\n this.turnCancelled = true;\n this.turnController.abort(new DOMException('Cancelled by user', 'AbortError'));\n }\n\n /**\n * Start a fresh per-turn abort scope. Chains `lifecycleController` into the\n * new `turnController` so a dispose mid-turn also aborts the request.\n */\n private beginTurn(): void {\n this.turnCancelled = false;\n this.turnController = new AbortController();\n const lifecycle = this.lifecycleController.signal;\n if (lifecycle.aborted) {\n this.turnController.abort(lifecycle.reason);\n this.unlinkLifecycleFromTurn = undefined;\n return;\n }\n const onDispose = () => this.turnController.abort(lifecycle.reason);\n lifecycle.addEventListener('abort', onDispose, { once: true });\n this.unlinkLifecycleFromTurn = () => lifecycle.removeEventListener('abort', onDispose);\n }\n\n /** Detach the lifecycle\u2192turn link so a long-lived lifecycle signal doesn't accumulate listeners. */\n private endTurn(): void {\n this.unlinkLifecycleFromTurn?.();\n this.unlinkLifecycleFromTurn = undefined;\n }\n\n /**\n * Finish a turn whose signal aborted. A user cancel adds a subtle \"Stopped.\"\n * marker; a dispose-driven abort stops quietly (the widget is gone and the\n * cached history would otherwise gain a stray marker on remount).\n */\n private completeAbortedTurn(): ChatDriverResult {\n if (this.turnCancelled) {\n logger.warn('ChatDriver: turn cancelled by user');\n this.appendToHistory({ role: 'system-event', content: 'Stopped.' });\n } else {\n logger.warn('ChatDriver: turn aborted (driver disposed)');\n }\n return { reason: 'done' };\n }\n\n /**\n * Build the `done` loop result, carrying the typed failure reason when the turn\n * bailed (PTC-0). The discriminant stays `'done'` either way \u2014 the same value a\n * clean turn returns \u2014 so consumers matching on `reason === 'done'` are unchanged;\n * `failureReason` is simply present on a failure and absent on success. Omitted\n * (rather than set to `undefined`) so a happy-path result stays byte-identical to\n * the historical `{ reason: 'done' }`.\n */\n private turnDone(\n failureReason?: TurnFailureReason,\n budget?: BudgetDetail,\n providerRefused?: ProviderRefusedDetail,\n ): ChatDriverResult {\n if (!failureReason) return { reason: 'done' };\n // Both payloads are omitted rather than set to `undefined`, so a failure that carries neither has\n // a shape unchanged for a consumer that structurally compares it.\n return {\n reason: 'done',\n failureReason,\n ...(budget ? { budget } : {}),\n ...(providerRefused ? { providerRefused } : {}),\n };\n }\n\n /**\n * Terminal budget outcome for a wall hit **outside** the tool loop \u2014 today,\n * `OrchestratingDriver`'s classification phase, which calls the provider\n * directly and so never enters `runToolLoop`.\n *\n * Does **not** publish `tool-loop-end`: no `tool-loop-start` was published for\n * the classify phase, and an unbalanced end would break start/end pairing for\n * subscribers that rely on it. The driver **return value** is what reports this\n * case \u2014 see `FoundationAiAssistant`'s latch, which reads both seams for\n * exactly this reason.\n *\n * The non-sub-agent tail of the in-loop `BudgetExhaustedError` branch lives\n * here so there is one copy of the log line, the debug-log entry, the\n * transcript bubble and the result shape rather than two that can drift.\n *\n * @param pendingUserMessage - a user message that has NOT yet been appended,\n * appended first so the answer does not end up replying to nothing. Only the\n * classification seam passes it: `OrchestratingDriver` dispatches the user's\n * text as an optimistic `history-updated` detail and leaves the real append\n * to `chatDriver.sendMessage`, which never runs when `classify()` throws \u2014 so\n * the bubble below would re-dispatch a history the user's own message was\n * never in, and it would vanish from the transcript on the next render. The\n * in-loop caller has already appended it and passes nothing.\n *\n * @internal\n */\n private budgetExhaustedBubble(wall?: {\n vendorLabel?: string;\n otherVendorAvailable?: boolean;\n }): string {\n // A host override wins verbatim \u2014 the white-label contract on\n // `ChatDriverConfig.budgetExhaustedMessage` (its copy may not even be\n // English; composing onto it would mangle it).\n if (this.budgetExhaustedMessageOverride != null) return this.budgetExhaustedMessageOverride;\n // Only a POSITIVE `otherVendorAvailable` earns the switch advice. `false`\n // means every other metered vendor is exhausted too, and `undefined` means\n // an older proxy did not say \u2014 in both cases advertising a switch to a\n // vendor that may itself be walled is worse than the neutral default. This\n // mirrors the blocked banner's rule, and closes the gap where the banner\n // said \"switch\" while the transcript bubble directly under it said only\n // \"contact your administrator\" (GENC-1464 tester finding).\n if (wall?.otherVendorAvailable !== true) return DEFAULT_BUDGET_EXHAUSTED_MESSAGE;\n // The label is display copy, nothing more \u2014 attribution (which vendor gets\n // WALLED) stays `budgetDetailOf`'s job. The parameter is the shared shape of\n // both call sites: the thrown `BudgetExhaustedError` on the direct path, and\n // the latched `budgetWallDetail` on the sub-agent path.\n const subject = wall?.vendorLabel\n ? `${wall.vendorLabel}'s AI usage limit`\n : 'your AI usage limit';\n return `You've reached ${subject}. Switch to another AI provider in Settings to keep going, or contact your administrator to raise it.`;\n }\n\n reportBudgetExhausted(\n e: BudgetExhaustedError,\n pendingUserMessage?: ChatMessage,\n ): ChatDriverResult {\n if (pendingUserMessage) this.appendToHistory(pendingUserMessage);\n this.budgetExhaustedThisTurn = true;\n logger.error('ChatDriver: AI budget exhausted', e);\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n // The registry ALIAS (e.g. 'high') is what `provider` records; the vendor\n // is the thing a per-vendor budget is actually scoped to, and it was known\n // at both ends and discarded in the middle until now. Taken from the\n // refusing transport's label first \u2014 this method also serves the\n // classification seam, where `lastResolvedProvider` is the PREVIOUS turn's\n // vendor (or nothing), because classify runs against the registry default.\n vendor:\n vendorTypeOfLabel(e.vendorLabel) ??\n vendorTypeOfLabel(e.serverVendor) ??\n this.lastResolvedProvider,\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n isSubAgent: this.isSubAgent,\n });\n this.appendToHistory({ role: 'assistant', content: this.budgetExhaustedBubble(e) });\n return this.turnDone('budget-exhausted', budgetDetailOf(e));\n }\n\n /**\n * The sentence shown when the upstream provider refuses (GENC-1506).\n *\n * Deliberately far simpler than `budgetExhaustedBubble`: no vendor name, no figures, no\n * switch-provider advice, and no branching on `kind`. The copy is cause-free by design \u2014 a user who\n * can see their own remaining spend must not be told about a limit, and we must not imply the bill\n * has gone unpaid \u2014 so there is nothing here to compose. A host override wins verbatim.\n */\n private providerRefusedBubble(): string {\n return this.providerRefusedMessageOverride ?? DEFAULT_PROVIDER_REFUSED_MESSAGE;\n }\n\n /**\n * Terminal provider-refusal outcome. Mirrors `reportBudgetExhausted` so the two walls behave\n * identically from the caller's side, while keeping their diagnostics distinct.\n *\n * `kind` reaches the debug log and the result but never the transcript: it is what lets an operator\n * tell \"top up the account\" from \"rotate the key\", and with cause-free user copy this is the only\n * place that distinction survives.\n */\n private reportProviderRefused(e: ProviderRefusedError): ChatDriverResult {\n const detail = providerRefusedDetailOf(e);\n this.providerRefusedThisTurn = true;\n this.providerRefusedDetail = detail;\n logger.error('ChatDriver: provider refused the request', e);\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,\n kind: e.kind,\n upstreamStatus: e.upstreamStatus,\n upstreamType: e.upstreamType,\n isSubAgent: this.isSubAgent,\n });\n this.appendToHistory({ role: 'assistant', content: this.providerRefusedBubble() });\n return this.turnDone('provider-refused', undefined, detail);\n }\n\n /** The typed failure reason on a loop result, or `undefined` for a clean turn / handoff. */\n private static failureReasonOf(result: ChatDriverResult): TurnFailureReason | undefined {\n return result.reason === 'done' ? result.failureReason : undefined;\n }\n\n /**\n * Build the `tool-loop-end` event detail for a turn's result. A failure carries a\n * `{ failureReason }` detail; a clean turn emits `undefined` \u2014 the historical shape,\n * kept byte-identical so subscribers see exactly what they always have.\n *\n * A budget failure additionally carries `vendor` \u2014 the concrete vendor\n * (`'anthropic'`/`'gemini'`) the walled turn resolved to, which the driver knows\n * and used to discard. Optional and additive: a subscriber reading only\n * `failureReason` is unaffected, a non-budget failure still emits the historical\n * `{ failureReason }` with no `vendor` key, and the value is a plain string so\n * the detail stays structured-cloneable for the cross-tab hop. It is the field a\n * per-vendor budget model needs and the one that would be awkward to retrofit.\n */\n private loopEndDetail(result: ChatDriverResult):\n | {\n failureReason: TurnFailureReason;\n vendor?: AIProviderType;\n budget?: BudgetDetail;\n }\n | undefined {\n const failureReason = ChatDriver.failureReasonOf(result);\n if (!failureReason) return undefined;\n if (failureReason !== 'budget-exhausted') {\n return { failureReason };\n }\n // The figures ride the event, not just the return value: this publish happens in\n // sendMessage's `finally`, so for an in-loop wall it reaches the host's latch FIRST\n // and the return-value seam is then a no-op (the latch is idempotent). Omitted\n // entirely \u2014 never set to undefined \u2014 when the proxy sent no figures.\n const budget = result.reason === 'done' ? result.budget : undefined;\n // Prefer the refusing transport's own attribution over the driver's\n // last-resolved provider, for the same staleness reason as `budgetDetailOf`.\n //\n // The fallback is legitimate ONLY for this driver's own wall \u2014 its resolved\n // provider IS the refuser then. When the wall came from a SUB-AGENT\n // (`budgetWallViaSubAgent`), the refuser is the child's vendor, and on a\n // mixed registry `lastResolvedProvider` is the one vendor known NOT to have\n // refused; an unattributable child wall degrades to the vendor-agnostic\n // event instead, which the host's latch handles fail-safe.\n const vendor =\n budget?.vendor ?? (this.budgetWallViaSubAgent ? undefined : this.lastResolvedProvider);\n return {\n failureReason,\n ...(vendor ? { vendor } : {}),\n ...(budget ? { budget } : {}),\n };\n }\n\n /**\n * Swap in a new agent's configuration. Called by OrchestratingDriver before\n * each specialist turn so the shared driver runs with the right tools and prompt.\n */\n applyAgent(config: AgentConfig): void {\n // A real swap to a different agent begins a NEW activation \u2014 the prior agent's\n // flow is over, so its `agentEnd`-tagged payloads become collapsible. Guarded\n // on a name change so re-applying the same agent (e.g. a per-turn re-resolve)\n // does not spuriously advance the clock and prematurely drop its payloads.\n if (config.name !== this.activeAgentName) this.currentActivation += 1;\n this.systemPrompt = config.systemPrompt;\n if (typeof config.toolDefinitions === 'function') {\n this.toolDefinitionsFactory = config.toolDefinitions;\n // Cleared each turn by the factory in runToolLoop; empty is safe in the\n // meantime (no LLM call happens before resolution).\n this.toolDefinitions = [];\n } else {\n this.toolDefinitionsFactory = undefined;\n this.toolDefinitions = config.toolDefinitions ?? [];\n }\n if (typeof config.toolHandlers === 'function') {\n this.toolHandlersFactory = config.toolHandlers;\n // Cleared each turn by the factory in runToolLoop; empty is safe in the\n // meantime (no LLM call happens before resolution).\n this.toolHandlers = {};\n } else {\n this.toolHandlersFactory = undefined;\n this.toolHandlers = config.toolHandlers ?? {};\n }\n this.primerHistory = config.primerHistory;\n this.activeAgentName = config.name;\n this.displayName = config.displayName;\n // Static string form resolves to a stable label up-front; the function\n // form gets re-resolved each tool-loop iteration. Falls back to the\n // canonical name when displayName is unset.\n this.activeAgentLabel =\n typeof config.displayName === 'string' ? config.displayName : config.name;\n this.debugSnapshotter = config.getDebugSnapshot;\n this.subAgentsMap = new Map((config.subAgents ?? []).map((s) => [s.name, s]));\n this.activeProviderInput = config.provider;\n this.activeTemperatureInput = config.temperature;\n this.activeToolChoiceInput = config.toolChoice;\n this.activeCachePolicyInput = config.cachePolicy;\n this.activeThinkingPolicyInput = config.thinkingPolicy;\n this.activeTailContextInput = config.tailContext;\n this.activeResponseSchemaInput = config.responseSchema;\n this.activeFallbacks = config.fallbacks;\n this.activeOnUnresolvedTool = config.onUnresolvedTool;\n this.resolvedProviderCache.clear();\n this.lastResolvedProviderName = undefined;\n // Static validation: resolve the name now so unknown-provider and missing-\n // capability errors fire at agent swap rather than on the first LLM call.\n // Function-form `provider` is validated lazily inside `resolveProviderForTurn`.\n if (typeof config.provider === 'string') {\n this.resolveProviderByName(config.provider, config.name);\n }\n // Reset fold state when agent changes \u2014 each specialist starts fresh\n this.foldStack = [];\n this.consecutiveFoldOps = 0;\n // Forget the previous agent's tools \u2014 \"previously available\" is scoped to\n // the current activation, so a stateful agent accumulates its tools across\n // states while a swap to a different specialist starts clean.\n this.everSeenToolNames.clear();\n }\n\n /**\n * Resolve the tool-result content for an unresolved tool call. Consults the\n * active agent's `onUnresolvedTool` hook (if any) with the attempted tool\n * name, the failure `kind`, and the currently dispatchable tools, and returns\n * the hook's non-empty string. Falls back to `fallback` when no hook is set,\n * the hook returns nothing/empty, or the hook throws \u2014 so a misbehaving hook\n * can never break tool dispatch.\n */\n private async resolveUnresolvedToolContent(\n toolName: string,\n kind: 'stale' | 'unknown',\n fallback: string,\n ): Promise<string> {\n if (typeof this.activeOnUnresolvedTool !== 'function') {\n return fallback;\n }\n try {\n const custom = await this.activeOnUnresolvedTool({\n toolName,\n kind,\n availableTools: Object.keys(this.toolHandlers),\n });\n return typeof custom === 'string' && custom.trim().length > 0 ? custom : fallback;\n } catch (e) {\n logger.warn(\n `ChatDriver: onUnresolvedTool threw for \"${toolName}\" \u2014 using default message`,\n e,\n );\n return fallback;\n }\n }\n\n /**\n * Returns the most recently resolved provider name. Falls back to the\n * registry's default when no per-turn resolution has happened yet.\n */\n getActiveProviderName(): string {\n return this.lastResolvedProviderName ?? this.providerRegistry.defaultName();\n }\n\n /**\n * Resolve a named provider against the registry. Cached per-agent so\n * repeated lookups during one agent's lifetime don't re-validate.\n * Validation lives in `resolveChatProvider`; this wrapper just adds the\n * cache.\n */\n private resolveProviderByName(name: string, agentName: string): AIProvider {\n const cached = this.resolvedProviderCache.get(name);\n if (cached) return cached;\n const provider = resolveChatProvider(this.providerRegistry, name, agentName);\n this.resolvedProviderCache.set(name, provider);\n return provider;\n }\n\n /**\n * Resolve the provider to use for the current turn. Walks the agent's\n * `provider` selector (static or function form) or falls back to the\n * registry default. Dispatches `provider-changed` when the resolved name\n * differs from the last dispatched value.\n */\n private async resolveProviderForTurn(ctx: SystemPromptContext): Promise<AIProvider> {\n let provider: AIProvider;\n let resolvedName: string;\n if (this.activeProviderInput === undefined) {\n provider = this.providerRegistry.default();\n resolvedName = this.providerRegistry.defaultName();\n } else {\n const name =\n typeof this.activeProviderInput === 'function'\n ? await this.activeProviderInput(ctx)\n : this.activeProviderInput;\n provider = this.resolveProviderByName(name, this.activeAgentName ?? '<unknown>');\n resolvedName = name;\n }\n this.lastResolvedProviderName = resolvedName;\n const status = await this.resolveStatusForProvider(resolvedName, provider);\n this.lastResolvedModel = status.model;\n this.lastResolvedProvider = status.provider;\n if (resolvedName !== this.lastDispatchedProviderName) {\n this.lastDispatchedProviderName = resolvedName;\n recordMetaEvent(this.sessionKey, 'provider.selected', {\n // `provider` is the registry SLOT (a tier name like 'high'), kept under that key\n // for compatibility; `model` and `vendor` are what it resolved to. Recording all\n // three is the difference between \"the agent switched to its high tier\" and\n // knowing which model that actually was \u2014 a tier can be repointed mid-session,\n // and a slot name alone cannot distinguish anthropic from gemini.\n provider: resolvedName,\n model: status.model,\n vendor: status.provider,\n agent: this.activeAgentName,\n });\n this.dispatchEvent(\n new CustomEvent<{ name: string }>('provider-changed', { detail: { name: resolvedName } }),\n );\n }\n return provider;\n }\n\n /**\n * Resolve model id and vendor from a provider via its optional `getStatus()`,\n * memoised by registry name. Used to stamp `model` and `provider` onto outgoing\n * messages. Best-effort: a provider without `getStatus`, a null status, or a\n * throw all yield empty fields \u2014 attribution is diagnostic, never load-bearing.\n */\n private async resolveStatusForProvider(\n name: string,\n provider: AIProvider,\n ): Promise<{ model?: string; provider?: AIProviderType }> {\n if (this.resolvedStatusCache.has(name)) return this.resolvedStatusCache.get(name)!;\n let status: { model?: string; provider?: AIProviderType } = {};\n try {\n const resolved = await provider.getStatus?.();\n if (resolved) {\n status = { model: resolved.model, provider: resolved.provider };\n }\n } catch {\n status = {};\n }\n this.resolvedStatusCache.set(name, status);\n return status;\n }\n\n /**\n * Resolve a per-turn config input that is either a static value or a function\n * of the turn context \u2014 the value-or-resolver shape shared by `provider`,\n * `temperature`, and `toolChoice`. Returns undefined when the input is unset.\n */\n private async resolveTurnInput<T>(\n input: T | ((ctx: SystemPromptContext) => T | Promise<T>) | undefined,\n ctx: SystemPromptContext,\n ): Promise<T | undefined> {\n if (input === undefined) return undefined;\n return typeof input === 'function'\n ? (input as (ctx: SystemPromptContext) => T | Promise<T>)(ctx)\n : input;\n }\n\n /**\n * Returns the early-stop result set by `completeSubAgent`, if any.\n * Called by a parent `ChatDriver` after running this instance as a sub-agent.\n */\n getSubAgentCompletion(): { result: unknown } | undefined {\n return this.subAgentCompletion;\n }\n\n /**\n * Mark this driver as running as a sub-agent. Called by a parent driver's\n * `invokeSubAgent` immediately after construction, before the first turn.\n * Enables forced tool use and typed failure reporting (see `isSubAgent`).\n */\n markAsSubAgent(): void {\n this.isSubAgent = true;\n }\n\n /**\n * Returns the typed failure recorded when a sub-agent run ended without\n * `completeSubAgent`, if any. Called by a parent `ChatDriver` after running\n * this instance as a sub-agent.\n */\n getSubAgentFailure():\n | {\n reason: SubAgentFailureReason;\n budget?: BudgetDetail;\n providerRefused?: ProviderRefusedDetail;\n }\n | undefined {\n return this.subAgentFailure;\n }\n\n /**\n * Record a sub-agent failure reason (first one wins). No-op for top-level\n * agents, so loop-exit sites can call it unconditionally. The parent reads\n * this via `getSubAgentFailure()` and emits the `subagent.failed` meta event\n * under its *own* session \u2014 see `invokeSubAgent`. (A child sub-agent runs\n * under a separate session key, so recording here would orphan the event off\n * the user-visible debug-log timeline.)\n */\n private failSubAgent(\n reason: SubAgentFailureReason,\n budget?: BudgetDetail,\n providerRefused?: ProviderRefusedDetail,\n ): void {\n if (!this.isSubAgent || this.subAgentFailure) return;\n // Each payload is omitted rather than set to `undefined` so a failure carrying neither has a shape\n // unchanged for a structural comparison, matching `turnDone`.\n this.subAgentFailure = {\n reason,\n ...(budget ? { budget } : {}),\n ...(providerRefused ? { providerRefused } : {}),\n };\n }\n\n /**\n * Returns true if `releaseAgent` was called during the most recent turn.\n * Consumed by the orchestrator to trigger the auto-pin release path.\n */\n getAgentReleaseRequested(): boolean {\n return this.agentReleaseRequested;\n }\n\n /**\n * Return the per-turn snapshots captured so far. Used by the host's debug\n * log exporter to show what the LLM saw on each turn \u2014 system prompt, tool\n * surface, and agent-supplied state (e.g. a machine snapshot).\n *\n * Ring-buffered at `MAX_TURN_SNAPSHOTS`; older entries are dropped.\n */\n getTurnSnapshots(): ReadonlyArray<TurnSnapshot> {\n return this.turnSnapshots;\n }\n\n /**\n * The `turn` + `message` diagnostic-log entries harvested from resolved interactions'\n * `InteractionResult.diagnostics` (e.g. a server-side ChatDriver's collated debug log). The host\n * concatenates these into its own debug log so `downloadDebugLog`/the persisted diagnostics stream\n * include external-engine logs; `event` entries are excluded here because they're merged into the\n * session's meta-event registry instead (see `resolveInteraction`) and reach the log via\n * `getMetaEvents`. Opaque, chronologically sorted by the host at assemble time. (GENC-1461.)\n */\n getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry> {\n return this.externalDiagnostics;\n }\n\n /**\n * Merge a sub-agent's turn snapshots into this driver's buffer so they surface\n * as `kind:'turn'` entries in the exported debug log. The child runs as a\n * separate, discarded driver, so its snapshots would otherwise be lost. Each is\n * re-labelled under the parent turn that activated the sub-agent: the child's\n * own (numeric) turns become `\"<parentTurn>-1\"`, `\"-2\"`, \u2026 (1-based, in order);\n * any already-forwarded grand-child labels (strings) have their leading segment\n * remapped the same way, so nesting composes (`\"5-2\"` \u2192 `\"5-2-1\"`).\n *\n * Note: two sub-agents invoked in the *same* parent turn share the prefix, so\n * their labels can repeat \u2014 `agentName` on each snapshot disambiguates them.\n */\n private forwardSubAgentSnapshots(childSnapshots: ReadonlyArray<TurnSnapshot>): void {\n if (childSnapshots.length === 0) return;\n // The activating parent turn = the most recent snapshot this driver recorded\n // before entering the tool handler that invoked the sub-agent.\n const parentTurn = Math.max(0, this.globalTurnIndex - 1);\n const ownTurnLabel = new Map<string, string>();\n let ownPos = 0;\n for (const snap of childSnapshots) {\n let turnIndex: string;\n if (!snap.turnIndex.includes('-')) {\n // The child's own turn (a bare counter) \u2192 number it under the parent turn.\n ownPos += 1;\n turnIndex = `${parentTurn}-${ownPos}`;\n ownTurnLabel.set(snap.turnIndex, turnIndex);\n } else {\n // An already-forwarded grand-child label \u2014 remap its leading segment.\n const [lead, ...rest] = snap.turnIndex.split('-');\n const leadLabel = ownTurnLabel.get(lead) ?? `${parentTurn}-${lead}`;\n turnIndex = [leadLabel, ...rest].join('-');\n }\n this.turnSnapshots.push({ ...snap, turnIndex });\n }\n while (this.turnSnapshots.length > this.maxTurnSnapshots) {\n this.turnSnapshots.shift();\n }\n }\n\n /**\n * Push one snapshot to the ring buffer. Called inside `runToolLoop` just\n * before each LLM call \u2014 that's the latest point where the prompt, tool\n * surface, and agent state line up with what the model is about to see.\n *\n * Returns the pushed object so the caller can back-fill what only the response\n * knows (`usage`). Mutating it after the fact is safe whether or not the ring\n * buffer has since evicted it \u2014 an evicted snapshot is simply no longer exported.\n */\n private recordTurnSnapshot(\n resolvedSystemPrompt: string | undefined,\n temperature: number | undefined,\n toolChoice: ChatToolChoice | undefined,\n tailContext: string | undefined,\n ): TurnSnapshot {\n let agentSnapshot: unknown;\n if (this.debugSnapshotter) {\n try {\n agentSnapshot = this.debugSnapshotter();\n } catch (e) {\n // A snapshotter throwing must not derail the LLM call \u2014 capture the\n // error string in place of the snapshot so the export still shows\n // *something* happened.\n agentSnapshot = `<getDebugSnapshot threw: ${e instanceof Error ? e.message : String(e)}>`;\n }\n }\n const turnIndex = String(this.globalTurnIndex);\n this.globalTurnIndex += 1;\n const snapshot: TurnSnapshot = {\n turnIndex,\n timestamp: new Date().toISOString(),\n agentName: this.activeAgentName,\n agentLabel: this.activeAgentLabel,\n systemPrompt: resolvedSystemPrompt,\n tailContext,\n toolNames: this.toolDefinitions.map((t) => t.name),\n temperature,\n toolChoice,\n agentSnapshot,\n };\n this.turnSnapshots.push(snapshot);\n if (this.turnSnapshots.length > this.maxTurnSnapshots) {\n this.turnSnapshots.shift();\n }\n return snapshot;\n }\n\n /**\n * Optional transform applied to conversation history immediately before each LLM request.\n * Cleared when `undefined`. Does not alter stored history.\n */\n setProviderHistoryTransform(transform?: (history: ChatMessage[]) => ChatMessage[]): void {\n this.providerHistoryTransform = transform;\n }\n\n getHistory(): ReadonlyArray<ChatMessage> {\n return this.history;\n }\n\n getRawHistory(): readonly ChatMessage[] {\n return this.history;\n }\n\n /** Returns the current fold stack names for debugging. */\n getActiveFoldNames(): string[] {\n return this.foldStack.map((f) => f.foldName);\n }\n\n async getSuggestions(\n history: ChatMessage[],\n prompt: string,\n count: number,\n allAgentInfo?: AllAgentSummary[],\n ): Promise<string[]> {\n // Suggestions are an out-of-turn UI helper, not bound to any single agent \u2014\n // always run against the registry default. Best-effort: a default with no\n // `prompt()` just means no suggestions, not a hard error.\n const defaultProvider = this.providerRegistry.default();\n if (!defaultProvider.prompt) {\n logger.warn('ChatDriver: default AI provider does not implement prompt()');\n return [];\n }\n\n let agentContext = '';\n let toolContext = '';\n\n if (allAgentInfo?.length) {\n const agentDescriptions = allAgentInfo\n .map((agent) => {\n const tools = agent.tools.map((t) => t.name).join(', ');\n return `- ${agent.name} (${agent.description}): ${tools ? `(Tools: ${tools})` : 'No tools'}`;\n })\n .join('\\n');\n agentContext = `The assistant has the following capabilities:\\n${agentDescriptions}`;\n\n const allToolNames = allAgentInfo\n .flatMap((agent) => agent.tools.map((t) => t.name))\n .filter((value, index, self) => self.indexOf(value) === index)\n .join(', ');\n toolContext = allToolNames\n ? `You have access to the following tools across all agents: ${allToolNames}.`\n : '';\n } else if (this.activeAgentName) {\n const toolNames = this.toolDefinitions.map((tool) => tool.name).join(', ');\n agentContext = `You are currently acting as the \"${this.activeAgentName}\" agent.`;\n toolContext = toolNames ? `You have access to the following tools: ${toolNames}.` : '';\n }\n\n // System prompt is intentionally short: it sets the role only. Concrete\n // instructions live in the user message *after* the transcript so the\n // immediately-preceding context for the model is \"here is data, now do X\"\n // rather than \"here is a dialogue, continue it\". This matters for Anthropic\n // \u2014 without it, Claude reads the transcript as an in-progress conversation\n // and produces a normal assistant turn instead of a list of suggestions.\n const systemPrompt =\n 'You generate suggested prompts that a user could send to an AI assistant. ' +\n 'You never continue the conversation or roleplay as the assistant.';\n\n const capabilitiesBlock =\n agentContext || toolContext\n ? `\\n\\n<capabilities>\\n${[agentContext, toolContext].filter(Boolean).join('\\n')}\\n</capabilities>\\nSuggestions must only cover what the agent is capable of. Do not suggest anything outside these capabilities.`\n : '';\n\n const guidanceBlock = prompt ? `\\n\\nAdditional guidance: \"${prompt}\"` : '';\n\n let userMessage: string;\n if (history.length === 0) {\n userMessage =\n `Generate exactly ${count} brief starter prompts to show a user what an AI assistant can do. ` +\n `Phrase each one as the user would write it. Keep them short and generic \u2014 do not invent specific names, IDs, or data (e.g. prefer \"Search for a trade\" over \"Find all trades with Client A\").` +\n capabilitiesBlock +\n guidanceBlock +\n `\\n\\nOutput format (strict):\\n` +\n `- Exactly ${count} lines.\\n` +\n `- One suggestion per line.\\n` +\n `- No numbering, bullets, markdown, emojis, code blocks, or quotes around the suggestion.\\n` +\n `- No preamble, headings, summary, or commentary before or after the list.`;\n } else {\n const conversationContext = history\n .filter(\n (m) =>\n (m.role === 'user' || m.role === 'assistant') &&\n !m.toolCalls?.length &&\n !m.thinking &&\n !!m.content?.trim(),\n )\n .slice(-SUGGESTIONS_HISTORY_WINDOW)\n .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)\n .join('\\n');\n\n userMessage =\n `<conversation_history>\\n${conversationContext}\\n</conversation_history>\\n\\n` +\n `The conversation above has ended. Do not continue it or respond as the assistant. ` +\n `Generate exactly ${count} follow-up prompts the *user* might send next, phrased in first person as the user would write them. ` +\n `The first ${Math.max(0, count - 1)} should be natural follow-ups to the last turn. ` +\n `Do not invent specific names, IDs, or data values that do not appear in <conversation_history>.` +\n capabilitiesBlock +\n guidanceBlock +\n `\\n\\nOutput format (strict):\\n` +\n `- Exactly ${count} lines.\\n` +\n `- One suggestion per line.\\n` +\n `- No numbering, bullets, markdown, emojis, code blocks, or quotes around the suggestion.\\n` +\n `- No preamble, headings, summary, or commentary before or after the list.`;\n }\n\n const text = await defaultProvider.prompt!(userMessage, { systemPrompt });\n\n // Lenient parsing as a defensive backstop: even with the strict prompt,\n // models occasionally slip in numbering, bullets, or surrounding markdown.\n return (\n text\n .split('\\n')\n .map((s) => s.trim())\n // strip leading bullets/numbers (\"- \", \"* \", \"\u2022 \", \"1. \", \"1) \")\n .map((s) => s.replace(/^([-*\u2022]|\\d+[.)])\\s+/, ''))\n // strip surrounding bold/italic markers\n .map((s) => s.replace(/^[*_]{1,3}|[*_]{1,3}$/g, '').trim())\n // drop empty lines, separators, and obvious preamble lines\n .filter((s) => s.length > 0)\n .filter((s) => !/^[-=]{2,}$/.test(s))\n .filter((s) => !/^here (are|is) /i.test(s))\n .filter((s) => !s.endsWith(':'))\n .slice(0, count)\n );\n }\n\n /**\n * Whether `compact()` would do anything right now \u2014 a summarizable run of older\n * turns exists behind a clean boundary. Uses the same `history` `compact()`\n * acts on, so the UI's gate can't disagree with the action (GENC-1351 follow-up).\n */\n canCompact(): boolean {\n return findCompactionCut(this.history) != null;\n }\n\n /**\n * Destructively compact older turns into a single `compacted-summary` message\n * (GENC-1351 \u00A75.7). Summarizes everything before a clean recent-tail boundary\n * via the registry-default provider's one-shot `prompt()`, then **atomically**\n * replaces the covered turns with one summary message at the head \u2014 history is\n * mutated only on success. Rolling: any existing head summary is folded into\n * the new one. Returns the created summary message, or `null` when there is\n * nothing worth compacting or the default provider cannot summarize.\n */\n async compact(): Promise<ChatMessage | null> {\n if (this.busy) return null;\n const defaultProvider = this.providerRegistry.default();\n if (!defaultProvider.prompt) {\n logger.warn('ChatDriver: default AI provider has no prompt(); cannot compact');\n return null;\n }\n\n const history = this.history;\n const cut = findCompactionCut(history);\n if (cut == null) return null;\n\n const toCompact = history.slice(0, cut);\n const tail = history.slice(cut);\n\n // Summarize BEFORE mutating history \u2014 a failed/empty call leaves the\n // transcript untouched (atomic generate-then-replace).\n const { systemPrompt, userMessage } = buildCompactionSummaryPrompt(toCompact);\n // Surface a failure the way turn errors are surfaced \u2014 a brief \"sorry\" agent\n // message \u2014 while leaving the transcript itself untouched (atomic). Retrying\n // is safe (nothing was spliced).\n const failMessage =\n \"Sorry, I couldn't compact the conversation just now. Nothing was changed \u2014 please try again.\";\n let summaryText: string;\n try {\n summaryText = (await defaultProvider.prompt!(userMessage, { systemPrompt }))?.trim() ?? '';\n } catch (e) {\n logger.warn(`ChatDriver: compaction summary failed: ${e instanceof Error ? e.message : e}`);\n this.appendToHistory({ role: 'assistant', content: failMessage });\n return null;\n }\n if (!summaryText) {\n logger.warn('ChatDriver: compaction summary was empty; leaving history untouched');\n this.appendToHistory({ role: 'assistant', content: failMessage });\n return null;\n }\n\n let tokensBefore: number | undefined;\n for (let i = history.length - 1; i >= 0; i -= 1) {\n if (history[i].inputTokens != null) {\n tokensBefore = history[i].inputTokens;\n break;\n }\n }\n const status = await defaultProvider.getStatus?.();\n const createdAt = new Date().toISOString();\n const summaryMessage: ChatMessage = {\n role: 'compacted-summary',\n content: summaryText,\n // Stamp with the covered region's start, not \"now\": the summary stands in\n // for the oldest messages and sits at the head of history, so this keeps it\n // sorted to the head in any timestamp-ordered view (the debug timeline) and\n // history time-monotonic. Its true creation time is in compaction.createdAt.\n timestamp: toCompact[0]?.timestamp ?? createdAt,\n compaction: {\n compactedCount: toCompact.length,\n coveredThroughTimestamp: toCompact[toCompact.length - 1]?.timestamp,\n tokensBefore,\n model: status?.model,\n createdAt,\n // Bank what the replaced turns spent. `toCompact` is dropped from history\n // below, taking its per-message cost/token fields with it \u2014 so a host total\n // re-derived from the transcript would otherwise fall by exactly this much\n // on every compaction. Summarising a turn does not refund what it cost.\n rolledUpUsage: sumUsage(toCompact),\n },\n };\n\n this.loadHistory([summaryMessage, ...tail]);\n return summaryMessage;\n }\n\n isBusy(): boolean {\n return this.busy;\n }\n\n /**\n * Wire a parent driver as the host for this driver's interactions. When set,\n * `requestInteraction` delegates upward so the widget renders in (and\n * resolves through) the parent's history and pending map. Calls chain\n * naturally: a grandchild \u2192 child \u2192 root.\n */\n public setHostInteractionRequester(\n fn: <T>(componentName: string, data: any, options?: InteractionRequestOptions) => Promise<T>,\n ): void {\n this.hostInteractionRequester = fn;\n }\n\n /**\n * Request a custom UI interaction. Emits a new message with the interaction.\n * Tool handlers can call this to pause execution until the user completes the UI interaction.\n *\n * If a host requester is wired (sub-agent case), the call delegates upward\n * so the interaction lives on the parent \u2014 the main UI is only listening to\n * the root driver. Only one interaction may be in flight at any time on a\n * given root: concurrent calls (e.g. two parallel sub-agents both spawning a\n * widget) throw. Parallel sub-agents are for parallel work, not for user\n * interaction, which is inherently sequential.\n *\n * @param componentName - The custom element name to render.\n * @param data - Data to pass to the component.\n * @param options - Optional per-call overrides, including\n * `chatInputDuringExecution` to hide or disable the main chat input while\n * the widget is awaiting user input (reverts when the interaction resolves),\n * and `presentation` to control whether the host wraps the widget in a chat\n * bubble and/or shows the \"Assistant\" label.\n */\n public async requestInteraction<T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ): Promise<T> {\n if (this.hostInteractionRequester) {\n return this.hostInteractionRequester<T>(componentName, data, options);\n }\n if (this.pendingInteractions.size > 0) {\n throw new Error(\n 'requestInteraction: another user interaction is already in flight. ' +\n 'Only one interaction may be active at a time \u2014 sequence them in a single tool handler ' +\n 'rather than spawning widgets from parallel sub-agents or parallel tool calls.',\n );\n }\n const interactionId = crypto.randomUUID();\n const chatInputDuringExecution = options?.chatInputDuringExecution;\n const timeoutMs = options?.timeoutMs;\n const presentation = options?.presentation;\n return new Promise((resolve, reject) => {\n this.pendingInteractions.set(interactionId, {\n resolve,\n reject,\n overrideId: chatInputDuringExecution ? interactionId : undefined,\n // Resolve the interaction with a timeout result if the user does not\n // respond in time. `resolveInteraction` runs the same teardown a normal\n // resolution does (marks the widget read-only, reverts any input\n // override) and clears any still-pending handle.\n timeoutHandle:\n timeoutMs != null\n ? setTimeout(() => {\n this.resolveInteraction(interactionId, {\n status: 'timeout',\n message: `Interaction timed out after ${timeoutMs}ms.`,\n } satisfies InteractionResult);\n }, timeoutMs)\n : undefined,\n });\n recordMetaEvent(this.sessionKey, 'interaction.requested', {\n interactionId,\n component: componentName,\n agent: this.activeAgentName,\n });\n // Signal the park boundary on the activity bus so turn-aware UI can tell\n // \"actively computing\" from \"parked awaiting the user\" \u2014 the latter is a\n // safe window for actions disallowed mid-request (e.g. switching provider\n // during a long journey step). Paired with `interaction-resolved`.\n this.activityBus.publish('interaction-requested', undefined);\n if (chatInputDuringExecution) {\n this.dispatchEvent(\n new CustomEvent('interaction-start', {\n detail: { interactionId, chatInputDuringExecution },\n }),\n );\n }\n // Create the live context (GENC-1390) BEFORE the widget can mount, so the\n // wrapper finds it when it builds the pending `interaction` descriptor.\n this.interactionContexts.set(interactionId, createInteractionContext(interactionId));\n this.appendToHistory({\n role: 'assistant',\n content: '',\n interaction: {\n interactionId,\n componentName,\n data,\n ...(presentation ? { presentation } : {}),\n },\n });\n });\n }\n\n /**\n * Resolve a pending interaction. The wrapper component calls this on completion.\n * Marks the interaction message as resolved so it renders read-only on re-render.\n */\n public resolveInteraction(interactionId: string, result: any): void {\n const interaction = this.pendingInteractions.get(interactionId);\n if (interaction) {\n // Clear the timeout so a user resolution doesn't later fire a stale\n // timeout (and a timeout firing here clears its own already-fired handle).\n if (interaction.timeoutHandle) clearTimeout(interaction.timeoutHandle);\n // Harvest any out-of-band diagnostic entries the widget collated (e.g. from a server-side\n // ChatDriver) so the host's debug log + persisted diagnostics include them. Independent of the\n // message `idx` below \u2014 they describe the widget's own work, not this message.\n //\n // The harvested entries carry the SOURCE engine's own index space (0-based turns/events), which\n // would collide with this host's cursors in the forward-capture persister \u2014 turns dedup by\n // `turnIndex`, events by an `index` high-water mark \u2014 so foreign entries get silently dropped\n // from the persisted stream. Route each kind through the host's own collision-safe machinery,\n // mirroring how a sub-agent's log is folded in (see `invokeSubAgent`):\n // \u2022 `event` \u2192 `mergeMetaEvents`, which re-indexes them onto this session's monotonic event\n // counter (clearing the high-water) while preserving their timestamps; they then\n // reach the log via `getMetaEvents` in `buildTimelineEntries`, not this buffer.\n // \u2022 `turn` \u2192 re-key `turnIndex` to the turn's local position within a per-batch namespace,\n // so turns stay unique even when one interaction folds in several independent\n // server runs that each number their own turns from 0 (a consolidator carries a\n // consolidator-code run AND a table-code run), and never collide with the host's\n // own bare-integer turn keys.\n // \u2022 `message` \u2192 kept as-is; the persister already keys messages by content, so they survive.\n // TODO(GENC-1461, option 2 / streaming): expose an imperative `appendDiagnostics(entries)` on\n // the handler context (see buildHandlerContext) that runs this same decomposition as SSE ticks\n // arrive, so a streaming widget can surface its external engine's log live rather than only at\n // resolve time. Batch-at-resolve (here) is the current, non-streaming path.\n const harvestedDiagnostics = (result as { diagnostics?: readonly unknown[] } | undefined)\n ?.diagnostics;\n if (Array.isArray(harvestedDiagnostics) && harvestedDiagnostics.length) {\n const batch = (this.externalDiagnosticsBatches += 1);\n const externalEvents: MetaEvent[] = [];\n let turnCount = 0;\n let messageCount = 0;\n for (const raw of harvestedDiagnostics) {\n // The harvest is external and typed `unknown[]`, so an element could be a primitive, null,\n // or an object without a string `kind`. Guard before reading `.kind` so a malformed entry\n // can't throw here (and gets skipped rather than derailing the whole fold).\n if (\n !raw ||\n typeof raw !== 'object' ||\n typeof (raw as { kind?: unknown }).kind !== 'string'\n ) {\n continue;\n }\n const entry = raw as DiagnosticEntry;\n if (entry.kind === 'event') {\n const { kind: _kind, ...event } = entry;\n externalEvents.push(event as unknown as MetaEvent);\n } else if (entry.kind === 'turn') {\n // Local position within THIS harvest, not the source engine's own `turnIndex`: one\n // interaction can carry several independent server runs (a consolidator folds in its\n // consolidator-code run and its table-code run), each numbering its turns from 0, so\n // keying by the source index would collide them. The local position keeps every turn key\n // distinct within the batch, so the persister's per-`turnIndex` dedup keeps them all.\n this.externalDiagnostics.push({\n ...entry,\n turnIndex: `server-generation.${batch}:${turnCount}`,\n });\n turnCount += 1;\n } else if (entry.kind === 'message') {\n messageCount += 1;\n this.externalDiagnostics.push(entry);\n }\n // Any other kind is intentionally dropped, not folded. A sibling's `buildTimelineEntries`\n // only ever emits message/turn/event; `meta-snapshot` is host/DOM-owned (latest-wins on\n // reassembly, plus its own persister dedup), so folding a foreign one would pollute this\n // host's timeline and meta cursor. Restricting to the three real kinds also keeps the\n // manifest counts accurate (nothing miscounted as a `message`).\n }\n if (externalEvents.length) mergeMetaEvents(this.sessionKey, externalEvents);\n // Manifest: one provenance marker for the fold itself \u2014 records that an out-of-band engine's\n // log crossed into this session and how much of each kind, so a regression that silently\n // drops a generation's diagnostics (e.g. a new path that forgets to thread them across the\n // boundary) surfaces as a zero/absent manifest rather than only by diffing a download. Also\n // the natural seed for the streaming PR's open/close bracket. Stamped at resolve, so it\n // closes the block on the sorted timeline. (GENC-1461.)\n recordMetaEvent(this.sessionKey, 'external-diagnostics.folded', {\n interactionId,\n batch,\n counts: { turn: turnCount, event: externalEvents.length, message: messageCount },\n });\n }\n const idx = this.history.findIndex((m) => m.interaction?.interactionId === interactionId);\n if (idx !== -1) {\n // Fold any widget-reported external (non-LLM) cost onto the message, so\n // the host's `sumCosts` recompute includes it in the session total.\n // Accumulates defensively in case a widget reports more than once.\n const costUsd =\n typeof result?.costUsd === 'number' &&\n Number.isFinite(result.costUsd) &&\n result.costUsd > 0\n ? result.costUsd\n : undefined;\n this.history[idx] = {\n ...this.history[idx],\n interaction: { ...this.history[idx].interaction!, resolved: result },\n ...(costUsd != null\n ? { externalCostUsd: (this.history[idx].externalCostUsd ?? 0) + costUsd }\n : {}),\n };\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n // A widget may opt into echoing its outcome on the user's side of the\n // chat by returning `userMessage`. Appended as a display-only\n // `'synthetic-user'` message: it is tracked in history (and the debug log)\n // and rendered like a user message, but transports never serialize it \u2014\n // the model already learns the outcome from this handler's return value.\n // Appended before `interaction.resolve` so it precedes the tool result and\n // any follow-up turn the resumed handler produces.\n if (typeof result?.userMessage === 'string' && result.userMessage.trim()) {\n this.appendToHistory({ role: 'synthetic-user', content: result.userMessage });\n }\n if (interaction.overrideId) {\n this.dispatchEvent(new CustomEvent('interaction-stop', { detail: { interactionId } }));\n }\n recordMetaEvent(this.sessionKey, 'interaction.resolved', { interactionId });\n // The park is ending and the loop is about to resume computing \u2014 paired\n // with `interaction-requested`. Fires for every resolution path (user\n // completion, timeout, cancellation), since all route through here.\n this.activityBus.publish('interaction-resolved', undefined);\n interaction.resolve(result);\n this.pendingInteractions.delete(interactionId);\n // Tear down the live context on RESOLVE (not on element unmount) \u2014 this closes\n // any sockets/timers the widget parked on it via `onDispose`. (GENC-1390)\n this.interactionContexts.get(interactionId)?.dispose();\n this.interactionContexts.delete(interactionId);\n } else {\n logger.warn(`Interaction with ID ${interactionId} not found.`);\n }\n }\n\n /**\n * The live {@link InteractionContext} for a pending interaction (GENC-1390), or\n * `undefined` once resolved/evicted. Read by `AiChatInteractionWrapper` (via the\n * host) to build the widget's pending `interaction` descriptor.\n */\n public getInteractionContext(interactionId: string): InteractionContext | undefined {\n return this.interactionContexts.get(interactionId)?.context;\n }\n\n /**\n * Resolve every in-flight interaction with a `'timeout'` result, closing its\n * widget read-only. Used when a sub-agent that owns the open widget times out:\n * the widget is parked in *this* driver's map (interactions resolve on the\n * host, not the child), so cancelling it here unblocks the sub-agent handler\n * awaiting it. The \"one interaction at a time\" invariant means there is at\n * most one.\n */\n private cancelPendingInteractions(message: string): void {\n for (const interactionId of [...this.pendingInteractions.keys()]) {\n this.resolveInteraction(interactionId, {\n status: 'timeout',\n message,\n } satisfies InteractionResult);\n }\n }\n\n /**\n * Seeds the driver with a prior conversation history so a new component instance\n * can continue an existing conversation. Call this before the first user message.\n */\n public loadHistory(messages: ChatMessage[]): void {\n this.history = [...messages];\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n\n async sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult> {\n if (this.busy || (!userInput.trim() && !attachments?.length)) return { reason: 'done' };\n\n this.busy = true;\n this.beginTurn();\n // A new user turn \u2014 advances the `turnEnd` clock (continuations after a\n // handoff stay on the same turn; they go through `continueFromHistory`).\n this.turnSeq += 1;\n this.subAgentCompletion = undefined;\n this.subAgentFailure = undefined;\n this.agentReleaseRequested = false;\n this.budgetExhaustedThisTurn = false;\n this.budgetWallDetail = undefined;\n this.budgetWallViaSubAgent = false;\n this.providerRefusedThisTurn = false;\n this.providerRefusedDetail = undefined;\n this.appendToHistory({ role: 'user', content: userInput, attachments });\n this.turnStartedAt = Date.now();\n recordMetaEvent(this.sessionKey, 'turn.start', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n });\n this.activityBus.publish('tool-loop-start', undefined);\n\n // Captured so the `finally` can carry the turn's outcome onto `tool-loop-end`.\n let result: ChatDriverResult = { reason: 'done' };\n try {\n result = await this.runToolLoop(userInput, attachments);\n return result;\n } catch (e) {\n logger.error('ChatDriver error:', e);\n recordTurnError(this.sessionKey, 'exception', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e instanceof Error ? e.name : undefined,\n message: e instanceof Error ? e.message : String(e),\n });\n this.appendToHistory({\n role: 'assistant',\n content: 'Sorry, something went wrong on my end. Please try again in a moment.',\n });\n result = this.turnDone('exception');\n return result;\n } finally {\n recordMetaEvent(this.sessionKey, 'turn.end', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n durationMs: Date.now() - this.turnStartedAt,\n });\n this.busy = false;\n this.endTurn();\n this.activityBus.publish('tool-loop-end', this.loopEndDetail(result));\n }\n }\n\n /**\n * Builds the context object passed to every tool handler call.\n * Centralised here so fold shortcut dispatch and the main tool loop use the\n * same context without duplication.\n *\n * @param activeToolCallId - The id of the tool call this context belongs to, so\n * `condenseWhen` can register against the right call (it stamps the clocks\n * straight off the driver). Absent for dispatch paths with no addressable tool\n * call (e.g. the fold-close handler), where `condenseWhen` is a no-op.\n * @param traceCapture - Optional per-tool-call accumulator. When provided, every\n * sub-agent call's trace is **appended** here rather than written to shared\n * instance state, so parallel tool calls each capture their own traces\n * independently.\n *\n * Deliberately a list of traces, not one slot. A single handler may call\n * `requestSubAgent` more than once \u2014 a code-driven scheduler dispatching a\n * dependency graph, a retry of a timed-out child, any fan-out helper \u2014 and a\n * single slot kept only the last, so every other child ran, was billed by the\n * provider, and then vanished from history. The loss was silent in the worst\n * way: `sumUsage` and `usageRows` both recurse into the trace, so they summed a\n * truncated input and still agreed with each other. Measured at 1 of 7 traces\n * kept on a seven-way fan-out, reporting ~2.3x under the real cost, with the\n * error growing as the fan-out widens.\n */\n private buildHandlerContext(\n activeToolCallId?: string,\n traceCapture?: { traces: ChatMessage[][] },\n ) {\n return {\n requestInteraction: <T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ): Promise<T> => this.requestInteraction(componentName, data, options),\n ...(this.subAgentsMap.size > 0 && {\n requestSubAgent: <T = never>(\n name: string,\n options?: SubAgentRequestOptions,\n ): Promise<\n | { ok: true; result: T; reason?: never }\n | { ok: false; result?: never; reason: SubAgentFailureReason }\n > =>\n this.invokeSubAgent<T>(name, options).then(({ outcome, trace }) => {\n // Append, never assign: see `traceCapture` on `buildHandlerContext`. Order\n // is completion order, which is fine \u2014 every message carries its own\n // timestamp and the timeline sorts on that.\n if (traceCapture && trace) traceCapture.traces.push(trace);\n return outcome;\n }),\n }),\n completeSubAgent: (result: unknown): void => {\n if (this.subAgentCompletion) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): completeSubAgent called more than once \u2014 ignoring`,\n );\n return;\n }\n this.subAgentCompletion = { result };\n // This activation's flow has ended \u2014 advance the clock so its\n // `agentEnd` payloads collapse and a re-run starts a fresh activation.\n this.currentActivation += 1;\n },\n releaseAgent: (): void => {\n if (this.agentReleaseRequested) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): releaseAgent called more than once \u2014 ignoring`,\n );\n return;\n }\n this.agentReleaseRequested = true;\n // The stateful flow has wrapped up \u2014 advance the clock so its `agentEnd`\n // payloads collapse and a re-run starts a fresh activation.\n this.currentActivation += 1;\n },\n endPhase: (): void => {\n // Advance the phase epoch so payloads registered with `{ on: phaseEnd }`\n // during the phase that just ended collapse on the next provider call.\n // Repeatable (no once-only guard, unlike releaseAgent/completeSubAgent):\n // each call opens a fresh phase for subsequent reads to accumulate in.\n this.currentPhaseEpoch += 1;\n },\n condenseWhen: (policy: CondensePolicy): void => {\n // No addressable tool call (e.g. fold-close handler) \u2014 nothing to attach to.\n if (!activeToolCallId) return;\n if (!policy?.args && !policy?.response) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called with neither args nor response \u2014 ignoring`,\n );\n return;\n }\n const triggers = Array.isArray(policy.on) ? policy.on : [policy.on];\n const validTrigger = (t: CondenseTrigger | undefined): boolean =>\n t?.kind === 'superseded'\n ? typeof t.by === 'string' && t.by.length > 0\n : t?.kind === 'age'\n ? typeof t.turns === 'number' && t.turns >= 1\n : t?.kind === 'turnEnd' || t?.kind === 'agentEnd' || t?.kind === 'phaseEnd';\n if (triggers.length === 0 || !triggers.every(validTrigger)) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called with an invalid trigger \u2014 ignoring`,\n );\n return;\n }\n // First-wins: a handler declares its policy once per call. A second\n // declaration for the same tool call is a handler bug, not a refinement.\n if (this.condensePolicies.has(activeToolCallId)) {\n logger.error(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called more than once for the same tool call \u2014 keeping the first policy, ignoring this one`,\n );\n return;\n }\n // Stamp the three clocks NOW (read straight off the driver \u2014 the handler\n // runs during the current model-call's tool batch).\n this.condensePolicies.set(activeToolCallId, {\n policy,\n iteration: this.modelCallSeq,\n turn: this.turnSeq,\n activation: this.currentActivation,\n phaseEpoch: this.currentPhaseEpoch,\n });\n },\n };\n }\n\n /**\n * Creates a child `ChatDriver` for the named sub-agent, runs it to completion,\n * and returns its structured result (or final text fallback) together with the\n * full child conversation trace. Callers receive both values so each parallel\n * invocation can capture its own trace without touching shared instance state.\n */\n private async invokeSubAgent<T = never>(\n name: string,\n options?: SubAgentRequestOptions,\n ): Promise<{\n // Closed union (see ChatToolHandlers.requestSubAgent) \u2014 keeps `result`/`reason`\n // accessible for consumers compiled without strictNullChecks.\n outcome:\n | { ok: true; result: T; reason?: never }\n | { ok: false; result?: never; reason: SubAgentFailureReason };\n trace: ChatMessage[];\n }> {\n const subConfig = this.subAgentsMap.get(name);\n if (!subConfig) {\n const available = [...this.subAgentsMap.keys()].join(', ') || '(none)';\n throw new Error(\n `Sub-agent \"${name}\" not found on agent \"${this.activeAgentName}\". Available: ${available}`,\n );\n }\n\n const { task, historyCap, context, timeoutMs } = options ?? {};\n\n // Exclude the current in-flight assistant message (the one with tool calls that\n // triggered this invocation) \u2014 it has unresolved tool calls that would confuse\n // the sub-agent into thinking it needs to handle tools it doesn't own.\n const lastMsg = this.history[this.history.length - 1];\n const baseHistory =\n lastMsg?.role === 'assistant' && lastMsg.toolCalls?.length\n ? this.history.slice(0, -1)\n : this.history;\n\n const snapshotHistory =\n historyCap != null ? applyHistoryCap(baseHistory, historyCap) : [...baseHistory];\n\n const contextMessages: ChatMessage[] = context\n ? [{ role: 'user', content: `[Sub-agent context]: ${JSON.stringify(context)}` }]\n : [];\n\n const effectivePrimer: ChatMessage[] = [\n ...snapshotHistory,\n ...contextMessages,\n ...(subConfig.primerHistory ?? []),\n ];\n\n // Unique per-invocation id \u2014 reused for the lifecycle event bracket below \u2014\n // and a child session key derived from it. The child files its meta events\n // under this own bucket (rather than the shared empty-key sink), so they can\n // be harvested into THIS session on completion and then discarded.\n const invocationId = crypto.randomUUID();\n const childSessionKey = `${this.sessionKey}::sub:${invocationId}`;\n const child = new ChatDriver(this.providerRegistry, {\n sessionKey: childSessionKey,\n // Inherit the parent's bus so the sub-agent's tool-loop events still surface\n // (off-browser this is the shared no-op).\n activityBus: this.activityBus,\n });\n // Mark before the first turn so the child forces tool use and reports a\n // typed failure (rather than user-facing text) if it never completes.\n child.markAsSubAgent();\n // Propagate disposal: if this (parent) driver is torn down while the\n // sub-agent is mid-flight, dispose the child too so its in-flight request\n // aborts. Detached in the `finally` below once the sub-agent completes.\n const disposeChild = () => child.dispose();\n if (this.lifecycleController.signal.aborted) {\n disposeChild();\n } else {\n this.lifecycleController.signal.addEventListener('abort', disposeChild, { once: true });\n }\n child.applyAgent({ ...subConfig, primerHistory: effectivePrimer });\n // Route interactions back through this driver so widgets render in the\n // parent's (ultimately the root's) history and resolve via the same\n // pending map the main UI is wired to. Recurses naturally for nested\n // sub-agents.\n child.setHostInteractionRequester(\n <R>(componentName: string, data: any, opts?: InteractionRequestOptions): Promise<R> =>\n this.requestInteraction<R>(componentName, data, opts),\n );\n\n const forwardTrace = (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('sub-agent-history-updated', {\n detail: { agentName: subConfig.name, history: (e as CustomEvent<ChatMessage[]>).detail },\n }),\n );\n };\n // Re-dispatch the child's `provider-changed` so the UI reflects whichever\n // provider is *actually* running right now (the sub-agent may use a\n // different provider than the parent). Restoration of the parent's\n // provider on `sub-agent-stop` is handled by the listener in main.ts.\n const forwardProviderChanged = (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('provider-changed', { detail: (e as CustomEvent).detail }),\n );\n };\n child.addEventListener('history-updated', forwardTrace);\n child.addEventListener('provider-changed', forwardProviderChanged);\n\n const chatInputDuringExecution = options?.chatInputDuringExecution;\n const lifecycleDetail = { name, invocationId, chatInputDuringExecution };\n\n this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: lifecycleDetail }));\n // Bracket the run on the timeline (mirrors turn.start/turn.end). Recorded\n // under THIS (parent) session \u2014 like subagent.completed/failed below \u2014 so the\n // sub-agent's span is visible on the user-facing timeline, not the child's.\n recordMetaEvent(this.sessionKey, 'subagent.started', { agent: name });\n let timedOut = false;\n const runPromise = child.sendMessage(task ?? '');\n try {\n if (timeoutMs == null) {\n await runPromise;\n } else {\n // Race the run against the deadline. On timeout, abort the child (which\n // cancels its in-flight provider request) and let the aborted run settle\n // before we tear down and return the timeout outcome.\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n const timeoutSignal = new Promise<'timeout'>((resolveTimeout) => {\n timeoutHandle = setTimeout(() => resolveTimeout('timeout'), timeoutMs);\n });\n const winner = await Promise.race([\n runPromise.then(() => 'done' as const),\n timeoutSignal,\n ]);\n if (winner === 'timeout') {\n timedOut = true;\n child.dispose();\n // The sub-agent may be parked awaiting a user interaction, which is\n // routed up to this driver and parked in *this* pending map (widgets\n // resolve on the host, not the child). Disposing the child does not\n // settle that promise, so the child stays suspended \u2014 cancel the\n // interaction to close the widget and unblock the child. Without this,\n // `await runPromise` below would hang forever and the timeout would\n // never complete (or record `subagent.failed`).\n this.cancelPendingInteractions(`Sub-agent \"${name}\" timed out after ${timeoutMs}ms.`);\n await runPromise.catch(() => undefined);\n }\n } finally {\n // Always clear the timer \u2014 even if the race rejects \u2014 so it never leaks.\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n } finally {\n this.lifecycleController.signal.removeEventListener('abort', disposeChild);\n child.removeEventListener('history-updated', forwardTrace);\n child.removeEventListener('provider-changed', forwardProviderChanged);\n // Tear the child down on every exit path, not just timeout/parent-abort.\n // A child that completes normally is otherwise never disposed, so its\n // provider-registry subscription (wired in the ChatDriver constructor)\n // would leak \u2014 the long-lived registry would retain every completed\n // sub-agent driver. dispose() is idempotent and only aborts the (already\n // settled) lifecycle, so the snapshot/completion reads below still work.\n child.dispose();\n this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: lifecycleDetail }));\n // Capture the child's diagnostics into THIS session, then ALWAYS discard its\n // transient bucket \u2014 done in the `finally` so an unexpected `sendMessage`\n // rejection (which propagates out of this method) can't orphan the bucket in\n // the registry, and a crashed sub-agent still leaves its turns/events behind.\n // Forward the child's per-LLM-call snapshots so they show as `kind:'turn'`\n // entries in the exported debug log, re-numbered under the activating parent turn.\n this.forwardSubAgentSnapshots(child.getTurnSnapshots());\n // Fold the sub-agent's high-value meta events (retries/errors/tool failures \u2014\n // see HARVESTED_SUBAGENT_EVENTS) into THIS session, preserving their original\n // timestamps so they interleave within the subagent.started\u2192completed/failed\n // bracket. Each is breadcrumbed `\"<parent> \u203A <sub-agent>\"`, composing for a\n // nested sub-agent whose own breadcrumb the child already merged.\n const parentName = this.activeAgentName ?? '?';\n const harvested = getMetaEvents(childSessionKey)\n .filter((e) => HARVESTED_SUBAGENT_EVENTS.has(e.type))\n .map((e) => {\n const existing = e.detail?.subAgent as string | undefined;\n return { ...e, detail: { ...e.detail, subAgent: `${parentName} \u203A ${existing ?? name}` } };\n });\n mergeMetaEvents(this.sessionKey, harvested);\n clearSession(childSessionKey);\n }\n\n const trace = child.getHistory() as ChatMessage[];\n\n if (timedOut) {\n // Same failure shape as any other non-completion \u2014 the parent handler\n // recovers on its existing `{ ok: false }` branch. Recorded under THIS\n // (parent) session so it lands on the user-visible debug-log timeline.\n recordMetaEvent(this.sessionKey, 'subagent.failed', { agent: name, reason: 'timeout' });\n return { outcome: { ok: false, reason: 'timeout' }, trace };\n }\n\n const completion = child.getSubAgentCompletion();\n\n if (completion) {\n recordMetaEvent(this.sessionKey, 'subagent.completed', { agent: name });\n return { outcome: { ok: true, result: completion.result as T }, trace };\n }\n\n // No completion \u2192 the sub-agent's loop ended without calling its completion\n // tool. Surface the typed reason it recorded; default to 'max_iterations'\n // for the defensive case where the loop ended with no reason set (e.g. a\n // provider ignored forced tool use and returned text). The previous\n // final-text fallback is intentionally gone \u2014 sub-agents return a\n // structured outcome only, and the parent handler decides how to recover.\n const failure = child.getSubAgentFailure();\n const reason = failure?.reason ?? 'max_iterations';\n // Record under THIS (parent) driver's session so the failure lands on the\n // user-visible debug-log timeline \u2014 the child ran under its own session key.\n // This is also the only telemetry for the defensive default above, where the\n // child's loop ended without recording an explicit failure reason.\n recordMetaEvent(this.sessionKey, 'subagent.failed', { agent: name, reason });\n // A child that hit the budget wall walls this driver too \u2014 the cap is shared,\n // and the parent's very next model call would 402 as well. Flagged (not\n // thrown) because the handler's return value is still appended as a tool\n // result: the loop reads the flag before the next provider call and ends the\n // turn there, which is what makes the `'budget_exhausted'` doc's \"terminal\n // for the parent too\" actually true.\n //\n // The child's attribution is inherited with it: the vendor that refused is\n // the child's, which under a mixed registry is not this driver's. See\n // `budgetWallDetail` for what mis-attributing it costs.\n //\n // FIRST attribution wins (`??=`). With batched delegations, child A walling\n // WITH attribution can be followed by child B walling WITHOUT one (a\n // figure-less 402 behind a transport label no vendor claims); a plain\n // assignment reset the field to `undefined` and the short-circuit's\n // fallback then named the parent's own vendor \u2014 the one known NOT to have\n // refused.\n if (reason === 'budget_exhausted') {\n this.budgetExhaustedThisTurn = true;\n this.budgetWallViaSubAgent = true;\n this.budgetWallDetail ??= failure?.budget;\n }\n // The PROVIDER wall via a child (GENC-1506) \u2014 the same shape as the budget wall above, and needed\n // for the same non-obvious reason: **the child is a separate driver instance**, so the flag it set\n // on itself is invisible here. Without this branch the child's failure was appended as an ordinary\n // tool result, the parent's short-circuit never fired, and the parent issued another model call\n // straight into the same wall. Worse, if that call happened to succeed the turn could finish\n // WITHOUT `failureReason: 'provider-refused'` at all \u2014 reporting a clean turn over a dead account.\n //\n // FIRST attribution wins (`??=`), for the reason spelled out on `budgetWallDetail`: batched\n // delegations can pair an attributable child refusal with an unattributable one, and a plain\n // assignment would let the later `undefined` erase what the earlier child knew.\n if (reason === 'provider_refused') {\n this.providerRefusedThisTurn = true;\n this.providerRefusedDetail ??= failure?.providerRefused;\n }\n return { outcome: { ok: false, reason }, trace };\n }\n\n /**\n * Continue the tool loop from current history without appending a new user message.\n * Used by OrchestratingDriver after an agent handoff.\n */\n async continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult> {\n if (this.busy) return { reason: 'done' };\n\n this.busy = true;\n this.beginTurn();\n this.subAgentCompletion = undefined;\n this.subAgentFailure = undefined;\n this.budgetExhaustedThisTurn = false;\n this.budgetWallDetail = undefined;\n this.budgetWallViaSubAgent = false;\n this.providerRefusedThisTurn = false;\n this.providerRefusedDetail = undefined;\n this.turnStartedAt = Date.now();\n recordMetaEvent(this.sessionKey, 'turn.start', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n });\n this.activityBus.publish('tool-loop-start', undefined);\n // Captured so the `finally` can carry the turn's outcome onto `tool-loop-end`.\n let result: ChatDriverResult = { reason: 'done' };\n try {\n result = await this.runToolLoop('', undefined, transientPrimer);\n return result;\n } catch (e) {\n logger.error('ChatDriver error:', e);\n recordTurnError(this.sessionKey, 'exception', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e instanceof Error ? e.name : undefined,\n message: e instanceof Error ? e.message : String(e),\n });\n this.appendToHistory({\n role: 'assistant',\n content: 'Sorry, something went wrong on my end. Please try again in a moment.',\n });\n result = this.turnDone('exception');\n return result;\n } finally {\n recordMetaEvent(this.sessionKey, 'turn.end', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n durationMs: Date.now() - this.turnStartedAt,\n });\n this.busy = false;\n this.endTurn();\n this.activityBus.publish('tool-loop-end', this.loopEndDetail(result));\n }\n }\n\n // ---------------------------------------------------------------------------\n // Fold mechanics\n // ---------------------------------------------------------------------------\n\n /** Extract ToolFold metadata from a handler, or undefined if it isn't a fold facade. */\n private getFold(toolName: string): ToolFold | undefined {\n const handler = this.toolHandlers[toolName];\n return handler ? ((handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined) : undefined;\n }\n\n /**\n * Search all currently registered fold facades (and their nested folds recursively)\n * to find which fold contains a given tool name. Returns the immediate parent fold name.\n */\n private findFoldContaining(toolName: string, handlers?: ChatToolHandlers): string | null {\n const source = handlers ?? this.toolHandlers;\n for (const [, handler] of Object.entries(source)) {\n const fold = (handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined;\n if (!fold) continue;\n // Direct inner tool match\n if (fold.handlers[toolName]) return fold.name;\n // Recurse into nested folds\n const nested = this.findFoldContaining(toolName, fold.handlers);\n if (nested) return fold.name;\n }\n return null;\n }\n\n /**\n * If an open fold is hiding a previously-available tool, return the name of\n * the fold to close to start getting it back. Only exclusive folds hide tools\n * (they replace the tool set on open rather than extending it), so a base tool\n * that was visible before the fold opened now sits in a fold-stack frame's\n * `previousHandlers` but not in the live handler map. Only the top fold's\n * `close_` tool is active, so that's always the actionable next step \u2014 even\n * when the tool lives further down the stack, closing repeatedly walks back to\n * it. Returns null when no open fold accounts for the tool.\n */\n private foldHidingTool(toolName: string): string | null {\n if (this.foldStack.length === 0) return null;\n const hidden = this.foldStack.some((f) => f.previousHandlers[toolName]);\n return hidden ? this.foldStack[this.foldStack.length - 1].foldName : null;\n }\n\n /**\n * Install the fold's inner tool set, replacing (exclusive) or extending (non-exclusive)\n * the current tool set. Also injects the close tool. Does NOT touch the fold stack.\n */\n private applyFoldToolSet(fold: ToolFold, foldName: string): void {\n const closeToolName = `close_${foldName}`;\n const newDefs: ChatToolDefinition[] = [];\n const newHandlers: ChatToolHandlers = {};\n\n if (!fold.exclusive) {\n // Non-exclusive: keep existing tools minus the facade we just opened\n for (const def of this.toolDefinitions) {\n if (def.name !== foldName) newDefs.push(def);\n }\n for (const [name, handler] of Object.entries(this.toolHandlers)) {\n if (name !== foldName) newHandlers[name] = handler;\n }\n }\n\n // Install inner tools from fold metadata\n newDefs.push(...fold.tools);\n Object.assign(newHandlers, fold.handlers);\n\n // Inject the close tool\n newDefs.push({\n name: closeToolName,\n description: `Close the ${foldName} fold and return to the previous set of tools.`,\n parameters: { type: 'object', properties: {} },\n });\n newHandlers[closeToolName] = async (): Promise<string> => this.closeFold();\n\n this.toolDefinitions = newDefs;\n this.toolHandlers = newHandlers;\n }\n\n /** Open a fold: push a stack frame, swap the tool set, return the response message. */\n private openFold(\n foldName: string,\n fold: ToolFold,\n args: Record<string, unknown>,\n activeToolCallId?: string,\n ): Promise<string> {\n // Shortcut dispatch: model passed inner tool args directly, e.g.\n // trading_tools({ search_trades: { side: \"BUY\" } })\n for (const key of Object.keys(args)) {\n const innerHandler = fold.handlers[key];\n if (innerHandler) {\n logger.debug(`ChatDriver: fold shortcut dispatch \"${foldName}\" \u2192 \"${key}\"`);\n // Open the fold first so the tool set is correct for subsequent calls\n this.pushFoldFrame(foldName);\n this.applyFoldToolSet(fold, foldName);\n this.consecutiveFoldOps = 0; // shortcut dispatch counts as real work\n const innerArgs =\n typeof args[key] === 'object' && args[key] !== null\n ? (args[key] as Record<string, unknown>)\n : {};\n return innerHandler(innerArgs, this.buildHandlerContext(activeToolCallId)).then((r) =>\n typeof r === 'string' ? r : JSON.stringify(r),\n );\n }\n }\n\n // Normal two-step open\n this.pushFoldFrame(foldName);\n this.applyFoldToolSet(fold, foldName);\n\n const innerToolNames = fold.tools.map((t) => t.name);\n const closeToolName = `close_${foldName}`;\n let message = `Fold opened: ${foldName}. Tools now available: ${[...innerToolNames, closeToolName].join(', ')}.`;\n if (fold.usageNotes) message += ` Notes: ${fold.usageNotes}`;\n message += ` Call ${closeToolName} when done to return to the previous tools.`;\n return Promise.resolve(message);\n }\n\n private pushFoldFrame(foldName: string): void {\n this.foldStack.push({\n foldName,\n previousDefinitions: [...this.toolDefinitions],\n previousHandlers: { ...this.toolHandlers },\n });\n }\n\n /** Close the top fold: pop the stack frame, restore the previous tool set. */\n private closeFold(): string {\n const frame = this.foldStack.pop();\n if (!frame) return 'No fold is currently open.';\n\n this.toolDefinitions = frame.previousDefinitions;\n this.toolHandlers = frame.previousHandlers;\n\n const toolNames = this.toolDefinitions.map((t) => t.name);\n return `Fold closed: ${frame.foldName}. Tools now available: ${toolNames.join(', ')}.`;\n }\n\n /** Build the fold-awareness suffix appended to the system prompt each LLM call. */\n private buildFoldSystemPromptSuffix(): string {\n // Collect fold facades from the current handler map\n const activeFolds: ToolFold[] = [];\n for (const handler of Object.values(this.toolHandlers)) {\n const fold = (handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined;\n if (fold) activeFolds.push(fold);\n }\n\n if (activeFolds.length === 0 && this.foldStack.length === 0) return '';\n\n const parts: string[] = ['\\n\\n--- Tool Folds ---'];\n parts.push(\n 'Some tools are grouped into folds. You may see tool calls in the conversation history for tools that are not currently available \u2014 they are inside a fold. To access them, invoke the fold tool first.',\n );\n\n if (this.foldStack.length > 0) {\n const current = this.foldStack[this.foldStack.length - 1];\n parts.push(\n `You are currently inside the \"${current.foldName}\" fold. Call close_${current.foldName} when you are done with these tools.`,\n );\n }\n\n for (const fold of activeFolds) {\n parts.push(`\u2022 ${fold.name}: ${fold.description}`);\n }\n\n return parts.join('\\n');\n }\n\n // ---------------------------------------------------------------------------\n // Tool loop\n // ---------------------------------------------------------------------------\n\n // oxlint-disable-next-line complexity\n private async runToolLoop(\n userInput: string,\n attachments?: ChatAttachment[],\n transientPrimer?: ChatMessage[],\n ): Promise<ChatDriverResult> {\n if (!this.systemPrompt) {\n logger.warn(\n 'ChatDriver: no systemPrompt set. The assistant will have no instructions \u2014 provide a systemPrompt via agents config or the foundation-ai-assistant property.',\n );\n }\n\n let currentInput = userInput;\n let currentAttachments: ChatAttachment[] | undefined = attachments;\n let iterations = 0;\n let malformedAttempts = 0;\n let emptyResponseAttempts = 0;\n // Bounded retries for transient throws while resolving the per-turn tool surface or\n // calling the provider. Without this, a single transient throw tears down the whole turn\n // and strands the agent's unflushed work behind an opaque error.\n let setupTransportAttempts = 0;\n // True only for the very first LLM call. Used to exclude the pending user message\n // from history (it is passed separately as currentInput). Must not be derived from\n // `iterations` because fold operations decrement iterations, which would incorrectly\n // re-trigger the slice on subsequent calls after a fold open/close.\n let firstLlmCall = !!currentInput;\n // Thinking posture for this WHOLE turn, resolved on the first model call and then held.\n //\n // Unlike temperature or toolChoice, this one cannot vary per iteration: a tool-use loop is\n // a single assistant turn, and Anthropic requires one thinking mode for its duration.\n // Toggling mid-loop does not error \u2014 the API silently disables thinking for that request\n // and strips blocks that would leave the turn structure invalid, so an `'auto' -> 'off'`\n // switch loses the reasoning continuity the opening call established while an\n // `'off' -> 'auto'` switch simply does not deliver the reasoning asked for. It also\n // invalidates the prompt cache, which costs more than the reasoning it was meant to save.\n // Resolved per USER turn instead, which is where the docs say to choose it.\n let pinnedThinkingPolicy: ChatThinkingPolicy | undefined;\n let thinkingPolicyPinned = false;\n\n while (iterations < this.maxToolIterations) {\n iterations += 1;\n // Monotonic across the driver's life \u2014 the age clock. Unlike `iterations`,\n // it is NOT reset per turn and NOT decremented for folds, so `age` keeps\n // counting model-calls once a turn ends. (See the `modelCallSeq` field.)\n this.modelCallSeq += 1;\n\n // A cancel (or dispose) that landed while the previous iteration's tool\n // batch was running takes effect here \u2014 before issuing another LLM call.\n // An abort during the call itself is handled by the catch below.\n if (this.turnController.signal.aborted) {\n return this.completeAbortedTurn();\n }\n\n // A budget wall observed earlier this turn ends it HERE, before another\n // model call. Reachable only via a sub-agent (this driver's own 402\n // returns straight out of the catch below) \u2014 `invokeSubAgent` sets the\n // flag, its `{ ok: false, reason: 'budget_exhausted' }` outcome is\n // appended as a tool result, and without this the loop would call the\n // provider again into the same wall: N batched sub-agent calls otherwise\n // cost N doomed children AND a doomed parent call.\n //\n // Scoped strictly to the budget reason: every other SubAgentFailureReason\n // is something the parent can legitimately recover from, so those still\n // let the loop continue.\n // A provider refusal seen earlier this turn ends it HERE, before another model call. Reachable\n // only via a sub-agent \u2014 this driver's own refusal returns straight out of the catch \u2014 and\n // without it the loop would call the provider again into the same wall (GENC-1506).\n if (this.providerRefusedThisTurn) {\n logger.error('ChatDriver: ending the turn \u2014 a sub-agent hit the provider wall');\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n kind: this.providerRefusedDetail?.kind,\n via: 'sub-agent',\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // The detail is forwarded, not just the reason \u2014 this driver may itself be an INTERMEDIATE\n // sub-agent, and a refusal that started in a grandchild reaches its own parent only through\n // this call. Dropping it here still stopped the top-level turn (the reason travels), but\n // arrived with no vendor and no kind, which is the whole diagnostic this payload exists to\n // carry across hops. The adjacent budget path forwards `budgetWallDetail` for the same reason.\n this.failSubAgent('provider_refused', undefined, this.providerRefusedDetail);\n } else {\n this.appendToHistory({ role: 'assistant', content: this.providerRefusedBubble() });\n }\n return this.turnDone('provider-refused', undefined, this.providerRefusedDetail);\n }\n if (this.budgetExhaustedThisTurn) {\n logger.error('ChatDriver: ending the turn \u2014 a sub-agent hit the AI budget wall');\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n // The CHILD's vendor when it knew one, and NOTHING otherwise. On this\n // path the wall is definitionally the child's, and on a mixed registry\n // `lastResolvedProvider` is this driver's own vendor \u2014 the one known\n // NOT to have refused. An unattributable child wall must degrade to\n // the vendor-agnostic block (which `latchBlockedFrom` handles\n // fail-safe), never to a vendor that is known to be wrong: naming the\n // parent's vendor here walled BOTH \u2014 the child's via its own\n // tool-loop-end, the parent's via this event \u2014 and derived `blocked`\n // over headroom that still existed.\n vendor: this.budgetWallDetail?.vendor,\n via: 'sub-agent',\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('budget_exhausted', this.budgetWallDetail);\n } else {\n // Composed from the DETAIL, not an error object: on this path the wall\n // arrived as a sub-agent's failure payload \u2014 `budgetWallDetail`, first\n // attribution wins \u2014 and an unattributable child wall (detail\n // undefined) composes the neutral default.\n this.appendToHistory({\n role: 'assistant',\n content: this.budgetExhaustedBubble(this.budgetWallDetail),\n });\n }\n // Carried onto the result so `loopEndDetail` publishes the refusing\n // vendor rather than falling through to `lastResolvedProvider`, and the\n // host's latch walls the vendor that actually ran out.\n return this.turnDone('budget-exhausted', this.budgetWallDetail);\n }\n\n const promptCtx: SystemPromptContext = {\n agentName: this.activeAgentName ?? '',\n history: this.history,\n turnIndex: iterations - 1,\n signal: this.turnController.signal,\n };\n\n // Re-resolve dynamic tool definitions before each LLM call. The static\n // case is a no-op (factory is undefined and `this.toolDefinitions` was\n // set by applyAgent). Folds operate on `this.toolDefinitions` and are\n // forbidden when a factory is set, so the array form is always valid.\n // Sequential await is required \u2014 each iteration must see fresh values\n // before constructing the LLM request.\n // A transient throw while building the tool surface should retry the iteration, not\n // tear down the whole turn and strand the agent's unflushed buffer behind an opaque\n // error. The handler-map factory re-resolves in lockstep so dispatch sees only the\n // handlers valid for the current state, in step with the tool definitions exposed\n // above. Folds are forbidden when either factory is set, so the fold-mutation paths\n // on `this.toolDefinitions` / `this.toolHandlers` are unreachable.\n try {\n if (this.toolDefinitionsFactory) {\n // oxlint-disable-next-line no-await-in-loop\n this.toolDefinitions = await this.toolDefinitionsFactory(promptCtx);\n }\n if (this.toolHandlersFactory) {\n // oxlint-disable-next-line no-await-in-loop\n this.toolHandlers = await this.toolHandlersFactory(promptCtx);\n }\n } catch (e) {\n setupTransportAttempts += 1;\n if (setupTransportAttempts < MAX_SETUP_TRANSPORT_RETRIES) {\n logger.warn(\n `ChatDriver: tool-surface resolution failed, retrying (${setupTransportAttempts}/${MAX_SETUP_TRANSPORT_RETRIES})`,\n );\n iterations -= 1;\n continue;\n }\n throw e;\n }\n\n // Record everything advertised this turn so the unknown-tool path can tell\n // a stale tool (real earlier, retired now) from a hallucinated one. Runs\n // for both the static and factory cases; folds also flow through here as\n // their inner tools become visible on the iteration after they open.\n for (const def of this.toolDefinitions) this.everSeenToolNames.add(def.name);\n\n const resolvedSystemPrompt =\n typeof this.systemPrompt === 'function'\n ? // oxlint-disable-next-line no-await-in-loop\n await this.systemPrompt(promptCtx)\n : this.systemPrompt;\n\n // Re-resolve the per-turn display label. Falls back to the canonical\n // agent name when displayName is unset. Stamped onto outgoing messages\n // and turn snapshots for UX only; routing/history-transform continues\n // to read `activeAgentName`.\n if (typeof this.displayName === 'function') {\n // oxlint-disable-next-line no-await-in-loop\n this.activeAgentLabel = await this.displayName(promptCtx);\n }\n\n // Volatile framework additions \u2014 the fold-surface suffix and the per-attempt malformed/empty\n // retry nudge \u2014 that would otherwise destabilize a cached system prompt. They are routed to\n // the framed tail (below), never appended to the system string, so the system prompt stays\n // byte-stable for every agent.\n const foldSuffix = this.buildFoldSystemPromptSuffix();\n const retryNudge =\n malformedAttempts > 0\n ? '\\n\\nIMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.'\n : emptyResponseAttempts > 0\n ? \"\\n\\nIMPORTANT: You must respond to the user's message. Call the appropriate tool or provide a text response \u2014 do not return an empty response.\"\n : '';\n const frameworkSystemSuffix = `${foldSuffix}${retryNudge}`;\n\n // Normalize the primer at the same chokepoint as the driver's own history\n // (GENC-1351 \u00A75.7): a parent's `compacted-summary` message rides into a\n // sub-agent's primer (`requestSubAgent` snapshots the parent's raw history),\n // and it must be translated to a `<conversation_summary>` user message here \u2014\n // otherwise the transports' role filter silently drops it and the sub-agent\n // loses all summarized context. `normalizeForProvider` only touches\n // `compacted-summary`, so it's a safe pass-through for everything else.\n const primer = normalizeForProvider([\n ...(this.primerHistory ?? []),\n ...(transientPrimer ?? []),\n ]);\n const baseHistory = firstLlmCall ? this.history.slice(0, -1) : this.history;\n firstLlmCall = false;\n // Collapse stale tool payloads this agent declared via `condenseWhen`\n // (GENC-1369), then translate any compacted-summary \u2192 a\n // <conversation_summary> user message (GENC-1351 \u00A75.7) before any per-agent\n // masking, so the raw display-only role can never reach a transport. Each\n // step runs on a copy \u2014 stored history is untouched.\n const condensedHistory = applyCondensation(\n [...baseHistory],\n this.condensePolicies,\n {\n modelCall: this.modelCallSeq,\n turn: this.turnSeq,\n // A call's activation has ended once a later activation is current \u2014 a\n // swap or release/complete both advance the counter.\n activationEnded: (activation) => activation < this.currentActivation,\n // A call's phase has ended once the app declared a later phase epoch\n // current via `endPhase()`.\n phaseEnded: (phaseEpoch) => phaseEpoch < this.currentPhaseEpoch,\n batchCalls: this.condenseBatchCalls,\n },\n (detail) => recordMetaEvent(this.sessionKey, 'context.condensed', detail),\n );\n const normalizedHistory = normalizeForProvider(condensedHistory);\n const historyForProvider = this.providerHistoryTransform\n ? this.providerHistoryTransform(normalizedHistory)\n : normalizedHistory;\n const historyForCall = [...primer, ...historyForProvider];\n\n // Resolve the per-turn temperature and tool-call mode the same way the\n // provider is resolved \u2014 static value or a function of the turn context\n // (which carries the live state for stateful agents). Resolved before the\n // snapshot so the debug log records the exact request config the model saw.\n const [\n resolvedTemperature,\n resolvedToolChoice,\n resolvedCachePolicy,\n resolvedTailContext,\n resolvedResponseSchema,\n firstResolvedThinkingPolicy,\n ] =\n // oxlint-disable-next-line no-await-in-loop\n await Promise.all([\n this.resolveTurnInput<number>(this.activeTemperatureInput, promptCtx),\n this.resolveTurnInput<ChatToolChoice>(this.activeToolChoiceInput, promptCtx),\n this.resolveTurnInput<CachePolicy>(this.activeCachePolicyInput, promptCtx),\n this.resolveTurnInput<string>(this.activeTailContextInput, promptCtx),\n this.resolveTurnInput<object | undefined>(this.activeResponseSchemaInput, promptCtx),\n // Only consulted on the first iteration (see `pinnedThinkingPolicy`); resolved\n // alongside the others so a resolver still sees the same turn context.\n thinkingPolicyPinned\n ? Promise.resolve(undefined)\n : this.resolveTurnInput<ChatThinkingPolicy | undefined>(\n this.activeThinkingPolicyInput,\n promptCtx,\n ),\n ]);\n if (!thinkingPolicyPinned) {\n pinnedThinkingPolicy = firstResolvedThinkingPolicy;\n thinkingPolicyPinned = true;\n }\n // The system prompt is always just the agent's resolved prompt \u2014 byte-stable, so it can be\n // cached. The framework's volatile additions (fold suffix, retry nudge) and the agent's tail\n // context all go to the framed tail: one uniform channel, no cache-scope branch. On a normal\n // turn `frameworkSystemSuffix` is empty, so the tail is empty too \u2014 a no-op. The framework\n // owns the framing; the corrective retry nudge lands last (recency).\n const systemPrompt = resolvedSystemPrompt || undefined;\n const tailBody = [resolvedTailContext, frameworkSystemSuffix]\n .map((part) => (part ?? '').trim())\n .filter((part) => part.length > 0)\n .join('\\n\\n');\n const tailContext = tailBody\n ? `<system-reminder>\\n${tailBody}\\n</system-reminder>`\n : undefined;\n // An agent/state-configured tool-call mode wins. Otherwise sub-agents must\n // finish by calling a tool (their completion tool) so the turn can't end\n // on a free-text answer; top-level agents stay 'auto'. (Transports no-op a\n // force when no tools are advertised.)\n const effectiveToolChoice = resolvedToolChoice ?? (this.isSubAgent ? 'required' : undefined);\n\n const turnSnapshot = this.recordTurnSnapshot(\n systemPrompt,\n resolvedTemperature,\n effectiveToolChoice,\n tailContext,\n );\n\n // Capture the pending user input, then clear the slots BEFORE the chat\n // call. `sendMessage` already appended the user message to `this.history`,\n // so on retries (empty / malformed) we must rely on history alone \u2014\n // otherwise the message gets sent twice (once via history, once via\n // `currentInput`), which Gemini answers with an empty response and then\n // we retry forever.\n const userInputForCall = currentInput;\n const attachmentsForCall = currentAttachments;\n currentInput = '';\n currentAttachments = undefined;\n\n const options: ChatRequestOptions = {\n systemPrompt,\n // Strip fold-only properties (foldEvent, foldPath) before sending to provider\n tools: this.toolDefinitions.length ? this.toolDefinitions : undefined,\n attachments: attachmentsForCall,\n // Per-turn signal: aborts on user cancel, and (via beginTurn's chain)\n // on driver dispose. Cancels the in-flight request either way.\n signal: this.turnController.signal,\n toolChoice: effectiveToolChoice,\n // Agent/state-configured sampling temperature (normalized 0\u20131); each\n // transport translates it to its native range. Undefined \u2192 provider default.\n temperature: resolvedTemperature,\n // Prompt-cache policy for this turn (Anthropic places breakpoints per scope; Gemini\n // caches implicitly regardless). Undefined \u2192 no caching requested.\n cachePolicy: resolvedCachePolicy,\n // Extended-thinking posture, pinned for the whole tool loop (one assistant turn) rather\n // than re-resolved per iteration \u2014 see `pinnedThinkingPolicy`. Undefined \u2014 unset, or the\n // resolver's answer for this turn \u2014 is NOT \"off\": it leaves the model on its own default,\n // so agents that never set this are priced exactly as before. Transports clamp models\n // that can't honour it.\n thinkingPolicy: pinnedThinkingPolicy,\n // Framed volatile context injected at the message tail (never stored). Undefined \u2192 none.\n tailContext,\n // Structured-output schema for this turn (agent/state-resolved). When set, the transport\n // constrains the final answer to it natively where the model supports it. Undefined \u2192 free text.\n responseSchema: resolvedResponseSchema,\n // Refusal-fallback chain (e.g. Fable 5 \u2192 Opus 4.8). Passed to the provider; applied\n // server-side where supported. Undefined \u2192 no fallback.\n fallbacks: this.activeFallbacks,\n };\n\n // Resolve the active provider for this turn. Static names were validated\n // in `applyAgent`; function-form names are validated on first resolution\n // here and cached for the agent's lifetime.\n // oxlint-disable-next-line no-await-in-loop\n const activeProvider = await this.resolveProviderForTurn(promptCtx);\n\n // Attribute the turn to the tier/model it resolved. Stamped HERE, not inside\n // `recordTurnSnapshot`: the snapshot is taken before this line runs, so reading\n // `lastResolved*` there yields the PREVIOUS call's model \u2014 wrong on precisely the\n // turn where an agent's per-state `provider` selector switches tier, which is the\n // turn a reader is looking for. `model` is refined to the serving model once the\n // response lands (see below); until then \u2014 and on a call that throws \u2014 it is the\n // model we ASKED for, which is the only thing knowable at that point.\n if (this.lastResolvedProviderName !== undefined) {\n turnSnapshot.providerName = this.lastResolvedProviderName;\n }\n if (this.lastResolvedProvider !== undefined)\n turnSnapshot.provider = this.lastResolvedProvider;\n if (this.lastResolvedModel !== undefined) turnSnapshot.model = this.lastResolvedModel;\n\n let response: ChatMessage;\n try {\n // oxlint-disable-next-line no-await-in-loop\n response = await activeProvider.chat!(historyForCall, userInputForCall, options);\n } catch (e) {\n if (e instanceof MalformedFunctionCallError) {\n malformedAttempts += 1;\n if (malformedAttempts < MAX_MALFORMED_RETRIES) {\n logger.warn(\n `ChatDriver: MALFORMED_FUNCTION_CALL, retrying (${malformedAttempts}/${MAX_MALFORMED_RETRIES})`,\n );\n recordTurnRetry(this.sessionKey, 'malformed-function-call', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempt: malformedAttempts,\n maxAttempts: MAX_MALFORMED_RETRIES,\n finishMessage: e.finishMessage,\n });\n iterations -= 1;\n continue;\n }\n logger.error('ChatDriver: MALFORMED_FUNCTION_CALL, max retries reached');\n recordTurnError(this.sessionKey, 'malformed-function-call', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempts: malformedAttempts,\n finishMessage: e.finishMessage,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('malformed_tool_call');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'While working on your request, I repeatedly called my tools incorrectly. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps.',\n });\n }\n return this.turnDone('malformed-function-call');\n }\n // The response was truncated at the provider's output-token cap while it\n // still carried a tool call \u2014 its arguments are incomplete and unusable.\n // Unlike a malformed call this is DETERMINISTIC: re-issuing the same\n // request hits the same cap, so a silent retry just loops. Bail with a\n // clear, actionable signal instead. The remedy is config (raise the\n // provider maxTokens) or a smaller step \u2014 neither is fixed by retrying.\n if (e instanceof ResponseTruncatedError) {\n logger.error('ChatDriver: response truncated at the output-token cap', e);\n recordTurnError(this.sessionKey, 'response-truncated', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n model: e.model,\n maxTokens: e.maxTokens,\n outputTokens: e.outputTokens,\n tools: e.toolNames,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('response_truncated');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'My response was cut off because a single step reached the model output limit. This usually means one step tried to produce too much at once \u2014 try breaking your request into smaller steps.',\n });\n }\n return this.turnDone('response-truncated');\n }\n // The AI-spend budget is gone and the proxy refused the request (HTTP\n // 402). Terminal in the strongest sense available to us: unlike a\n // truncation \u2014 which a smaller request would get past \u2014 *no* request\n // succeeds until someone raises the budget out of band. So there is no\n // retry here and no \"try again\" in the copy; the turn ends and the host\n // locks the composer off the `'budget-exhausted'` failure reason (see\n // `FoundationAiAssistant.blocked`).\n // The upstream vendor refused this ACCOUNT (GENC-1506) \u2014 its credit is gone, a usage cap is\n // reached, or the credential is dead. Terminal in the strongest sense available: unlike a\n // truncation, no smaller request gets past it, and unlike our own budget wall nobody in this\n // system can raise anything to clear it. So no retry and no \"try again\" in the copy.\n //\n // Placed before the transient-retry step below, which is the whole point: without this the\n // error is an untyped transport failure, gets re-issued MAX_SETUP_TRANSPORT_RETRIES times\n // against a wall that cannot move, and then surfaces as \"something went wrong on my end\" \u2014\n // wrong twice over, since nothing went wrong on our end and trying again will not help.\n if (e instanceof ProviderRefusedError) {\n if (this.isSubAgent) {\n logger.error('ChatDriver: provider refused the request', e);\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,\n kind: e.kind,\n upstreamStatus: e.upstreamStatus,\n upstreamType: e.upstreamType,\n isSubAgent: true,\n });\n // The detail is BUBBLED, not merely flagged. Setting `providerRefusedThisTurn` on `this`\n // would be pointless here \u2014 `this` is the CHILD, and the parent that must stop is a\n // different driver instance. `invokeSubAgent` reads this payload off the child and sets its\n // own flag; see the branch there.\n const detail = providerRefusedDetailOf(e);\n this.failSubAgent('provider_refused', undefined, detail);\n return this.turnDone('provider-refused', undefined, detail);\n }\n return this.reportProviderRefused(e);\n }\n if (e instanceof BudgetExhaustedError) {\n // Flagged as well as returned: a sub-agent's wall reaches the PARENT\n // only as a tool result, and the parent must not issue another model\n // call after it (see the short-circuit at the top of this loop).\n this.budgetExhaustedThisTurn = true;\n this.budgetWallDetail = budgetDetailOf(e);\n // Paired with the detail everywhere it is written: this is the\n // driver's OWN wall, so the sub-agent marker must not survive from an\n // earlier child and suppress the `lastResolvedProvider` fallback that\n // is legitimate here. Unreachable today (the short-circuit fires\n // before a second wall can land in one turn) \u2014 kept structural so the\n // pairing does not depend on that ordering staying true.\n this.budgetWallViaSubAgent = false;\n if (this.isSubAgent) {\n logger.error('ChatDriver: AI budget exhausted', e);\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor:\n vendorTypeOfLabel(e.vendorLabel) ??\n vendorTypeOfLabel(e.serverVendor) ??\n this.lastResolvedProvider,\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n isSubAgent: true,\n });\n // Bubble a typed failure to the parent instead of speaking to the\n // user, carrying the attribution so the parent walls the vendor that\n // actually refused rather than its own.\n this.failSubAgent('budget_exhausted', this.budgetWallDetail);\n return this.turnDone('budget-exhausted', this.budgetWallDetail);\n }\n return this.reportBudgetExhausted(e);\n }\n // A request timeout from the transport (tagged `TimeoutError`) is not a\n // bug on our end \u2014 surface it distinctly instead of letting it fall\n // through to the generic \"something went wrong\" catch. No auto-retry:\n // the timeout ceiling is already minutes long, so a silent retry would\n // just make the user wait again.\n if (e instanceof DOMException && e.name === 'TimeoutError') {\n logger.error('ChatDriver: request timed out', e);\n recordTurnError(this.sessionKey, 'exception', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e.name,\n message: e.message,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('timeout');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'The request timed out. You can ask me to try again, or break this into a smaller step.',\n });\n }\n // Recorded as `exception` above (there is no separate `timeout` member of\n // TurnFailureReason for the main turn); surface the same reason here.\n return this.turnDone('exception');\n }\n // The request was aborted: either a user cancel (turnController) or a\n // driver dispose (lifecycleController, chained into the turn). A user\n // cancel adds a \"Stopped.\" marker; a dispose stops quietly. Handled\n // before the transient-retry below so an intentional abort/timeout is\n // never retried.\n if (e instanceof DOMException && e.name === 'AbortError') {\n return this.completeAbortedTurn();\n }\n // A transient provider/transport error should retry the SAME iteration a bounded\n // number of times rather than tearing down the whole turn (which strands the\n // agent's unflushed buffer behind an opaque error message).\n setupTransportAttempts += 1;\n if (setupTransportAttempts < MAX_SETUP_TRANSPORT_RETRIES) {\n logger.warn(\n `ChatDriver: provider/transport error, retrying (${setupTransportAttempts}/${MAX_SETUP_TRANSPORT_RETRIES})`,\n );\n iterations -= 1;\n continue;\n }\n throw e;\n }\n\n // Attribute the response to the concrete model + registry slot that\n // produced it (resolved for this turn in `resolveProviderForTurn`). Carried\n // on the assistant message so the debug-log timeline shows per-message\n // model lineage \u2014 and thus per-tool-call, since tool calls ride on the\n // assistant message that requests them. Harmless on a response later\n // discarded as empty/retried; only kept copies reach history.\n //\n // Attach each key only when resolved: a provider with no `getStatus` (etc.)\n // leaves the key off entirely rather than carrying it as `undefined`.\n // JSON.stringify already drops undefined from the exported log, so this is\n // chiefly about keeping the in-memory message shape honest.\n // Fill, never overwrite \u2014 but still only when there is something to fill with.\n // A transport that already stamped a model knows something the driver does not:\n // `lastResolvedModel` is the model we ASKED for, so overwriting would relabel a\n // fallback-served turn as the requested model and misattribute its spend.\n // Written as a guard rather than `??=` because `??=` ASSIGNS undefined, which\n // would create the key and break the omit-when-unresolved contract above.\n if (response.model === undefined && this.lastResolvedModel !== undefined) {\n response.model = this.lastResolvedModel;\n }\n if (this.lastResolvedProvider !== undefined) response.provider = this.lastResolvedProvider;\n if (this.lastResolvedProviderName !== undefined) {\n response.providerName = this.lastResolvedProviderName;\n }\n\n // Back-fill what this call cost onto the snapshot taken just before it, so the\n // exported debug log prices each model call next to the prompt/tools/state that\n // produced it (GENC-1480 follow-up). Stamped BEFORE the empty-response branch\n // below deliberately: a blank or refused response is billed and then thrown away,\n // so the snapshot is the only place that spend is ever recorded.\n turnSnapshot.usage = messageUsage(response);\n // Take the SERVING model over the requested one, now that it is known. `response.model`\n // was just filled from `lastResolvedModel` if the transport left it unset, so this is\n // the same rule the message gets \u2014 which is the point: a turn and the message it\n // produced must never disagree about which model ran, including when a server-side\n // fallback chain answered on a different model than the one we asked for.\n if (response.model !== undefined) turnSnapshot.model = response.model;\n\n const isThinkingStep = response.content && response.toolCalls?.length;\n const isEmptyResponse = !response.content?.trim() && !response.toolCalls?.length;\n // A pre-output refusal (safety-classifier decline, e.g. Fable 5 `stop_reason: 'refusal'`)\n // comes back with empty content, so it looks like a blank response \u2014 but it is deterministic:\n // retrying re-sends the identical request and refuses again, burning up to\n // MAX_EMPTY_RESPONSE_RETRIES turns on the most expensive models for the same outcome, ending\n // in the misleading \"blank response\" message. Treat it as a terminal, non-retried failure with\n // its own reason and message. (GENC-1461)\n const isRefusal = response.responseMeta?.finishReason === 'refusal';\n\n if (isEmptyResponse) {\n emptyResponseAttempts += 1;\n if (!isRefusal && emptyResponseAttempts < MAX_EMPTY_RESPONSE_RETRIES) {\n logger.warn(\n `ChatDriver: empty model response, retrying (${emptyResponseAttempts}/${MAX_EMPTY_RESPONSE_RETRIES})`,\n );\n recordTurnRetry(this.sessionKey, 'empty-response', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempt: emptyResponseAttempts,\n maxAttempts: MAX_EMPTY_RESPONSE_RETRIES,\n // Provider diagnostic (Gemini: finishReason, thoughtsTokens, parts,\n // blockReason) so the timeline shows *why* the turn came back blank \u2014\n // e.g. a high thoughtsTokens with a 'STOP' finish is \"thought, then\n // stopped without answering\".\n ...response.responseMeta,\n });\n iterations -= 1;\n continue;\n }\n const failureReason = isRefusal ? 'refusal' : 'empty-response';\n logger.error(\n isRefusal\n ? 'ChatDriver: model refused the request (safety decline) \u2014 not retrying'\n : 'ChatDriver: empty model response after all retries',\n );\n recordTurnError(this.sessionKey, failureReason, {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempts: emptyResponseAttempts,\n isSubAgent: this.isSubAgent,\n ...response.responseMeta,\n });\n if (this.isSubAgent) {\n this.failSubAgent(isRefusal ? 'refusal' : 'empty_response');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content: isRefusal\n ? 'This request was declined. Try rephrasing it, or breaking it into smaller steps.'\n : 'While working on your request, I repeatedly generated a blank response. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps.',\n });\n }\n return this.turnDone(failureReason);\n } else {\n // Split one model response into separate, individually-toggleable messages so each has its\n // own visibility toggle and debug-log category:\n // - reasoning (chain-of-thought summary) \u2192 category 'reasoning', hidden unless showThinkingSteps\n // - narration (interstitial prose emitted alongside a tool call) \u2192 category 'narration',\n // hidden unless showNarration\n // - the answer / tool-call message \u2192 always shown; carries this turn's usage.\n // Cost invariant (GENC-1410): exactly ONE message carries cost/tokens and is appended LAST, so\n // `sumCosts`/`sumTokens` don't double-count and `contextTokens` reads it. Reasoning/narration are\n // display-only (usage undefined) and are skipped when building the provider request. `model` /\n // `provider` / `providerName` stay on every split message so each is still attributed.\n //\n // EVERY usage field has to be cleared here, not just the three the invariant was\n // originally written against \u2014 keep this list in step with the usage fields on\n // `ChatMessage`. The cache buckets arrived later (GENC-1475) and were left riding\n // along on the copies, so a response carrying reasoning AND narration counted its\n // cache read/write volume three times in `sumUsage`/`usageRows` \u2014 invisible in the\n // cost total (which comes from `cost`) but wrong in every bucket display and in the\n // exported log.\n const { reasoning, ...rest } = response;\n const displayOnly = {\n cost: undefined,\n externalCostUsd: undefined,\n inputTokens: undefined,\n outputTokens: undefined,\n cacheReadTokens: undefined,\n cacheWriteTokens: undefined,\n };\n if (reasoning) {\n this.appendToHistory({\n ...rest,\n ...displayOnly,\n content: reasoning,\n toolCalls: undefined,\n category: 'reasoning',\n });\n }\n if (isThinkingStep) {\n // content + tool call \u2192 the content is interstitial narration, not the final answer.\n this.appendToHistory({\n ...rest,\n ...displayOnly,\n toolCalls: undefined,\n category: 'narration',\n });\n this.appendToHistory({ ...rest, content: '' });\n } else {\n // No tool call \u2192 `content` is the final answer (always shown), or this is a bare tool-call\n // turn with no narration. Either way it carries this turn's usage; append it last.\n this.appendToHistory(rest);\n }\n }\n\n // Reset retry budgets on any productive (non-empty) response, so the caps mean\n // \"N CONSECUTIVE failures\" not \"N total per turn\".\n emptyResponseAttempts = 0;\n malformedAttempts = 0;\n setupTransportAttempts = 0;\n\n if (!response.toolCalls?.length) {\n break;\n }\n\n const [toolCalls, systemCalls] = response.toolCalls.reduce<[ChatToolCall[], ChatToolCall[]]>(\n (acc, tc) => {\n if (tc.name === REQUEST_CONTINUATION_TOOL) acc[1].push(tc);\n else acc[0].push(tc);\n return acc;\n },\n [[], []],\n );\n\n const executedById = new Map<\n string,\n {\n toolCallId: string;\n content: string;\n attachments?: ChatImageAttachment[];\n subAgentTrace?: ChatMessage[];\n }\n >();\n const unknownToolIds = new Set<string>();\n // Subset of unknownToolIds that were stale (previously available) rather\n // than hallucinated \u2014 drives the `stale` UI flag back-patched below.\n const staleToolIds = new Set<string>();\n let anyRealToolExecuted = false;\n let hitUnknownToolLimit = false;\n\n if (toolCalls.length > 0) {\n // oxlint-disable-next-line no-await-in-loop -- Promise.all is correct parallelism, not sequential loop awaiting\n await Promise.all(\n toolCalls.map(async (tc) => {\n // Check for fold facade\n const fold = this.getFold(tc.name);\n if (fold) {\n this.consecutiveFoldOps += 1;\n if (this.consecutiveFoldOps > this.maxFoldOperations) {\n logger.warn(\n `ChatDriver: fold operation limit (${this.maxFoldOperations}) reached \u2014 injecting guidance`,\n );\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `You have opened and closed folds ${this.consecutiveFoldOps} times without calling any tools. Please call a specific tool to make progress, or respond to the user.`,\n });\n return;\n }\n const content = await this.openFold(tc.name, fold, tc.args, tc.id);\n executedById.set(tc.id, { toolCallId: tc.id, content });\n // Fold open/close does NOT count as a real iteration \u2014 decrement to compensate\n iterations -= 1;\n return;\n }\n\n // Check for close-fold tool\n if (tc.name.startsWith('close_') && this.foldStack.length > 0) {\n const topFoldName = this.foldStack[this.foldStack.length - 1].foldName;\n if (tc.name === `close_${topFoldName}`) {\n this.consecutiveFoldOps += 1;\n if (this.consecutiveFoldOps > this.maxFoldOperations) {\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `You have opened and closed folds ${this.consecutiveFoldOps} times without calling any tools. Please call a specific tool to make progress, or respond to the user.`,\n });\n return;\n }\n const content = this.closeFold();\n executedById.set(tc.id, { toolCallId: tc.id, content });\n iterations -= 1;\n return;\n }\n }\n\n // Regular tool \u2014 check if it's inside a fold and guide the model\n const handler = this.toolHandlers[tc.name];\n if (!handler) {\n const containingFold = this.findFoldContaining(tc.name);\n if (containingFold) {\n logger.debug(\n `ChatDriver: model called folded tool \"${tc.name}\" \u2014 guiding to open \"${containingFold}\"`,\n );\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: 'folded',\n fold: containingFold,\n });\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `\"${tc.name}\" is not directly available. It is inside the \"${containingFold}\" fold. Call ${containingFold} first to access it.`,\n });\n // Guidance does not count as a real iteration or fold op\n iterations -= 1;\n return;\n }\n\n // Not in any registered fold. If the tool was advertised earlier\n // in this agent's lifetime it's *stale* (a stateful agent moved on,\n // or an exclusive fold is hiding it) rather than hallucinated \u2014 a\n // distinction worth making, because the model should stop retrying\n // a retired tool rather than treat the failure as a typo. Stale\n // calls still trip loop protection, but at a higher ceiling than\n // hallucinated tools (see below) \u2014 they are self-correcting, so the\n // guidance, telemetry, and limit differ.\n if (this.everSeenToolNames.has(tc.name)) {\n this.consecutiveUnknownToolCalls += 1;\n const hidingFold = this.foldHidingTool(tc.name);\n let content: string;\n if (hidingFold) {\n content = `\"${tc.name}\" is not available while the \"${hidingFold}\" fold is open. Call close_${hidingFold} to return to the previous set of tools, then call ${tc.name}.`;\n logger.warn(\n `ChatDriver: tool \"${tc.name}\" is hidden behind open fold \"${hidingFold}\" (${this.consecutiveUnknownToolCalls}/${MAX_STALE_TOOL_CALLS})`,\n );\n } else {\n content = `\"${tc.name}\" was available earlier but is not part of the current step \u2014 that step is complete, so do not call it again. Continue with the tools available now: ${Object.keys(this.toolHandlers).join(', ') || '(none)'}.`;\n logger.warn(\n `ChatDriver: stale tool \"${tc.name}\" \u2014 advertised earlier this activation but retired in the current state (${this.consecutiveUnknownToolCalls}/${MAX_STALE_TOOL_CALLS})`,\n );\n }\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: hidingFold ? 'fold-hidden' : 'stale',\n fold: hidingFold ?? undefined,\n consecutive: this.consecutiveUnknownToolCalls,\n max: MAX_STALE_TOOL_CALLS,\n });\n // Fold-hidden tools keep their fold-specific guidance; a plain\n // stale tool is a step-ordering miss, so offer the agent's\n // redirect when it supplies one.\n const staleContent = hidingFold\n ? content\n : await this.resolveUnresolvedToolContent(tc.name, 'stale', content);\n executedById.set(tc.id, { toolCallId: tc.id, content: staleContent });\n unknownToolIds.add(tc.id);\n staleToolIds.add(tc.id);\n this.recentUnknownToolNames.add(tc.name);\n this.recentStaleToolNames.add(tc.name);\n if (this.consecutiveUnknownToolCalls >= MAX_STALE_TOOL_CALLS) {\n hitUnknownToolLimit = true;\n }\n return;\n }\n\n // Never advertised \u2014 a hallucinated tool name.\n this.consecutiveUnknownToolCalls += 1;\n logger.warn(\n `ChatDriver: no handler registered for tool \"${tc.name}\" (${this.consecutiveUnknownToolCalls}/${DEFAULT_MAX_UNKNOWN_TOOL_CALLS}). Available tools: ${Object.keys(this.toolHandlers).join(', ') || '(none)'}`,\n );\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: 'unknown',\n consecutive: this.consecutiveUnknownToolCalls,\n max: DEFAULT_MAX_UNKNOWN_TOOL_CALLS,\n availableTools: Object.keys(this.toolHandlers),\n });\n const unknownContent = await this.resolveUnresolvedToolContent(\n tc.name,\n 'unknown',\n `Unknown tool: ${tc.name}`,\n );\n executedById.set(tc.id, { toolCallId: tc.id, content: unknownContent });\n unknownToolIds.add(tc.id);\n this.recentUnknownToolNames.add(tc.name);\n if (this.consecutiveUnknownToolCalls >= DEFAULT_MAX_UNKNOWN_TOOL_CALLS) {\n hitUnknownToolLimit = true;\n }\n return;\n }\n\n // Real tool execution.\n //\n // The accumulator is declared OUTSIDE the try so the catch can attach it\n // too: a handler that ran sub-agents and then threw (post-processing their\n // results failed, say) has already spent real money on children that\n // completed. Losing their traces on the error path would under-report the\n // run exactly as the single-slot bug did \u2014 and just as silently, since\n // `sumUsage` and `usageRows` would still agree with each other.\n const traceCapture: { traces: ChatMessage[][] } = { traces: [] };\n const capturedTrace = (): ChatMessage[] | undefined =>\n traceCapture.traces.length ? traceCapture.traces.flat() : undefined;\n try {\n const result = await handler(tc.args, this.buildHandlerContext(tc.id, traceCapture));\n // A handler that returns images gets them carried as real attachments instead of\n // JSON-stringified into the text \u2014 the difference between a model reading\n // `{\"kind\":\"image\",\"data\":\"iVBOR\u2026\"}` as prose and actually SEEING the render.\n // The guard is deliberately narrow (every entry must carry `kind: 'image'`) so an\n // ordinary object return that happens to have an `attachments` key still\n // stringifies exactly as before.\n const resultImages = toolResultImages(result);\n const content = resultImages\n ? typeof (result as { content?: unknown }).content === 'string'\n ? (result as { content: string }).content\n : JSON.stringify({ ...(result as object), attachments: undefined })\n : typeof result === 'string'\n ? result\n : JSON.stringify(result);\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content,\n ...(resultImages ? { attachments: resultImages } : {}),\n // Concatenated when a handler invoked several children, so none is lost.\n // Stays `undefined` when nothing was captured \u2014 readers key off presence,\n // and an empty array is a different claim from \"no sub-agent ran\".\n subAgentTrace: capturedTrace(),\n });\n anyRealToolExecuted = true;\n } catch (e) {\n logger.error(`ChatDriver tool \"${tc.name}\" failed:`, e);\n recordMetaEvent(this.sessionKey, 'tool.failed', {\n tool: tc.name,\n agent: this.activeAgentName,\n message: e instanceof Error ? e.message : String(e),\n });\n executedById.set(tc.id, {\n toolCallId: tc.id,\n // Structured recovery hint so the model retries or routes around a tool\n // failure instead of apologising and giving up.\n content: `Tool error: ${(e as Error).message}\\nRECOVERY: this tool failed once \u2014 you may retry it, or take a different valid action to make progress. Do NOT abandon the task, ask the user to rephrase, or claim you cannot make changes. If a planning tool failed, retry it or proceed with the information you already have.`,\n // Children that completed before the throw were still billed \u2014 keep\n // their traces so the run's cost stays whole.\n subAgentTrace: capturedTrace(),\n });\n anyRealToolExecuted = true; // treat errors as real work for fold op counting\n }\n }),\n );\n }\n\n // Reset counters whenever a real tool executes\n if (anyRealToolExecuted) {\n this.consecutiveFoldOps = 0;\n this.consecutiveUnknownToolCalls = 0;\n this.recentUnknownToolNames.clear();\n this.recentStaleToolNames.clear();\n }\n\n // Tag tool calls with fold UI metadata before appending results\n const foldPath = this.foldStack.map((f) => f.foldName);\n\n for (const tc of response.toolCalls) {\n if (tc.name === REQUEST_CONTINUATION_TOOL) {\n this.appendToHistory({\n role: 'tool',\n content: '',\n toolResult: { toolCallId: tc.id, content: HANDOFF_TOOL_RESULT_PLACEHOLDER },\n });\n } else {\n const r = executedById.get(tc.id);\n if (r) {\n // Persist only `toolCallId`/`content` on the tool result \u2014 the sub-agent\n // trace lives on the tool *call* (back-patched below from `executedById`),\n // which is what the UI's trace panel and `sumCosts` read. Appending the\n // trace here too would duplicate the entire child conversation in history\n // (and the exported debug log) for no reader.\n this.appendToHistory({\n role: 'tool',\n content: '',\n toolResult: {\n toolCallId: r.toolCallId,\n content: r.content,\n // Images DO persist, unlike the sub-agent trace above: they are the payload\n // the model must see on every replay of this turn, not a one-off UI artefact.\n // `condenseWhen` is what sheds them once they are spent \u2014 see condense-history.\n ...(r.attachments ? { attachments: r.attachments } : {}),\n },\n });\n }\n }\n }\n\n // Back-patch foldEvent and foldPath onto the tool call message we just appended.\n // The response was appended before execution \u2014 find it and annotate.\n let tcMsgIdx = -1;\n for (let i = this.history.length - 1; i >= 0; i -= 1) {\n if (this.history[i].role === 'assistant' && this.history[i].toolCalls?.length) {\n tcMsgIdx = i;\n break;\n }\n }\n if (tcMsgIdx !== -1) {\n const tcMsg = this.history[tcMsgIdx];\n const availableToolNames = Object.keys(this.toolHandlers);\n const annotatedCalls = tcMsg.toolCalls!.map((tc) => {\n const isFoldOpen =\n !!this.getFold(tc.name) ||\n // Was a fold facade at time of the call (now the tool set has changed)\n // \u2014 detect by checking if the result message indicated a fold open\n executedById.get(tc.id)?.content?.startsWith('Fold opened:');\n const isFoldClose = executedById.get(tc.id)?.content?.startsWith('Fold closed:');\n const isUnknown = unknownToolIds.has(tc.id);\n return {\n ...tc,\n foldEvent: isFoldOpen\n ? ('open' as const)\n : isFoldClose\n ? ('close' as const)\n : undefined,\n // Use the fold path that was active at the START of this iteration (before any opens/closes)\n foldPath: !isFoldOpen && !isFoldClose && foldPath.length > 0 ? foldPath : undefined,\n unknown: isUnknown || undefined,\n availableTools: isUnknown ? availableToolNames : undefined,\n // Distinguish a retired tool from a hallucinated one so the UI can\n // say \"no longer available here\" rather than \"does not exist\".\n stale: staleToolIds.has(tc.id) || undefined,\n subAgentTrace: executedById.get(tc.id)?.subAgentTrace,\n };\n });\n this.history[tcMsgIdx] = { ...tcMsg, toolCalls: annotatedCalls };\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n\n if (hitUnknownToolLimit) {\n logger.error(\n `ChatDriver: unknown-tool limit (${DEFAULT_MAX_UNKNOWN_TOOL_CALLS}) reached \u2014 stopping`,\n );\n const unknownTools = [\n ...new Set([\n ...this.recentUnknownToolNames,\n ...(response.toolCalls ?? [])\n .filter((tc) => unknownToolIds.has(tc.id))\n .map((tc) => tc.name),\n ]),\n ];\n // Stale tools were real earlier this activation; hallucinated tools\n // never existed. The hard stop counts both the same way, but the split\n // tells a triager whether the cause is a state/prompt-design problem\n // (stale) or a model inventing tool names (hallucinated).\n const staleTools = [\n ...new Set([\n ...this.recentStaleToolNames,\n ...(response.toolCalls ?? [])\n .filter((tc) => staleToolIds.has(tc.id))\n .map((tc) => tc.name),\n ]),\n ];\n const hallucinatedTools = unknownTools.filter((t) => !staleTools.includes(t));\n recordTurnError(this.sessionKey, 'unknown-tool-limit', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n unknownTools,\n staleTools,\n hallucinatedTools,\n availableTools: Object.keys(this.toolHandlers),\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('unknown_tool_limit');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n \"I'm sorry, I repeatedly tried to use tools that aren't available to me, so I couldn't complete that. If a 'Download agent log' option appears in the Settings (cog) menu, you can download the log and share it with whoever set up this assistant to help fix the issue.\",\n });\n }\n return this.turnDone('unknown-tool-limit');\n }\n\n const firstContinuation = systemCalls[0];\n if (firstContinuation) {\n const { summary, remaining_task: remainingTask } = firstContinuation.args as {\n summary: string;\n remaining_task: string;\n };\n return { reason: 'agent-handoff', summary, remainingTask };\n }\n\n // Sub-agent early exit \u2014 checked here so the exit point mirrors the\n // system-call pattern above. Set by completeSubAgent() in a tool handler.\n if (this.subAgentCompletion) {\n return this.turnDone();\n }\n }\n\n // The loop fell through: either it hit the iteration cap (a failure) or it\n // broke on a clean final answer (success). Only the former carries a reason.\n let failureReason: TurnFailureReason | undefined;\n if (iterations >= this.maxToolIterations) {\n logger.warn('ChatDriver: reached max tool iterations, stopping');\n recordTurnError(this.sessionKey, 'max-iterations', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n iterations,\n limit: this.maxToolIterations,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('max_iterations');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n \"I've reached my limit for this response. You can ask me to continue and I'll pick up where I left off.\",\n });\n }\n failureReason = 'max-iterations';\n }\n\n return this.turnDone(failureReason);\n }\n\n private appendToHistory(message: ChatMessage): void {\n const tagged: ChatMessage = {\n ...message,\n // Stamp on first append; preserve any caller-supplied timestamp.\n timestamp: message.timestamp ?? new Date().toISOString(),\n ...(this.activeAgentName\n ? {\n agentName: this.activeAgentName,\n // Display-only \u2014 falls back to agentName in renderers when unset.\n agentLabel: this.activeAgentLabel,\n }\n : {}),\n };\n this.history = [...this.history, tagged];\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n}\n", "import type {\n AIProviderRegistry,\n ChatAttachment,\n ChatDriverResult,\n ChatMessage,\n ChatRequestOptions,\n} from '@genesislcap/foundation-ai';\nimport { BudgetExhaustedError } from '@genesislcap/foundation-ai';\nimport type { ActivityBus } from '../../channel/ai-activity-bus';\nimport type {\n AgentConfig,\n FallbackAgentConfig,\n SpecialistAgentConfig,\n SystemPromptContext,\n SystemPromptInput,\n} from '../../config/config';\nimport { validateStaticAgentProviders } from '../../config/validate-providers';\nimport { recordMetaEvent } from '../../state/debug-event-log';\nimport type { DiagnosticEntry } from '../../state/persistence/diagnostics';\nimport type { InteractionContext } from '../../types/interaction-context';\nimport { transformHistoryForAgent } from '../../utils/history-transform';\nimport { logger } from '../../utils/logger';\nimport type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';\nimport {\n ChatDriver,\n REQUEST_CONTINUATION_TOOL,\n type TurnSnapshot,\n} from '../chat-driver/chat-driver';\n\nconst DEFAULT_MAX_HANDOFFS = 3;\nconst DEFAULT_CLASSIFIER_HISTORY_LENGTH = 4;\nconst DEFAULT_CLASSIFIER_RETRIES = 2;\n\nconst REQUEST_CONTINUATION_DEFINITION = {\n name: REQUEST_CONTINUATION_TOOL,\n description:\n \"Call this when you have completed your part of the task but fulfilling the user's full request requires capabilities outside your domain. Do not call this if you can complete the request yourself. Pass a plain-language description of what still needs to be done \u2014 another specialist will be selected automatically.\",\n parameters: {\n type: 'object',\n required: ['summary', 'remaining_task'],\n properties: {\n summary: {\n type: 'string',\n description: 'What you found or did \u2014 passed as context to the next specialist.',\n },\n remaining_task: {\n type: 'string',\n description:\n 'What still needs to be done, in plain language. Used to route to the right specialist.',\n },\n },\n },\n};\n\nfunction isSpecialist(agent: AgentConfig): agent is SpecialistAgentConfig {\n return !agent.fallback;\n}\n\nfunction isFallback(agent: AgentConfig): agent is FallbackAgentConfig {\n return agent.fallback === true;\n}\n\nfunction buildFallbackSystemPrompt(\n fallback: FallbackAgentConfig,\n specialists: SpecialistAgentConfig[],\n): SystemPromptInput | undefined {\n const agentList = specialists.map((s) => `- ${s.name}: ${s.description}`).join('\\n');\n if (typeof fallback.systemPrompt === 'string') {\n return fallback.systemPrompt.replace('{{agents}}', agentList);\n }\n if (typeof fallback.systemPrompt === 'function') {\n // Function-form fallback prompt \u2014 pass through unchanged. The `{{agents}}`\n // substitution is a string-template convenience; consumers using the\n // function form can compose the agent list themselves if they want it.\n return fallback.systemPrompt;\n }\n return `You are a helpful assistant. You cannot directly help with the user's request, but the following specialists are available:\\n\\n${agentList}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request.`;\n}\n\n/**\n * Orchestrates multiple specialist agents. Sits between `FoundationAiAssistant`\n * and `ChatDriver`, classifying each user message and routing it to the right\n * specialist \u2014 each with its own focused system prompt, tools, and primer.\n *\n * @beta\n */\nexport class OrchestratingDriver extends EventTarget implements AiDriver {\n private readonly chatDriver: ChatDriver;\n private readonly specialists: SpecialistAgentConfig[];\n private readonly fallback?: FallbackAgentConfig;\n private readonly maxHandoffs: number;\n private readonly classifierHistoryLength: number;\n private readonly classifierRetries: number;\n private readonly sessionKey: string;\n /**\n * Aborted on driver disposal. Threaded into `AgentLifecycleContext.signal`\n * so long-running `onActivate` work can bail if the session disconnects.\n */\n private readonly lifecycleAbortController = new AbortController();\n /**\n * Set by `cancel()` for the duration of a `sendMessage` run. Breaks the\n * handoff loop so we don't classify or start another agent turn after the\n * user stops. Reset at the start of each `sendMessage`.\n */\n private cancelled = false;\n /**\n * Whether the CURRENT turn's user message has reached the inner driver's\n * history. False through the pre-first-turn classify (where the only echo of\n * the message is an optimistic `history-updated` dispatch), true from the\n * moment `chatDriver.sendMessage` is entered \u2014 including through every later\n * handoff classify. Read by the budget-wall catch in `sendMessage` to decide\n * whether `reportBudgetExhausted` must append the message itself: appending\n * it when already appended duplicated it; not appending it when unappended\n * made it vanish. Reset at the top of each `runOrchestratedTurn`.\n */\n private userMessageAppended = false;\n /**\n * Sticky user pick from the picker (or the host's `setAgent` API). Only\n * changes on explicit user action. Survives flow completion: when a stateful\n * agent releases, the user-pin stays put and routing falls back to it on\n * the next turn.\n */\n private pinnedAgentName: string | null = null;\n /**\n * Transient flow lock \u2014 set when a stateful agent's `onActivate` fires,\n * cleared by `releaseActiveAgent`. While non-null, routing precedence goes\n * to this agent and the picker is locked. Independent of\n * `pinnedAgentName` so completing a flow doesn't wipe the user's sticky\n * choice.\n */\n private flowOwnerAgentName: string | null = null;\n\n /**\n * Per-agent restored state for a rehydrated session, keyed by agent name.\n * Primed by the host on restore; each entry is passed to that agent's\n * `onActivate` as `ctx.restored` on its next activation, then deleted so a\n * later re-activation starts fresh.\n */\n private restoredAgentStates: Record<string, unknown> = {};\n\n activeAgent?: AgentConfig;\n\n constructor(\n private readonly providerRegistry: AIProviderRegistry,\n private readonly agents: AgentConfig[],\n options: {\n sessionKey?: string;\n maxHandoffs?: number;\n classifierHistoryLength?: number;\n classifierRetries?: number;\n maxToolIterations?: number;\n maxFoldOperations?: number;\n maxTurnSnapshots?: number;\n /** Activity bus passed through to the inner ChatDriver (browser host injects the singleton). */\n activityBus?: ActivityBus;\n /** Budget-wall transcript copy, passed through to the inner ChatDriver (GENC-1464). */\n budgetExhaustedMessage?: string;\n } = {},\n ) {\n super();\n this.sessionKey = options.sessionKey ?? '';\n this.maxHandoffs = options.maxHandoffs ?? DEFAULT_MAX_HANDOFFS;\n this.classifierHistoryLength =\n options.classifierHistoryLength ?? DEFAULT_CLASSIFIER_HISTORY_LENGTH;\n this.classifierRetries = options.classifierRetries ?? DEFAULT_CLASSIFIER_RETRIES;\n\n // Static-name validation: walk every agent (and nested sub-agents). Any\n // `provider: '<name>'` that isn't registered, or resolves to a provider\n // without `chat()`, throws now rather than at first turn.\n validateStaticAgentProviders(agents, providerRegistry);\n\n // Specialists drive the classifier. `excludeFromClassifier` agents are still\n // resolvable by name (so manual pinning works) but never auto-routed.\n this.specialists = agents.filter(isSpecialist).filter((a) => !a.excludeFromClassifier);\n const fallbacks = agents.filter(isFallback);\n if (fallbacks.length > 1) {\n logger.warn(\n 'OrchestratingDriver: multiple fallback agents found \u2014 only the first will be used.',\n );\n }\n\n const rawFallback = fallbacks[0];\n this.fallback = rawFallback\n ? { ...rawFallback, systemPrompt: buildFallbackSystemPrompt(rawFallback, this.specialists) }\n : undefined;\n\n this.chatDriver = new ChatDriver(providerRegistry, {\n maxToolIterations: options.maxToolIterations,\n maxFoldOperations: options.maxFoldOperations,\n maxTurnSnapshots: options.maxTurnSnapshots,\n sessionKey: this.sessionKey,\n activityBus: options.activityBus,\n budgetExhaustedMessage: options.budgetExhaustedMessage,\n });\n\n // Proxy events from the shared driver\n this.chatDriver.addEventListener('history-updated', (e: Event) => {\n this.dispatchEvent(new CustomEvent('history-updated', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('sub-agent-history-updated', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('sub-agent-history-updated', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('sub-agent-start', (e: Event) => {\n this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('sub-agent-stop', (e: Event) => {\n this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('interaction-start', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('interaction-start', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('interaction-stop', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('interaction-stop', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('provider-changed', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('provider-changed', { detail: (e as CustomEvent).detail }),\n );\n });\n }\n\n resolveInteraction(interactionId: string, result: unknown): void {\n this.chatDriver.resolveInteraction(interactionId, result);\n }\n\n getInteractionContext(interactionId: string): InteractionContext | undefined {\n return this.chatDriver.getInteractionContext(interactionId);\n }\n\n isBusy(): boolean {\n return this.chatDriver.isBusy();\n }\n\n /** Currently active provider name from the underlying ChatDriver. */\n getActiveProviderName(): string {\n return this.chatDriver.getActiveProviderName();\n }\n\n /**\n * Pins routing to a specific agent by name. While pinned, the classifier is\n * skipped and the continuation tool is hidden from the agent's tool list, so\n * the agent cannot quietly hand back to the orchestrator. Pass `null` to\n * return to automatic routing.\n */\n setPinnedAgent(name: string | null): void {\n this.pinnedAgentName = name;\n }\n\n /**\n * Set the flow-owner lock \u2014 used to restore state from Redux on driver\n * reconstruction (agents-array changes, pop-in/pop-out). Not intended for\n * external callers to manipulate routing; that's what `setPinnedAgent` is\n * for.\n */\n setFlowOwner(name: string | null): void {\n this.flowOwnerAgentName = name;\n }\n\n loadHistory(messages: ChatMessage[]): void {\n this.chatDriver.loadHistory(messages);\n }\n\n getRawHistory(): readonly ChatMessage[] {\n return this.chatDriver.getHistory();\n }\n\n /** {@inheritDoc AiDriver.compact} */\n compact(): Promise<ChatMessage | null> {\n return this.chatDriver.compact();\n }\n\n /** {@inheritDoc AiDriver.canCompact} */\n canCompact(): boolean {\n return this.chatDriver.canCompact();\n }\n\n /** Delegates to the inner {@link ChatDriver} \u2014 turns are captured there. */\n getTurnSnapshots(): ReadonlyArray<TurnSnapshot> {\n return this.chatDriver.getTurnSnapshots();\n }\n\n /** Delegates to the inner {@link ChatDriver} \u2014 interactions resolve there, so it holds the buffer. */\n getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry> {\n return this.chatDriver.getExternalDiagnostics();\n }\n\n async getSuggestions(\n history: ChatMessage[],\n prompt: string,\n count: number,\n allAgentInfo?: AllAgentSummary[],\n ): Promise<string[]> {\n // When pinned to a specialist, scope suggestions to that agent so the\n // proposed prompts reflect the active routing instead of the full panel.\n const pinned = this.resolvePinnedAgent();\n const candidates = pinned && isSpecialist(pinned) ? [pinned] : this.specialists;\n const agentInfo = candidates.map((s) => ({\n name: s.name,\n description: s.description,\n // Suggestions use tool names for prompt hints. Dynamic agents resolve\n // their tools per-turn against a SystemPromptContext we don't have here\n // \u2014 pass an empty list rather than invoke the factory with a fake one.\n tools: Array.isArray(s.toolDefinitions) ? s.toolDefinitions : [],\n }));\n return this.chatDriver.getSuggestions(history, prompt, count, agentInfo);\n }\n\n async sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult> {\n try {\n return await this.runOrchestratedTurn(input, attachments);\n } catch (e) {\n // The classifier calls the provider directly, outside any ChatDriver turn,\n // so a budget wall raised there would escape as an unhandled rejection \u2014\n // `FoundationAiAssistant.send()` has a `finally` but no `catch`. Land it on\n // the driver that owns the transcript, which appends the user-facing copy\n // and returns the same terminal result an in-loop wall would.\n //\n // The user's message rides along ONLY while it is genuinely unappended.\n // `classify()` runs at two seams: before the first agent turn \u2014 where the\n // `history-updated` dispatch in `runOrchestratedTurn` is optimistic only\n // and the real append lives inside `chatDriver.sendMessage`, which the\n // wall prevents from ever running \u2014 and again at the END of every handoff\n // iteration, by which point `chatDriver.sendMessage` HAS appended it.\n // Passing the message unconditionally duplicated it on the handoff seam:\n // `['user','assistant','tool','user','assistant']` in the transcript, the\n // snapshot, and the history sent to the model once the budget is raised.\n if (e instanceof BudgetExhaustedError) {\n return this.chatDriver.reportBudgetExhausted(\n e,\n this.userMessageAppended\n ? undefined\n : {\n role: 'user',\n content: input,\n ...(attachments ? { attachments } : {}),\n },\n );\n }\n throw e;\n }\n }\n\n private async runOrchestratedTurn(\n input: string,\n attachments?: ChatAttachment[],\n ): Promise<ChatDriverResult> {\n this.cancelled = false;\n this.userMessageAppended = false;\n const history = this.chatDriver.getHistory() as ChatMessage[];\n\n // Emit the user message immediately so the UI reflects it during the classify\n // round-trip \u2014 without this the chat appears frozen until classify returns.\n this.dispatchEvent(\n new CustomEvent('history-updated', {\n detail: [...history, { role: 'user', content: input, attachments }],\n }),\n );\n\n const pinned = this.resolvePinnedAgent();\n if (!pinned) this.dispatchEvent(new CustomEvent('orchestrating-start'));\n let currentAgent = pinned ?? (await this.classify(input, history, this.activeAgent));\n let isHandoff = false;\n let handoffs = 0;\n let handoffSummary = '';\n let remainingTask = '';\n // The outcome of the agent turn that ENDS the loop \u2014 see the return below.\n let lastResult: ChatDriverResult | undefined;\n\n while (true) {\n // Cancelled before a (next) agent turn started \u2014 e.g. during classify.\n // The chat driver appends its own \"Stopped.\" marker when a turn it was\n // running is cancelled, so we just stop here without a duplicate.\n if (this.cancelled) break;\n\n // oxlint-disable-next-line no-await-in-loop\n await this.applyAgent(currentAgent);\n\n let result: ChatDriverResult;\n if (isHandoff) {\n const contextPrimer: ChatMessage[] = handoffSummary\n ? [{ role: 'user', content: `[Context from previous agent]: ${handoffSummary}` }]\n : [];\n // oxlint-disable-next-line no-await-in-loop\n result = await this.chatDriver.continueFromHistory(contextPrimer);\n } else {\n // From here the inner driver owns the user message \u2014 it appends it as\n // its first act, before any provider call can throw. Set BEFORE the\n // await so a wall raised anywhere inside the turn (or on a later\n // handoff classify) sees the append as done.\n this.userMessageAppended = true;\n // oxlint-disable-next-line no-await-in-loop\n result = await this.chatDriver.sendMessage(input, attachments);\n }\n lastResult = result;\n\n // Release check: a stateful agent called `releaseAgent` from a terminal\n // tool handler. Fire onDeactivate, clear the pin, drop the user back to\n // classifier-mode. The LLM has already emitted its final wrap-up message\n // by the time we get here \u2014 release is purely a teardown.\n if (this.chatDriver.getAgentReleaseRequested()) {\n // oxlint-disable-next-line no-await-in-loop\n await this.releaseActiveAgent();\n break;\n }\n\n // Pinned agents never hand off \u2014 the continuation tool is filtered out in\n // applyAgent, but this guards against a model hallucinating a handoff result.\n if (result.reason !== 'agent-handoff' || isFallback(currentAgent) || pinned) {\n break;\n }\n\n handoffs += 1;\n if (handoffs > this.maxHandoffs) {\n this.appendInlineMessage(\n `I wasn't able to fully complete your request \u2014 the task required more hand-offs between specialists than allowed. Please try breaking your request into smaller steps.`,\n );\n break;\n }\n\n handoffSummary = result.summary;\n remainingTask = result.remainingTask;\n isHandoff = true;\n\n const updatedHistory = this.chatDriver.getHistory() as ChatMessage[];\n this.dispatchEvent(new CustomEvent('orchestrating-start'));\n // oxlint-disable-next-line no-await-in-loop\n currentAgent = await this.classify(remainingTask, updatedHistory);\n }\n\n // The orchestrated turn reports the outcome of the agent turn that ENDED it.\n // The hardcoded `{ reason: 'done' }` that used to live here made every\n // typed failure unreachable for an agents-configured host \u2014 including\n // `'budget-exhausted'`, which the element latches its blocked state off.\n //\n // \"Last wins\" cannot hide an earlier failure behind a later success: a\n // failing inner turn always ends the loop, because the loop only continues\n // on `reason === 'agent-handoff'`. The two breaks that hold a non-'done'\n // result (the handoff cap, and the pinned/fallback break) both carry\n // `'agent-handoff'`, which is an internal routing protocol that must never\n // escape to the host \u2014 the collapse below strips it. A cancel before the\n // first turn leaves `lastResult` undefined; the release break returns the\n // inner turn's real result, which is correct, because that turn ran.\n return lastResult?.reason === 'done' ? lastResult : { reason: 'done' };\n }\n\n async continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult> {\n return this.chatDriver.continueFromHistory(transientPrimer);\n }\n\n /** {@inheritDoc AiDriver.primeRestoredAgentState} */\n primeRestoredAgentState(snapshots: Record<string, unknown>): void {\n this.restoredAgentStates = { ...snapshots };\n }\n\n /** {@inheritDoc AiDriver.getActiveAgent} */\n getActiveAgent(): AgentConfig | undefined {\n return this.activeAgent;\n }\n\n private async applyAgent(agent: AgentConfig): Promise<void> {\n const previousAgent = this.activeAgent;\n const isSwitch = !previousAgent || previousAgent.name !== agent.name;\n\n // Record the agent transition on the debug-log timeline. A `null` `from`\n // marks the initial activation; a named `from` is a handoff between agents.\n if (isSwitch) {\n recordMetaEvent(this.sessionKey, 'agent.handoff', {\n from: previousAgent?.name ?? null,\n to: agent.name,\n // GENC-1351: was a restored snapshot waiting for this agent at activation?\n restored: this.restoredAgentStates[agent.name] !== undefined,\n });\n }\n\n // Fire lifecycle hooks around the swap \u2014 outgoing first, then incoming.\n // Both are awaited so a heavy `onActivate` (e.g. machine restore) completes\n // before the agent's first turn runs.\n if (isSwitch && previousAgent?.onDeactivate) {\n try {\n await previousAgent.onDeactivate({\n agentName: previousAgent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: onDeactivate(\"${previousAgent.name}\") threw:`, e);\n }\n }\n if (isSwitch && agent.onActivate) {\n // On a session restore, hand this agent its persisted state exactly once\n // (consumed here) so a stateful machine resumes at the right step; a later\n // re-activation of the same agent then starts fresh.\n const restored = this.restoredAgentStates[agent.name];\n if (restored !== undefined) delete this.restoredAgentStates[agent.name];\n try {\n await agent.onActivate({\n agentName: agent.name,\n sessionKey: this.sessionKey,\n previousAgentName: previousAgent?.name,\n signal: this.lifecycleAbortController.signal,\n restored,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: onActivate(\"${agent.name}\") threw:`, e);\n }\n }\n\n const hasLifecycleHooks = !!(agent.onActivate || agent.onDeactivate);\n\n // Stateful agents auto-lock the flow on activation. The lock guarantees\n // the machine survives subsequent turns (the classifier would otherwise be\n // free to route away mid-flow, tearing the machine down). Release happens\n // when the agent calls `releaseAgent` from a terminal-state tool handler\n // \u2014 see the post-sendMessage check below. We write `flowOwnerAgentName`\n // rather than `pinnedAgentName` so completing a flow doesn't wipe the\n // user's sticky picker choice.\n if (isSwitch && hasLifecycleHooks && this.flowOwnerAgentName !== agent.name) {\n this.flowOwnerAgentName = agent.name;\n this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: agent.name }));\n }\n\n // Terminal agents do not get the cross-agent handoff tool. Four cases:\n // \u2022 fallback \u2014 already a leaf; handoff would loop\n // \u2022 user-pinned \u2014 user explicitly selected this agent; do not auto-route away\n // \u2022 flow-owner \u2014 a stateful flow is mid-stream; do not auto-route away\n // \u2022 stateful \u2014 agents with lifecycle hooks own state for the duration of\n // their flow. Initiating a handoff mid-flow would abandon\n // that state with no clean exit and dump the user into the\n // classifier mid-machine. Capture the tool loop until the\n // user (or the agent itself, via `releaseAgent`) releases.\n const isTerminal =\n isFallback(agent) ||\n this.pinnedAgentName !== null ||\n this.flowOwnerAgentName !== null ||\n hasLifecycleHooks;\n\n let agentToApply: AgentConfig = agent;\n if (!isTerminal) {\n const declaredTools = agent.toolDefinitions;\n agentToApply = {\n ...agent,\n toolDefinitions:\n typeof declaredTools === 'function'\n ? async (ctx: SystemPromptContext) => [\n ...(await declaredTools(ctx)),\n REQUEST_CONTINUATION_DEFINITION,\n ]\n : [...(declaredTools ?? []), REQUEST_CONTINUATION_DEFINITION],\n };\n }\n\n if (previousAgent && previousAgent.name !== agent.name) {\n const rawHistory = this.chatDriver.getHistory() as ChatMessage[];\n this.chatDriver.loadHistory([\n ...rawHistory,\n { role: 'system-event', content: agent.name, timestamp: new Date().toISOString() },\n ]);\n }\n\n this.chatDriver.setProviderHistoryTransform((h) => transformHistoryForAgent(h, agent.name));\n this.chatDriver.applyAgent(agentToApply);\n this.activeAgent = agent;\n this.dispatchEvent(new CustomEvent('orchestrating-stop'));\n this.dispatchEvent(new CustomEvent('agent-changed', { detail: agent }));\n }\n\n /**\n * Release the current stateful agent: fire `onDeactivate`, clear the\n * flow-owner lock, dispatch events so the host (and Redux) reflect the\n * unlocked state. Called automatically when a tool handler invokes\n * `context.releaseAgent`.\n *\n * The user-pin (`pinnedAgentName`) is intentionally *not* cleared \u2014 a user\n * who explicitly picked this agent should stay on it after the flow ends,\n * so the next message starts a fresh flow on the same agent rather than\n * routing through the classifier.\n */\n private async releaseActiveAgent(): Promise<void> {\n const agent = this.activeAgent;\n if (!agent) return;\n if (agent.onDeactivate) {\n try {\n await agent.onDeactivate({\n agentName: agent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: release onDeactivate(\"${agent.name}\") threw:`, e);\n }\n }\n this.activeAgent = undefined;\n if (this.flowOwnerAgentName !== null) {\n this.flowOwnerAgentName = null;\n this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: null }));\n }\n this.dispatchEvent(new CustomEvent('agent-released', { detail: agent }));\n this.dispatchEvent(new CustomEvent('agent-changed', { detail: undefined }));\n }\n\n /**\n * Stop the current turn (user \"stop\" button). Cancels the inner chat driver's\n * in-flight request and breaks the handoff loop so no further agent turn or\n * classify runs. The driver stays usable for the next message.\n */\n cancel(): void {\n this.cancelled = true;\n this.chatDriver.cancel();\n }\n\n /**\n * Fire `onDeactivate` on the current active agent and abort any pending\n * lifecycle work. Called by the host on session teardown so machines can\n * release resources cleanly.\n */\n async dispose(): Promise<void> {\n const previousAgent = this.activeAgent;\n if (previousAgent?.onDeactivate) {\n try {\n await previousAgent.onDeactivate({\n agentName: previousAgent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: dispose onDeactivate(\"${previousAgent.name}\") threw:`, e);\n }\n }\n this.lifecycleAbortController.abort();\n // Tear down the inner driver too, so any in-flight provider request aborts.\n this.chatDriver.dispose();\n this.activeAgent = undefined;\n }\n\n private async classify(\n input: string,\n history: ChatMessage[],\n contextAgent?: AgentConfig,\n ): Promise<AgentConfig> {\n // Single-candidate short-circuits. No point asking the LLM to route\n // when there's only one viable choice. Skipped if a fallback is\n // configured \u2014 that's an explicit \"escape hatch\" signal from the\n // consumer, and we preserve the LLM's ability to send unrelated\n // messages there by returning -1 from select_agent.\n if (this.specialists.length === 1 && !this.fallback) {\n return this.specialists[0];\n }\n if (this.specialists.length === 0) {\n // No classifier-eligible specialists. If exactly one non-fallback\n // agent exists (typically a stateful agent flagged\n // `excludeFromClassifier`) and there's no fallback to preserve as an\n // escape hatch, route to it \u2014 this is what fixes the previously-\n // silent single-stateful-agent case. Otherwise drop to the fallback;\n // excluded specialists remain reachable via manual pin.\n if (!this.fallback) {\n const routable = this.agents.filter((a) => !isFallback(a));\n if (routable.length === 1) {\n return routable[0];\n }\n }\n return this.fallback ?? { name: 'Assistant', fallback: true };\n }\n\n const agentList = this.specialists\n .map((a, i) => `${i}: ${a.name} \u2014 ${a.description}`)\n .join('\\n');\n\n const recentMessages = history\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .slice(-this.classifierHistoryLength)\n .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)\n .join('\\n');\n\n const continuationHint =\n contextAgent && isSpecialist(contextAgent)\n ? `\\n\\nThe previous turn was handled by \"${contextAgent.name}\". If the new message is a refinement, correction, or continuation of that work, prefer \"${contextAgent.name}\" \u2014 unless the topic has clearly shifted to another specialist's domain.`\n : '';\n\n const classifierPrompt = `You are a routing classifier. Call select_agent with the index of the best matching agent for the user message. Use -1 only if the request is entirely unrelated to every agent listed \u2014 prefer the closest match when in doubt. If the request spans multiple agents, pick the one that should act first; I will re-classify and route again once that agent is done.\\n\\nAgents:\\n${agentList}${continuationHint}${recentMessages ? `\\n\\nRecent conversation:\\n${recentMessages}` : ''}`;\n\n const routingTool = {\n name: 'select_agent',\n description: 'Select the most appropriate agent for the user message.',\n parameters: {\n type: 'object',\n required: ['agent_index'],\n properties: {\n agent_index: {\n type: 'integer',\n description: 'Zero-based index of the matching agent, or -1 if no agent matches.',\n },\n },\n },\n };\n\n // True only when the classifier RAN and answered \"no match\" (index -1). The\n // no-fallback apology below is gated on it: an exhausted-retries exit never\n // earned that apology, and emitting it there put a routing excuse ahead of\n // the real error the routed turn is about to produce.\n let routedNoMatch = false;\n\n for (let attempt = 0; attempt <= this.classifierRetries; attempt += 1) {\n try {\n const options: ChatRequestOptions = {\n systemPrompt: classifierPrompt,\n tools: [routingTool],\n };\n // Classification is orchestrator-level, not bound to any single agent \u2014\n // always run against the registry default.\n const classifierProvider = this.providerRegistry.default();\n if (!classifierProvider.chat) {\n logger.warn(\n 'OrchestratingDriver: default AI provider does not implement chat() \u2014 cannot classify.',\n );\n break;\n }\n // oxlint-disable-next-line no-await-in-loop\n const response = await classifierProvider.chat([], input, options);\n const tc = response.toolCalls?.[0];\n const index = tc?.name === 'select_agent' ? (tc.args.agent_index as number) : -1;\n\n if (index >= 0 && index < this.specialists.length) {\n return this.specialists[index];\n }\n // index === -1 \u2014 fall through to fallback\n routedNoMatch = true;\n break;\n } catch (e) {\n // Terminal: no ladder clears a budget wall. Short-circuit the\n // classifier's own retries the same way 402 short-circuits the\n // transport's \u2014 this loop is a SECOND retry ladder stacked on that one,\n // so without this a single wall costs `classifierRetries + 1` doomed\n // classifier calls and then a doomed fallback turn on top. Deliberately\n // narrow: a generic classifier failure must still retry and fall back.\n if (e instanceof BudgetExhaustedError) throw e;\n logger.warn(`OrchestratingDriver: classifier attempt ${attempt + 1} failed:`, e);\n if (attempt === this.classifierRetries) {\n logger.error('OrchestratingDriver: classifier failed after all retries, using fallback');\n }\n }\n }\n\n if (this.fallback) return this.fallback;\n\n // No fallback configured. Route to the first specialist as a no-op \u2014 but\n // only APOLOGISE when the classifier actually said \"none of these\". On an\n // exhausted-retries exit the classifier never expressed an opinion, so the\n // apology would be a routing excuse the user reads immediately above the\n // real error that turn is about to produce.\n if (routedNoMatch) {\n const specialistNames = this.specialists.map((s) => s.name).join(', ');\n this.appendInlineMessage(\n `I'm not sure how to help with that. I can assist with: ${specialistNames}.`,\n );\n }\n return this.specialists[0];\n }\n\n /**\n * Returns the agent that the current turn is locked to, if any. Flow-owner\n * (transient, set by stateful-agent activation) wins over user-pin (sticky,\n * set by picker click). `undefined` falls back to the classifier.\n *\n * Logs and returns `undefined` if a name no longer matches the agents array\n * \u2014 protects against stale state after an agents-array reassignment.\n */\n private resolvePinnedAgent(): AgentConfig | undefined {\n const name = this.flowOwnerAgentName ?? this.pinnedAgentName;\n if (name === null) return undefined;\n const match = this.agents.find((a) => a.name === name);\n if (!match) {\n logger.warn(\n `OrchestratingDriver: pinned agent \"${name}\" not found in agents array \u2014 falling back to classifier.`,\n );\n return undefined;\n }\n return match;\n }\n\n private appendInlineMessage(content: string): void {\n const history = this.chatDriver.getHistory() as ChatMessage[];\n this.chatDriver.loadHistory([\n ...history,\n { role: 'assistant', content, timestamp: new Date().toISOString() },\n ]);\n this.dispatchEvent(\n new CustomEvent('history-updated', { detail: this.chatDriver.getHistory() }),\n );\n }\n}\n", "import type {\n CachePolicy,\n ChatFallback,\n ChatInputDuringExecutionMode,\n ChatMessage,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n} from '@genesislcap/foundation-ai';\n\nexport type {\n CachePolicy,\n ChatFallback,\n ChatInputDuringExecutionMode,\n ChatThinkingPolicy,\n ChatToolChoice,\n};\n\n/**\n * Context passed to `onActivate` / `onDeactivate` lifecycle hooks on an agent.\n *\n * @beta\n */\nexport interface AgentLifecycleContext {\n /** The agent the hook is firing for. */\n agentName: string;\n /** The assistant session key \u2014 stable across reloads, unique per assistant instance. */\n sessionKey: string;\n /** The agent that was active immediately before this one, if any. Only set on `onActivate`. */\n previousAgentName?: string;\n /** Aborted if the session disconnects mid-activation. */\n signal: AbortSignal;\n /**\n * A previously-serialized state image for this agent (from the agent's\n * `serialize`), passed only on `onActivate` when resuming a persisted\n * session. A stateful\n * agent's `init` rebuilds from it \u2014 e.g. via `restoreMachine` \u2014 or starts\n * fresh when it is `undefined`.\n */\n restored?: unknown;\n}\n\n/**\n * Context passed to an agent's `resumable` predicate (GENC-1351 \u00A75.9), evaluated\n * at session-save time on the active agent (which, for a locked guided flow, is\n * the flow-owner).\n *\n * @beta\n */\nexport interface AgentPersistenceContext {\n /** The agent being consulted. */\n agentName: string;\n /** The assistant session key \u2014 stable across reloads. */\n sessionKey: string;\n /**\n * This agent's just-serialized state image \u2014 the value its `serialize()`\n * returned for this save (or the carried-forward image). Inspect the machine\n * step here. Derive the decision from this (not live closure state): the\n * predicate must be a pure function of the state so a resumable snapshot stays\n * resumable when re-evaluated on restore.\n */\n state: unknown;\n /** Full conversation transcript at save time. */\n messages: ReadonlyArray<ChatMessage>;\n /** True when this agent currently owns the guided flow (`name === flowOwnerAgentName`). */\n isFlowOwner: boolean;\n}\n\n/**\n * Context passed to the function form of `systemPrompt` / `toolDefinitions`.\n * Resolved each tool-loop iteration so the agent can vary what the LLM sees per turn.\n *\n * @beta\n */\nexport interface SystemPromptContext {\n /** The active agent's name. */\n agentName: string;\n /** Full conversation history up to (but not including) the message being processed. */\n history: ReadonlyArray<ChatMessage>;\n /** 0 = first LLM call this turn; > 0 = retry or subsequent tool-loop iteration. */\n turnIndex: number;\n /** Aborted if the turn is cancelled. */\n signal: AbortSignal;\n}\n\n/**\n * System prompt for an agent. Either a static string (resolved once) or a function\n * resolved each tool-loop iteration. The function form lets the agent compute the\n * prompt from external state \u2014 e.g. a state machine's current step.\n *\n * @beta\n */\nexport type SystemPromptInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Tool definitions for an agent. Either a static array (the conventional shape) or\n * a function resolved each tool-loop iteration. The function form lets the agent\n * narrow the tool surface per turn \u2014 e.g. expose only the tools valid in the\n * current state of a state machine.\n *\n * @beta\n */\nexport type ToolDefinitionsInput =\n | ChatToolDefinition[]\n | ((ctx: SystemPromptContext) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>);\n\n/**\n * Tool handlers for an agent. Either a static map (the conventional shape) or a\n * function resolved each tool-loop iteration. The function form lets the agent\n * narrow the dispatchable handler set per turn \u2014 pair it with the function form\n * of `toolDefinitions` so the LLM-visible tools and the dispatchable handlers\n * stay in lockstep, and handlers don't have to defend themselves against being\n * dispatched in states where their tool isn't advertised.\n *\n * @beta\n */\nexport type ToolHandlersInput =\n | ChatToolHandlers\n | ((ctx: SystemPromptContext) => ChatToolHandlers | Promise<ChatToolHandlers>);\n\n/**\n * Names which registered `AIProviderRegistry` entry an agent uses. Either\n * a static string (resolved once at agent registration) or a function resolved\n * each tool-loop iteration \u2014 pick the function form to vary the provider by\n * current state (e.g. a stateful agent that switches providers between\n * machine states).\n *\n * Unknown provider names hard-error: static names at agent registration time,\n * function-resolved names on first resolution.\n *\n * @beta\n */\nexport type ProviderInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Sampling temperature for an agent, normalized to `0`\u2013`1` (`0` = deterministic,\n * `1` = the most random the active provider allows). Either a static number\n * (resolved once) or a function resolved each tool-loop iteration \u2014 pick the\n * function form to vary it by current state (e.g. a lower temperature for a\n * precise extraction step, higher for brainstorming). Each transport translates\n * the normalized value into its own native range. Omit to use the\n * provider/model default. See `ChatRequestOptions.temperature`.\n *\n * @beta\n */\nexport type TemperatureInput = number | ((ctx: SystemPromptContext) => number | Promise<number>);\n\n/**\n * Tool-call mode for an agent. Either a static `ChatToolChoice` (resolved\n * once) or a function resolved each tool-loop iteration \u2014 pick the function form\n * to vary it by current state (e.g. force a classifier tool in an intake step,\n * then `'auto'` everywhere multi-step work happens). Omit to use the default\n * (`'auto'`, except sub-agent turns which force `'required'`).\n *\n * @beta\n */\nexport type ToolChoiceInput =\n | ChatToolChoice\n | ((ctx: SystemPromptContext) => ChatToolChoice | Promise<ChatToolChoice>);\n\n/**\n * Prompt-cache policy for an agent. Either a static `CachePolicy` (resolved once) or a\n * function resolved each tool-loop iteration \u2014 pick the function form to vary it by current state\n * (e.g. cache `'history'` in a long generating phase, `'default'` in short low-touch ones). Omit\n * to request no caching. Resolved and applied the same way as {@link TemperatureInput}.\n *\n * @beta\n */\nexport type CachePolicyInput =\n | CachePolicy\n | ((ctx: SystemPromptContext) => CachePolicy | Promise<CachePolicy>);\n\n/**\n * Extended-thinking posture for an agent \u2014 whether the model reasons before answering. Either a\n * static `ChatThinkingPolicy` or a function resolved **once per user turn**, at the start of the\n * tool loop. Pick the function form to vary it by current state: reason in the state that makes a\n * real decision, and drop it in states that only step a known sequence, where reasoning bills at\n * the full output rate to re-derive what the state machine already knows.\n *\n * Note the resolution point, which differs from every other per-turn input here: a tool-use loop\n * is a single assistant turn and its thinking mode must hold for the whole of it, so this resolver\n * is consulted on the first model call of a turn and its answer reused for the rest. A resolver\n * that returns a different value part-way through a loop will not see it applied until the next\n * user turn.\n *\n * **Omit \u2014 or return `undefined` from the function \u2014 to keep the model's own default**, which is\n * a distinct third state rather than a synonym for either value: Sonnet 5 and Fable 5 think by\n * default, the rest do not. So an agent that leaves this unset, or a resolver that answers\n * `undefined` on some turns, behaves and prices exactly as it did before this option existed.\n *\n * A request, not a guarantee \u2014 transports clamp what a model cannot honour (Fable 5 and Gemini\n * 2.5 Pro always think) and warn once instead of failing the turn. Resolved and applied the same\n * way as {@link TemperatureInput}. See `ChatThinkingPolicy`.\n *\n * @beta\n */\nexport type ThinkingPolicyInput =\n | ChatThinkingPolicy\n | ((\n ctx: SystemPromptContext,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);\n\n/**\n * Per-turn tail context for an agent \u2014 volatile content (current file/spec, diagnostics, live\n * state) injected at the tail of every model-call so the model sees it without invalidating the\n * cached prefix. Either a static string or a function resolved each tool-loop iteration. **Provide\n * raw content** \u2014 the framework frames it (wraps it in a `<system-reminder>` marker) so the model\n * reads it as ambient context, not user input. Omit, or return an empty string, for none.\n *\n * @beta\n */\nexport type TailContextInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Structured-output schema for an agent. When set, the model's final (non-tool) answer is\n * constrained to this JSON Schema instead of free text. Either a static schema or a function\n * resolved each tool-loop iteration \u2014 return the schema on the turn(s) it should apply and\n * `undefined` otherwise, so \"whole-loop\" vs \"finalize-turn\" enforcement is just what the\n * resolver returns (e.g. `({ state }) => state.machine.matches('finalizing') ? schema : undefined`).\n *\n * Orthogonal to {@link ToolChoiceInput}: an agent can carry both `tools` and a `responseSchema`.\n * Each provider applies it natively where possible (Anthropic `output_config.format`, Gemini\n * JSON mode) and degrades gracefully otherwise. The schema is a plain JSON Schema object; keep to\n * the portable subset providers share (`additionalProperties: false`, explicit `required`, enums,\n * `anyOf` for nullables \u2014 no numeric/string constraints or recursion).\n *\n * @beta\n */\nexport type ResponseSchemaInput =\n | object\n | ((ctx: SystemPromptContext) => object | undefined | Promise<object | undefined>);\n\n/**\n * Context passed to an agent's `onUnresolvedTool` hook when the model calls a\n * tool the driver cannot dispatch.\n *\n * @beta\n */\nexport interface UnresolvedToolContext {\n /** The tool name the model attempted to call. */\n toolName: string;\n /**\n * Why the call could not be dispatched:\n * - `'stale'` \u2014 the tool was advertised earlier this activation but is not\n * part of the current step (e.g. a stateful agent has moved on).\n * - `'unknown'` \u2014 the tool was never advertised this activation (a\n * hallucinated name).\n */\n kind: 'stale' | 'unknown';\n /**\n * The tool names dispatchable right now, so the hook can steer the model\n * back to a valid call.\n */\n availableTools: string[];\n}\n\n/**\n * Optional per-agent hook consulted only on the already-failing unresolved-tool\n * path \u2014 when the model calls a tool the driver cannot dispatch. Lets the agent\n * replace the framework's default message with a context-aware redirect.\n *\n * Return a non-empty string to override the default tool-result message; return\n * `undefined` (or an empty/whitespace string, or throw) to fall back to the\n * framework default. The happy path is never affected. See\n * {@link UnresolvedToolContext}.\n *\n * @beta\n */\nexport type UnresolvedToolInput = (\n ctx: UnresolvedToolContext,\n) => string | undefined | Promise<string | undefined>;\n\n/**\n * Opts an agent in to manual selection from the assistant's agent picker.\n *\n * Only applies to top-level agents \u2014 sub-agents are never user-selectable.\n * Has no effect unless the assistant's `agentPicker` is also enabled.\n *\n * @beta\n */\nexport interface ManualSelectionConfig {\n /**\n * Whether this agent appears in the picker.\n */\n enabled: boolean;\n /**\n * Optional short description shown as a tooltip on the picker entry, and as\n * a secondary line in the dropdown variant.\n */\n hint?: string;\n}\n\ninterface BaseAgentConfig {\n /**\n * Stable identity for this agent. Used for classifier routing, manual\n * pinning, and history filtering \u2014 must not vary per turn. For a per-turn\n * display label (e.g. \"Guided Booking (Counterparties)\"), supply\n * {@link BaseAgentConfig.displayName}.\n */\n name: string;\n /**\n * Optional per-turn display label. Resolved each tool-loop iteration and\n * stamped onto outgoing messages (`agentLabel`) and the debug-log timeline.\n * Renderers fall back to `name` when this is unset. Use the function form\n * to vary the label by current state (e.g. a state machine's step).\n *\n * Identity stays on `name` \u2014 this is for UX only.\n */\n displayName?: SystemPromptInput;\n /**\n * System prompt injected into every conversation turn for this agent.\n *\n * Either a string (resolved once) or a function resolved each tool-loop\n * iteration \u2014 pick the function form when the prompt depends on per-turn state\n * (e.g. a state machine's current step). See {@link SystemPromptInput}.\n */\n systemPrompt?: SystemPromptInput;\n /**\n * Tool definitions (JSON Schema) passed to the AI provider for this agent.\n *\n * Either a static array or a function resolved each tool-loop iteration \u2014\n * pick the function form to narrow the tool surface per turn (e.g. expose\n * only the tools valid in the current state of a state machine).\n * See {@link ToolDefinitionsInput}.\n */\n toolDefinitions?: ToolDefinitionsInput;\n /**\n * Tool handler implementations for this agent.\n *\n * Either a static map or a function resolved each tool-loop iteration \u2014\n * pick the function form to narrow the dispatchable handler set per turn,\n * matching the function form of `toolDefinitions`.\n * See {@link ToolHandlersInput}.\n */\n toolHandlers?: ToolHandlersInput;\n /**\n * Which registered AI provider this agent uses, by name. Either a static\n * string (resolved once at agent registration) or a function resolved each\n * tool-loop iteration \u2014 pick the function form to vary the provider by\n * current state (e.g. a stateful agent that switches providers between\n * machine states).\n *\n * Omit to use the registry's default provider. Unknown names hard-error:\n * static names at registration time, function-resolved names on first\n * resolution.\n *\n * Known limitation: switching provider mid-conversation can blow the\n * smaller provider's context window if history accumulated under a\n * larger one. No automatic trimming is performed.\n *\n * @beta\n */\n provider?: ProviderInput;\n /**\n * Sampling temperature for this agent, normalized to `0`\u2013`1`. Either a static\n * number or a function resolved each tool-loop iteration \u2014 pick the function\n * form to vary it by current state. Omit to use the provider/model default.\n * Resolved and applied the same way as {@link BaseAgentConfig.provider}.\n * See {@link TemperatureInput}.\n *\n * @beta\n */\n temperature?: TemperatureInput;\n /**\n * Tool-call mode for this agent \u2014 whether the model may, must, or must not\n * call a tool this turn (and optionally which one). Either a static value or\n * a function resolved each tool-loop iteration \u2014 pick the function form to\n * vary it by current state (e.g. force a single tool at a known juncture).\n * Omit to use the default (`'auto'`, except sub-agent turns which force\n * `'required'`). See {@link ToolChoiceInput}.\n *\n * @beta\n */\n toolChoice?: ToolChoiceInput;\n /**\n * Prompt-cache policy for this agent \u2014 whether to emit cache breakpoints and how far up the\n * prefix. Either a static value or a function resolved each tool-loop iteration (vary by state).\n * Resolved and applied the same way as {@link BaseAgentConfig.temperature}. Omit to request no\n * caching. Provider-neutral \u2014 see {@link CachePolicyInput} / `CachePolicy` for the\n * Anthropic-vs-Gemini behaviour. See {@link CachePolicyInput}.\n *\n * @beta\n */\n cachePolicy?: CachePolicyInput;\n /**\n * Extended-thinking posture for this agent \u2014 whether the model reasons before answering. Either\n * a static value or a function resolved **once per user turn** and held for that turn's whole\n * tool loop (vary by state: `'auto'` where the turn is a genuine decision, `'off'` where it only\n * steps a known sequence and reasoning is billed at the full output rate for no benefit). Omit \u2014\n * or return `undefined` \u2014 to keep the model's own default, which is neither `'auto'` nor `'off'`\n * uniformly. Provider-neutral; transports clamp models that cannot honour it.\n * See {@link ThinkingPolicyInput}.\n *\n * @beta\n */\n thinkingPolicy?: ThinkingPolicyInput;\n /**\n * Volatile per-turn context injected at the tail of every model-call (after the history and any\n * cache breakpoint), so it is seen each turn without busting the cached prefix \u2014 the place to put\n * the changing parts (current file/spec, diagnostics, live state) that would otherwise\n * destabilize a cached system prompt. Provide *raw* content; the framework frames it (wraps it in\n * a `<system-reminder>` marker). Resolved per turn like {@link BaseAgentConfig.temperature}. See\n * {@link TailContextInput}.\n *\n * @beta\n */\n tailContext?: TailContextInput;\n /**\n * Structured-output schema for this agent. When resolved to a schema on a turn, the model's\n * final (non-tool) answer is constrained to it instead of free text. Composes with `tools`;\n * resolved per turn like {@link BaseAgentConfig.cachePolicy}, so returning `undefined` on\n * working turns and the schema on the finalize turn gives finalize-turn enforcement for free.\n * See {@link ResponseSchemaInput}.\n *\n * @beta\n */\n responseSchema?: ResponseSchemaInput;\n /**\n * Refusal-fallback chain for this agent (provider-neutral). If the model declines a turn\n * (`stop_reason: 'refusal'` \u2014 e.g. Fable 5 safety classifiers), the provider re-runs it on the\n * next listed model. Typical use: a Fable 5 agent with `[{ model: 'claude-opus-4-8' }]`. Static\n * (not per-turn); providers that support it apply it server-side, others ignore it.\n *\n * @beta\n */\n fallbacks?: ChatFallback[];\n /**\n * Optional hook consulted when the model calls a tool the driver cannot\n * dispatch \u2014 either a *stale* tool (advertised earlier this activation but\n * not part of the current step) or an *unknown* one (never advertised this\n * activation). Return a context-aware redirect string to replace the\n * framework's default message, or `undefined` to keep it. Consulted only on\n * the already-failing unresolved-tool path; the happy path is unaffected.\n * See {@link UnresolvedToolInput}.\n *\n * @beta\n */\n onUnresolvedTool?: UnresolvedToolInput;\n /**\n * Optional primer history prepended to every call (not visible to the user).\n * Used to establish agent identity and behavioural rules.\n */\n primerHistory?: ChatMessage[];\n /**\n * Sub-agents available to this agent's tool handlers via `requestSubAgent`.\n */\n subAgents?: AgentConfig[];\n /**\n * How the main chat input area behaves while this agent is executing.\n * Defaults to `'disabled'`. See {@link ChatInputDuringExecutionMode}.\n */\n chatInputDuringExecution?: ChatInputDuringExecutionMode;\n /**\n * Opts this agent in to manual selection from the assistant's agent picker.\n * Has no effect on sub-agents or when the assistant's `agentPicker` is\n * disabled. See {@link ManualSelectionConfig}.\n */\n manualSelection?: ManualSelectionConfig;\n /**\n * Fires when this agent becomes the active specialist (including being pinned).\n * Use to instantiate per-agent state that should outlive a single turn \u2014 e.g.\n * a state machine the agent owns across the conversation. Awaited before the\n * agent's first turn runs.\n *\n * Capture dependencies (services, redux store refs, etc.) via closure on the\n * host element rather than expecting them on the context.\n *\n * @beta\n */\n onActivate?: (ctx: AgentLifecycleContext) => void | Promise<void>;\n /**\n * Fires when this agent is being deactivated (the user switches to another\n * agent, the session is torn down, or the agent is unpinned and replaced).\n * Use to dispose per-agent state created in `onActivate`. Awaited before the\n * incoming agent's `onActivate` runs.\n *\n * @beta\n */\n onDeactivate?: (ctx: AgentLifecycleContext) => void | Promise<void>;\n /**\n * Returns an agent-supplied debug payload for the export log. Called once per\n * LLM call by the driver (alongside the resolved prompt and tool list) and\n * once at log-export time for the latest snapshot. Stateful agents should\n * return their machine state and captured context so the exported timeline\n * captures what drove each turn.\n *\n * Return value must be JSON-serializable. {@link defineStatefulAgent} wires a\n * sensible default that snapshots any machine-shaped state automatically.\n *\n * @beta\n */\n getDebugSnapshot?: () => unknown;\n /**\n * Returns a lossless, JSON-serializable image of the agent's state for session\n * persistence \u2014 distinct from `getDebugSnapshot`, which may abbreviate for\n * readability. Pass the value back to the agent on restore (as\n * `ctx.restored` in its `init`) to resume. {@link defineStatefulAgent} wires a\n * default that snapshots any machine-shaped state via `getPersistedSnapshot()`\n * and returns plain state as-is.\n *\n * @beta\n */\n serialize?: () => unknown;\n /**\n * Whether the agent's current state is resumable \u2014 i.e. worth persisting so the\n * session can be restored mid-flow (GENC-1351 \u00A75.9). Consulted at save time on\n * the active agent (the flow-owner during a locked flow). Return `true`\n * (or leave the field absent) to persist and resume normally; return `false`\n * for a point that shouldn't be resumed \u2014 the session is not persisted, and on\n * return the assistant shows {@link AgentConfig.notResumableMessage} (or a\n * default) and pre-fills the composer with the prompt that started the flow so\n * the user can re-run it.\n *\n * Only consulted when the user has persistence enabled. Must be a **pure\n * function of `ctx.state`** \u2014 it may be re-evaluated on a restored snapshot, so\n * a resumable state must stay resumable. A thrown error is treated as `true`\n * (fail-safe: never drop a resumable chat on a predicate bug).\n *\n * @beta\n */\n resumable?: (ctx: AgentPersistenceContext) => boolean | Promise<boolean>;\n /**\n * Message shown on return when {@link AgentConfig.resumable} returned `false`\n * and the user comes back to a non-resumable session (GENC-1351 \u00A75.9). Falls\n * back to a built-in default when omitted.\n *\n * @beta\n */\n notResumableMessage?: string;\n}\n\n/**\n * Configuration for a specialist agent.\n *\n * Specialist agents are offered to the classifier for intent routing. The\n * `description` is used to auto-generate the classifier prompt \u2014 no manual\n * routing prompt authoring required.\n *\n * @beta\n */\nexport interface SpecialistAgentConfig extends BaseAgentConfig {\n /**\n * Plain-language description of what this agent handles.\n * Used by the classifier to auto-generate its routing prompt.\n */\n description: string;\n fallback?: never;\n /**\n * When `true`, the classifier never auto-routes to this agent. The user can\n * still select it manually via the picker, provided both prerequisites are\n * met: this agent has `manualSelection.enabled` set to `true`, *and* the\n * assistant has the picker enabled via `chatConfig.picker.mode`.\n *\n * Use this for agents that overlap heavily with a sibling (e.g. a guided\n * wizard sitting next to a free-form agent in the same domain) and should\n * only be reached intentionally rather than via classifier routing.\n *\n * @beta\n */\n excludeFromClassifier?: boolean;\n}\n\n/**\n * Configuration for a fallback agent.\n *\n * Invoked when the classifier returns no match. Excluded from the classifier\n * prompt. Only one fallback is permitted per agents array.\n *\n * @beta\n */\nexport interface FallbackAgentConfig extends BaseAgentConfig {\n /**\n * Marks this agent as the fallback for unrecognised requests.\n */\n fallback: true;\n description?: never;\n}\n\n/**\n * Configuration for an agent passed to `FoundationAiAssistant`.\n *\n * Either a specialist (requires `description`) or a fallback (requires\n * `fallback: true`). Passing both or neither is a compile error.\n *\n * @beta\n */\nexport type AgentConfig = SpecialistAgentConfig | FallbackAgentConfig;\n\n/**\n * Identity helper that infers the narrowest possible type for an agent config,\n * preserving string literal types (including `name`) without requiring `as const`.\n *\n * Use this when you need `typeof myAgent` to carry the literal `name` type \u2014\n * for example, when wiring `ChatToolHandlers<typeof myAgent>`.\n *\n * ```ts\n * const myAgent = defineAgent({ name: 'my_agent', ... });\n * type Handlers = ChatToolHandlers<typeof myAgent>;\n * // requestSubAgent name param is now typed as 'my_agent'\n * ```\n *\n * @beta\n */\n\nexport function defineAgent<const T extends AgentConfig>(config: T): T {\n return config;\n}\n", "import type {\n CachePolicy,\n ChatMessage,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n} from '@genesislcap/foundation-ai';\nimport { TOOL_FOLD_SYMBOL } from '../utils/tool-fold';\nimport type {\n AgentConfig,\n AgentLifecycleContext,\n AgentPersistenceContext,\n CachePolicyInput,\n ChatInputDuringExecutionMode,\n ManualSelectionConfig,\n ProviderInput,\n SystemPromptContext,\n SystemPromptInput,\n TailContextInput,\n TemperatureInput,\n ThinkingPolicyInput,\n ToolChoiceInput,\n ToolDefinitionsInput,\n ToolHandlersInput,\n UnresolvedToolContext,\n UnresolvedToolInput,\n} from './config';\n\n/**\n * Context passed to per-turn resolvers on a stateful agent \u2014 the standard\n * {@link SystemPromptContext} plus the live `state` value. Used by\n * `systemPrompt`, `displayName`, and the function form of `toolDefinitions`.\n *\n * Exported so consumers can lift resolvers into separate files without\n * re-deriving the shape.\n *\n * @beta\n */\nexport type StatefulAgentContext<S> = SystemPromptContext & { state: S };\n\n/**\n * Context passed to a stateful agent's `resumable` predicate (GENC-1351 \u00A75.9) \u2014\n * the standard {@link AgentPersistenceContext} but with `state` as the **live**\n * state bag `S` (not the serialized image), so a machine agent can gate on its\n * current step directly.\n *\n * @beta\n */\nexport type StatefulAgentPersistenceContext<S> = Omit<AgentPersistenceContext, 'state'> & {\n state: S;\n};\n\n/**\n * Init options for {@link defineStatefulAgent}. Generic over the state shape `S`\n * the agent owns (a state machine, an observable controller, anything).\n *\n * The helper threads `state` through `systemPrompt`, `toolDefinitions`, and the\n * `toolHandlers` factory so consumer code never has to reach for a closure or\n * a module-level mutable.\n *\n * @beta\n */\nexport interface StatefulAgentInit<S> {\n /** Display name \u2014 must be unique within the agents array. */\n name: string;\n /** Plain-language description used by the classifier. Required: stateful agents are always specialists. */\n description: string;\n /**\n * Hide this agent from the classifier \u2014 only reachable via manual pinning.\n * Stateful agents are always specialists; they cannot be the fallback (a\n * fallback is a leaf invoked when no specialist matches, with no flow to\n * own state for).\n */\n excludeFromClassifier?: boolean;\n /** Static primer history prepended to every call (not visible to the user). */\n primerHistory?: ChatMessage[];\n /** Sub-agents available to this agent's tool handlers via `requestSubAgent`. */\n subAgents?: AgentConfig[];\n /** Opt this agent in to manual picker selection. */\n manualSelection?: ManualSelectionConfig;\n /** How the main chat input behaves while this agent is executing. */\n chatInputDuringExecution?: ChatInputDuringExecutionMode;\n\n /**\n * Construct the agent-scoped state. Called by the framework when this agent\n * becomes active (`onActivate`). Awaited before the agent's first turn runs.\n *\n * On a persisted-session restore, `ctx.restored` carries this agent's previous\n * `serialize` output \u2014 rebuild from it (e.g. via `restoreMachine`), or start\n * fresh when it is `undefined`.\n */\n init: (ctx: AgentLifecycleContext) => S | Promise<S>;\n\n /**\n * Tear down the agent-scoped state. Called when the agent is being replaced.\n * Awaited before the incoming agent's `init` runs.\n */\n dispose?: (ctx: AgentLifecycleContext & { state: S }) => void | Promise<void>;\n\n /**\n * System prompt composed from current state. Resolved each tool-loop\n * iteration. Use this to feed the LLM whatever the current state implies\n * (e.g. a state machine's `meta.systemPrompt` plus captured context).\n */\n systemPrompt?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;\n\n /**\n * Per-turn display label, e.g. \"Guided Booking (Counterparties)\". Resolved\n * each tool-loop iteration and stamped onto outgoing messages and the\n * debug-log timeline \u2014 display only. The agent's `name` stays as the\n * canonical identity used for routing/history filtering.\n */\n displayName?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;\n\n /**\n * Tool definitions the LLM sees. Either a static array (resolved once) or a\n * function resolved each tool-loop iteration. The function form is how a\n * machine-driven agent narrows the surface per state.\n *\n * **Constraint:** the resolved handlers (returned from {@link StatefulAgentInit.toolHandlers})\n * must not include fold facades. Folds are an LLM-driven UX optimisation\n * that competes with the machine for control of the tool view; one of them\n * has to be in charge. Helper throws at init time if a fold-tagged handler\n * is detected.\n */\n toolDefinitions?:\n | ChatToolDefinition[]\n | ((ctx: StatefulAgentContext<S>) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>);\n\n /**\n * Factory returning the handler map for the **current state**. Called each\n * tool-loop iteration with the live `state` value, so the handler set the\n * driver dispatches against matches what `toolDefinitions` exposes to the\n * LLM that turn. Return only the handlers valid right now \u2014 no need to\n * advertise every handler the agent might ever expose, and no defensive\n * `if (!machine.matches(...))` guards inside each handler.\n *\n * Pair with the function form of `toolDefinitions` so the visible tools and\n * the dispatchable handlers stay in lockstep.\n *\n * **Constraint:** resolved handlers must not include fold facades. Folds and\n * state-machine-driven tool filtering both try to control the LLM's tool\n * view \u2014 pick one. Helper samples once on activation (init state) and\n * throws if a fold-tagged handler is detected; subsequent resolves also\n * validate, so misuse on a non-init state surfaces when that state is\n * reached.\n */\n toolHandlers?: (state: S) => ChatToolHandlers | Promise<ChatToolHandlers>;\n\n /**\n * Which registered AI provider this agent uses, by name. Either a static\n * string or a function resolved each tool-loop iteration with the current\n * `state` \u2014 pick the function form to vary provider per machine state\n * (e.g. swap to a heavier model only for the planning step).\n *\n * Omit to use the registry's default provider. Unknown names hard-error.\n */\n provider?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);\n\n /**\n * Sampling temperature, normalized to `0`\u2013`1`. Either a static number or a\n * function resolved each tool-loop iteration with the current `state` \u2014 pick\n * the function form to vary it per machine state (e.g. low for a precise\n * extraction step, higher for free-form drafting). Omit for the default.\n */\n temperature?: number | ((ctx: StatefulAgentContext<S>) => number | Promise<number>);\n\n /**\n * Tool-call mode. Either a static `ChatToolChoice` or a function\n * resolved each tool-loop iteration with the current `state` \u2014 pick the\n * function form to force a specific tool in one state (e.g. a classifier in\n * intake) and leave `'auto'` in states where multi-step work happens. Omit\n * for the default.\n */\n toolChoice?:\n | ChatToolChoice\n | ((ctx: StatefulAgentContext<S>) => ChatToolChoice | Promise<ChatToolChoice>);\n\n /**\n * Prompt-cache policy. Either a static `CachePolicy` or a function resolved each tool-loop\n * iteration with the current `state` \u2014 pick the function form to vary it per machine state\n * (e.g. `'history'` in a long generating phase, `'default'` in short low-touch ones). Omit to\n * request no caching.\n */\n cachePolicy?:\n | CachePolicy\n | ((ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>);\n\n /**\n * Extended-thinking posture. Either a static `ChatThinkingPolicy` or a function resolved with\n * the current `state` **once per user turn** \u2014 the function form is the point of this option on\n * a machine agent: `'auto'` in the state that makes a real decision, `'off'` in the states that\n * only step a known sequence, where reasoning is billed at the full output rate to re-derive\n * what the machine already knows. Omit, or return `undefined` from the function, to keep the\n * model's own default for that turn.\n *\n * Resolved once per turn rather than per tool-loop iteration (unlike `temperature` and\n * `toolChoice`): a tool-use loop is one assistant turn and its thinking mode must hold for the\n * whole of it. A state transition part-way through a loop therefore takes effect on the next\n * user turn, not immediately.\n */\n thinkingPolicy?:\n | ChatThinkingPolicy\n | ((\n ctx: StatefulAgentContext<S>,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);\n\n /**\n * Volatile per-turn tail context (current file/spec, diagnostics, live state). Either a static\n * string or a function resolved each tool-loop iteration with the current `state`. Provide raw\n * content; the framework frames it. Omit, or return an empty string, for none.\n */\n tailContext?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);\n\n /**\n * Hook consulted when the model calls a tool that isn't dispatchable in the\n * current state \u2014 a *stale* tool (valid in an earlier state of this agent) or\n * an *unknown* one. Receives the current `state` alongside the attempted tool\n * name and the currently dispatchable tools, so a machine-driven agent can\n * return a step-aware redirect (e.g. \"that belongs to a later step \u2014 finish\n * this one first\"). Return `undefined` to keep the framework default; a\n * pre-init call also degrades to the default rather than throwing.\n * See {@link UnresolvedToolContext}.\n */\n onUnresolvedTool?: (\n ctx: UnresolvedToolContext & { state: S },\n ) => string | undefined | Promise<string | undefined>;\n\n /**\n * Optional getter for the debug-log snapshot. Defaults to auto-snapshotting\n * any property on `state` that looks like a foundation-state-machine\n * instance (has `state`, `context`, and `complete` fields). Override when\n * the default doesn't capture what you need \u2014 e.g. multiple machines, or\n * non-machine state worth recording.\n *\n * Return value must be JSON-serializable.\n */\n getDebugSnapshot?: (state: S) => unknown;\n\n /**\n * Lossless serializer for session persistence \u2014 infra-agnostic. Return any\n * JSON/structured-clone-safe image of `state`.\n * \u2022 Machine agents (`{ machine }`): omit \u2014 the default snapshots every\n * machine-shaped property via `getPersistedSnapshot()`.\n * \u2022 Plain-data agents (e.g. `{ plan, cursor }`): omit too \u2014 the default\n * returns plain state as-is. Provide one only when the state holds\n * something the default can't capture.\n * Distinct from `getDebugSnapshot` (which may be lossy by design). Pair with\n * `init` reading `ctx.restored` to rebuild.\n */\n serialize?: (state: S) => unknown;\n\n /**\n * Whether the agent's current state is resumable \u2014 worth persisting so the\n * session restores mid-flow (GENC-1351 \u00A75.9). Receives the **live** state bag\n * `S` (like the other per-turn resolvers), so a machine agent gates on its step\n * directly: `resumable: ({ state }) => state.machine.state !== 'confirm'`.\n * Return `false` for a point that shouldn't resume \u2014 the session isn't persisted,\n * and on return the assistant shows {@link StatefulAgentInit.notResumableMessage}\n * (or a default) and pre-fills the composer with the prompt that started the flow.\n * Only consulted with persistence enabled; a thrown error is treated as `true`\n * (fail-safe \u2014 never drop a resumable chat on a predicate bug).\n */\n resumable?: (ctx: StatefulAgentPersistenceContext<S>) => boolean | Promise<boolean>;\n /**\n * Message shown on return when {@link StatefulAgentInit.resumable} returned\n * `false`. Falls back to a built-in default when omitted.\n */\n notResumableMessage?: string;\n}\n\n/**\n * Walk a state object and snapshot any machine-shaped values found on it.\n * Recognises foundation-state-machine instances by structural shape rather\n * than `instanceof`, so the helper stays free of a runtime dep on\n * foundation-state-machine.\n *\n * Strips the `errors`/`error` framework noise from each machine's context \u2014\n * these are foundation-state-machine internals (an ErrorMap instance and its\n * last-error pointer) that bloat the debug payload without aiding debugging.\n */\nfunction defaultStatefulDebugSnapshot(state: unknown): unknown {\n if (!state || typeof state !== 'object') return state;\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(state as Record<string, unknown>)) {\n if (val && typeof val === 'object' && 'state' in val && 'context' in val && 'complete' in val) {\n const m = val as {\n state: unknown;\n context: Record<string, unknown>;\n complete: unknown;\n output?: unknown;\n };\n const ctx = m.context ?? {};\n const { errors: _e, error: _err, ...userContext } = ctx;\n result[key] = {\n state: m.state,\n context: userContext,\n complete: m.complete,\n output: m.output,\n };\n }\n }\n return Object.keys(result).length\n ? result\n : '<no auto-snapshot \u2014 state has no machine-shaped properties; provide getDebugSnapshot>';\n}\n\n/**\n * Build a restore-ready snapshot of agent state. Each property exposing a\n * `getPersistedSnapshot()` method (a foundation-state-machine `AbstractMachine`)\n * is replaced by its persisted snapshot \u2014 the lossless, JSON-safe image\n * {@link restoreMachine} feeds back via `start({ state })`. Every other property\n * is kept as-is, so plain serializable state (e.g. a planner's `{ plan, cursor }`)\n * round-trips directly with no per-agent `serialize`.\n *\n * Distinct from `defaultStatefulDebugSnapshot`, which abbreviates for the debug\n * log and is not guaranteed lossless.\n */\nfunction defaultStatefulSerialize(state: unknown): unknown {\n if (!state || typeof state !== 'object') return state;\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(state as Record<string, unknown>)) {\n result[key] =\n val &&\n typeof val === 'object' &&\n typeof (val as { getPersistedSnapshot?: unknown }).getPersistedSnapshot === 'function'\n ? (val as { getPersistedSnapshot: () => unknown }).getPersistedSnapshot()\n : val;\n }\n return result;\n}\n\n/**\n * Restore a foundation-state-machine instance from a snapshot produced by the\n * default serializer (or `machine.getPersistedSnapshot()`). Call inside a\n * stateful agent's `init` to resume the machine in its exact prior place:\n *\n * ```ts\n * init: ({ restored }) => {\n * const machine = new MyMachine();\n * restoreMachine(machine, restored); // resume, or no-op on a fresh start\n * return { machine };\n * }\n * ```\n *\n * No-ops when there is nothing to restore (a fresh session), leaving the\n * freshly-constructed machine in its initial state.\n *\n * @param machine - the machine to restore (already constructed/started).\n * @param restored - the agent's serialized image (`ctx.restored` in `init`).\n * @param key - the property the machine occupies in the snapshot; defaults to\n * `'machine'` to match the conventional `{ machine }` state bag.\n * @beta\n */\nexport function restoreMachine(\n machine: { stop: () => void; start: (options?: { state?: unknown }) => void },\n restored: unknown,\n key = 'machine',\n): void {\n const snapshot = (restored as Record<string, unknown> | undefined)?.[key];\n if (snapshot === undefined || snapshot === null) {\n return;\n }\n machine.stop();\n machine.start({ state: snapshot });\n}\n\n/**\n * Build an `AgentConfig` whose `systemPrompt`, `toolDefinitions`, and tool\n * handlers all close over a long-lived state object created on activation.\n *\n * The framework wires the lifecycle: `init` on `onActivate`, `dispose` on\n * `onDeactivate`. State is held inside the helper's closure \u2014 never exposed on\n * the resulting `AgentConfig` \u2014 so the redux serializer doesn't see it.\n *\n * @example\n * ```ts\n * const guidedBooking = defineStatefulAgent<{ machine: GuidedBookingMachine }>({\n * name: 'Guided Booking',\n * description: 'Books a trade via a guided wizard.',\n * excludeFromClassifier: true,\n * manualSelection: { enabled: true, hint: 'Step-by-step trade booking' },\n * init: () => ({ machine: new GuidedBookingMachine() }),\n * dispose: ({ state }) => state.machine.stop(),\n * systemPrompt: ({ state }) => composeFromMachine(state.machine),\n * toolDefinitions: ({ state }) => toolsForState(state.machine.state),\n * toolHandlers: ({ machine }) => ({ ... }),\n * });\n * ```\n *\n * @beta\n */\nexport function defineStatefulAgent<S>(opts: StatefulAgentInit<S>): AgentConfig {\n let state: S | undefined;\n\n const assertNoFolds = (handlers: ChatToolHandlers): void => {\n for (const [name, handler] of Object.entries(handlers)) {\n if ((handler as any)[TOOL_FOLD_SYMBOL]) {\n throw new Error(\n `Stateful agent \"${opts.name}\" tool \"${name}\" carries fold metadata. ` +\n `Folds and state-machine-driven tool filtering both try to control the ` +\n `LLM's tool view \u2014 pick one. Remove the fold or migrate this agent to ` +\n `a non-stateful AgentConfig.`,\n );\n }\n }\n };\n\n // Wrap the optional dynamic-tools factory so it threads `state` in and asserts\n // we never accidentally resolved a fold-tagged tool. Static arrays are passed\n // through unchanged.\n const wrappedTools: ToolDefinitionsInput | undefined = (() => {\n const td = opts.toolDefinitions;\n if (typeof td === 'function') {\n return async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" tools called before init`);\n }\n return td({ ...ctx, state });\n };\n }\n return td;\n })();\n\n // Wrap the handler factory into the ctx-shaped form the driver expects, and\n // validate folds on each resolve. The driver re-resolves this per tool-loop\n // iteration, so the handler set the driver dispatches against always\n // matches the LLM-visible tools for the current state \u2014 handlers don't need\n // defensive `if (!machine.matches(...))` guards.\n const wrappedHandlers: ToolHandlersInput | undefined = opts.toolHandlers\n ? async () => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" handlers called before init`);\n }\n const handlers = await opts.toolHandlers!(state);\n assertNoFolds(handlers);\n return handlers;\n }\n : undefined;\n\n const wrappedDisplayName: SystemPromptInput | undefined = opts.displayName\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" displayName called before init`);\n }\n return opts.displayName!({ ...ctx, state });\n }\n : undefined;\n\n // Function-form `provider` needs `state` injected the same way the other\n // per-turn resolvers do; the static-string form is passed through unchanged\n // and validated up-front by OrchestratingDriver.\n const wrappedProvider: ProviderInput | undefined =\n typeof opts.provider === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" provider called before init`);\n }\n return (opts.provider as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({\n ...ctx,\n state,\n });\n }\n : opts.provider;\n\n // `temperature` and `toolChoice` thread `state` in exactly like `provider`;\n // static values pass through unchanged.\n const wrappedTemperature: TemperatureInput | undefined =\n typeof opts.temperature === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" temperature called before init`);\n }\n return (opts.temperature as (ctx: StatefulAgentContext<S>) => number | Promise<number>)({\n ...ctx,\n state,\n });\n }\n : opts.temperature;\n\n const wrappedToolChoice: ToolChoiceInput | undefined =\n typeof opts.toolChoice === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" toolChoice called before init`);\n }\n return (\n opts.toolChoice as (\n ctx: StatefulAgentContext<S>,\n ) => ChatToolChoice | Promise<ChatToolChoice>\n )({ ...ctx, state });\n }\n : opts.toolChoice;\n\n const wrappedCachePolicy: CachePolicyInput | undefined =\n typeof opts.cachePolicy === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" cachePolicy called before init`);\n }\n return (\n opts.cachePolicy as (ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>\n )({ ...ctx, state });\n }\n : opts.cachePolicy;\n\n // Unlike the resolvers above, a pre-init call returns `undefined` rather than throwing: that is\n // this option's \"model default\" state, so degrading to it costs a turn its thinking preference\n // instead of breaking the turn outright.\n const wrappedThinkingPolicy: ThinkingPolicyInput | undefined =\n typeof opts.thinkingPolicy === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) return undefined;\n return (\n opts.thinkingPolicy as (\n ctx: StatefulAgentContext<S>,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>\n )({ ...ctx, state });\n }\n : opts.thinkingPolicy;\n\n const wrappedTailContext: TailContextInput | undefined =\n typeof opts.tailContext === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" tailContext called before init`);\n }\n return (opts.tailContext as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({\n ...ctx,\n state,\n });\n }\n : opts.tailContext;\n\n // `onUnresolvedTool` threads `state` in like the resolvers above, but unlike\n // them returns `undefined` before init rather than throwing: it fires on the\n // tool-dispatch path, so a pre-init call must degrade to the framework\n // default instead of breaking dispatch.\n const wrappedOnUnresolvedTool: UnresolvedToolInput | undefined =\n typeof opts.onUnresolvedTool === 'function'\n ? async (ctx) => {\n if (!state) {\n return undefined;\n }\n return opts.onUnresolvedTool!({ ...ctx, state });\n }\n : opts.onUnresolvedTool;\n\n // `resumable` threads the LIVE state bag in (like the resolvers above) rather\n // than the serialized image the raw `AgentConfig` form receives \u2014 so a machine\n // agent gates on `state.machine.state` directly. Consulted only while active\n // (state is set); a pre-init call degrades to `true` (resumable, fail-safe).\n const wrappedResumable: AgentConfig['resumable'] | undefined = opts.resumable\n ? async (ctx: AgentPersistenceContext): Promise<boolean> => {\n if (state === undefined) return true;\n return opts.resumable!({\n agentName: ctx.agentName,\n sessionKey: ctx.sessionKey,\n messages: ctx.messages,\n isFlowOwner: ctx.isFlowOwner,\n state,\n });\n }\n : undefined;\n\n const base = {\n name: opts.name,\n displayName: wrappedDisplayName,\n primerHistory: opts.primerHistory,\n subAgents: opts.subAgents,\n manualSelection: opts.manualSelection,\n chatInputDuringExecution: opts.chatInputDuringExecution,\n toolDefinitions: wrappedTools,\n toolHandlers: wrappedHandlers,\n provider: wrappedProvider,\n temperature: wrappedTemperature,\n toolChoice: wrappedToolChoice,\n cachePolicy: wrappedCachePolicy,\n thinkingPolicy: wrappedThinkingPolicy,\n tailContext: wrappedTailContext,\n onUnresolvedTool: wrappedOnUnresolvedTool,\n resumable: wrappedResumable,\n notResumableMessage: opts.notResumableMessage,\n\n onActivate: async (ctx: AgentLifecycleContext) => {\n state = await opts.init(ctx);\n // Sample once with the init state to fail loud on fold misuse at the\n // agent-switch boundary instead of waiting for the first tool call.\n // The driver re-resolves the factory each iteration, so misuse on\n // handlers gated behind a non-init state surfaces when that state is\n // reached \u2014 same loud failure mode, narrower coverage.\n if (opts.toolHandlers) {\n const sampled = await opts.toolHandlers(state);\n assertNoFolds(sampled);\n }\n },\n\n onDeactivate: async (ctx: AgentLifecycleContext) => {\n if (state !== undefined && opts.dispose) {\n await opts.dispose({ ...ctx, state });\n }\n // Orchestrator serializes onActivate/onDeactivate; concurrent calls\n // cannot interleave the read-then-write of `state`.\n // eslint-disable-next-line require-atomic-updates\n state = undefined;\n },\n\n systemPrompt: opts.systemPrompt\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" systemPrompt called before init`);\n }\n return opts.systemPrompt!({ ...ctx, state });\n }\n : undefined,\n\n // Called per LLM call by ChatDriver, and once at debug-log export time.\n // Returns `undefined` before activation (state hasn't been built yet) and\n // after deactivation (state was disposed) \u2014 the snapshotter is best-effort\n // and the driver tolerates undefined.\n getDebugSnapshot: () => {\n if (!state) return undefined;\n return opts.getDebugSnapshot\n ? opts.getDebugSnapshot(state)\n : defaultStatefulDebugSnapshot(state);\n },\n\n // Lossless restore image for session persistence (see `serialize` on the\n // config). Returns undefined before activation / after disposal.\n serialize: () => {\n if (state === undefined) return undefined;\n return opts.serialize ? opts.serialize(state) : defaultStatefulSerialize(state);\n },\n };\n\n return {\n ...base,\n description: opts.description,\n excludeFromClassifier: opts.excludeFromClassifier,\n } as AgentConfig;\n}\n", "import type { FallbackAgentConfig } from './config';\n\n/**\n * A warm, conversational fallback agent. Acknowledges it can't help directly,\n * explains what the available specialists can do, and invites the user to retry.\n *\n * The system prompt is generated at runtime by `OrchestratingDriver` from the\n * specialist list \u2014 no manual authoring required.\n *\n * @beta\n */\nexport const friendlyFallbackAgent: FallbackAgentConfig = {\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a warm, friendly assistant. For general conversation like \"Hi\" or \"How are you\", you can have a friendly chat. For anything more complex, you cannot directly help, but you can explain what specialists are available. The available specialists are:\\n\\n{{agents}}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request if it is outside your scope.`,\n};\n\n/**\n * A brief, professional fallback agent. States what is available without\n * elaboration. The `{{agents}}` placeholder is replaced at runtime by\n * `OrchestratingDriver` with the generated specialist list.\n *\n * @beta\n */\nexport const strictFallbackAgent: FallbackAgentConfig = {\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a concise assistant. The user's request is outside your scope. Respond with a single short sentence stating what you can assist with. Do not elaborate. The available specialists are: {{agents}}.`,\n};\n", "import type { AggregateUsage, AIProviderType, ChatMessage } from '@genesislcap/foundation-ai';\nimport { vendorOfModel } from '@genesislcap/foundation-ai';\n\n/**\n * One billable unit of spend, projected out of a transcript.\n *\n * @remarks\n * Deliberately **not** a `ChatMessage`, and not an extension of one. A row is a\n * derived record for a ledger, and keeping the types distinct makes the one\n * dangerous mistake \u2014 feeding rows back into `sumUsage`, which does its own\n * recursion and would count everything twice \u2014 a compile error rather than a\n * plausible wrong number.\n *\n * @beta\n */\nexport interface UsageRow {\n /**\n * Where the spend came from.\n *\n * - `'request'` \u2014 one model call, with a message behind it.\n * - `'compaction'` \u2014 spend **banked** by a compaction. The turns that incurred it\n * were summarised and deleted, so there is no single call to attribute it to;\n * the amount survives on the summary's `compaction.rolledUpUsage`. Emitted as\n * its own row because otherwise this money is simply missing from a per-call\n * view while remaining present in the total, and the two disagree silently.\n */\n source: 'request' | 'compaction';\n /**\n * Model that produced the call. `undefined` on a `'compaction'` row: the banked\n * spend covers however many turns were summarised, which may have run on\n * different models, so attributing it to one would invent a fact. (The summary's\n * `compaction.model` is the model that did the *summarising* \u2014 a different thing,\n * and not what this spend was.)\n */\n model?: string;\n /**\n * Vendor that served the call. Taken from the provider the driver stamped on the message,\n * which is authoritative and covers vendors the model allowlists do not \u2014 a server-proxied\n * `gpt-5` turn is `'openai'` here and unknown to `vendorOfModel`. Falls back to resolving\n * {@link UsageRow.model} through `vendorOfModel` only for messages persisted before that\n * field existed, and is left unset when neither knows rather than guessed at.\n */\n provider?: AIProviderType;\n /**\n * USD for this row, as reported by the provider and stamped by the transport.\n *\n * `undefined` means no cost was reported \u2014 **not** zero. Nothing here estimates\n * one from the token counts: an estimate is plausible, unremarkable and quietly\n * wrong, whereas a total that is visibly too low gets investigated. A row with\n * tokens but no `costUsd` is worth alarming on; that is the shape that check needs.\n */\n costUsd?: number;\n /** Non-LLM spend a host reported for this turn (an external service it called). */\n externalCostUsd?: number;\n /** Prompt tokens billed at the full uncached rate \u2014 the remainder after the cache buckets. */\n uncachedInputTokens: number;\n /** Prompt tokens served from the provider's cache. */\n cacheReadTokens: number;\n /** Prompt tokens written to the provider's cache. */\n cacheWriteTokens: number;\n /** Generated tokens, including reasoning tokens the provider bills as output. */\n outputTokens: number;\n /** Agent that produced the call, when known. */\n agentName?: string;\n /** Delegation depth: 0 for the top-level conversation, 1 for a sub-agent, 2 for its sub-agent, \u2026 */\n subAgentDepth: number;\n /** Id of the tool call that spawned this row's conversation \u2014 correlates a row back to its delegation. */\n subAgentOf?: string;\n}\n\n/** Whether a message carries anything a ledger would record. */\nfunction hasUsage(m: ChatMessage): boolean {\n return (\n m.cost != null ||\n m.externalCostUsd != null ||\n m.inputTokens != null ||\n m.outputTokens != null ||\n m.cacheReadTokens != null ||\n m.cacheWriteTokens != null\n );\n}\n\n/**\n * Project a transcript into one row per billable unit of spend.\n *\n * @remarks\n * Reads the messages and returns a table; it stores nothing, mutates nothing, and\n * adds nothing to history. Use it where an **aggregate is not enough** \u2014 writing\n * usage rows for per-project attribution, a cost dashboard, or auditing which turns\n * came back unpriced. For a single total, `sumUsage` is the answer and this is the\n * wrong tool.\n *\n * Walks the same shape `sumUsage` does, and is guaranteed to agree with it: summing\n * `costUsd` and `externalCostUsd` across these rows equals `sumUsage(...).costUsd`\n * over the same input, and the four token buckets reconcile likewise. That property\n * is the point of the function \u2014 a per-call view that quietly disagrees with the\n * total is worse than no per-call view, because both look right in isolation.\n *\n * Covers the two places spend hides:\n *\n * - **Sub-agent conversations.** A delegating tool call carries the child's entire\n * conversation on `toolCall.subAgentTrace`, so a walk of top-level messages alone\n * misses everything a delegating agent spent. A consumer that reimplemented this\n * and omitted the branch reported $0.106 on a run that cost $0.234.\n * - **Compactions.** A compaction deletes the messages it summarises, banking their\n * spend on the summary. Those turns produce a single `source: 'compaction'` row.\n *\n * Messages carrying no usage at all (a user turn, a narration) produce no row.\n *\n * **Do not pass the result to `sumUsage`** \u2014 the types prevent it, and the reason is\n * that both recurse, so a pre-flattened list would be counted twice. Both functions\n * take raw history.\n *\n * @beta\n */\nexport function usageRows(messages: readonly ChatMessage[]): UsageRow[] {\n return collectRows(messages, 0, undefined);\n}\n\n/** Map an already-bucketed {@link AggregateUsage} onto a row's token fields. */\nfunction bucketsOf(\n usage: AggregateUsage,\n): Pick<UsageRow, 'uncachedInputTokens' | 'cacheReadTokens' | 'cacheWriteTokens' | 'outputTokens'> {\n return {\n uncachedInputTokens: usage.uncachedInputTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n outputTokens: usage.outputTokens,\n };\n}\n\nfunction collectRows(\n messages: readonly ChatMessage[],\n depth: number,\n subAgentOf: string | undefined,\n): UsageRow[] {\n const rows: UsageRow[] = [];\n for (const m of messages) {\n if (hasUsage(m)) {\n const cacheReadTokens = m.cacheReadTokens ?? 0;\n const cacheWriteTokens = m.cacheWriteTokens ?? 0;\n rows.push({\n source: 'request',\n model: m.model,\n // The driver stamps `ChatMessage.provider` from the resolved provider's own\n // status, so it is AUTHORITATIVE and covers vendors the model allowlists do\n // not \u2014 a server-proxied `gpt-5` turn is `provider: 'openai'` on the message\n // and unknown to `vendorOfModel`. Prefer it; fall back to resolving the model\n // id only for messages persisted before the field existed. Still left\n // undefined when neither knows, rather than guessed at.\n provider: m.provider ?? (m.model ? vendorOfModel(m.model) : undefined),\n ...(m.cost != null && { costUsd: m.cost }),\n ...(m.externalCostUsd != null && { externalCostUsd: m.externalCostUsd }),\n // Uncached input is the REMAINDER, matching `sumUsage`: `inputTokens` is the\n // whole prompt and the cache fields break it down. Clamped for the same\n // reason \u2014 hand-edited history must not drive a total negative.\n uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),\n cacheReadTokens,\n cacheWriteTokens,\n outputTokens: m.outputTokens ?? 0,\n ...(m.agentName != null && { agentName: m.agentName }),\n subAgentDepth: depth,\n ...(subAgentOf != null && { subAgentOf }),\n });\n }\n\n // Spend the compaction banked on this summary's behalf. Its buckets are already\n // disjoint (it is an `AggregateUsage`), so they map across without the\n // subtraction a per-message record needs.\n const rolled = m.compaction?.rolledUpUsage;\n if (rolled) {\n rows.push({\n source: 'compaction',\n ...(rolled.costUsd != null && { costUsd: rolled.costUsd }),\n ...bucketsOf(rolled),\n ...(m.agentName != null && { agentName: m.agentName }),\n subAgentDepth: depth,\n ...(subAgentOf != null && { subAgentOf }),\n });\n }\n\n for (const tc of m.toolCalls ?? []) {\n if (tc.subAgentTrace) rows.push(...collectRows(tc.subAgentTrace, depth + 1, tc.id));\n }\n }\n return rows;\n}\n", "import type { ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * A chat message lifted into the debug-log timeline as a `kind: 'message'` entry.\n *\n * @beta\n */\nexport type TimelineMessage = ChatMessage & {\n kind: 'message';\n /**\n * Set only on entries hoisted out of a `subAgentTrace`: the sub-agent's own\n * (un-breadcrumbed) `agentName`, kept for filtering since the displayed\n * `agentName` is rewritten to a `\"<parent> \u203A <sub-agent>\"` breadcrumb.\n */\n subAgentName?: string;\n /** Delegation depth \u2014 absent/0 for top-level, 1 for a sub-agent, 2 for a sub-agent's sub-agent, \u2026 */\n subAgentDepth?: number;\n /** Id of the parent tool call that spawned this run \u2014 correlates a hoisted message back to its delegation. */\n subAgentOf?: string;\n};\n\n/**\n * Flatten sub-agent conversations into a single top-level message stream for the\n * debug-log timeline.\n *\n * A tool call that delegates to a sub-agent carries the sub-agent's entire\n * conversation on `toolCall.subAgentTrace`. The live UI reads that nested shape,\n * but a top-to-bottom timeline reads far better with those messages inline next to\n * the turn that produced them. This walks the list and, for every tool call with a\n * `subAgentTrace`, hoists the sub-agent's messages up as their own timeline\n * entries while **removing** the nested copy from the emitted parent tool call \u2014 a\n * move, not a copy. The data is relocated, never duplicated: the export stays the\n * same size and a naive `sum(timeline[].cost)` does not double-count (the\n * canonical `sumCosts` total still reads the un-flattened history).\n *\n * Hoisted entries are:\n * - **breadcrumbed**: `agentName` becomes `\"<parent> \u203A <sub-agent>\"`, composing for\n * nested sub-agents (`\"<parent> \u203A <sub> \u203A <subsub>\"`); the raw sub-agent name is\n * preserved on `subAgentName`.\n * - **depth-tagged** (`subAgentDepth`) and **correlated** to the spawning tool call\n * (`subAgentOf`), so the delegation tree is reconstructable even when two\n * sub-agents run within the same parent turn.\n *\n * Top-level messages (depth 0) are emitted unchanged apart from the trace strip.\n * Order is preserved within each list; the caller sorts the whole timeline by\n * timestamp afterwards, and every sub-agent message carries its own timestamp, so\n * hoisted entries interleave chronologically between the parent's tool-call and\n * tool-result messages.\n *\n * @internal\n */\nexport function flattenSubAgentMessages(\n messages: readonly ChatMessage[],\n prefix = '',\n depth = 0,\n subAgentOf?: string,\n): TimelineMessage[] {\n return messages.flatMap((m) => {\n const breadcrumb = prefix ? `${prefix} \u203A ${m.agentName ?? '?'}` : m.agentName;\n const traceCalls = m.toolCalls?.filter((tc) => tc.subAgentTrace?.length) ?? [];\n\n const entry: TimelineMessage = {\n kind: 'message',\n ...m,\n // Move the (about-to-be-hoisted) child conversations out of the emitted tool\n // calls. Setting it to `undefined` drops the key from the serialized export.\n ...(traceCalls.length > 0 && {\n toolCalls: m.toolCalls!.map((tc) =>\n tc.subAgentTrace ? { ...tc, subAgentTrace: undefined } : tc,\n ),\n }),\n // Mark + breadcrumb hoisted sub-agent messages; top-level (depth 0) stays as-is.\n ...(depth > 0 && {\n agentName: breadcrumb,\n subAgentName: m.agentName,\n subAgentDepth: depth,\n subAgentOf,\n }),\n };\n\n if (traceCalls.length === 0) return [entry];\n\n const hoisted = traceCalls.flatMap((tc) =>\n flattenSubAgentMessages(tc.subAgentTrace!, breadcrumb ?? '', depth + 1, tc.id),\n );\n return [entry, ...hoisted];\n });\n}\n", "/**\n * Shared, pure builder for the debug-log timeline entries (`message` / `turn` / `event`) \u2014 the\n * common core of the host element's `buildDiagnosticEntries` and any HEADLESS consumer that drives\n * a `ChatDriver` of its own (e.g. `ai-service` running the engine server-side) and needs to harvest\n * that engine's debug log for the client to fold into its own download / persisted stream\n * (GENC-1461 unified diagnostics). DOM-clean and dependency-light so it works in bare Node.\n *\n * It deliberately excludes the `meta-snapshot` entry: that block is host/DOM-specific (it reads\n * `window.location.host`, the element's agent list, live context/cost), and a merged log keeps only\n * the newest snapshot anyway \u2014 a headless source's agent/prompt/tools are already captured in its\n * `turn` entries.\n *\n * @packageDocumentation\n */\n\nimport type { ChatMessage } from '@genesislcap/foundation-ai';\nimport { flattenSubAgentMessages } from '../../utils/flatten-sub-agent-messages';\nimport type { MetaEvent } from '../debug-event-log';\nimport type { DiagnosticEntry } from './diagnostics';\n\n/**\n * The minimal shape this builder reads off a turn snapshot. The driver's full `TurnSnapshot` is a\n * structural superset, so it assigns to this without the builder depending on the component layer.\n */\nexport interface TurnSnapshotLike {\n turnIndex: string;\n systemPrompt?: string;\n}\n\n/**\n * Build the `message` / `turn` / `event` timeline entries from a driver's pull surfaces\n * (`getRawHistory()` / `getTurnSnapshots()` / `getMetaEvents(sessionKey)`). Order within the array\n * is message \u2192 turn \u2192 event; the caller (`assembleDebugLog`) sorts the whole timeline by timestamp,\n * so this ordering only sets the co-timestamp tie-break. Pure.\n */\nexport function buildTimelineEntries(input: {\n turnSnapshots: readonly TurnSnapshotLike[];\n messages: readonly ChatMessage[];\n metaEvents: readonly MetaEvent[];\n}): DiagnosticEntry[] {\n const { turnSnapshots, messages, metaEvents } = input;\n\n // Collapse a turn's systemPrompt when byte-identical to the previous turn's \u2014 a stable agent\n // repeats the same (often multi-KB) prompt every turn, while a stateful agent's changes. The\n // prompt is shown in full whenever it changes, so prompt evolution stays visible.\n let lastFullPrompt: string | undefined;\n let lastFullIndex = '';\n const turns = turnSnapshots.map((t) => {\n let { systemPrompt } = t;\n if (systemPrompt != null && systemPrompt === lastFullPrompt) {\n systemPrompt = `<repeated \u2014 identical to turn ${lastFullIndex}>`;\n } else if (systemPrompt != null) {\n lastFullPrompt = systemPrompt;\n lastFullIndex = t.turnIndex;\n }\n return { kind: 'turn' as const, ...t, systemPrompt };\n });\n\n // Sub-agent conversations are stored nested on the parent tool call's `subAgentTrace`;\n // `flattenSubAgentMessages` hoists them to top-level `kind: 'message'` entries (breadcrumbed +\n // correlated, the nested copy moved out \u2014 not duplicated) so the timeline reads chronologically.\n const messageEntries = flattenSubAgentMessages(messages);\n const eventEntries = metaEvents.map((e) => ({ kind: 'event' as const, ...e }));\n\n return [...messageEntries, ...turns, ...eventEntries] as DiagnosticEntry[];\n}\n", "/**\n * Server-saved diagnostics (GENC-1351 \u00A75.8) \u2014 the forward-only stream that lets\n * the debug log persist across a whole session lifetime, not just the current\n * page load. This module owns the *pure* pieces: the entry type and the\n * reassembly back into the `{ readme, sessionUsage, timeline, meta }` debug-log\n * shape. The element owns capture/cadence; the provider owns storage layout.\n *\n * @packageDocumentation\n */\n\nimport type { AggregateUsage } from '@genesislcap/foundation-ai';\n\n/**\n * One entry in the diagnostics stream \u2014 the debug-log timeline-entry union\n * (`message` / `turn` / `event`, as `getDebugLog()` builds) plus a point-in-time\n * **`meta-snapshot`** carrying the export-time `meta` block (agent summary,\n * context, active debug snapshot, \u2026). Kept permissive: a provider stores and\n * returns these opaquely, and reassembly reads only `kind`, `timestamp` (for\n * ordering), `usage` (on a turn) and `meta` (on a snapshot).\n *\n * @public\n */\nexport interface DiagnosticEntry {\n kind: 'message' | 'turn' | 'event' | 'meta-snapshot';\n /** ISO timestamp \u2014 string-comparable, so it orders the stream chronologically. */\n timestamp?: string;\n /** Present on `meta-snapshot` entries: the export-time `meta` block. */\n meta?: unknown;\n /**\n * Present on a `turn` entry once its model call has returned and reported usage \u2014\n * the four token buckets plus USD for that one call (`TurnSnapshot.usage`).\n *\n * Read by the forward-capture delta as well as by readers: the turn entry is\n * created *before* the call, so a flush that lands mid-call persists it without\n * usage, and the delta re-emits it once (see `collectDiagnosticsDelta`) so the\n * priced copy reaches the stream. {@link assembleDebugLog} then collapses the pair.\n */\n usage?: AggregateUsage;\n /**\n * Present on `meta-snapshot` entries: a stable signature of the near-static config\n * (excludes volatile timestamp/context/debug-snapshot), used by the forward-capture\n * delta to skip re-appending an unchanged block (GENC-1351 \u00A75.8). Absent on other\n * kinds and on pre-signature entries (the delta falls back to the full `meta` then).\n */\n dedupSignature?: string;\n [key: string]: unknown;\n}\n\n/** The reassembled debug log \u2014 the exact shape `getDebugLog()` returns. @public */\nexport interface DebugLog {\n readme: readonly string[];\n /**\n * Session usage \u2014 the four token buckets plus USD cost \u2014 lifted out of the newest\n * `meta-snapshot`'s `meta.context.sessionUsage` so the headline spend figures sit at\n * the top of an exported log rather than buried under the (large) `meta` block. The\n * same object, not a second derivation.\n *\n * `undefined` when the stream carries no `meta-snapshot`, or one written before the\n * field existed. Never re-derived from the timeline: the per-request costs the\n * transports stamped are authoritative, and a ring-buffered timeline can have lost\n * entries the total still legitimately counts.\n *\n * **As current as the snapshot it came from, which is not automatically \"now\".** The\n * forward-capture delta only re-appends a `meta-snapshot` when the near-static config\n * signature changes, so the newest STORED snapshot of a session whose config never\n * changed is its first \u2014 with the totals frozen there. A caller reassembling a stored\n * stream on its own therefore gets stale figures unless it appends an export-time\n * snapshot first: see {@link withFreshMetaSnapshot}, which is what the assistant's own\n * download path does. `meta.timestamp` against the newest timeline entry tells you\n * which case you are holding.\n */\n sessionUsage?: AggregateUsage;\n timeline: DiagnosticEntry[];\n meta: unknown;\n}\n\n/**\n * Stable identity for a message diagnostic entry \u2014 `timestamp::role::subAgentOf::category`.\n * Used by the forward-capture delta (skip already-emitted messages) and by the\n * restore watermark (skip messages already present in a prior load's stream).\n * `null` when the entry has no timestamp \u2192 treat as always-new. Shared so the\n * element's diagnostics capture and the `SessionPersister`'s restore watermark\n * compute identity identically (GENC-1351 \u00A75.8/\u00A75.10).\n *\n * `category` is part of the key because the reasoning/narration/answer split (GENC-1411) emits\n * SEVERAL messages from one model response \u2014 the thought summary, any interstitial narration, and\n * the answer/tool-call message \u2014 which share `timestamp` + `role` + `subAgentOf`. Keying on those\n * alone collapsed them to one, so the forward-capture dropped all but the first: a server\n * generation's answer message vanished from the persisted debug log while its reasoning survived\n * (GENC-1461). `category` is stable across a message's in-place annotation (only `toolCalls` change,\n * which is deliberately excluded), so a genuine re-append of the same message still dedups.\n *\n * @internal\n */\nexport function diagnosticsMessageKey(entry: DiagnosticEntry): string | null {\n return typeof entry.timestamp === 'string'\n ? `${entry.timestamp}::${(entry.role as string) ?? ''}::${(entry.subAgentOf as string) ?? ''}::${(entry.category as string) ?? ''}`\n : null;\n}\n\n/**\n * Identity of a `turn` entry \u2014 `turnIndex::timestamp::agentName`.\n *\n * Deliberately NOT the serialized entry, which two copies of the same call do not always\n * share. `buildTimelineEntries` renders `systemPrompt` *relative to the preceding\n * snapshots* (collapsing it to `<repeated \u2014 identical to turn N>` when it matches the\n * previous full prompt), so if the snapshot holding that full prompt is evicted from the\n * ring buffer between the unpriced flush and the priced one, the surviving turn renders\n * its prompt differently and the two serializations diverge. Both copies are in the\n * stream by then, so nothing would collapse them \u2014 and the log whose purpose is per-call\n * cost would show one model call as two turns, one of them unpriced.\n *\n * All three components are fixed when the snapshot is created and never re-derived.\n * `turnIndex` alone is not enough: it restarts at `'0'` on each page load, and a lifetime\n * log legitimately holds one turn `'0'` per load. `agentName` separates two sub-agents\n * invoked in the same parent turn, which share a `turnIndex` prefix by construction (see\n * `forwardSubAgentSnapshots`).\n */\nfunction turnIdentity(entry: DiagnosticEntry): string {\n return `turn::${String(entry.turnIndex ?? '')}::${entry.timestamp ?? ''}::${String(entry.agentName ?? '')}`;\n}\n\n// Tie-break co-timestamped entries by cause \u2192 call \u2192 output (event, turn, message),\n// matching the original in-place `getDebugLog` sort.\nconst KIND_RANK: Record<string, number> = { event: 0, turn: 1, message: 2 };\n// Any non-{event,turn,message} kind (shouldn't reach the timeline \u2014 meta-snapshots\n// are filtered out first) sorts last.\nconst UNKNOWN_KIND_RANK = 99;\n\n/**\n * Reassemble diagnostic entries into the `{ readme, sessionUsage, timeline, meta }`\n * debug-log shape (GENC-1351 \u00A75.8). `timeline` = the `message`/`turn`/`event` entries sorted\n * by ISO `timestamp` (kind-rank tie-break). `meta` = the **newest** `meta-snapshot`'s\n * block only \u2014 a \"state at export\" photo, matching the single-page log. The older\n * snapshots are intentionally dropped: the per-turn evolution they would show is\n * already in the timeline (`turn.agentSnapshot` + `context.updated` events), so\n * keeping them would just repeat the bulky, near-static `agentSummary`. `readme` =\n * the passed (current) constant. `sessionUsage` = that same newest snapshot's\n * `meta.context.sessionUsage`, lifted to the top level. Pure \u2014 reused for both the\n * live current-page log and the reassembled lifetime log stitched from the persisted\n * stream, so both come out shape-identical.\n *\n * NOTE for a caller stitching a STORED stream (a headless consumer harvesting its own\n * lifetime log, say): the newest stored `meta-snapshot` is frozen at the last\n * config-signature change, so `meta` and `sessionUsage` are as old as that unless you\n * pass a fresh snapshot of your own \u2014 {@link withFreshMetaSnapshot} does exactly that,\n * and the element's download path goes through it.\n */\nexport function assembleDebugLog(entries: DiagnosticEntry[], readme: readonly string[]): DebugLog {\n // Safety net for exact-duplicate entries: two element instances sharing one\n // session (bubble + popped-out panel) can each append the same entry, and a\n // reload's second instance can re-append restored history. Such copies are\n // byte-identical, so collapse by serialized identity \u2014 genuinely-distinct entries\n // (e.g. two real `assistant.connected` from two instances) differ in index /\n // placement and are kept. (The shared cursor store prevents most of this at\n // write time; this guards the read path regardless of what's in the stream.)\n //\n // A `turn` is identified by `turnIndex` + `timestamp` + `agentName` instead (see\n // `turnIdentity`), so the unpriced copy a mid-call flush persisted and the priced copy\n // that follows it collapse into ONE turn \u2014 the priced one \u2014 rather than reading as two\n // model calls.\n const seenAt = new Map<string, number>();\n let latestMeta: DiagnosticEntry | undefined;\n const timeline: DiagnosticEntry[] = [];\n for (const entry of entries) {\n if (entry.kind === 'meta-snapshot') {\n if (!latestMeta || (entry.timestamp ?? '') >= (latestMeta.timestamp ?? '')) {\n latestMeta = entry;\n }\n continue;\n }\n const id = entry.kind === 'turn' ? turnIdentity(entry) : JSON.stringify(entry);\n const at = seenAt.get(id);\n if (at !== undefined) {\n // Same entry seen twice \u2014 keep the richer copy. `usage` on a turn is the only\n // field that can arrive late, so it is the only upgrade there is to make.\n if (entry.usage && !timeline[at].usage) timeline[at] = entry;\n continue;\n }\n seenAt.set(id, timeline.length);\n timeline.push(entry);\n }\n timeline.sort((a, b) => {\n const ta = a.timestamp ?? '';\n const tb = b.timestamp ?? '';\n if (ta < tb) return -1;\n if (ta > tb) return 1;\n return (KIND_RANK[a.kind] ?? UNKNOWN_KIND_RANK) - (KIND_RANK[b.kind] ?? UNKNOWN_KIND_RANK);\n });\n // The session totals live inside the newest snapshot's `meta`, which is `unknown` by\n // design (a provider stores these opaquely) \u2014 so this narrows just the one path it\n // reads rather than typing the whole block.\n const context = (latestMeta?.meta as { context?: { sessionUsage?: AggregateUsage } } | undefined)\n ?.context;\n return { readme, sessionUsage: context?.sessionUsage, timeline, meta: latestMeta?.meta };\n}\n\n/**\n * A stored diagnostics stream with its `meta-snapshot`s replaced by `fresh` \u2014 what to\n * pass {@link assembleDebugLog} when reassembling a persisted stream for export.\n *\n * The stored snapshots are dropped rather than out-timestamped. `assembleDebugLog` keeps\n * whichever claims the later time, and a stream written on another machine can carry a\n * skewed clock; `fresh` is built from live state and so is the more current by\n * construction. Only one snapshot ever survives reassembly, so the count is unchanged \u2014\n * though a snapshot taken while the driver is unwired (mid-popout) can leave\n * `activeFoldStack`/`activeDebugSnapshot` unset where a stored one had them. The figures\n * this exists for \u2014 the context block and `sessionUsage` \u2014 read the session store and\n * element props, which survive an unwire.\n *\n * Pure, and separate from the element for that reason: the swap it performs is the fix\n * for a silent bug (a lifetime log reporting near-zero spend against a transcript full of\n * priced messages), so it needs to be testable without mounting anything.\n */\nexport function withFreshMetaSnapshot(\n stored: readonly DiagnosticEntry[],\n fresh: DiagnosticEntry,\n): DiagnosticEntry[] {\n return [...stored.filter((e) => e.kind !== 'meta-snapshot'), fresh];\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0CO,SAAS,OAAO,GAAG,GAAG;AAC3B,MAAI,IAAI,CAAC;AACT,WAAS,KAAK,EAAG,KAAI,OAAO,UAAU,eAAe,KAAK,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI;AAC9E,MAAE,CAAC,IAAI,EAAE,CAAC;AACd,MAAI,KAAK,QAAQ,OAAO,OAAO,0BAA0B;AACrD,aAAS,IAAI,GAAG,IAAI,OAAO,sBAAsB,CAAC,GAAG,IAAI,EAAE,QAAQ,KAAK;AACpE,UAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,KAAK,OAAO,UAAU,qBAAqB,KAAK,GAAG,EAAE,CAAC,CAAC;AACzE,UAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAAA,IACxB;AACJ,SAAO;AACT;AA8DO,SAAS,UAAU,SAAS,YAAY,GAAG,WAAW;AAC3D,WAAS,MAAM,OAAO;AAAE,WAAO,iBAAiB,IAAI,QAAQ,IAAI,EAAE,SAAU,SAAS;AAAE,cAAQ,KAAK;AAAA,IAAG,CAAC;AAAA,EAAG;AAC3G,SAAO,KAAK,MAAM,IAAI,UAAU,SAAU,SAAS,QAAQ;AACvD,aAAS,UAAU,OAAO;AAAE,UAAI;AAAE,aAAK,UAAU,KAAK,KAAK,CAAC;AAAA,MAAG,SAAS,GAAG;AAAE,eAAO,CAAC;AAAA,MAAG;AAAA,IAAE;AAC1F,aAAS,SAAS,OAAO;AAAE,UAAI;AAAE,aAAK,UAAU,OAAO,EAAE,KAAK,CAAC;AAAA,MAAG,SAAS,GAAG;AAAE,eAAO,CAAC;AAAA,MAAG;AAAA,IAAE;AAC7F,aAAS,KAAK,QAAQ;AAAE,aAAO,OAAO,QAAQ,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK,EAAE,KAAK,WAAW,QAAQ;AAAA,IAAG;AAC7G,UAAM,YAAY,UAAU,MAAM,SAAS,cAAc,CAAC,CAAC,GAAG,KAAK,CAAC;AAAA,EACxE,CAAC;AACH;AA8CO,SAAS,SAAS,GAAG;AAC1B,MAAI,IAAI,OAAO,WAAW,cAAc,OAAO,UAAU,IAAI,KAAK,EAAE,CAAC,GAAG,IAAI;AAC5E,MAAI,EAAG,QAAO,EAAE,KAAK,CAAC;AACtB,MAAI,KAAK,OAAO,EAAE,WAAW,SAAU,QAAO;AAAA,IAC1C,MAAM,WAAY;AACd,UAAI,KAAK,KAAK,EAAE,OAAQ,KAAI;AAC5B,aAAO,EAAE,OAAO,KAAK,EAAE,GAAG,GAAG,MAAM,CAAC,EAAE;AAAA,IAC1C;AAAA,EACJ;AACA,QAAM,IAAI,UAAU,IAAI,4BAA4B,iCAAiC;AACvF;AA6CO,SAAS,QAAQ,GAAG;AACzB,SAAO,gBAAgB,WAAW,KAAK,IAAI,GAAG,QAAQ,IAAI,QAAQ,CAAC;AACrE;AAEO,SAAS,iBAAiB,SAAS,YAAY,WAAW;AAC/D,MAAI,CAAC,OAAO,cAAe,OAAM,IAAI,UAAU,sCAAsC;AACrF,MAAI,IAAI,UAAU,MAAM,SAAS,cAAc,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC;AAC5D,SAAO,IAAI,OAAO,QAAQ,OAAO,kBAAkB,aAAa,gBAAgB,QAAQ,SAAS,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,UAAU,WAAW,GAAG,EAAE,OAAO,aAAa,IAAI,WAAY;AAAE,WAAO;AAAA,EAAM,GAAG;AACtN,WAAS,YAAY,GAAG;AAAE,WAAO,SAAU,GAAG;AAAE,aAAO,QAAQ,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM;AAAA,IAAG;AAAA,EAAG;AAC9F,WAAS,KAAK,GAAG,GAAG;AAAE,QAAI,EAAE,CAAC,GAAG;AAAE,QAAE,CAAC,IAAI,SAAU,GAAG;AAAE,eAAO,IAAI,QAAQ,SAAU,GAAG,GAAG;AAAE,YAAE,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,OAAO,GAAG,CAAC;AAAA,QAAG,CAAC;AAAA,MAAG;AAAG,UAAI,EAAG,GAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAAA,IAAG;AAAA,EAAE;AACvK,WAAS,OAAO,GAAG,GAAG;AAAE,QAAI;AAAE,WAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AAAA,IAAG,SAAS,GAAG;AAAE,aAAO,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;AAAA,IAAG;AAAA,EAAE;AACjF,WAAS,KAAK,GAAG;AAAE,MAAE,iBAAiB,UAAU,QAAQ,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,SAAS,MAAM,IAAI,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;AAAA,EAAG;AACvH,WAAS,QAAQ,OAAO;AAAE,WAAO,QAAQ,KAAK;AAAA,EAAG;AACjD,WAAS,OAAO,OAAO;AAAE,WAAO,SAAS,KAAK;AAAA,EAAG;AACjD,WAAS,OAAO,GAAG,GAAG;AAAE,QAAI,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,OAAQ,QAAO,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAAA,EAAG;AACnF;AAEO,SAAS,iBAAiB,GAAG;AAClC,MAAI,GAAG;AACP,SAAO,IAAI,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,SAAS,SAAU,GAAG;AAAE,UAAM;AAAA,EAAG,CAAC,GAAG,KAAK,QAAQ,GAAG,EAAE,OAAO,QAAQ,IAAI,WAAY;AAAE,WAAO;AAAA,EAAM,GAAG;AAC1I,WAAS,KAAK,GAAG,GAAG;AAAE,MAAE,CAAC,IAAI,EAAE,CAAC,IAAI,SAAU,GAAG;AAAE,cAAQ,IAAI,CAAC,KAAK,EAAE,OAAO,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC,IAAI;AAAA,IAAG,IAAI;AAAA,EAAG;AACvI;AAEO,SAAS,cAAc,GAAG;AAC/B,MAAI,CAAC,OAAO,cAAe,OAAM,IAAI,UAAU,sCAAsC;AACrF,MAAI,IAAI,EAAE,OAAO,aAAa,GAAG;AACjC,SAAO,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO,aAAa,aAAa,SAAS,CAAC,IAAI,EAAE,OAAO,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAG,EAAE,OAAO,aAAa,IAAI,WAAY;AAAE,WAAO;AAAA,EAAM,GAAG;AAC9M,WAAS,KAAK,GAAG;AAAE,MAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAU,GAAG;AAAE,aAAO,IAAI,QAAQ,SAAU,SAAS,QAAQ;AAAE,YAAI,EAAE,CAAC,EAAE,CAAC,GAAG,OAAO,SAAS,QAAQ,EAAE,MAAM,EAAE,KAAK;AAAA,MAAG,CAAC;AAAA,IAAG;AAAA,EAAG;AAC/J,WAAS,OAAO,SAAS,QAAQ,GAAG,GAAG;AAAE,YAAQ,QAAQ,CAAC,EAAE,KAAK,SAASA,IAAG;AAAE,cAAQ,EAAE,OAAOA,IAAG,MAAM,EAAE,CAAC;AAAA,IAAG,GAAG,MAAM;AAAA,EAAG;AAC7H;;;AC5PA,IAAM,OAAO,MAAM;AAAE;AA8Bd,SAAS,eAAe,SAAS;AACpC,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,KAAK,IAAI;AAG9C,QAAM,aAAa,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO;AAC/C,MAAI,YAAY;AACZ,eAAW,MAAM,WAAW,MAAM;AAClC,WAAO,EAAE,QAAQ,WAAW,QAAQ,SAAS,KAAK;AAAA,EACtD;AAGA,WAAS,UAAU;AACf,eAAW,KAAK,QAAQ;AACpB,QAAE,oBAAoB,SAAS,OAAO;AAAA,IAC1C;AAAA,EACJ;AAGA,WAAS,UAAU;AACf,eAAW,MAAM,KAAK,MAAM;AAC5B,YAAQ;AAAA,EACZ;AACA,aAAW,KAAK,QAAQ;AACpB,MAAE,iBAAiB,SAAS,OAAO;AAAA,EACvC;AACA,SAAO,EAAE,QAAQ,WAAW,QAAQ,QAAQ;AAChD;;;ACzDA,IAAM,YAAY;AAAA,EAChB,QAAQ,OAAO;AAAA,EACf,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS,OAAO;AAClB;AACA,IAAM,WAAW;AAAA;AAAA,EAEf,QAAQ;AAAA,IACN,OAAO;AAAA,EACT;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,MAAM;AAAA,IACJ,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,MAAM;AAAA,IACJ,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,SAAS;AAAA,IACP,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,MAAM;AAAA,IACJ,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA,EACA,KAAK;AAAA,IACH,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,OAAO,UAAU;AAAA,EACnB;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,OAAO,UAAU;AAAA,EACnB;AACF;AAEA,SAAS,gBAAgB,OAAO;AAC9B,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,MAAI,cAAc,QAAQ,cAAc,OAAO,aAAa,OAAO,eAAe,SAAS,MAAM,MAAM;AACrG,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,OAAO;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,eAAe,OAAO;AAC/B,WAAO,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,MAAM,YAAY,UAAU,YAAY,KAAK,QAAQ;AAC5D,MAAI,CAAC,gBAAgB,QAAQ,GAAG;AAC9B,WAAO,MAAM,YAAY,CAAC,GAAG,WAAW,MAAM;AAAA,EAChD;AACA,QAAM,SAAS,OAAO,OAAO,CAAC,GAAG,QAAQ;AACzC,aAAW,OAAO,YAAY;AAC5B,QAAI,QAAQ,eAAe,QAAQ,eAAe;AAChD;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,GAAG;AAC5B,QAAI,UAAU,QAAQ,UAAU,QAAQ;AACtC;AAAA,IACF;AACA,QAAI,UAAU,OAAO,QAAQ,KAAK,OAAO,SAAS,GAAG;AACnD;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,QAAQ,OAAO,GAAG,CAAC,GAAG;AACtD,aAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,OAAO,GAAG,CAAC;AAAA,IACzC,WAAW,gBAAgB,KAAK,KAAK,gBAAgB,OAAO,GAAG,CAAC,GAAG;AACjE,aAAO,GAAG,IAAI;AAAA,QACZ;AAAA,QACA,OAAO,GAAG;AAAA,SACT,YAAY,GAAG,SAAS,MAAM,MAAM,IAAI,SAAS;AAAA,QAClD;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AACA,SAAS,WAAW,QAAQ;AAC1B,SAAO,IAAI;AAAA;AAAA,IAET,WAAW,OAAO,CAAC,GAAG,MAAM,MAAM,GAAG,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC;AAAA;AAE3D;AACA,IAAM,OAAO,WAAW;AAExB,SAAS,cAAc,KAAK;AAC1B,SAAO,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM;AACjD;AACA,SAAS,SAAS,KAAK;AACrB,MAAI,CAAC,cAAc,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,IAAI,WAAW,CAAC,IAAI,MAAM;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,IAAI,OAAO;AACb,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,IAAI,SAAS;AACb,IAAM,QAAQ,CAAC;AACf,IAAM,UAAN,MAAM,SAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,UAAU,CAAC,GAAG;AACxB,UAAM,QAAQ,QAAQ,SAAS;AAC/B,SAAK,UAAU;AAAA,MACb;AAAA,QACE,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,QAAQ,SAAS;AAAA,QAChC,OAAO,mBAAmB,QAAQ,OAAO,KAAK;AAAA,QAC9C,WAAW,CAAC,GAAG,QAAQ,aAAa,CAAC,CAAC;AAAA,MACxC;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,UAAU;AAAA,QACV,aAAa;AAAA,QACb,eAAe;AAAA,UACb,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW;AAAA,QACf;AAAA,QACA,GAAG,KAAK,QAAQ;AAAA,QAChB,GAAG,MAAM,IAAI;AAAA,MACf;AACA,WAAK,IAAI,IAAI,KAAK,WAAW,QAAQ;AACrC,WAAK,IAAI,EAAE,MAAM,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,QAAQ;AACvB,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,WAAW,CAAC;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,QAAQ;AACV,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAM,OAAO;AACf,SAAK,QAAQ,QAAQ;AAAA,MACnB;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,SAAS,MAAM;AACpB,QAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AACA,WAAO,KAAK,QAAQ,OAAO,SAAS,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,SAAS;AACd,UAAM,WAAW,IAAI,SAAQ;AAAA,MAC3B,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,IACL,CAAC;AACD,QAAI,KAAK,SAAS;AAChB,eAAS,UAAU,KAAK,OAAO;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,UAAU;AACrB,WAAO,KAAK,OAAO;AAAA,MACjB,GAAG,KAAK;AAAA,MACR,UAAU;AAAA,QACR,GAAG,KAAK,QAAQ;AAAA,QAChB,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,KAAK;AACX,WAAO,KAAK,aAAa;AAAA,MACvB,KAAK,KAAK,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,MAAM,MAAM,MAAM;AAAA,IAC3E,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,UAAU;AACpB,SAAK,QAAQ,UAAU,KAAK,QAAQ;AACpC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,UAAU;AACvB,QAAI,UAAU;AACZ,YAAM,IAAI,KAAK,QAAQ,UAAU,QAAQ,QAAQ;AACjD,UAAI,MAAM,IAAI;AACZ,eAAO,KAAK,QAAQ,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3C;AAAA,IACF,OAAO;AACL,WAAK,QAAQ,UAAU,OAAO,CAAC;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,WAAW;AACtB,SAAK,QAAQ,YAAY,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AAC1E,WAAO;AAAA,EACT;AAAA,EACA,UAAU;AACR,SAAK,YAAY;AACjB,SAAK,QAAQ;AAAA,EACf;AAAA,EACA,aAAa;AACX,SAAK,eAAe;AACpB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAIA,cAAc;AACZ,eAAW,QAAQ,KAAK,QAAQ,OAAO;AACrC,UAAI,CAAC,QAAQ,OAAO,IAAI,GAAG;AACzB,gBAAQ,OAAO,IAAI,IAAI,QAAQ,IAAI;AAAA,MACrC;AACA,cAAQ,IAAI,IAAI,KAAK,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,iBAAiB;AACf,eAAW,QAAQ,KAAK,QAAQ,OAAO;AACrC,UAAI,QAAQ,OAAO,IAAI,GAAG;AACxB,gBAAQ,IAAI,IAAI,QAAQ,OAAO,IAAI;AACnC,eAAO,QAAQ,OAAO,IAAI;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,UAAU;AACR,SAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK;AAC3C,SAAK,YAAY,KAAK,QAAQ,QAAQ,KAAK;AAAA,EAC7C;AAAA,EACA,YAAY,QAAQ,MAAM;AACxB,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,UAAU,OAAO;AAAA,IAC1B;AACA,WAAO,QAAQ,CAAC,SAAS;AACvB,WAAK,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAa;AACX,SAAK,eAAe,KAAK,QAAQ,MAAM;AACvC,SAAK,eAAe,KAAK,QAAQ,MAAM;AAAA,EACzC;AAAA,EACA,eAAe,QAAQ;AACrB,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AACA,QAAI,OAAO,SAAS;AAClB,aAAO,QAAQ,OAAO;AACtB,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAIA,YAAY;AACV,aAAS;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAIA,aAAa;AACX,aAAS;AACT,UAAM,SAAS,MAAM,OAAO,CAAC;AAC7B,eAAW,QAAQ,QAAQ;AACzB,WAAK,CAAC,EAAE,OAAO,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,QAAQ;AAChB,UAAM,UAAU,UAAU,KAAK,QAAQ;AACvC,SAAK,UAAU;AACf,QAAI,OAAO,YAAY,YAAY;AACjC;AAAA,IACF;AACA,eAAW,QAAQ,KAAK,QAAQ,OAAO;AACrC,WAAK,IAAI,IAAI,QAAQ,MAAM,KAAK,QAAQ,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI;AACjE,WAAK,IAAI,EAAE,MAAM,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,WAAW,UAAU,OAAO;AAC1B,WAAO,IAAI,SAAS;AAClB,UAAI,QAAQ;AACV,cAAM,KAAK,CAAC,MAAM,UAAU,MAAM,KAAK,CAAC;AACxC;AAAA,MACF;AACA,aAAO,KAAK,OAAO,UAAU,MAAM,KAAK;AAAA,IAC1C;AAAA,EACF;AAAA,EACA,OAAO,UAAU,MAAM,OAAO;AAC5B,SAAK,SAAS,SAAS,KAAK,KAAK,OAAO;AACtC,aAAO;AAAA,IACT;AACA,UAAM,SAAS;AAAA,MACb,MAAsB,oBAAI,KAAK;AAAA,MAC/B,MAAM,CAAC;AAAA,MACP,GAAG;AAAA,MACH,OAAO,mBAAmB,SAAS,OAAO,KAAK,QAAQ,KAAK;AAAA,IAC9D;AACA,QAAI,CAAC,SAAS,KAAK,WAAW,KAAK,SAAS,KAAK,CAAC,CAAC,GAAG;AACpD,aAAO,OAAO,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC/B,OAAO;AACL,aAAO,OAAO,CAAC,GAAG,IAAI;AAAA,IACxB;AACA,QAAI,OAAO,SAAS;AAClB,aAAO,KAAK,QAAQ,OAAO,OAAO;AAClC,aAAO,OAAO;AAAA,IAChB;AACA,QAAI,OAAO,YAAY;AACrB,UAAI,CAAC,MAAM,QAAQ,OAAO,UAAU,GAAG;AACrC,eAAO,aAAa,OAAO,WAAW,MAAM,IAAI;AAAA,MAClD;AACA,aAAO,KAAK,KAAK,OAAO,OAAO,WAAW,KAAK,IAAI,CAAC;AACpD,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,YAAY,IAAI;AAC5E,WAAO,MAAM,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;AAC3D,UAAM,aAAa,CAAC,SAAS,UAAU;AACrC,YAAM,YAAY,KAAK,SAAS,SAAS,KAAK,KAAK,QAAQ;AAC3D,UAAI,KAAK,SAAS,UAAU,WAAW,GAAG;AACxC,cAAM,QAAQ,CAAC,GAAG,KAAK,SAAS,OAAO,IAAI;AAC3C,YAAI,WAAW,GAAG;AAChB,gBAAM,KAAK,aAAa,QAAQ,SAAS;AAAA,QAC3C;AACA,aAAK,KAAK,EAAE,GAAG,KAAK,SAAS,QAAQ,MAAM,MAAM,CAAC;AAClD,aAAK,SAAS,QAAQ;AAAA,MACxB;AACA,UAAI,QAAQ;AACV,aAAK,SAAS,SAAS;AACvB,aAAK,KAAK,MAAM;AAAA,MAClB;AAAA,IACF;AACA,iBAAa,KAAK,SAAS,OAAO;AAClC,UAAM,WAAW,KAAK,SAAS,QAAQ,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,QAAQ,IAAI;AAC5G,SAAK,SAAS,OAAO,OAAO;AAC5B,QAAI,WAAW,KAAK,QAAQ,UAAU;AACpC,UAAI;AACF,cAAM,gBAAgB,KAAK,UAAU;AAAA,UACnC,OAAO;AAAA,UACP,OAAO;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AACD,cAAM,YAAY,KAAK,SAAS,eAAe;AAC/C,aAAK,SAAS,aAAa;AAC3B,YAAI,WAAW;AACb,eAAK,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK;AACnD,cAAI,KAAK,SAAS,QAAQ,KAAK,QAAQ,aAAa;AAClD,iBAAK,SAAS,UAAU;AAAA,cACtB;AAAA,cACA,KAAK,QAAQ;AAAA,YACf;AACA;AAAA,UACF;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MACR;AAAA,IACF;AACA,eAAW,IAAI;AAAA,EACjB;AAAA,EACA,KAAK,QAAQ;AACX,eAAW,YAAY,KAAK,QAAQ,WAAW;AAC7C,eAAS,IAAI,QAAQ;AAAA,QACnB,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AACA,SAAS,mBAAmB,OAAO,QAAQ,CAAC,GAAG,eAAe,GAAG;AAC/D,MAAI,UAAU,QAAQ;AACpB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,KAAK,KAAK,MAAM,KAAK,EAAE,UAAU,QAAQ;AACjD,WAAO,MAAM,KAAK,EAAE;AAAA,EACtB;AACA,SAAO;AACT;AACA,QAAQ,UAAU,MAAM,QAAQ,UAAU;AAC1C,QAAQ,UAAU,SAAS,QAAQ,UAAU;AAC7C,QAAQ,UAAU,QAAQ,QAAQ,UAAU;AAC5C,QAAQ,UAAU,YAAY,QAAQ,UAAU;AAChD,QAAQ,UAAU,OAAO,QAAQ,UAAU;AAC3C,QAAQ,UAAU,QAAQ,QAAQ,UAAU;AAC5C,QAAQ,UAAU,SAAS,QAAQ,UAAU;AAC7C,SAAS,cAAc,UAAU,CAAC,GAAG;AACnC,SAAO,IAAI,QAAQ,OAAO;AAC5B;;;AC1fA,IAAM,kBAAN,MAAsB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,SAAS;AACnB,SAAK,UAAU,EAAE,GAAG,QAAQ;AAC5B,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAAA,MACnB,GAAG;AAAA;AAAA,MAEH,GAAG;AAAA;AAAA,MAEH,GAAG;AAAA;AAAA,IAEL;AACA,SAAK,eAAe;AAAA,MAClB,SAAS;AAAA;AAAA,IAEX;AAAA,EACF;AAAA,EACA,UAAU,OAAO;AACf,QAAI,QAAQ,GAAG;AACb,aAAO,QAAQ,WAAW,QAAQ;AAAA,IACpC;AACA,QAAI,UAAU,GAAG;AACf,aAAO,QAAQ,UAAU,QAAQ;AAAA,IACnC;AACA,WAAO,QAAQ,SAAS,QAAQ;AAAA,EAClC;AAAA,EACA,IAAI,QAAQ;AACV,UAAM,eAAe,KAAK,UAAU,OAAO,KAAK;AAChD,UAAM,OAAO,OAAO,SAAS,QAAQ,KAAK,OAAO;AACjD,UAAM,MAAM,OAAO,OAAO;AAC1B,UAAM,QAAQ,KAAK,aAAa,OAAO,IAAI,KAAK,KAAK,cAAc,OAAO,KAAK,KAAK,KAAK;AACzF,UAAM,QAAQ;AAAA,oBACE,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAMrB,UAAM,QAAQ,KAAK,CAAC,KAAK,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC;AACxD,QAAI,OAAO,OAAO,KAAK,CAAC,MAAM,UAAU;AACtC;AAAA,QACE,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,QAC5B;AAAA;AAAA,QAEA;AAAA,QACA,GAAG,OAAO,KAAK,MAAM,CAAC;AAAA,MACxB;AAAA,IACF,OAAO;AACL,mBAAa,OAAO,OAAO,GAAG,OAAO,IAAI;AAAA,IAC3C;AAAA,EACF;AACF;AAEA,SAASC,eAAc,UAAU,CAAC,GAAG;AACnC,QAAM,WAAW,cAAgB;AAAA,IAC/B,WAAW,QAAQ,aAAa,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC;AAAA,IACxD,OAAO,SAAS,WAAW,CAAC,GAAG;AAC7B,UAAI,SAAS,SAAS,WAAW;AAC/B,eAAO,QAAQ,QAAQ,QAAQ,OAAO,CAAC;AAAA,MACzC;AACA,aAAO,QAAQ,QAAQ,OAAO,OAAO,CAAC;AAAA,IACxC;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACD,SAAO;AACT;AACA,IAAM,UAAUA,eAAc;;;ACtDvB,IAAM,uBAAuB;AAAA,EAChC,OAAO,UAAU;AACrB;AA8BO,SAAS,aAAa,MAAM,UAAU,sBAAsB;AAC/D,QAAMC,iBAAgB,OAAO,WAAW,cAAcA,iBAAuB;AAC7E,QAAMC,UAASD,eAAc,EAAE,QAAQ,IAAI;AAC3C,OAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,WAAW;AACtE,IAAAC,QAAO,QAAQ,QAAQ;AAC3B,QAAM,cAAcA;AACpB,cAAY,aAAa,CAAC,QAAQ,cAAc,wCAAwC,yBAAyB;AAC7G,gBAAY,KAAK,2BAA2B,MAAM,MAAM,WAAW,IAAI,GAAG,uBAAuB,8BAA8B,oBAAoB,MAAM,EAAE,EAAE;AAAA,EACjK;AACA,SAAO;AACX;;;AC5DO,IAAM,SAAS,aAAa,eAAe;;;ACAlD,IAAM,gBAAgB;AAAA,EAClB,MAAM;AAAA,EACN,YAAY;AAAA,IACR,OAAO,EAAE,MAAM,UAAU,aAAa,qCAAqC;AAAA,IAC3E,UAAU;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,MACH,MAAM,CAAC,UAAU,UAAU,WAAW,MAAM;AAAA,MAC5C,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA,EACA,UAAU,CAAC,SAAS,YAAY,OAAO;AAAA,EACvC,sBAAsB;AAC1B;AAOO,IAAM,uBAAuB;AAAA,EAChC,MAAM;AAAA,EACN,YAAY;AAAA,IACR,QAAQ;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,QACH,MAAM;AAAA,QACN,YAAY;AAAA,UACR,OAAO;AAAA,YACH,MAAM;AAAA,YACN,MAAM,CAAC,OAAO,IAAI;AAAA,YAClB,aAAa;AAAA,UACjB;AAAA,UACA,SAAS;AAAA,YACL,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa;AAAA,UACjB;AAAA,UACA,SAAS;AAAA,YACL,MAAM;AAAA,YACN,OAAO;AAAA,UACX;AAAA,QACJ;AAAA,QACA,UAAU,CAAC,SAAS,WAAW,SAAS;AAAA,QACxC,sBAAsB;AAAA,MAC1B;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,UAAU,CAAC,QAAQ;AAAA,EACnB,sBAAsB;AAC1B;AAcA,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB,SAAS,0BAA0B,SAAS,CAAC,GAAG,oBAAoB;AACvE,QAAM,YAAY,OACb,IAAI,CAAC,MAAM;AACZ,QAAI,IAAI,IAAI,IAAI;AAChB,WAAO,OAAO,MAAM,WACd,KACE,MAAM,MAAM,MAAM,KAAK,MAAM,QAAQ,MAAM,SAAS,SAAS,EAAE,UAAU,QAAQ,OAAO,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,SAAS,EAAE,UAAU,QAAQ,OAAO,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,SAAS,EAAE,WAAW,QAAQ,OAAO,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,SAAS,EAAE,WAAW,QAAQ,OAAO,SAAS,KAAK;AAAA,EACjW,CAAC,EACI,OAAO,OAAO,EACd,KAAK,IAAI;AACd,QAAM,aAAa,uBAAuB,QAAQ,uBAAuB,SAAS,qBAAqB;AACvG,QAAM,aAAa,qBAAqB,aAAa,4DAA4D;AACjH,SAAO,GAAG,UAAU;AAAA,EAAK,UAAU;AACvC;AAMO,SAAS,wBAAwB,OAAO;AAC3C,SAAO,yBAAyB,KAAK;AACzC;AAMO,SAAS,sBAAsB,MAAM;AACxC,MAAI,EAAE,SAAS,QAAQ,SAAS,SAAS,SAAS,KAAK,KAAK,IAAI;AAC5D,WAAO,MAAM,4CAA4C;AACzD,WAAO;AAAA,EACX;AACA,MAAI;AACA,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,EAAE,WAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,WAAW,CAAC,MAAM,QAAQ,OAAO,MAAM,GAAG;AACnG,aAAO,MAAM,8DAA8D;AAC3E,aAAO;AAAA,IACX;AACA,WAAO;AAAA,MACH,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ,SACO,GAAG;AACN,WAAO,MAAM,uCAAuC,CAAC;AACrD,WAAO;AAAA,EACX;AACJ;;;ACxIO,IAAM,oBAAN,MAAwB;AAAA,EAC3B,YAAY,QAAQ,WAAW;AAC3B,SAAK,YAAY;AACjB,SAAK,uBAAuB,OAAO;AAAA,EACvC;AAAA,EACA,YAAY;AACR,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,SAAS,KAAK,UAAU,UAAU;AACxC,aAAO,EAAE,UAAU,aAAa,OAAO,OAAO,OAAO,cAAc,OAAO,aAAa;AAAA,IAC3F,CAAC;AAAA,EACL;AAAA,EACA,kBAAkB,OAAO,SAAS;AAC9B,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI;AACJ,YAAM,UAAU,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,YAAY,QAAQ,OAAO,SAAS,KAAK,CAAC;AACzH,YAAM,eAAe,0BAA0B,QAAQ,KAAK,oBAAoB;AAChF,YAAM,aAAa,wBAAwB,KAAK;AAChD,UAAI;AACA,cAAM,MAAM,MAAM,KAAK,UAAU,qBAAqB;AAAA,UAClD;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QACpB,CAAC;AACD,eAAO,sBAAsB,GAAG;AAAA,MACpC,SACO,GAAG;AACN,eAAO,MAAM,+CAA+C,CAAC;AAC7D,eAAO;AAAA,MACX;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EACA,OAAO,SAAS,SAAS;AACrB,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,WAAW,MAAM,KAAK,UAAU,gBAAgB,CAAC,GAAG,SAAS,OAAO;AAC1E,aAAO,SAAS;AAAA,IACpB,CAAC;AAAA,EACL;AAAA,EACA,KAAK,SAAS,aAAa,SAAS;AAChC,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,aAAO,KAAK,UAAU,gBAAgB,SAAS,aAAa,OAAO;AAAA,IACvE,CAAC;AAAA,EACL;AAAA,EACA,WAAW,SAAS,aAAa,SAAS;AACtC,WAAO,iBAAiB,MAAM,WAAW,UAAU,eAAe;AAC9D,UAAI,uBAAuB,KAAK,aAC5B,OAAO,KAAK,UAAU,sBAAsB,YAAY;AACxD,cAAM,QAAQ,OAAO,iBAAiB,cAAc,KAAK,UAAU,kBAAkB,SAAS,aAAa,OAAO,CAAC,CAAC,CAAC;AAAA,MACzH,OACK;AACD,cAAM,MAAM,MAAM,QAAQ,KAAK,UAAU,gBAAgB,SAAS,aAAa,OAAO,CAAC;AACvF,cAAM,MAAM,QAAQ,EAAE,OAAO,IAAI,SAAS,MAAM,MAAM,WAAW,IAAI,UAAU,CAAC;AAAA,MACpF;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;;;ACxDO,IAAM,oBAAN,MAAwB;AAAA,EAC3B,YAAY;AACR,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,aAAO,EAAE,UAAU,QAAQ,OAAO,GAAG;AAAA,IACzC,CAAC;AAAA,EACL;AAAA,EACA,kBAAkB,QAAQ,UAAU;AAChC,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,aAAO;AAAA,IACX,CAAC;AAAA,EACL;AACJ;;;ACTO,IAAM,iBAAN,MAAqB;AAAA,EACxB,YAAY,QAAQ,WAAW;AAC3B,SAAK,YAAY;AACjB,SAAK,uBAAuB,OAAO;AAAA,EACvC;AAAA,EACA,YAAY;AACR,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,SAAS,KAAK,UAAU,UAAU;AACxC,aAAO,EAAE,UAAU,UAAU,OAAO,OAAO,OAAO,cAAc,OAAO,aAAa;AAAA,IACxF,CAAC;AAAA,EACL;AAAA,EACA,kBAAkB,OAAO,SAAS;AAC9B,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI;AACJ,YAAM,UAAU,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,YAAY,QAAQ,OAAO,SAAS,KAAK,CAAC;AACzH,YAAM,eAAe,0BAA0B,QAAQ,KAAK,oBAAoB;AAChF,YAAM,aAAa,wBAAwB,KAAK;AAChD,UAAI;AACA,cAAM,MAAM,MAAM,KAAK,UAAU,qBAAqB;AAAA,UAClD;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QACpB,CAAC;AACD,eAAO,sBAAsB,GAAG;AAAA,MACpC,SACO,GAAG;AACN,eAAO,MAAM,4CAA4C,CAAC;AAC1D,eAAO;AAAA,MACX;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EACA,OAAO,SAAS,SAAS;AACrB,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,WAAW,MAAM,KAAK,UAAU,gBAAgB,CAAC,GAAG,SAAS,OAAO;AAC1E,aAAO,SAAS;AAAA,IACpB,CAAC;AAAA,EACL;AAAA,EACA,KAAK,SAAS,aAAa,SAAS;AAChC,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,aAAO,KAAK,UAAU,gBAAgB,SAAS,aAAa,OAAO;AAAA,IACvE,CAAC;AAAA,EACL;AAAA,EACA,WAAW,SAAS,aAAa,SAAS;AACtC,WAAO,iBAAiB,MAAM,WAAW,UAAU,eAAe;AAC9D,UAAI,uBAAuB,KAAK,aAC5B,OAAO,KAAK,UAAU,sBAAsB,YAAY;AACxD,cAAM,QAAQ,OAAO,iBAAiB,cAAc,KAAK,UAAU,kBAAkB,SAAS,aAAa,OAAO,CAAC,CAAC,CAAC;AAAA,MACzH,OACK;AAED,cAAM,MAAM,MAAM,QAAQ,KAAK,UAAU,gBAAgB,SAAS,aAAa,OAAO,CAAC;AACvF,cAAM,MAAM,QAAQ,EAAE,OAAO,IAAI,SAAS,MAAM,MAAM,WAAW,IAAI,UAAU,CAAC;AAAA,MACpF;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;;;ACtDO,IAAM,uBAAuB;AAkC7B,IAAM,gBAAgB,OAAO,OAAO;AAAA,EACvC,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AACZ,CAAC;AAuBM,IAAM,mBAAmB,OAAO,OAAO;AAAA,EAC1C;AAAA,EACA;AACJ,CAAC;AAeD,IAAM,uBAAuB,IAAI,IAAI,OAAO,QAAQ,aAAa,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AAAA,EACtF,MAAM,YAAY;AAAA,EAClB;AACJ,CAAC,CAAC;AAYK,SAAS,kBAAkB,OAAO;AACrC,MAAI,OAAO,UAAU;AACjB,WAAO;AACX,SAAO,qBAAqB,IAAI,MAAM,KAAK,EAAE,YAAY,CAAC;AAC9D;AAUO,IAAM,yBAAyB;AAc/B,IAAM,mCAAmC;AAoBzC,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC5C,YAEA,aAEA,WAEA,UAEA,QAOA,OAAO;AACH,UAAM,GAAG,WAAW,wDACf,aAAa,OACR,WAAW,YAAY,OAAO,IAAI,QAAQ,KAAK,mBAAmB,UAAU,SAAS,aACrF,OACL,SAAS,KAAK,MAAM,KAAK,MAC1B,kEAA6D;AACjE,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,uBAAuB,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM;AAChF,SAAK,eAAe,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM;AAAA,EAC5E;AACJ;AAyBO,IAAM,oBAAoB,CAAC,QAAQ,SAAS,WAAW,0BAA0B,SAAS;AAQ1F,IAAM,uBAAuB,CAAC,SAAS;AAC1C,MAAI;AACA,WAAO,KAAK,MAAM,IAAI;AAAA,EAC1B,SACO,IAAI;AACP,WAAO;AAAA,EACX;AACJ;AAQO,IAAM,SAAS,CAAC,YAAY;AAC/B,QAAM,OAAO,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ;AACvE,SAAO,OAAO,SAAS,WAAW,OAAO;AAC7C;AAEA,IAAM,oBAAoB,CAAC,UAAU,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AAEnG,IAAM,qBAAqB,CAAC,UAAU,OAAO,UAAU,YAAY,QAAQ;AAE3E,IAAM,oBAAoB,CAAC,UAAU,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,KAAK,QAAQ;AAuBzF,SAAS,oBAAoB,aAAa,SAAS,gBAAgB;AACtE,MAAI,IAAI,IAAI,IAAI;AAChB,QAAM,OAAQ,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAI3E,QAAM,UAAW,OAAO,KAAK,YAAY,YAAY,KAAK,YAAY,OAAO,KAAK,UAAU,CAAC;AAC7F,QAAM,SAAS,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAC7D,SAAO,IAAI,qBAAqB,cAAc,KAAK,kBAAkB,KAAK,SAAS,OAAO,QAAQ,OAAO,SAAS,KAAK,kBAAkB,QAAQ,SAAS,IAAI,KAAK,kBAAkB,KAAK,QAAQ,OAAO,QAAQ,OAAO,SAAS,KAAK,kBAAkB,QAAQ,QAAQ,GAAG,QAAQ;AAAA,IAC/Q,uBAAuB,KAAK,mBAAmB,KAAK,oBAAoB,OAAO,QAAQ,OAAO,SAAS,KAAK,mBAAmB,QAAQ,oBAAoB;AAAA,IAC3J,eAAe,KAAK,kBAAkB,KAAK,MAAM,OAAO,QAAQ,OAAO,SAAS,KAAK,kBAAkB,QAAQ,MAAM;AAAA,EACzH,CAAC;AACL;;;AChOO,IAAM,wBAAwB;AA+B9B,IAAM,mCAAmC;AAazC,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC5C,YAEA,aAEA,MAQA,gBAEA,cAEA,QAAQ;AACJ,UAAM,GAAG,WAAW,yBAAyB,IAAI,OAC5C,kBAAkB,OAAO,gBAAW,cAAc,KAAK,OACvD,eAAe,IAAI,YAAY,KAAK,OACpC,SAAS,KAAK,MAAM,KAAK,MAC1B,2EAAsE;AAC1E,SAAK,cAAc;AACnB,SAAK,OAAO;AACZ,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EAChB;AACJ;AA6BA,IAAM,0BAA0B,OAAO,OAAO;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAED,IAAM,uBAAuB,OAAO,OAAO;AAAA,EACvC;AAAA,EACA;AACJ,CAAC;AAaD,SAAS,mBAAmB,SAAS;AACjC,MAAI;AACJ,QAAM,QAAQ,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAE3E,aAAW,aAAa;AAAA,IACpB,MAAM;AAAA,KACL,KAAK,MAAM,aAAa,QAAQ,OAAO,SAAS,SAAS,GAAG;AAAA,EACjE,GAAG;AACC,QAAI,OAAO,cAAc,YAAY,cAAc,MAAM;AACrD,YAAM,EAAE,MAAM,QAAQ,IAAI;AAC1B,aAAO;AAAA,QACH,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,QACxC,SAAS,OAAO,YAAY,WAAW,UAAU;AAAA,MACrD;AAAA,IACJ;AAAA,EACJ;AACA,SAAO;AACX;AAOA,SAAS,WAAW,SAAS;AACzB,QAAM,QAAS,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAC5E,QAAM,SAAU,OAAO,MAAM,YAAY,YAAY,MAAM,YAAY,OAAO,MAAM,UAAU,CAAC;AAC/F,aAAW,aAAa,CAAC,MAAM,MAAM,OAAO,IAAI,GAAG;AAC/C,QAAI,cAAc,UAAU,cAAc;AACtC,aAAO;AAAA,EACf;AACA,SAAO;AACX;AAQA,SAAS,qBAAqB,SAAS;AACnC,QAAM,OAAO,mBAAmB,OAAO;AACvC,MAAI,EAAE,SAAS,QAAQ,SAAS,SAAS,SAAS,KAAK;AACnD,WAAO;AACX,MAAI,qBAAqB,SAAS,KAAK,IAAI;AACvC,WAAO;AAGX,MAAI,KAAK,SAAS;AACd,WAAO;AACX,SAAO;AACX;AAgBO,SAAS,kBAAkB,QAAQ,MAAM,SAAS;AACrD,MAAI,IAAI;AAmBR,MAAI,SAAS,uBAAuB;AAChC,YAAQ,MAAM,KAAK,WAAW,OAAO,OAAO,QAAQ,OAAO,SAAS,KAAK,qBAAqB,OAAO,OAAO,QAAQ,OAAO,SAAS,KAAK;AAAA,EAC7I;AACA,MAAI,WAAW;AACX,WAAO;AAIX,QAAM,aAAa,qBAAqB,OAAO;AAC/C,MAAI;AACA,WAAO;AAIX,QAAM,OAAO,mBAAmB,OAAO;AACvC,OAAK,SAAS,QAAQ,SAAS,SAAS,SAAS,KAAK,UAAU,2BAA2B,KAAK,SAAS;AACrG,UAAM,UAAU,KAAK;AACrB,QAAI,wBAAwB,KAAK,CAAC,WAAW,OAAO,KAAK,OAAO,CAAC;AAC7D,aAAO;AAAA,EACf;AACA,SAAO;AACX;AASO,SAAS,oBAAoB,aAAa,MAAM,gBAAgB,SAAS,gBAAgB;AAC5F,MAAI;AACJ,QAAM,OAAO,mBAAmB,OAAO;AACvC,SAAO,IAAI,qBAAqB,aAAa,MAAM,gBAAgB,SAAS,QAAQ,SAAS,SAAS,SAAS,KAAK,OAAO,KAAK,SAAS,QAAQ,SAAS,SAAS,SAAS,KAAK,aAAa,QAAQ,OAAO,SAAS,KAAK,cAAc;AAC7O;AASO,SAAS,uBAAuB,aAAa;AAChD,QAAM,QAAQ,OAAO,QAAQ,aAAa,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,WAAW;AACrF,SAAO,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM,CAAC;AAChE;;;ACtTO,IAAM,6BAA6B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAEO,IAAM,gCAAgC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AA0BO,SAAS,cAAc,SAAS;AACnC,MAAI,8BAA8B,SAAS,OAAO;AAC9C,WAAO;AACX,MAAI,2BAA2B,SAAS,OAAO;AAC3C,WAAO;AACX,SAAO;AACX;;;ACjCO,SAAS,mBAAmB,UAAU;AACzC,SAAO,aAAa,cAAc,eAAe;AACrD;AAgBO,SAAS,kBAAkB,MAAM;AACpC,SAAO,KAAK,QAAQ,uBAAuB,EAAE;AACjD;;;AC/BA,IAAM,iBAAiB;AAmBhB,SAAS,iBAAiB,YAAY,EAAE,aAAa,QAAQ,GAAG;AACnE,QAAM,IAAI,KAAK,IAAI,KAAK,IAAI,YAAY,CAAC,GAAG,CAAC;AAC7C,SAAO,KAAK,iBACL,IAAI,iBAAkB,cACvB,eAAgB,IAAI,mBAAmB,IAAI,mBAAoB,UAAU;AACnF;;;ACgBA,IAAM,qBAAqB;AAU3B,IAAM,oBAAoB;AAAA,EACtB,6BAA6B,EAAE,kBAAkB,GAAG,qBAAqB,EAAE;AAAA;AAAA,EAE3E,kBAAkB,EAAE,kBAAkB,IAAI,qBAAqB,GAAG;AAAA;AAAA;AAAA,EAGlE,mBAAmB,EAAE,kBAAkB,GAAG,qBAAqB,GAAG;AAAA,EAClE,mBAAmB,EAAE,kBAAkB,GAAG,qBAAqB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASlE,mBAAmB,EAAE,kBAAkB,GAAG,qBAAqB,GAAG;AAAA;AAAA,EAElE,qBAAqB,EAAE,kBAAkB,GAAG,qBAAqB,GAAG;AACxE;AAeO,SAAS,kBAAkB,OAAO;AACrC,SAAO,kBAAkB,KAAK;AAClC;AAUO,IAAM,kCAAkC;AAExC,IAAM,sCAAsC;AAE5C,IAAM,sCAAsC;AAM5C,SAAS,mBAAmB,OAAO,OAAO;AAC7C,QAAM,EAAE,kBAAkB,oBAAoB,IAAI,kBAAkB,KAAK;AACzE,QAAM,IAAI;AAKV,QAAM,qBAAqB,KAAK,IAAI,GAAG,MAAM,mBAAmB,MAAM,kBAAkB;AACxF,QAAM,aAAc,MAAM,sBAAsB,IAAK;AACrD,QAAM,gBAAiB,MAAM,kBAAkB,IAAK,mBAAmB;AACvE,QAAM,iBAAkB,qBAAqB,IAAK,mBAAmB,sCAChE,MAAM,qBAAqB,IAAK,mBAAmB;AACxD,QAAM,gBAAiB,MAAM,eAAe,IAAK;AAKjD,QAAM,gBAAiB,MAAM,kBAAkB,IAAK;AACpD,QAAM,iBAAkB,MAAM,mBAAmB,IAAK;AACtD,SAAO;AAAA,IACH,SAAS,aAAa,gBAAgB,iBAAiB;AAAA,IACvD,UAAU,gBAAgB,iBAAiB,iBAAiB;AAAA,IAC5D,WAAW;AAAA,MACP,WAAW;AAAA,MACX,cAAc;AAAA,MACd,eAAe;AAAA,MACf,cAAc;AAAA,IAClB;AAAA,EACJ;AACJ;AAWO,IAAM,gCAAgC;AAWtC,IAAM,iCAAiC;AAK9C,IAAM,iBAAiB;AAAA,EACnB,yBAAyB;AAAA,IACrB,MAAM;AAAA,IACN,MAAM,EAAE,kBAAkB,KAAK,qBAAqB,IAAI;AAAA,EAC5D;AAAA,EACA,oBAAoB,EAAE,MAAM,QAAQ,MAAM,EAAE,kBAAkB,KAAK,qBAAqB,IAAI,EAAE;AAAA,EAC9F,kBAAkB;AAAA,IACd,MAAM;AAAA,IACN,UAAU,EAAE,kBAAkB,MAAM,qBAAqB,GAAK;AAAA,IAC9D,aAAa,EAAE,kBAAkB,KAAK,qBAAqB,GAAK;AAAA,EACpE;AAAA,EACA,yBAAyB;AAAA,IACrB,MAAM;AAAA,IACN,MAAM,EAAE,kBAAkB,MAAM,qBAAqB,IAAI;AAAA,EAC7D;AAAA,EACA,oBAAoB,EAAE,MAAM,QAAQ,MAAM,EAAE,kBAAkB,KAAK,qBAAqB,EAAI,EAAE;AAAA,EAC9F,0BAA0B;AAAA,IACtB,MAAM;AAAA,IACN,UAAU,EAAE,kBAAkB,GAAK,qBAAqB,GAAK;AAAA,IAC7D,aAAa,EAAE,kBAAkB,GAAK,qBAAqB,GAAK;AAAA,EACpE;AACJ;AAgBO,SAAS,eAAe,OAAO,cAAc;AAChD,QAAM,UAAU,eAAe,KAAK;AACpC,MAAI,QAAQ,SAAS,QAAQ;AACzB,WAAO,QAAQ;AAAA,EACnB;AACA,SAAO,eAAe,gCAAgC,QAAQ,cAAc,QAAQ;AACxF;AAMO,SAAS,gBAAgB,OAAO,OAAO;AAE1C,QAAM,EAAE,kBAAkB,oBAAoB,IAAI,eAAe,OAAO,MAAM,YAAY;AAC1F,QAAM,IAAI;AACV,QAAM,uBAAuB,KAAK,IAAI,GAAG,MAAM,eAAe,MAAM,YAAY;AAChF,QAAM,aAAc,uBAAuB,IAAK;AAChD,QAAM,gBAAiB,MAAM,eAAe,IAAK,mBAAmB;AAGpE,QAAM,iBAAkB,MAAM,kBAAkB,MAAM,iBAAiB,IAAK;AAC5E,SAAO;AAAA,IACH,SAAS,aAAa,gBAAgB;AAAA;AAAA,IAEtC,UAAW,MAAM,eAAe,IAAK,mBAAmB;AAAA,IACxD,WAAW;AAAA,MACP,WAAW;AAAA,MACX,cAAc;AAAA,MACd,eAAe;AAAA,MACf,cAAc;AAAA,IAClB;AAAA,EACJ;AACJ;;;AC1OA,IAAM,kBAAkB,CAAC,cAAc,qBAAqB,SAAS,aAAa;AAElF,IAAM,mBAAmB,CAAC,SAAS,SAAS,SAAS,aAAa;AAElE,IAAM,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AACA,IAAMC,iBAAgB,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAEpF,SAAS,WAAW,OAAO;AACvB,MAAI,MAAM,QAAQ,KAAK;AACnB,WAAO,MAAM,IAAI,UAAU;AAC/B,MAAIA,eAAc,KAAK,GAAG;AACtB,UAAM,MAAM,CAAC;AACb,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK;AACrC,UAAI,CAAC,IAAI,WAAW,CAAC;AACzB,WAAO;AAAA,EACX;AACA,SAAO;AACX;AAeA,SAAS,gBAAgB,MAAM,OAAO,MAAM;AACxC,QAAM,MAAM,CAAC;AACb,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC7C,UAAM,OAAO,GAAG,IAAI,IAAI,GAAG;AAC3B,QAAI,gBAAgB,SAAS,GAAG,KAAKA,eAAc,KAAK,GAAG;AACvD,UAAI,GAAG,IAAI,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AAAA,QACvE;AAAA,QACAA,eAAc,KAAK,IAAI,MAAM,OAAO,GAAG,IAAI,IAAI,IAAI,EAAE,IAAI,WAAW,KAAK;AAAA,MAC7E,CAAC,CAAC;AAAA,IACN,WACS,iBAAiB,SAAS,GAAG,KAAK,MAAM,QAAQ,KAAK,GAAG;AAC7D,UAAI,GAAG,IAAI,MAAM,IAAI,CAAC,OAAO,MAAMA,eAAc,KAAK,IAAI,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,EAAE,IAAI,WAAW,KAAK,CAAC;AAAA,IAC9G,WACS,kBAAkB,SAAS,GAAG,GAAG;AACtC,UAAIA,eAAc,KAAK;AACnB,YAAI,GAAG,IAAI,MAAM,OAAO,IAAI;AAAA,eACvB,MAAM,QAAQ,KAAK;AAExB,YAAI,GAAG,IAAI,MAAM,IAAI,CAAC,OAAO,MAAMA,eAAc,KAAK,IAAI,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,EAAE,IAAI,WAAW,KAAK,CAAC;AAAA;AAE1G,YAAI,GAAG,IAAI,WAAW,KAAK;AAAA,IACnC,OACK;AACD,UAAI,GAAG,IAAI,WAAW,KAAK;AAAA,IAC/B;AAAA,EACJ;AACA,SAAO;AACX;AACA,SAAS,UAAU,MAAM,WAAW,OAAO,IAAI;AAC3C,SAAO,UAAU,gBAAgB,MAAM,CAAC,OAAO,cAAc,UAAU,OAAO,WAAW,SAAS,GAAG,IAAI,GAAG,IAAI;AACpH;AASA,IAAM,yBAAyB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAUA,IAAM,uBAAuB,CAAC,SAAS,KAAK;AAsBrC,SAAS,0BAA0B,YAAY;AAClD,QAAM,WAAW,CAAC;AAClB,QAAM,aAAa,CAAC;AACpB,QAAM,cAAc,CAAC;AACrB,QAAM,SAAS,UAAU,YAAY,CAAC,MAAM,SAAS;AACjD,eAAW,WAAW,wBAAwB;AAC1C,UAAI,WAAW,MAAM;AACjB,eAAO,KAAK,OAAO;AACnB,iBAAS,KAAK,GAAG,IAAI,IAAI,OAAO,EAAE;AAAA,MACtC;AAAA,IACJ;AAEA,QAAI,OAAO,KAAK,aAAa,YAAY,KAAK,WAAW,GAAG;AACxD,aAAO,KAAK;AACZ,eAAS,KAAK,GAAG,IAAI,WAAW;AAAA,IACpC;AACA,eAAW,WAAW,sBAAsB;AACxC,UAAI,WAAW;AACX,oBAAY,KAAK,GAAG,IAAI,IAAI,OAAO,EAAE;AAAA,IAC7C;AAUA,UAAM,eAAe,KAAK,SAAS,YAC9B,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,QAAQ,KACxDA,eAAc,KAAK,UAAU;AACjC,QAAI,cAAc;AACd,UAAI,KAAK,yBAAyB,OAAO;AACrC,YAAI,KAAK,yBAAyB,QAAW;AACzC,qBAAW,KAAK,GAAG,IAAI,uBAAuB;AAAA,QAClD;AACA,aAAK,uBAAuB;AAAA,MAChC;AAAA,IACJ;AACA,WAAO;AAAA,EACX,CAAC;AACD,SAAO,EAAE,QAAQ,UAAU,YAAY,YAAY;AACvD;AAWO,SAAS,2BAA2B,YAAY,UAAU;AAC7D,QAAM,EAAE,QAAQ,UAAU,YAAY,YAAY,IAAI,0BAA0B,UAAU;AAC1F,MAAI,SAAS,QAAQ;AACjB,WAAO,KAAK,6BAA6B,QAAQ,qHACa,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,EACvF;AACA,MAAI,WAAW,QAAQ;AACnB,WAAO,KAAK,6BAA6B,QAAQ,gHACa,WAAW,KAAK,IAAI,CAAC,+DAC3B;AAAA,EAC5D;AACA,MAAI,YAAY,QAAQ;AACpB,WAAO,KAAK,6BAA6B,QAAQ,sDACzC,YAAY,KAAK,IAAI,CAAC,qJAC0D;AAAA,EAC5F;AACA,SAAO;AACX;AAOA,IAAM,8BAA8B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AACJ;AAEA,SAAS,eAAe,MAAM,KAAK;AAC/B,MAAI,CAAC,IAAI,WAAW,IAAI;AACpB,WAAO;AACX,MAAI,UAAU;AACd,aAAW,WAAW,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG;AAC3C,QAAI,CAACA,eAAc,OAAO;AACtB,aAAO;AACX,cAAU,QAAQ,QAAQ,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA,EACrE;AACA,SAAOA,eAAc,OAAO,IAAI,UAAU;AAC9C;AAaA,SAAS,WAAW,MAAM,MAAM,MAAM,YAAY;AAU9C,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC5D,SAAO,OAAO,CAAC,QAAQ,IAAI,GAAG,GAAG;AAC7B,UAAM,SAAS,eAAe,MAAM,GAAG;AACvC,QAAI,CAAC;AACD;AACJ,UAAM,EAAE,MAAM,SAAS,IAAI,SAAS,WAAW,OAAO,SAAS,CAAC,MAAM,CAAC;AACvE,cAAU,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,WAAW,MAAM,CAAC,GAAG,QAAQ;AACvE,cAAU,oBAAI,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC;AACnC,UAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAAA,EAC5D;AACA,MAAI,OAAO,QAAQ,SAAS;AACxB,eAAW,KAAK,QAAQ,IAAI;AAChC,SAAO,gBAAgB,SAAS,CAAC,UAAU,WAAW,MAAM,OAAO,SAAS,UAAU,GAAG,EAAE;AAC/F;AAwBO,SAAS,eAAe,YAAY;AACvC,QAAM,aAAa,CAAC;AACpB,QAAM,UAAU,WAAW,YAAY,YAAY,oBAAI,IAAI,GAAG,UAAU;AACxE,MAAI,WAAW,QAAQ;AACnB,WAAO,KAAK,6GACS,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,EAAE,KAAK,IAAI,CAAC,6JAEd;AAAA,EAC9C;AACA,QAAM,aAAa,UAAU,SAAS,CAAC,SAAS;AAE5C,QAAI,MAAM,QAAQ,KAAK,IAAI,GAAG;AAC1B,YAAM,QAAQ,KAAK,KAAK,OAAO,CAAC,MAAM,MAAM,MAAM;AAClD,UAAI,MAAM,WAAW,KAAK,KAAK,KAAK,WAAW,MAAM,QAAQ;AACzD,aAAK,OAAO,MAAM,CAAC;AACnB,aAAK,WAAW;AAAA,MACpB;AAAA,IACJ;AAEA,QAAI,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC3B,YAAM,WAAW,KAAK,MAAM,OAAOA,cAAa;AAChD,YAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AACxD,UAAI,SAAS,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC/C,cAAM,EAAE,OAAO,SAAS,IAAI,MAAM,WAAW,OAAO,MAAM,CAAC,OAAO,CAAC;AACnE,eAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,GAAG,EAAE,UAAU,KAAK,CAAC;AAAA,MACnG;AAAA,IACJ;AACA,QAAI,WAAW,MAAM;AACjB,WAAK,OAAO,CAAC,KAAK,KAAK;AACvB,aAAO,KAAK;AAAA,IAChB;AACA,eAAW,WAAW;AAClB,aAAO,KAAK,OAAO;AASvB,eAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACjC,UAAI,IAAI,WAAW,GAAG,KAAK,QAAQ;AAC/B,eAAO,KAAK,GAAG;AAAA,IACvB;AACA,WAAO;AAAA,EACX,CAAC;AACD,SAAO;AACX;;;AC3TO,SAAS,yBAAyB,OAAO,eAAe,cAAc;AACzE,QAAM,eAAe,iBAAiB,gBAAgB,iBAAiB,WAClE,MAAM,SAAS,gBAAgB,MAAM,SAAS;AACnD,MAAI,CAAC;AACD,WAAO;AACX,MAAI,iBAAiB,QAAQ,iBAAiB,SAAS,SAAS,aAAa;AACzE,WAAO,aAAa;AACxB,MAAI,cAAc;AACd,WAAO,cAAc;AACzB,SAAO;AACX;;;ACpBO,SAAS,eAAe,IAAI,QAAQ;AACvC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAM,cAAc,MAAM;AAAE,UAAI;AAAI,cAAQ,KAAK,WAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,YAAY,QAAQ,OAAO,SAAS,KAAK,IAAI,aAAa,8BAA8B,YAAY;AAAA,IAAG;AAC/M,QAAI,WAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,SAAS;AAChE,aAAO,YAAY,CAAC;AACpB;AAAA,IACJ;AACA,UAAM,UAAU,MAAM;AAClB,mBAAa,KAAK;AAClB,aAAO,YAAY,CAAC;AAAA,IACxB;AACA,UAAM,QAAQ,WAAW,MAAM;AAC3B,iBAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,oBAAoB,SAAS,OAAO;AAC3F,cAAQ;AAAA,IACZ,GAAG,EAAE;AACL,eAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC5G,CAAC;AACL;;;AChBA,IAAM,gCAAgC;AAgB/B,SAAS,eAAe,QAAQ,SAAS,aAAa,cAAc;AACvE,SAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAM,SAAS,OAAO,UAAU;AAChC,UAAM,UAAU,IAAI,YAAY;AAChC,QAAI,SAAS;AACb,UAAM,iBAAiB,CAAC,SAAS,IAAI,MAAM,GAAG,WAAW,kCAAkC,KAAK,MAAM,GAAG,6BAA6B,CAAC,EAAE;AACzI,UAAM,YAAY,CAAC,SAAS;AACxB,UAAI,CAAC;AACD,eAAO;AACX,UAAI;AACJ,UAAI;AACA,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC5B,SACO,IAAI;AACP,cAAM,eAAe,IAAI;AAAA,MAC7B;AAGA,UAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AACxE,cAAM,eAAe,IAAI;AAAA,MAC7B;AACA,YAAM,QAAQ;AACd,UAAI,MAAM,MAAM,MAAM;AAClB,YAAI,MAAM,QAAQ,MAAM;AACpB,gBAAM,IAAI,MAAM,GAAG,WAAW,wCAAwC;AAAA,QAC1E;AACA,eAAO;AAAA,MACX;AACA,UAAI,MAAM,MAAM,OAAO;AAGnB,YAAI,OAAO,MAAM,WAAW,UAAU;AAClC,gBAAM,IAAI,MAAM,GAAG,WAAW,mDAAmD;AAAA,QACrF;AACA,eAAO;AAAA,MACX;AACA,UAAI,MAAM,MAAM,QAAQ;AAMpB,YAAI,eAAe,KACf,OAAO,MAAM,qBAAqB,YAClC,MAAM,mBAAmB,cAAc;AACvC,gBAAM,IAAI,aAAa,GAAG,WAAW,oCAAoC,MAAM,gBAAgB,6CAA6C,YAAY,OAAO,cAAc;AAAA,QACjL;AACA,eAAO;AAAA,MACX;AACA,aAAO;AAAA,IACX;AACA,QAAI;AACA,iBAAS;AAEL,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI;AACA;AACJ,gBAAQ;AACR,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,YAAI,UAAU,OAAO,QAAQ,IAAI;AACjC,eAAO,YAAY,IAAI;AACnB,gBAAM,OAAO,OAAO,MAAM,GAAG,OAAO,EAAE,KAAK;AAC3C,mBAAS,OAAO,MAAM,UAAU,CAAC;AACjC,gBAAMC,SAAQ,UAAU,IAAI;AAC5B,cAAIA;AACA,mBAAOA;AACX,oBAAU,OAAO,QAAQ,IAAI;AAAA,QACjC;AAAA,MACJ;AAEA,YAAM,QAAQ,WAAW,SAAS,QAAQ,OAAO,GAAG,KAAK,CAAC;AAC1D,UAAI;AACA,eAAO;AACX,YAAM,IAAI,MAAM,GAAG,WAAW,8CAA8C;AAAA,IAChF,UACA;AAGI,WAAK,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,MAAE,CAAC;AAAA,IACxC;AAAA,EACJ,CAAC;AACL;;;AC/DO,IAAM,kCAAkC;AAmBxC,IAAM,wCAAwC;AAErD,IAAM,sBAAsB;AAE5B,IAAM,gBAAgB;AASf,SAAS,eAAe,SAAS;AACpC,MAAI;AACJ,QAAM,SAAS,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,SAAS,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,SAAS,mBAAmB;AAC5J,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,YAAY,MAAM;AACvE;AASO,SAAS,aAAa,SAAS;AAClC,MAAI;AACJ,QAAM,OAAO,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,SAAS,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,SAAS,aAAa;AACpJ,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM;AAC1C,WAAO;AACX,QAAM,UAAU,OAAO,IAAI,KAAK,CAAC;AACjC,MAAI,OAAO,SAAS,OAAO;AACvB,WAAO,KAAK,IAAI,GAAG,UAAU,aAAa;AAC9C,QAAM,KAAK,KAAK,MAAM,GAAG;AACzB,MAAI,OAAO,MAAM,EAAE;AACf,WAAO;AACX,SAAO,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC;AACtC;AAYO,SAAS,YAAY,SAAS;AACjC,QAAM,QAAQ,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAC3E,QAAM,SAAS,OAAO,MAAM,YAAY,YAAY,MAAM,YAAY,OAChE,MAAM,UACN;AACN,aAAW,UAAU,CAAC,MAAM,OAAO,WAAW,QAAQ,WAAW,SAAS,SAAS,OAAO,KAAK,GAAG;AAC9F,UAAM,UAAU,WAAW,QAAQ,WAAW,SAAS,SAAS,OAAO;AACvE,QAAI,CAAC,MAAM,QAAQ,OAAO;AACtB;AACJ,eAAW,SAAS,SAAS;AACzB,YAAM,OAAO,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM,OAAO;AACxE,UAAI,OAAO,SAAS,YAAY,CAAC,KAAK,SAAS,sBAAsB;AACjE;AACJ,YAAM,QAAQ,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM;AAElE,UAAI,OAAO,UAAU;AACjB;AACJ,YAAM,UAAU,OAAO,MAAM,QAAQ,MAAM,EAAE,CAAC;AAC9C,UAAI,OAAO,SAAS,OAAO,KAAK,WAAW;AACvC,eAAO,UAAU;AAAA,IACzB;AAAA,EACJ;AACA,SAAO;AACX;AAaO,SAAS,iBAAiB,SAAS,QAAQ,UAAU,oBAAoB,OAAO,mBAAmB;AACtG,QAAM,SAAS,SAAS,KAAK,IAAI,GAAG,OAAO;AAC3C,MAAI,YAAY,QAAQ,CAAC,OAAO,SAAS,QAAQ;AAC7C,WAAO;AAKX,QAAM,WAAW,KAAK,IAAI,UAAU,iCAAiC,KAAK,IAAI,GAAG,iBAAiB,CAAC;AACnG,SAAO,KAAK,IAAI,QAAQ,QAAQ;AACpC;AAQO,SAAS,qBAAqB,YAAY,UAAU;AACvD,SAAO,KAAK,IAAI,GAAG,aAAa,QAAQ;AAC5C;;;AC9JA,IAAM,cAAc;AASb,SAAS,cAAc,SAAS;AACnC,SAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAC5B,UAAM,EAAE,KAAK,SAAS,MAAM,aAAa,aAAa,mBAAmB,SAAS,cAAc,eAAe,OAAQ,IAAI;AAG3H,UAAM,SAAS,uBAAuB,WAAW;AAMjD,QAAI,qBAAqB;AAKzB,UAAM,UAAU,CAAC,SAAS,aAAa;AACnC,YAAM,WAAW,gBAAgB,KAAK,IAAI,GAAG,OAAO;AACpD,YAAM,cAAc,wCAAwC;AAC5D,YAAM,SAAS,iBAAiB,SAAS,eAAe,UAAU,WAAW;AAC7E,4BAAsB,qBAAqB,QAAQ,QAAQ;AAC3D,UAAI,YAAY,QAAQ,SAAS,UAAU;AAGvC,eAAO,KAAK,GAAG,WAAW,4DAA4D,KAAK,MAAM,MAAM,CAAC,aAAa,KAAK,MAAM,QAAQ,CAAC,KAAK;AAAA,MAClJ,WACS,YAAY,QAAQ,WAAW,UAAU;AAG9C,eAAO,KAAK,GAAG,WAAW,kEAAkE,KAAK,MAAM,QAAQ,CAAC,WAAW,qCAAqC,6DAAwD,KAAK,MAAM,MAAM,CAAC,IAAI;AAAA,MAClP;AACA,aAAO,eAAe,QAAQ,MAAM;AAAA,IACxC;AAGA,aAAS,UAAU,GAAG,WAAW,aAAa,WAAW,GAAG;AACxD,YAAM,oBAAoB,IAAI,gBAAgB;AAU9C,YAAM,YAAY,YAAY,IAAI;AAClC,UAAI;AACJ,UAAI;AACJ,YAAM,kBAAkB,MAAM;AAC1B,cAAM,SAAS,KAAK,MAAM,YAAY,IAAI,IAAI,SAAS;AACvD,YAAI,cAAc,QAAW;AACzB,iBAAO,GAAG,WAAW,4BAA4B,MAAM;AAAA,QAC3D;AACA,eAAO,GAAG,WAAW,4BAA4B,MAAM,gCAA2B,KAAK,MAAM,YAAY,SAAS,CAAC,qBAAqB,kBAAkB,QAAQ,kBAAkB,SAAS,gBAAgB,SAAS;AAAA,MAC1N;AAIA,UAAI,YAAY,WAAW,MAAM,kBAAkB,MAAM,IAAI,aAAa,gBAAgB,GAAG,cAAc,CAAC,GAAG,OAAO;AAMtH,YAAM,kBAAkB,MAAM;AAC1B,YAAI,gBAAgB;AAChB;AACJ,qBAAa,SAAS;AACtB,oBAAY,WAAW,MAAM,kBAAkB,MAAM,IAAI,aAAa,GAAG,WAAW,iCAAiC,YAAY,OAAO,cAAc,CAAC,GAAG,YAAY;AAAA,MAC1K;AAMA,YAAM,EAAE,QAAQ,gBAAgB,QAAQ,IAAI,eAAe,CAAC,QAAQ,kBAAkB,MAAM,CAAC;AAG7F,UAAI;AACA,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAC9B,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,UACzB,QAAQ;AAAA,UACR;AAAA,QACJ,CAAC;AAGD,oBAAY,YAAY,IAAI;AAG5B,yBAAiB,MAAM,MAAM,KAAK,SAAS,aAAa,QAAQ,OAAO,SAAS,SAAS,GAAG,SAAS,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,IAAI,cAAc,OAAO,QAAQ,OAAO,SAAS,KAAK;AACpM,YAAI,CAAC,SAAS,IAAI;AAiBd,gBAAM,UAAU,MAAM,SAAS,KAAK;AACpC,gBAAM,SAAS,qBAAqB,OAAO;AAQ3C,gBAAM,UAAU,kBAAkB,QAAQ,OAAO,MAAM,GAAG,MAAM;AAChE,cAAI,SAAS;AACT,kBAAM,oBAAoB,aAAa,SAAS,SAAS,QAAQ,QAAQ,WAAW,MAAS;AAAA,UACjG;AAUA,cAAI,kBAAkB,SAAS,QAAQ,OAAO,MAAM,CAAC,GAAG;AACpD,kBAAM,oBAAoB,aAAa,QAAQ,WAAW,MAAS;AAAA,UACvE;AAIA,gBAAM,eAAe,eAAe,SAAS,OAAO;AACpD,cAAI,kBAAkB,SAAS,SAAS,MAAM,KAAK,CAAC,gBAAgB,UAAU,aAAa;AACvF,mBAAO,KAAK,GAAG,WAAW,+BAA+B,SAAS,MAAM,uBAAuB,UAAU,CAAC,IAAI,WAAW,GAAG;AAC5H,yBAAa,SAAS;AAItB,kBAAM,QAAQ,SAAS,aAAa,SAAS,OAAO,KAAK,YAAY,MAAM,CAAC;AAC5E;AAAA,UACJ;AACA,gBAAM,IAAI,MAAM,GAAG,WAAW,kBAAkB,SAAS,MAAM,KAAK,OAAO,EAAE;AAAA,QACjF;AAIA,cAAM,MAAM,KAAK,SAAS,aAAa,QAAQ,OAAO,SAAS,SAAS,GAAG,IAAI,cAAc,OAAO,QAAQ,OAAO,SAAS,SAAS,GAAG,YAAY,EAAE,SAAS,sBAAsB,MACjL,SAAS,MAAM;AACf,0BAAgB;AAChB,gBAAM,QAAQ,MAAM,eAAe,SAAS,MAAM,iBAAiB,aAAa,YAAY;AAC5F,cAAI,MAAM,MAAM;AACZ,mBAAO,MAAM;AAIjB,cAAI,MAAM,SAAS,oBAAoB;AAGnC,kBAAM,IAAI,aAAa,GAAG,WAAW,sBAAsB,KAAK,MAAM,WAAW,QAAQ,OAAO,SAAS,KAAK,kBAAkB,IAAI,cAAc;AAAA,UACtJ;AAaA,gBAAM,gBAAgB,kBAAkB,QAAQ,MAAM,MAAM,KAAK;AACjE,cAAI,eAAe;AACf,kBAAM,oBAAoB,aAAa,eAAe,MAAM,QAAQ,OAAO,MAAM,KAAK;AAAA,UAC1F;AACA,cAAI,kBAAkB,MAAM,QAAQ,MAAM,IAAI,GAAG;AAC7C,kBAAM,oBAAoB,aAAa,KAAK;AAAA,UAChD;AAKA,cAAI,kBAAkB,SAAS,MAAM,MAAM,KAAK,UAAU,aAAa;AACnE,mBAAO,KAAK,GAAG,WAAW,+BAA+B,MAAM,MAAM,mCAAmC,UAAU,CAAC,IAAI,WAAW,GAAG;AACrI,yBAAa,SAAS;AACtB,kBAAM,QAAQ,SAAS,YAAY,KAAK,CAAC;AACzC;AAAA,UACJ;AACA,gBAAM,IAAI,MAAM,GAAG,WAAW,kBAAkB,MAAM,MAAM,MAAM,KAAK,MAAM,WAAW,QAAQ,OAAO,SAAS,KAAK,KAAK,UAAU,MAAM,OAAO,CAAC,EAAE;AAAA,QACxJ;AACA,eAAQ,MAAM,SAAS,KAAK;AAAA,MAChC,SACO,GAAG;AAIN,cAAM,yBAAyB,GAAG,kBAAkB,QAAQ,MAAM;AAAA,MACtE,UACA;AACI,qBAAa,SAAS;AACtB,gBAAQ;AAAA,MACZ;AAAA,IACJ;AAEA,UAAM,IAAI,MAAM,GAAG,WAAW,uCAAuC;AAAA,EACzE,CAAC;AACL;;;AChOA,IAAM,uBAAuB;AAC7B,IAAM,wBAAwB;AAC9B,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AACxB,IAAM,wBAAwB;AAC9B,IAAM,qBAAqB;AAE3B,IAAM,gCAAgC;AACtC,IAAM,4BAA4B;AAKlC,SAAS,sBAAsB,QAAQ;AACnC,MAAI,CAAC,UAAU,WAAW;AACtB,WAAO;AACX,MAAI,WAAW;AACX,WAAO,EAAE,MAAM,MAAM;AACzB,MAAI,WAAW;AACX,WAAO,EAAE,MAAM,OAAO;AAC1B,SAAO,EAAE,MAAM,QAAQ,MAAM,OAAO,KAAK;AAC7C;AAKA,IAAM,2BAA2B;AAAA,EAC7B,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,6BAA6B;AACjC;AAMA,IAAM,8BAA8B;AAEpC,IAAM,4BAA4B;AAClC,SAAS,8BAA8B,OAAO;AAC1C,MAAI,CAAC,8BAA8B,SAAS,KAAK,GAAG;AAChD,UAAM,IAAI,MAAM,0CAA0C,KAAK,kBAAkB,8BAA8B,KAAK,IAAI,CAAC,GAAG;AAAA,EAChI;AACJ;AAKA,SAAS,sBAAsB,OAAO;AAClC,SAAQ,UAAU,oBACd,UAAU,qBACV,UAAU,qBACV,UAAU;AAClB;AAOA,SAAS,+BAA+B,OAAO;AAC3C,SAAQ,UAAU,oBACd,UAAU,qBACV,UAAU,qBACV,UAAU;AAClB;AAMA,SAAS,yBAAyB,OAAO;AACrC,SAAO,UAAU;AACrB;AAMA,SAAS,oBAAoB,OAAO;AAChC,SAAO,UAAU;AACrB;AAiCA,SAAS,kBAAkB,OAAO,QAAQ;AACtC,QAAM,qBAAqB,UAAU,qBAAqB,oBAAoB,KAAK;AACnF,QAAM,WAAW,EAAE,MAAM,YAAY,SAAS,aAAa;AAC3D,MAAI,WAAW,OAAO;AAElB,QAAI,oBAAoB,KAAK;AACzB,aAAO;AAEX,WAAO,qBAAqB,EAAE,MAAM,WAAW,IAAI;AAAA,EACvD;AACA,MAAI,WAAW,QAAQ;AACnB,WAAO,yBAAyB,KAAK,IAAI,WAAW;AAAA,EACxD;AAIA,MAAI,WAAW,QAAW;AACtB,WAAO,yBAAyB,KAAK,IAAI,WAAW;AAAA,EACxD;AAEA,SAAO,qBAAqB,WAAW;AAC3C;AAiBA,SAAS,eAAe,OAAO;AAC3B,SAAO,UAAU,oBAAoB,UAAU,qBAAqB,UAAU;AAClF;AAWA,IAAM,mBAAmB;AAAA,EACrB,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,KAAK;AACT;AACA,SAAS,gBAAgB,OAAO,QAAQ;AACpC,MAAI,WAAW,UAAa,WAAW,UAAU,WAAW;AACxD,WAAO;AACX,MAAI,CAAC,eAAe,KAAK,KAAK,CAAC,yBAAyB,KAAK;AACzD,WAAO;AACX,SAAO,iBAAiB,MAAM;AAClC;AAKA,IAAM,yBAAyB;AAuBxB,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAC9C,YAEA,OAMA,WAEA,cAEA,WAAW;AACP,UAAM,yBAAyB,aAAa,OAAO,uBAAuB,SAAS,MAAM,gCAAgC,cAAc,KAAK,MACvI,UAAU,SAAS,IAAI,iCAAiC,UAAU,KAAK,IAAI,CAAC,KAAK,MAClF,8IAAyI;AAC7I,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EAChB;AACJ;AAWO,IAAM,qBAAN,MAAM,oBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5B,0BAA0B,QAAQ;AAC9B,QAAI,KAAK;AACL;AACJ,UAAM,UAAU,KAAK,aAAa,MAAM;AACxC,QAAI,CAAC;AACD;AACJ,SAAK,wBAAwB;AAC7B,WAAO,KAAK,OAAO;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,QAAQ;AACjB,YAAQ,QAAQ;AAAA,MACZ,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO,oBAAoB,KAAK,KAAK,IAC/B,2DAAsD,KAAK,KAAK,qIAChE;AAAA,MACV,KAAK;AACD,eAAO,yBAAyB,KAAK,KAAK,IACpC,SACA,4DAAuD,KAAK,KAAK;AAAA,MAC3E,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,YAAI,CAAC,yBAAyB,KAAK,KAAK,KAAK,CAAC,eAAe,KAAK,KAAK,GAAG;AACtE,iBAAO,uCAAuC,MAAM,oBAAe,KAAK,KAAK;AAAA,QACjF;AAGA,eAAO;AAAA,MACX,SAAS;AACL,cAAM,aAAa;AACnB,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,YAAY,SAAS,CAAC,GAAG;AACrB,QAAI,IAAI,IAAI,IAAI;AAOhB,SAAK,kBAAkB;AAMvB,SAAK,qBAAqB;AAK1B,SAAK,wBAAwB;AAK7B,SAAK,6BAA6B,oBAAI,IAAI;AAC1C,UAAM,SAAS,KAAK,OAAO,WAAW,QAAQ,OAAO,SAAS,KAAK;AACnE,kCAA8B,KAAK;AACnC,SAAK,QAAQ;AACb,QAAI,UAAU,mBAAmB;AAC7B,aAAO,KAAK,yNAAoN;AAAA,IACpO,WACS,UAAU,qBAAqB;AACpC,aAAO,KAAK,uHAAkH;AAAA,IAClI,WACS,UAAU,qBAAqB,UAAU,mBAAmB;AACjE,aAAO,KAAK,6BAA6B,KAAK,gGAA2F;AAAA,IAC7I,WACS,UAAU,kBAAkB;AACjC,aAAO,KAAK,8UAAqU;AAAA,IACrV;AACA,SAAK,WAAW,KAAK,OAAO,aAAa,QAAQ,OAAO,SAAS,KAAK;AACtE,SAAK,gBAAgB,KAAK,OAAO,kBAAkB,QAAQ,OAAO,SAAS,KAAK;AAChF,SAAK,SAAS,OAAO;AACrB,SAAK,iBAAiB,OAAO;AAC7B,SAAK,aAAa,KAAK,OAAO,eAAe,QAAQ,OAAO,SAAS,KAAK;AAAA,EAC9E;AAAA,EACA,YAAY;AACR,WAAO;AAAA,MACH,UAAU;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,cAAc,yBAAyB,KAAK,KAAK;AAAA,IACrD;AAAA,EACJ;AAAA;AAAA,EAEA,kBAAkB;AACd,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAEA,oBAAoB;AAChB,SAAK,kBAAkB;AACvB,SAAK,qBAAqB;AAAA,EAC9B;AAAA;AAAA,EAEA,qBAAqB,SAAS;AAC1B,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI,IAAI;AACZ,YAAM,EAAE,cAAc,YAAY,eAAe,IAAI;AACrD,YAAM,WAAW,CAAC,EAAE,MAAM,QAAQ,SAAS,WAAW,CAAC;AACvD,YAAM,OAAO;AAAA,QACT,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB;AAAA,MACJ;AACA,UAAI;AACA,aAAK,SAAS;AAKlB,YAAM,YAAY,kBAAkB,QAAQ,+BAA+B,KAAK,KAAK;AACrF,YAAM,gBAAgB,kBAAkB,QAAQ,CAAC;AACjD,UAAI,WAAW;AACX,aAAK,gBAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,KAAK,aAAa,GAAG,EAAE,QAAQ,EAAE,MAAM,eAAe,QAAQ,eAAe,EAAE,CAAC;AAAA,MACzI,WACS,eAAe;AACpB,aAAK,QAAQ;AAAA,UACT;AAAA,YACI,MAAM;AAAA,YACN,aAAa;AAAA,YACb,cAAc;AAAA,UAClB;AAAA,QACJ;AACA,aAAK,cAAc,EAAE,MAAM,QAAQ,MAAM,4BAA4B;AAAA,MACzE;AAMA,UAAI,KAAK,UAAU;AACf,aAAK,WAAW,EAAE,MAAM,WAAW;AACvC,YAAM,WAAW,MAAM,KAAK,KAAK,IAAI;AACrC,UAAI,eAAe;AACf,cAAM,YAAY,KAAK,SAAS,aAAa,QAAQ,OAAO,SAAS,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,2BAA2B;AACzJ,eAAO,UAAU,KAAK,WAAW,KAAK,QAAQ,WAAW,QAAQ,OAAO,SAAS,KAAK,CAAC,CAAC,IAAI;AAAA,MAChG;AAEA,eAAS,KAAK,SAAS,aAAa,QAAQ,OAAO,SAAS,KAAK,CAAC,GAC7D,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAC/B,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AAAA,IAChB,CAAC;AAAA,EACL;AAAA;AAAA,EAEA,gBAAgB,SAAS,aAAa,SAAS;AAC3C,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI,IAAI,IAAI,IAAI;AAKpB,YAAM,kBAAkB,oBAAI,IAAI;AAAA,QAC5B,KAAK;AAAA,QACL,KAAK,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,eAAe,QAAQ,OAAO,SAAS,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,MAC1I,CAAC;AACD,YAAM,WAAW,KAAK,oBAAoB,SAAS,aAAa,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,aAAa,eAAe;AACtJ,YAAM,OAAO;AAAA,QACT,OAAO,KAAK;AAAA;AAAA,QAEZ,aAAa,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,eAAe,QAAQ,OAAO,SAAS,KAAK,KAAK;AAAA,QAC7H;AAAA,MACJ;AACA,UAAI,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ;AAC1D,aAAK,SAAS,QAAQ;AAC1B,WAAK,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,WAAW,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAOvH,aAAK,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAO,OAAO,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,EAAE,aAAa,cAAc,EAAE,gBACvG,2BAA2B,EAAE,YAAY,EAAE,IAAI,IAC/C,EAAE,WAAW,GAAI,EAAE,gBAAgB,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAE,CAAE;AAAA,MACzE;AAIA,WAAK,KAAK,KAAK,WAAW,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAClE,cAAM,aAAa,sBAAsB,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,UAAU;AAC7G,YAAI;AACA,eAAK,cAAc;AAAA,MAC3B;AAKA,WAAK,0BAA0B,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc;AACvG,YAAM,WAAW,kBAAkB,KAAK,OAAO,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc;AACvH,UAAI;AACA,aAAK,WAAW;AAKpB,YAAM,SAAS,gBAAgB,KAAK,OAAO,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc;AACnH,UAAI;AACA,aAAK,gBAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,KAAK,aAAa,GAAG,EAAE,OAAO,CAAC;AAWxF,YAAM,mBAAmB,aAAa,QAAQ,aAAa,SAAS,SAAS,SAAS,UAAU;AAChG,WAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,gBAAgB,QAAQ,CAAC,sBAAsB,KAAK,KAAK,KAAK,CAAC,iBAAiB;AAC3I,aAAK,cAAc,iBAAiB,QAAQ,aAAa;AAAA,UACrD,aAAa;AAAA,UACb,SAAS;AAAA,QACb,CAAC;AAAA,MACL;AAMA,WAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,mBAAmB,+BAA+B,KAAK,KAAK,GAAG;AAC1H,aAAK,gBAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,KAAK,aAAa,GAAG,EAAE,QAAQ,EAAE,MAAM,eAAe,QAAQ,QAAQ,eAAe,EAAE,CAAC;AAAA,MACjJ;AAIA,WAAK,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAC3H,aAAK,YAAY,QAAQ,UAAU,IAAI,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE,OAAO,EAAE,OAAO,YAAY,EAAE,UAAU,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC;AAAA,MACxI;AAEA,UAAI,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,aAAa;AACvE,aAAK,kBAAkB,MAAM,QAAQ,WAAW;AAAA,MACpD;AAGA,UAAI,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,aAAa;AACvE,aAAK,kBAAkB,MAAM,QAAQ,WAAW;AAAA,MACpD;AACA,YAAM,WAAW,MAAM,KAAK,KAAK,MAAM,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,MAAM;AACvG,aAAO,KAAK,sBAAsB,UAAU,KAAK,UAAU;AAAA,IAC/D,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,kBAAkB,MAAM,QAAQ;AAC5B,QAAI,IAAI;AACR,QAAI,OAAO,UAAU;AACjB;AACJ,UAAM,eAAe,OAAO,QAAQ,OAAO,EAAE,MAAM,aAAa,KAAK,KAAK,IAAI,EAAE,MAAM,YAAY;AAClG,QAAI,OAAO,UAAU,SAAS;AAC1B,WAAK,KAAK,KAAK,WAAW,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAClE,aAAK,MAAM,KAAK,MAAM,SAAS,CAAC,EAAE,gBAAgB;AAAA,MACtD;AACA;AAAA,IACJ;AAIA,QAAI,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,SAAS,GAAG;AAC3D,WAAK,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,QAAQ,eAAe,aAAa,CAAC;AAAA,IACnF,YACU,KAAK,KAAK,WAAW,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AACvE,WAAK,MAAM,KAAK,MAAM,SAAS,CAAC,EAAE,gBAAgB;AAAA,IACtD;AACA,QAAI,OAAO,UAAU,WAAW;AAC5B,YAAM,cAAc,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC;AAC1D,UAAI,eAAe,MAAM,QAAQ,YAAY,OAAO,KAAK,YAAY,QAAQ,SAAS,GAAG;AACrF,oBAAY,QAAQ,YAAY,QAAQ,SAAS,CAAC,EAAE,gBAAgB;AAAA,MACxE;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,MAAM,aAAa;AACjC,UAAM,QAAQ,EAAE,MAAM,QAAQ,MAAM,YAAY;AAChD,UAAM,cAAc,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC;AAC1D,SAAK,gBAAgB,QAAQ,gBAAgB,SAAS,SAAS,YAAY,UAAU,UAAU,MAAM,QAAQ,YAAY,OAAO,GAAG;AAC/H,kBAAY,QAAQ,KAAK,KAAK;AAAA,IAClC,OACK;AACD,WAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,CAAC,KAAK,EAAE,CAAC;AAAA,IACzD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,OAAO,cAAc,iBAAiB,iBAAiB,qBAAqB,uBAAuB;AAK7G,UAAM,EAAE,SAAS,UAAU,UAAU,IAAI,mBAAmB,OAAO;AAAA,MAC/D,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd;AAAA,MACA,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,IACxB,CAAC;AACD,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAC3B,UAAM,KAAK,oBAAmB;AAC9B,YAAQ,IAAI,8BAA8B,KAAK,OAAO;AACtD,YAAQ,IAAI,qBAAqB,YAAY,MAAM,UAAU,UAAU,QAAQ,EAAE,CAAC,GAAG;AACrF,YAAQ,IAAI,qBAAqB,eAAe,MAAM,UAAU,aAAa,QAAQ,EAAE,CAAC,GAAG;AAC3F,YAAQ,IAAI,qBAAqB,mBAAmB,MAAM,UAAU,cAAc,QAAQ,EAAE,CAAC,GAAG;AAChG,YAAQ,IAAI,qBAAqB,eAAe,MAAM,UAAU,aAAa,QAAQ,EAAE,CAAC,GAAG;AAC3F,YAAQ,IAAI,sBAAsB,QAAQ,QAAQ,EAAE,CAAC,EAAE;AACvD,YAAQ,IAAI,sBAAsB,SAAS,QAAQ,EAAE,CAAC,eAAe,KAAK,mBAAmB,QAAQ,EAAE,CAAC,GAAG;AAC3G,YAAQ,IAAI,sBAAsB,KAAK,gBAAgB,QAAQ,EAAE,CAAC,EAAE;AACpE,YAAQ,IAAI,4BAA4B;AACxC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,oBAAoB,SAAS,aAAa,aAAa,kBAAkB,oBAAI,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG;AAC5F,QAAI,IAAI,IAAI,IAAI;AAChB,UAAM,WAAW,CAAC;AAClB,UAAM,YAAY,CAAC,MAAM,UAAU;AAC/B,YAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,UAAI,QAAQ,KAAK,SAAS,QAAQ,MAAM,QAAQ,KAAK,OAAO,GAAG;AAC3D,aAAK,QAAQ,KAAK,KAAK;AACvB;AAAA,MACJ;AACA,eAAS,KAAK,EAAE,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;AAAA,IAC5C;AAQA,UAAM,mBAAmB,CAAC,SAAS;AAC/B,YAAM,SAAS,CAAC;AAChB,YAAM,QAAQ,CAAC;AACf,iBAAW,OAAO,MAAM;AACpB,YAAI,IAAI,SAAS,SAAS;AACtB,iBAAO,KAAK;AAAA,YACR,MAAM;AAAA,YACN,QAAQ;AAAA,cACJ,MAAM;AAAA,cACN,YAAY,mBAAmB,IAAI,QAAQ;AAAA,cAC3C,MAAM,kBAAkB,IAAI,IAAI;AAAA,YACpC;AAAA,UACJ,CAAC;AAAA,QACL,OACK;AACD,gBAAM,KAAK,EAAE,MAAM,QAAQ,MAAM,UAAU,IAAI,IAAI;AAAA,EAAM,IAAI,OAAO,GAAG,CAAC;AAAA,QAC5E;AAAA,MACJ;AACA,aAAO,EAAE,QAAQ,MAAM;AAAA,IAC3B;AACA,eAAW,OAAO,SAAS;AACvB,UAAI,IAAI,SAAS,YACb,IAAI,SAAS,kBACb,IAAI,SAAS,oBACb,IAAI,SAAS,uBACb,IAAI,aAAa,eACjB,IAAI,aAAa,eACjB,IAAI;AAEJ;AACJ,UAAI,IAAI,YAAY;AAChB,cAAM,gBAAgB,KAAK,IAAI,WAAW,iBAAiB,QAAQ,OAAO,SAAS,KAAK,CAAC;AACzF,kBAAU,QAAQ;AAAA,UACd,MAAM;AAAA,UACN,aAAa,IAAI,WAAW;AAAA;AAAA,UAE5B,SAAS,aAAa,SAChB;AAAA;AAAA;AAAA;AAAA;AAAA,YAKE,GAAI,IAAI,WAAW,UACb,CAAC,EAAE,MAAM,QAAQ,MAAM,IAAI,WAAW,QAAQ,CAAC,IAC/C,CAAC;AAAA,YACP,GAAG,aAAa,IAAI,CAAC,SAAS;AAAA,cAC1B,MAAM;AAAA,cACN,QAAQ;AAAA,gBACJ,MAAM;AAAA,gBACN,YAAY,mBAAmB,IAAI,QAAQ;AAAA,gBAC3C,MAAM,kBAAkB,IAAI,IAAI;AAAA,cACpC;AAAA,YACJ,EAAE;AAAA,UACN,IACE,IAAI,WAAW;AAAA,QACzB,CAAC;AACD;AAAA,MACJ;AACA,WAAK,KAAK,IAAI,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAMrE,mBAAW,SAAS,KAAK,kBAAkB,IAAI,UAAU,CAAC,GAAG,eAAe,GAAG;AAC3E,oBAAU,aAAa,KAAK;AAAA,QAChC;AACA,YAAI,IAAI,SAAS;AACb,oBAAU,aAAa,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAAA,QAC9D;AACA,mBAAW,MAAM,IAAI,WAAW;AAC5B,oBAAU,aAAa;AAAA,YACnB,MAAM;AAAA,YACN,IAAI,GAAG;AAAA,YACP,MAAM,GAAG;AAAA,YACT,QAAQ,KAAK,GAAG,UAAU,QAAQ,OAAO,SAAS,KAAK,CAAC;AAAA,UAC5D,CAAC;AAAA,QACL;AACA;AAAA,MACJ;AACA,YAAM,OAAO,IAAI,SAAS,SAAS,SAAS;AAC5C,UAAI,SAAS,YAAY,KAAK,IAAI,iBAAiB,QAAQ,OAAO,SAAS,SAAS,GAAG,SAAS;AAC5F,cAAM,EAAE,QAAQ,MAAM,IAAI,iBAAiB,IAAI,WAAW;AAC1D,mBAAW,SAAS;AAChB,oBAAU,MAAM,KAAK;AAKzB,YAAI,IAAI;AACJ,oBAAU,MAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,CAAC;AACvD,mBAAW,QAAQ;AACf,oBAAU,MAAM,IAAI;AAAA,MAC5B,WACS,IAAI,SAAS;AAClB,kBAAU,MAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAAA,MACvD;AAAA,IACJ;AACA,QAAI,gBAAgB,gBAAgB,QAAQ,gBAAgB,SAAS,SAAS,YAAY,SAAS;AAC/F,YAAM,EAAE,QAAQ,MAAM,IAAI,iBAAiB,gBAAgB,QAAQ,gBAAgB,SAAS,cAAc,CAAC,CAAC;AAC5G,iBAAW,SAAS;AAChB,kBAAU,QAAQ,KAAK;AAC3B,UAAI,aAAa;AACb,kBAAU,QAAQ,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AAAA,MACzD;AACA,iBAAW,QAAQ;AACf,kBAAU,QAAQ,IAAI;AAAA,IAC9B;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,kBAAkB,WAAW,iBAAiB;AAC1C,QAAI,IAAI,IAAI;AACZ,UAAM,SAAS,KAAK,UAAU,sBAAsB,QAAQ,OAAO,SAAS,SAAS,GAAG,sBAAsB;AAC9G,QAAI,CAAC;AACD,aAAO,CAAC;AACZ,UAAM,cAAc,KAAK,MAAM,eAAe,QAAQ,OAAO,SAAS,KAAK,CAAC;AAC5E,UAAM,mBAAmB,MAAM,mBAAmB,KAAK,SAAS,gBAAgB,IAAI,MAAM,KAAK;AAC/F,UAAM,UAAU,MAAM,UAAU,KAAK,SAAS;AAC9C,WAAO,CAAC,GAAG,YAAY,GAAI,WAAY,KAAK,MAAM,eAAe,QAAQ,OAAO,SAAS,KAAK,CAAC,IAAK,CAAC,CAAE;AAAA,EAC3G;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,UAAU;AACnB,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,UAAU,WAAW,KAAK;AAC3B,aAAO,KAAK;AAChB,QAAI,8BAA8B,SAAS,MAAM,GAAG;AAChD,aAAO;AAAA,IACX;AAKA,QAAI,CAAC,KAAK,2BAA2B,IAAI,MAAM,GAAG;AAC9C,WAAK,2BAA2B,IAAI,MAAM;AAC1C,aAAO,KAAK,+CAA+C,MAAM,sEAC5B,KAAK,KAAK,8HAC0C;AAAA,IAC7F;AACA,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,kBAAkB,SAAS,OAAO,gBAAgB;AAC9C,QAAI;AACJ,UAAM,KAAK,MAAM,mBAAmB,QAAQ,OAAO,SAAS,KAAK,KAAK;AAClE,aAAO;AACX,WAAO,QAAQ,SAAS,aAAa;AAAA,EACzC;AAAA;AAAA,EAEA,YAAY,OAAO,OAAO;AACtB,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACxB,UAAM,aAAa,KAAK,MAAM,6BAA6B,QAAQ,OAAO,SAAS,KAAK;AAIxF,UAAM,YAAY,MAAM;AACxB,UAAM,mBAAmB,KAAK,cAAc,QAAQ,cAAc,SAAS,SAAS,UAAU,+BAA+B,QAAQ,OAAO,SAAS,KAAK;AAC1J,UAAM,iBAAiB,KAAK,MAAM,iCAAiC,QAAQ,OAAO,SAAS,KAAM,cAAc,KAAK,UAAU,+BAA+B,QAAQ,OAAO,SAAS,KAAK,KAAK,kBAAkB;AACjN,WAAO,KAAK,cAAc,QAAQ,KAAK,MAAM,kBAAkB,QAAQ,OAAO,SAAS,KAAK,IAAI,KAAK,MAAM,mBAAmB,QAAQ,OAAO,SAAS,KAAK,GAAG,WAAW,eAAe,eAAe;AAAA,EAC3M;AAAA,EACA,sBAAsB,UAEtB,qBAAqB,KAAK,WAAW;AACjC,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAC5B,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,eAAe,KAAK,aAAa,QAAQ;AAC/C,QAAI,SAAS,OAAO;AAChB,YAAM,iBAAiB,KAAK,SAAS,MAAM,kBAAkB,QAAQ,OAAO,SAAS,KAAK;AAC1F,YAAM,aAAa,KAAK,SAAS,MAAM,6BAA6B,QAAQ,OAAO,SAAS,KAAK;AACjG,YAAM,YAAY,SAAS,MAAM;AACjC,YAAM,mBAAmB,KAAK,cAAc,QAAQ,cAAc,SAAS,SAAS,UAAU,+BAA+B,QAAQ,OAAO,SAAS,KAAK;AAC1J,YAAM,iBAAiB,KAAK,SAAS,MAAM,iCAAiC,QAAQ,OAAO,SAAS,KAAM,cAAc,KAAK,UAAU,+BAA+B,QAAQ,OAAO,SAAS,KAAK,KAAK,kBAAkB;AAM1N,YAAM,WAAW,SAAS,MAAM;AAChC,UAAI,aAAa,QAAQ,aAAa,SAAS,SAAS,SAAS,QAAQ;AACrE,cAAM,UAAU,SAAS,gBAAgB;AACzC,eAAO,SAAS,OAAO,CAAC,OAAO,SAAS,UAAU;AAC9C,cAAIC;AACJ,gBAAM,SAASA,MAAK,QAAQ,WAAW,QAAQA,QAAO,SAASA,MAAK;AACpE,cAAI,KAAK,kBAAkB,SAAS,OAAO,UAAU,SAAS,SAAS,KAAK,OAAO,GAAG;AAClF,mBAAO;AAAA,UACX;AAMA,gBAAM,QAAQ,QAAQ,QAAQ,KAAK,aAAa,EAAE,OAAO,QAAQ,MAAM,CAAC,IAAI,KAAK;AACjF,iBAAO,QAAQ,KAAK,YAAY,OAAO,KAAK;AAAA,QAChD,GAAG,CAAC;AAAA,MACR,WACS,KAAK,kBAAkB,CAAC,GAAG,SAAS,OAAO,SAAS,gBAAgB,SAAS,GAAG;AAKrF,eAAO;AAAA,MACX,OACK;AACD,eAAO,KAAK,YAAY,cAAc,SAAS,KAAK;AAAA,MACxD;AAKA,oBAAc,gBAAgB,YAAY;AAK1C,wBAAkB;AAClB,yBAAmB;AACnB,UAAI,SAAS,MAAM,iBAAiB,MAAM;AACtC,uBAAe,SAAS,MAAM;AAAA,MAClC;AAAA,IACJ;AACA,UAAM,UAAU,KAAK,SAAS,aAAa,QAAQ,OAAO,SAAS,KAAK,CAAC;AACzE,UAAM,YAAY,CAAC;AACnB,UAAM,eAAe,CAAC;AACtB,UAAM,YAAY,CAAC;AAInB,UAAM,kBAAkB,CAAC;AAOzB,UAAM,gBAAgB,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,UAAU;AACtE,UAAM,iBAAiB,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU;AACjE,eAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,GAAG;AAC3C,YAAM,eAAe,QAAQ;AAC7B,UAAI,MAAM,SAAS,YAAY;AAG3B,YAAI,cAAc;AACd,oBAAU,KAAK;AAAA,YACX,IAAI,MAAM;AAAA,YACV,MAAM,MAAM;AAAA,YACZ,OAAO,KAAK,MAAM,WAAW,QAAQ,OAAO,SAAS,KAAK,CAAC;AAAA,UAC/D,CAAC;AAAA,QACL;AAAA,MACJ,WACS,MAAM,SAAS,YAAY;AAChC,YAAI;AACA,0BAAgB,KAAK,KAAK;AAC9B,qBAAa,KAAK,MAAM,QAAQ;AAAA,MACpC,WACS,MAAM,SAAS,qBAAqB;AAEzC,YAAI;AACA,0BAAgB,KAAK,KAAK;AAAA,MAClC,WACS,MAAM,SAAS,QAAQ;AAC5B,kBAAU,KAAK,MAAM,IAAI;AAAA,MAC7B;AAAA,IACJ;AAOA,QAAI,UAAU,SAAS,MAAM,gBAAgB,SAAS,KAAK,eAAe,SAAS,IAAI;AACnF,YAAM,QAAQ;AAAA,QACV,WAAW;AAAA,QACX,OAAO;AAAA,QACP,gBAAgB,KAAK;AAAA,MACzB;AACA,UAAI,eAAe,SAAS;AACxB,cAAM,YAAY;AACtB,gBAAU,CAAC,EAAE,mBAAmB,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,UAAU,CAAC,EAAE,gBAAgB,GAAG,EAAE,CAAC,sBAAsB,GAAG,MAAM,CAAC;AAAA,IACvI;AAOA,QAAI,SAAS,gBAAgB,gBAAgB,UAAU,SAAS,GAAG;AAC/D,YAAM,IAAI,uBAAuB,KAAK,OAAO,oBAAoB,cAAc,UAAU,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,IACjH;AAKA,UAAM,YAAY,aAAa,KAAK,EAAE,KAAK;AAC3C,UAAM,OAAO,UAAU,SAAS,IAC1B,EAAE,MAAM,aAAa,SAAS,UAAU,KAAK,EAAE,GAAG,WAAW,UAAU,IACvE,EAAE,MAAM,aAAa,SAAS,UAAU,KAAK,EAAE,GAAG,UAAU;AAClE,QAAI,eAAe;AACf,WAAK,cAAc;AACvB,QAAI,gBAAgB;AAChB,WAAK,eAAe;AACxB,QAAI,mBAAmB;AACnB,WAAK,kBAAkB;AAC3B,QAAI,oBAAoB;AACpB,WAAK,mBAAmB;AAC5B,QAAI,QAAQ;AACR,WAAK,OAAO;AAKhB,SAAK,QAAQ;AAKb,QAAI,SAAS,gBAAgB,cAAc;AACvC,WAAK,eAAe,EAAE,cAAc,aAAa;AAAA,IACrD;AAMA,QAAI,SAAS,gBAAgB,WAAW;AACpC,WAAK,eAAe,EAAE,cAAc,UAAU;AAAA,IAClD;AACA,WAAO;AAAA,EACX;AAAA,EACA,gBAAgB;AACZ,QAAI,KAAK,QAAQ;AACb,aAAO;AAAA,QACH,KAAK;AAAA,QACL,SAAS;AAAA,UACL,gBAAgB;AAAA,UAChB,aAAa,KAAK;AAAA,UAClB,qBAAqB;AAAA;AAAA;AAAA,UAGrB,6CAA6C;AAAA,QACjD;AAAA,QACA,aAAa;AAAA,MACjB;AAAA,IACJ;AACA,QAAI,KAAK,gBAAgB;AACrB,aAAO;AAAA,QACH,KAAK,KAAK;AAAA;AAAA;AAAA,QAGV,SAAS,EAAE,gBAAgB,oBAAoB,QAAQ,uBAAuB;AAAA,QAC9E,aAAa;AAAA,MACjB;AAAA,IACJ;AACA,UAAM,IAAI,MAAM,sJAC4E;AAAA,EAChG;AAAA,EACA,KAAK,MAAM,QAAQ;AACf,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI;AACJ,YAAM,EAAE,KAAK,SAAS,YAAY,IAAI,KAAK,cAAc;AAGzD,YAAM,mBAAmB,KAAK,KAAK,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,UAChF,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,OAAO,GAAG,EAAE,kBAAkB,CAAC,QAAQ,gBAAgB,GAAG,yBAAyB,EAC5G,OAAO,OAAO,EACd,KAAK,GAAG,EAAE,CAAC,IAAI;AAC5B,aAAQ,MAAM,cAAc;AAAA,QACxB;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,aAAa,cAAc;AAAA,QAC3B,mBAAmB,oBAAmB;AAAA,QACtC,SAAS,KAAK;AAAA,QACd,cAAc,KAAK;AAAA,QACnB,eAAe,oBAAmB;AAAA,QAClC;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AACJ;AAEA,mBAAmB,qBAAqB;AACxC,mBAAmB,sBAAsB;AACzC,mBAAmB,oBAAoB;AACvC,mBAAmB,6BAA6B;AAChD,mBAAmB,oBAAoB;AACvC,mBAAmB,qBAAqB;AAAA,EACpC,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,mBAAmB;AACvB;AAEA,mBAAmB,kBAAkB;;;AC1jCrC,IAAM,wBAAwB;AAC9B,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AAC1B,IAAM,YAAY;AAQlB,IAAM,8BAAN,MAAkC;AAAA,EAC9B,YAAY,KAAK;AACb,SAAK,MAAM;AACX,SAAK,MAAM;AAAA,EACf;AAAA,EACA,QAAQ;AACJ,UAAM,SAAS,KAAK,IAAI,QAAQ,qBAAqB;AACrD,QAAI,WAAW;AACX,WAAK,KAAK;AAId,UAAM,UAAU,iBAAiB,KAAK,KAAK,IAAI,MAAM,GAAG,MAAM,CAAC;AAC/D,SAAK,MAAM;AACX,UAAM,OAAO,KAAK,UAAU;AAC5B,SAAK,eAAe;AACpB,QAAI,SAAS;AACT,WAAK,OAAO,GAAG;AACf,WAAK,eAAe;AAAA,IACxB;AAGA,QAAI,KAAK,QAAQ,KAAK,IAAI;AACtB,WAAK,KAAK;AACd,WAAO;AAAA,EACX;AAAA,EACA,YAAY;AACR,SAAK,cAAc,qBAAqB;AACxC,UAAM,OAAO,KAAK,eAAe;AACjC,SAAK,OAAO,GAAG;AACf,UAAM,OAAO,KAAK,YAAY;AAC9B,SAAK,OAAO,GAAG;AACf,WAAO,EAAE,MAAM,KAAK;AAAA,EACxB;AAAA,EACA,cAAc;AACV,UAAM,OAAO,CAAC;AACd,eAAS;AACL,WAAK,eAAe;AAEpB,UAAI,KAAK,KAAK,MAAM;AAChB;AACJ,YAAM,MAAM,KAAK,eAAe;AAChC,WAAK,eAAe;AACpB,WAAK,OAAO,GAAG;AACf,WAAK,eAAe;AACpB,YAAM,QAAQ,KAAK,WAAW;AAC9B,UAAI,OAAO,UAAU,eAAe,KAAK,MAAM,GAAG;AAC9C,aAAK,KAAK;AACd,WAAK,GAAG,IAAI;AACZ,WAAK,eAAe;AACpB,YAAM,OAAO,KAAK,KAAK;AACvB,UAAI,SAAS,KAAK;AACd,aAAK,OAAO;AACZ;AAAA,MACJ;AACA,UAAI,SAAS;AACT;AACJ,WAAK,KAAK;AAAA,IACd;AACA,WAAO;AAAA,EACX;AAAA,EACA,aAAa;AACT,UAAM,KAAK,KAAK,KAAK;AACrB,QAAI,OAAO,OAAO,OAAO;AACrB,aAAO,KAAK,WAAW;AAC3B,QAAI,OAAO,OAAO,OAAO,OAAO,KAAK,QAAQ,EAAE;AAC3C,aAAO,KAAK,WAAW;AAC3B,QAAI,WAAW,KAAK,EAAE;AAClB,aAAO,KAAK,aAAa;AAE7B,WAAO,KAAK,KAAK;AAAA,EACrB;AAAA,EACA,aAAa;AACT,UAAM,QAAQ,KAAK,IAAI,KAAK,GAAG;AAC/B,SAAK,OAAO;AACZ,QAAI,MAAM;AACV,eAAS;AACL,UAAI,KAAK,OAAO,KAAK,IAAI;AACrB,aAAK,KAAK;AACd,YAAM,IAAI,KAAK,IAAI,KAAK,GAAG;AAC3B,WAAK,OAAO;AACZ,UAAI,MAAM;AACN,eAAO;AACX,UAAI,MAAM,MAAM;AACZ,eAAO,KAAK,WAAW;AACvB;AAAA,MACJ;AACA,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EACA,aAAa;AACT,QAAI,KAAK,OAAO,KAAK,IAAI;AACrB,WAAK,KAAK;AACd,UAAM,IAAI,KAAK,IAAI,KAAK,GAAG;AAC3B,SAAK,OAAO;AACZ,YAAQ,GAAG;AAAA,MACP,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO,KAAK,iBAAiB,qBAAqB;AAAA,MACtD,KAAK;AACD,eAAO,KAAK,iBAAiB,iBAAiB;AAAA,MAClD;AAEI,eAAO,KAAK,KAAK;AAAA,IACzB;AAAA,EACJ;AAAA,EACA,iBAAiB,QAAQ;AACrB,UAAM,MAAM,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,MAAM,MAAM;AACtD,QAAI,IAAI,WAAW,UAAU,CAAC,iBAAiB,KAAK,GAAG;AACnD,WAAK,KAAK;AACd,SAAK,OAAO;AACZ,WAAO,OAAO,aAAa,SAAS,KAAK,SAAS,CAAC;AAAA,EACvD;AAAA,EACA,aAAa;AACT,UAAM,QAAQ,KAAK;AACnB,QAAI,KAAK,KAAK,MAAM,OAAO,KAAK,KAAK,MAAM;AACvC,WAAK,OAAO;AAChB,WAAO,KAAK,MAAM,KAAK,IAAI,UAAU,aAAa,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,GAAG;AACxE,WAAK,OAAO;AAAA,IAChB;AACA,UAAM,QAAQ,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK,GAAG,CAAC;AACpD,QAAI,CAAC,OAAO,SAAS,KAAK;AACtB,WAAK,KAAK;AACd,WAAO;AAAA,EACX;AAAA,EACA,eAAe;AACX,UAAM,OAAO,KAAK,eAAe;AACjC,YAAQ,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AACD,eAAO;AAAA;AAAA;AAAA,MAGX,KAAK;AAAA,MACL,KAAK;AACD,eAAO;AAAA,MACX;AACI,eAAO,KAAK,KAAK;AAAA,IACzB;AAAA,EACJ;AAAA,EACA,iBAAiB;AACb,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,YAAY,KAAK,KAAK,KAAK,CAAC;AAC7B,WAAK,KAAK;AACd,WAAO,KAAK,MAAM,KAAK,IAAI,UAAU,eAAe,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,GAAG;AAC1E,WAAK,OAAO;AAAA,IAChB;AACA,WAAO,KAAK,IAAI,MAAM,OAAO,KAAK,GAAG;AAAA,EACzC;AAAA,EACA,QAAQ,IAAI;AACR,WAAO,MAAM,OAAO,MAAM;AAAA,EAC9B;AAAA,EACA,OAAO;AACH,WAAO,KAAK,MAAM,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GAAG,IAAI;AAAA,EAC7D;AAAA,EACA,iBAAiB;AACb,WAAO,KAAK,MAAM,KAAK,IAAI,UAAU,KAAK,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,GAAG;AAChE,WAAK,OAAO;AAAA,IAChB;AAAA,EACJ;AAAA,EACA,OAAO,IAAI;AACP,QAAI,KAAK,IAAI,KAAK,GAAG,MAAM;AACvB,WAAK,KAAK;AACd,SAAK,OAAO;AAAA,EAChB;AAAA,EACA,cAAc,SAAS;AACnB,QAAI,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,MAAM,QAAQ,MAAM,MAAM;AACxD,WAAK,KAAK;AACd,SAAK,OAAO,QAAQ;AAAA,EACxB;AAAA,EACA,OAAO;AACH,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACnE;AACJ;AAOO,SAAS,4BAA4B,eAAe,kBAAkB;AACzE,MAAI,CAAC;AACD,WAAO;AACX,MAAI;AACJ,MAAI;AACA,WAAO,IAAI,4BAA4B,aAAa,EAAE,MAAM;AAAA,EAChE,SACO,IAAI;AACP,WAAO;AAAA,EACX;AACA,MAAI,CAAC,iBAAiB,IAAI,KAAK,IAAI;AAC/B,WAAO;AACX,SAAO;AACX;;;ACtOA,IAAM,oBAAoB,CAAC,UAAU,2DAA2D,KAAK;AACrG,IAAMC,iBAAgB;AACtB,IAAMC,mBAAkB;AACxB,IAAMC,yBAAwB;AAK9B,IAAM,wBAAwB;AAAA,EAC1B,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,yBAAyB;AAAA,EACzB,oBAAoB;AAAA,EACpB,yBAAyB;AAAA,EACzB,0BAA0B;AAC9B;AAEA,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAK/B,SAAS,mBAAmB,QAAQ;AAChC,MAAI,CAAC,UAAU,WAAW;AACtB,WAAO;AACX,MAAI,WAAW;AACX,WAAO,EAAE,uBAAuB,EAAE,MAAM,MAAM,EAAE;AACpD,MAAI,WAAW;AACX,WAAO,EAAE,uBAAuB,EAAE,MAAM,OAAO,EAAE;AACrD,SAAO,EAAE,uBAAuB,EAAE,MAAM,OAAO,sBAAsB,CAAC,OAAO,IAAI,EAAE,EAAE;AACzF;AACA,SAAS,2BAA2B,OAAO;AACvC,MAAI,CAAC,2BAA2B,SAAS,KAAK,GAAG;AAC7C,UAAM,IAAI,MAAM,uCAAuC,KAAK,kBAAkB,2BAA2B,KAAK,IAAI,CAAC,GAAG;AAAA,EAC1H;AACJ;AAMA,IAAM,wBAAwB;AAAA,EAC1B,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,0BAA0B;AAC9B;AAsBA,IAAM,8BAA8B;AAAA,EAChC;AAAA,EACA;AACJ;AAEA,IAAM,gCAAgC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACJ;AAEA,IAAM,8BAA8B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACJ;AAOA,IAAM,wBAAwB;AAAA,EAC1B,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,KAAK;AACT;AAYA,IAAM,4BAA4B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACJ;AACA,IAAM,sBAAsB;AAAA,EACxB,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AACV;AACA,IAAM,gBAAgB,CAAC,MAAM,MAAM,UAAa,MAAM,UAAU,MAAM;AACtE,SAAS,qBAAqB,OAAO,QAAQ;AACzC,MAAI,cAAc,MAAM,KAAK,4BAA4B,SAAS,KAAK,GAAG;AACtE,UAAM,QAAQ,sBAAsB,MAAM;AAC1C,WAAO;AAAA,MACH,iBAAiB;AAAA,MACjB,eAAe,0BAA0B,SAAS,KAAK,IAAI,oBAAoB,KAAK,IAAI;AAAA,IAC5F;AAAA,EACJ;AACA,MAAI,WAAW,SAAS,4BAA4B,SAAS,KAAK,GAAG;AAEjE,WAAO,EAAE,iBAAiB,OAAO,gBAAgB,EAAE;AAAA,EACvD;AACA,MAAI,WAAW,UAAU,4BAA4B,SAAS,KAAK,GAAG;AAClE,WAAO,EAAE,iBAAiB,MAAM,gBAAgB,GAAG;AAAA,EACvD;AAEA,SAAO,EAAE,iBAAiB,KAAK;AACnC;AASA,IAAM,iBAAiB;AAKvB,IAAM,sBAAsB;AAS5B,SAAS,qBAAqB,MAAM;AAChC,QAAM,aAAa,CAAC;AACpB,QAAM,YAAY,CAAC;AACnB,aAAW,OAAO,MAAM;AACpB,QAAI,IAAI,SAAS,SAAS;AACtB,iBAAW,KAAK;AAAA,QACZ,YAAY;AAAA,UACR,UAAU,mBAAmB,IAAI,QAAQ;AAAA,UACzC,MAAM,kBAAkB,IAAI,IAAI;AAAA,QACpC;AAAA,MACJ,CAAC;AAAA,IACL,OACK;AACD,gBAAU,KAAK,EAAE,MAAM,UAAU,IAAI,IAAI;AAAA,EAAM,IAAI,OAAO,GAAG,CAAC;AAAA,IAClE;AAAA,EACJ;AACA,SAAO,EAAE,YAAY,UAAU;AACnC;AAQO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAClD,YAAY,eAAe;AACvB,UAAM,yCAAyC;AAC/C,SAAK,gBAAgB;AACrB,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,kBAAN,MAAM,iBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAezB,0BAA0B,QAAQ;AAC9B,QAAI,KAAK,uBAAuB;AAC5B;AAAA,IACJ;AACA,QAAI,WAAW,SAAS,CAAC,4BAA4B,SAAS,KAAK,KAAK,GAAG;AACvE,WAAK,wBAAwB;AAC7B,aAAO,KAAK,wDAAmD,KAAK,KAAK,4KAA4K;AACrP;AAAA,IACJ;AACA,QAAI,cAAc,MAAM,KAAK,CAAC,4BAA4B,SAAS,KAAK,KAAK,GAAG;AAC5E,WAAK,wBAAwB;AAC7B,aAAO,KAAK,oCAAoC,MAAM,oBAAe,KAAK,KAAK,0LAA0L;AAAA,IAC7Q;AAAA,EACJ;AAAA,EACA,YAAY,SAAS,CAAC,GAAG;AACrB,QAAI,IAAI,IAAI;AAOZ,SAAK,kBAAkB;AAMvB,SAAK,qBAAqB;AAK1B,SAAK,wBAAwB;AAC7B,UAAM,SAAS,KAAK,OAAO,WAAW,QAAQ,OAAO,SAAS,KAAKF;AACnE,+BAA2B,KAAK;AAChC,SAAK,QAAQ;AACb,UAAM,UAAU,sBAAsB,KAAK;AAC3C,QAAI,SAAS;AACT,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,SAAK,WAAW,KAAK,OAAO,aAAa,QAAQ,OAAO,SAAS,KAAKC;AACtE,SAAK,gBAAgB,KAAK,OAAO,kBAAkB,QAAQ,OAAO,SAAS,KAAKC;AAChF,SAAK,SAAS,OAAO;AACrB,SAAK,iBAAiB,OAAO;AAAA,EACjC;AAAA,EACA,YAAY;AACR,WAAO;AAAA,MACH,UAAU;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,cAAc,sBAAsB,KAAK,KAAK;AAAA,IAClD;AAAA,EACJ;AAAA;AAAA,EAEA,kBAAkB;AACd,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAEA,oBAAoB;AAChB,SAAK,kBAAkB;AACvB,SAAK,qBAAqB;AAAA,EAC9B;AAAA;AAAA,EAEA,qBAAqB,SAAS;AAC1B,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI;AACJ,YAAM,EAAE,cAAc,YAAY,eAAe,IAAI;AACrD,YAAM,WAAW,CAAC;AAClB,UAAI,cAAc;AACd,iBAAS,KAAK,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE,MAAM,aAAa,CAAC,EAAE,CAAC;AAC/D,iBAAS,KAAK,EAAE,MAAM,SAAS,OAAO,CAAC,EAAE,MAAM,cAAc,CAAC,EAAE,CAAC;AAAA,MACrE;AACA,eAAS,KAAK,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE,MAAM,WAAW,CAAC,EAAE,CAAC;AAC7D,YAAM,WAAW,MAAM,KAAK,KAAK,EAAE,OAAO,KAAK,OAAO,UAAU,eAAe,CAAC;AAChF,cAAQ,KAAK,aAAa,QAAQ,aAAa,SAAS,SAAS,SAAS,aAAa,QAAQ,OAAO,SAAS,KAAK;AAAA,IACxH,CAAC;AAAA,EACL;AAAA;AAAA,EAEA,gBAAgB,SAAS,aAAa,SAAS;AAC3C,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI,IAAI;AAOZ,YAAM,WAAW,KAAK,iBAAiB,SAAS,aAAa,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,WAAW;AAGlI,UAAI,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,aAAa;AACvE,iBAAS,KAAK,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE,MAAM,QAAQ,YAAY,CAAC,EAAE,CAAC;AAAA,MAC1E;AAMA,YAAM,UAAU,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,WAAW,QAAQ,OAAO,SAAS,SAAS,GAAG,UACxH;AAAA,QACE;AAAA,UACI,sBAAsB,QAAQ,MAAM,IAAI,CAAC,OAAO;AAAA,YAC5C,MAAM,EAAE;AAAA,YACR,aAAa,EAAE;AAAA,YACf,YAAY,eAAe,EAAE,UAAU;AAAA,UAC3C,EAAE;AAAA,QACN;AAAA,MACJ,IACE;AACN,YAAM,qBAAqB,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,gBAC/E,EAAE,MAAM,UAAU,OAAO,CAAC,EAAE,MAAM,QAAQ,aAAa,CAAC,EAAE,IAC1D;AAON,YAAM,aAAa,QAAQ,mBAAmB,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,UAAU,IAAI;AAMtH,WAAK,0BAA0B,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc;AACvG,YAAM,mBAAmB,EAAE,gBAAgB,qBAAqB,KAAK,OAAO,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc,EAAE;AAGtJ,WAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,cAAc,MAAM;AAC/E,yBAAiB,kBAAkB,QAAQ;AAAA,MAC/C;AAKA,YAAM,iBAAiB;AAAA,QACnB,IAAK,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,iBAAiB,QAAQ,OAAO,SAAS,KAAK,CAAC;AAAA,QACnH,GAAG,QAAQ,QAAQ,CAAC,MAAM;AAAE,cAAIC;AAAI,kBAAQA,MAAK,EAAE,iBAAiB,QAAQA,QAAO,SAASA,MAAK,CAAC;AAAA,QAAG,CAAC;AAAA;AAAA;AAAA;AAAA,QAItG,GAAG,QAAQ,QAAQ,CAAC,MAAM;AAAE,cAAIA,KAAIC;AAAI,kBAAQA,OAAMD,MAAK,EAAE,gBAAgB,QAAQA,QAAO,SAAS,SAASA,IAAG,iBAAiB,QAAQC,QAAO,SAASA,MAAK,CAAC;AAAA,QAAG,CAAC;AAAA,MACxK,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS,WAAW,IAAI,MAAM;AAIlD,WAAK,mBAAmB,QAAQ,mBAAmB,SAAS,SAAS,eAAe,UAAU,WAC1F,eAAe,UACf,8BAA8B,SAAS,KAAK,KAAK,GAAG;AACpD,yBAAiB,kBAAkB,oBAAoB,eAAe,OAAO,YAAY,CAAC;AAAA,MAC9F;AAGA,WAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,gBAAgB,MAAM;AACjF,yBAAiB,cAAc,iBAAiB,QAAQ,aAAa;AAAA,UACjE,aAAa;AAAA,UACb,SAAS;AAAA,QACb,CAAC;AAAA,MACL;AAGA,YAAM,mBAAmB,IAAI,MAAM,KAAK,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,WAAW,QAAQ,OAAO,SAAS,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAMhK,YAAM,0BAA0B,KAAK,MAAM,WAAW,UAAU;AAChE,YAAM,uBAAuB,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,mBAAmB,SAAS,CAAC,SAAS;AAC7H,YAAM,WAAW,MAAM,KAAK,KAAK,OAAO,OAAO;AAAA,QAAE,OAAO,KAAK;AAAA,QAAO;AAAA,QAChE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAiB,GAAI,sBACnB,EAAE,gBAAgB,eAAe,QAAQ,cAAc,EAAE,IACzD,CAAC,CAAE,GAAG,YAAY,QAAQ,YAAY,SAAS,SAAS,QAAQ,MAAM;AAC5E,aAAO,KAAK,mBAAmB,UAAU,kBAAkB,iBAAiB,eAAe;AAAA,IAC/F,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,cAAc,iBAAiB,eAAe,cAAc;AAKtE,UAAM,EAAE,SAAS,UAAU,UAAU,IAAI,gBAAgB,KAAK,OAAO;AAAA,MACjE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ,CAAC;AACD,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAC3B,UAAM,KAAK,iBAAgB;AAC3B,YAAQ,IAAI,2BAA2B,KAAK,KAAK,OAAO;AACxD,YAAQ,IAAI,qBAAqB,YAAY,KAAK,YAAY,cAAc,UAAU,UAAU,QAAQ,EAAE,CAAC,OAAO,UAAU,aAAa,QAAQ,EAAE,CAAC,GAAG;AACvJ,YAAQ,IAAI,qBAAqB,eAAe,MAAM,aAAa,gBAAgB,UAAU,aAAa,QAAQ,EAAE,CAAC,GAAG;AACxH,YAAQ,IAAI,sBAAsB,QAAQ,QAAQ,EAAE,CAAC,EAAE;AACvD,YAAQ,IAAI,sBAAsB,SAAS,QAAQ,EAAE,CAAC,eAAe,KAAK,mBAAmB,QAAQ,EAAE,CAAC,GAAG;AAC3G,YAAQ,IAAI,sBAAsB,KAAK,gBAAgB,QAAQ,EAAE,CAAC,EAAE;AACpE,YAAQ,IAAI,4BAA4B;AACxC,WAAO;AAAA,EACX;AAAA,EACA,iBAAiB,SAAS,aAAa,aAAa;AAChD,QAAI,IAAI,IAAI,IAAI;AAChB,UAAM,WAAW,CAAC;AAGlB,UAAM,mBAAmB,oBAAI,IAAI;AACjC,eAAW,OAAO,SAAS;AACvB,UAAI,IAAI,SAAS,YACb,IAAI,SAAS,kBACb,IAAI,SAAS,oBACb,IAAI,SAAS,uBACb,IAAI,aAAa,eACjB,IAAI,aAAa,eACjB,IAAI;AAEJ;AACJ,YAAM,OAAO,IAAI,SAAS,SAAS,SAAS;AAC5C,UAAI,IAAI,YAAY;AAChB,cAAM,UAAU,KAAK,iBAAiB,IAAI,IAAI,WAAW,UAAU,OAAO,QAAQ,OAAO,SAAS,KAAK,IAAI,WAAW;AACtH,iBAAS,KAAK;AAAA,UACV,MAAM;AAAA,UACN,OAAO;AAAA,YACH;AAAA,cACI,kBAAkB;AAAA,gBACd,MAAM;AAAA,gBACN,UAAU,EAAE,SAAS,IAAI,WAAW,QAAQ;AAAA,cAChD;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ,CAAC;AAMD,cAAM,gBAAgB,KAAK,IAAI,WAAW,iBAAiB,QAAQ,OAAO,SAAS,KAAK,CAAC;AACzF,YAAI,aAAa,QAAQ;AACrB,mBAAS,KAAK;AAAA,YACV,MAAM;AAAA,YACN,OAAO,aAAa,IAAI,CAAC,SAAS;AAAA,cAC9B,YAAY,EAAE,UAAU,mBAAmB,IAAI,QAAQ,GAAG,MAAM,IAAI,KAAK;AAAA,YAC7E,EAAE;AAAA,UACN,CAAC;AAAA,QACL;AAAA,MACJ,YACU,KAAK,IAAI,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,QAAQ;AAC1E,mBAAW,MAAM,IAAI,WAAW;AAC5B,2BAAiB,IAAI,GAAG,IAAI,GAAG,IAAI;AAAA,QACvC;AACA,iBAAS,KAAK;AAAA,UACV,MAAM;AAAA,UACN,OAAO,IAAI,UAAU,IAAI,CAAC,IAAI,MAAM;AAChC,gBAAID;AACJ,kBAAM,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,MAAM,GAAG,KAAK,EAAE;AAC9D,kBAAM,SAASA,MAAK,GAAG,sBAAsB,QAAQA,QAAO,SAAS,SAASA,IAAG,mBAAmB;AAOpG,kBAAM,OAAO,UAAU,QAAQ,UAAU,SAAS,SAAS,MAAM,WAAW,KAAK,QAAQ,MAAM,mBAAmB;AAClH,gBAAI,KAAK;AACL,mBAAK,mBAAmB;AAAA,YAC5B,WACS,MAAM,GAAG;AACd,mBAAK,mBAAmB;AAAA,YAC5B;AACA,mBAAO;AAAA,UACX,CAAC;AAAA,QACL,CAAC;AAAA,MACL,WACS,SAAS,YAAY,KAAK,IAAI,iBAAiB,QAAQ,OAAO,SAAS,SAAS,GAAG,SAAS;AACjG,cAAM,EAAE,YAAAE,aAAY,WAAAC,WAAU,IAAI,qBAAqB,IAAI,WAAW;AAGtE,iBAAS,KAAK;AAAA,UACV,MAAM;AAAA,UACN,OAAO,CAAC,GAAGD,aAAY,GAAI,IAAI,UAAU,CAAC,EAAE,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAI,GAAGC,UAAS;AAAA,QACxF,CAAC;AAAA,MACL,OACK;AACD,iBAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE,MAAM,IAAI,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC1D;AAAA,IACJ;AACA,UAAM,EAAE,YAAY,UAAU,IAAI,qBAAqB,gBAAgB,QAAQ,gBAAgB,SAAS,cAAc,CAAC,CAAC;AACxH,QAAI,eAAe,WAAW,UAAU,UAAU,QAAQ;AACtD,eAAS,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,CAAC,GAAG,YAAY,GAAI,cAAc,CAAC,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,GAAI,GAAG,SAAS;AAAA,MACxF,CAAC;AAAA,IACL;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,gBAAgB,eAAe;AAC3B,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACxB,QAAI,CAAC;AACD,aAAO,CAAC;AACZ,UAAM,QAAQ;AACd,UAAM,OAAO,KAAK,eAAe,KAAK,MAAM,sBAAsB,QAAQ,OAAO,SAAS,KAAK,IAAI,KAAK,MAAM,0BAA0B,QAAQ,OAAO,SAAS,KAAK,IAAI,KAAK,MAAM,wBAAwB,QAAQ,OAAO,SAAS,KAAK,IAAI,KAAK,MAAM,6BAA6B,QAAQ,OAAO,SAAS,KAAK,CAAC;AACnT,WAAO;AAAA,MACH,aAAa,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMnB,cAAc,MAAM,wBAAwB,QAAQ,MAAM,sBAAsB,SACxE,KAAK,MAAM,0BAA0B,QAAQ,OAAO,SAAS,KAAK,OAAO,KAAK,MAAM,wBAAwB,QAAQ,OAAO,SAAS,KAAK,KAC3I;AAAA,MACN,gBAAgB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,MAKtB,iBAAiB,MAAM;AAAA,MACvB;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,mBAAmB,UAAU,mBAAmB,oBAAI,IAAI,GAMxD,oBAAoB;AAChB,QAAI,IAAI,IAAI,IAAI;AAChB,UAAM,EAAE,aAAa,cAAc,gBAAgB,iBAAiB,KAAK,IAAI,KAAK,gBAAgB,SAAS,aAAa;AACxH,UAAM,aAAa,aAAa,QAAQ,aAAa,SAAS,SAAS,SAAS;AAChF,UAAM,iBAAiB,eAAe,QAAQ,eAAe,SAAS,SAAS,WAAW,CAAC;AAC3F,UAAM,SAAS,MAAM,KAAK,mBAAmB,QAAQ,mBAAmB,SAAS,SAAS,eAAe,aAAa,QAAQ,OAAO,SAAS,SAAS,GAAG,WAAW,QAAQ,OAAO,SAAS,KAAK,CAAC;AACnM,UAAM,YAAY,CAAC;AACnB,UAAM,eAAe,CAAC;AACtB,UAAM,YAAY,CAAC;AACnB,eAAW,QAAQ,OAAO;AACtB,UAAI,KAAK,cAAc;AAKnB,cAAM,QAAQ,EAAE,OAAO,KAAK,MAAM;AAClC,YAAI,KAAK,kBAAkB;AACvB,gBAAM,mBAAmB,KAAK;AAAA,QAClC;AACA,kBAAU,KAAK;AAAA,UACX,IAAI,OAAO,WAAW;AAAA,UACtB,MAAM,KAAK,aAAa;AAAA,UACxB,OAAO,KAAK,KAAK,aAAa,UAAU,QAAQ,OAAO,SAAS,KAAK,CAAC;AAAA,UACtE,kBAAkB,EAAE,CAAC,mBAAmB,GAAG,MAAM;AAAA,QACrD,CAAC;AAAA,MACL,WACS,KAAK,WAAW,KAAK,MAAM;AAChC,qBAAa,KAAK,KAAK,IAAI;AAAA,MAC/B,WACS,KAAK,MAAM;AAChB,kBAAU,KAAK,KAAK,IAAI;AAAA,MAC5B;AAAA,IACJ;AAMA,SAAK,mBAAmB,QAAQ,mBAAmB,SAAS,SAAS,eAAe,kBAAkB,2BAA2B;AAC7H,YAAM,WAAW,4BAA4B,eAAe,eAAe,gBAAgB;AAC3F,UAAI,CAAC,UAAU;AACX,cAAM,IAAI,2BAA2B,eAAe,aAAa;AAAA,MACrE;AACA,gBAAU,KAAK,EAAE,IAAI,OAAO,WAAW,GAAG,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK,CAAC;AAAA,IACxF;AAOA,UAAM,YAAY,aAAa,KAAK,EAAE;AACtC,UAAM,YAAY,UAAU,KAAK,EAAE;AACnC,UAAM,OAAO,UAAU,SAAS,IAC1B,EAAE,MAAM,aAAa,SAAS,WAAW,WAAW,aAAa,QAAW,UAAU,IACtF,EAAE,MAAM,aAAa,SAAS,WAAW,WAAW,aAAa,OAAU;AAKjF,UAAM,eAAe,mBAAmB,QAAQ,mBAAmB,SAAS,SAAS,eAAe;AACpG,UAAM,UAAU,UAAU,WAAW,KAAK,CAAC,aAAa,CAAC;AACzD,QAAI,WACC,gBAAgB,iBAAiB,UAAU,iBAAiB,2BAA4B;AACzF,WAAK,oBAAoB,UAAU;AAAA,QAC/B;AAAA,QACA,mBAAmB,UAAU;AAAA,QAC7B,cAAc,aAAa;AAAA,QAC3B,WAAW,UAAU;AAAA,MACzB,CAAC;AAAA,IACL;AACA,SAAK,yBAAyB,cAAc,WAAW,WAAW,cAAc,kBAAkB;AAClG,QAAI,eAAe;AACf,WAAK,cAAc;AACvB,QAAI,gBAAgB;AAChB,WAAK,eAAe;AACxB,QAAI,mBAAmB;AACnB,WAAK,kBAAkB;AAC3B,QAAI,QAAQ;AACR,WAAK,OAAO;AAIhB,UAAM,eAAe,KAAK,SAAS,oBAAoB,QAAQ,OAAO,SAAS,SAAS,GAAG;AAC3F,QAAI,gBAAgB,QAAQ,kBAAkB,QAAQ,eAAe,MAAM;AACvE,WAAK,eAAe;AAAA,QAChB;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACH,cAAc,UAAU;AAAA,UACxB,SAAS,aAAa;AAAA,UACtB,MAAM,UAAU;AAAA,QACpB;AAAA,QACA;AAAA,MACJ;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,yBAAyB,cAAc,WAAW,WAAW,cAE7D,oBAAoB;AAChB,QAAI,iBAAiB;AACjB;AAGJ,QAAI,UAAU,WAAW,KAAK,UAAU,KAAK,MAAM;AAC/C;AACJ,UAAM,IAAI,uBAAuB,KAAK,OAAO,oBAAoB,cAAc,UAAU,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,EACjH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,oBAAoB,UAAU,QAAQ;AAClC,QAAI,IAAI,IAAI;AACZ,UAAM,SAAU,KAAK,SAAS,mBAAmB,QAAQ,OAAO,SAAS,KAAK,CAAC;AAC/E,UAAM,aAAa,MAAM,KAAK,SAAS,gBAAgB,QAAQ,OAAO,SAAS,SAAS,GAAG,CAAC,OAAO,QAAQ,OAAO,SAAS,KAAK,CAAC;AACjI,WAAO,KAAK,4CAA4C;AAAA,MACpD,OAAO,KAAK;AAAA,MACZ,cAAc,OAAO;AAAA,MACrB,eAAe,UAAU;AAAA,MACzB,OAAO;AAAA,QACH,OAAO,OAAO,oBAAoB,OAAO,eAAe,OAAO;AAAA,QAC/D,cAAc,OAAO;AAAA,QACrB,SAAS,OAAO;AAAA,QAChB,MAAM,OAAO;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,QACH,kBAAkB,MAAM;AAAA,QACxB,sBAAsB,MAAM;AAAA,QAC5B,oBAAoB,MAAM;AAAA,QAC1B,iBAAiB,MAAM;AAAA,MAC3B;AAAA,MACA,gBAAgB,SAAS;AAAA,MACzB,eAAe,UAAU;AAAA,MACzB,kBAAkB,UAAU;AAAA,IAChC,CAAC;AAAA,EACL;AAAA,EACA,cAAc,MAAM;AAChB,QAAI,KAAK,QAAQ;AACb,aAAO;AAAA,QACH,KAAK,GAAG,kBAAkB,KAAK,KAAK,CAAC,QAAQ,KAAK,MAAM;AAAA,QACxD,SAAS,KAAK,gBAAgB,IAAI;AAAA,QAClC,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,aAAa;AAAA,MACjB;AAAA,IACJ;AACA,QAAI,KAAK,gBAAgB;AACrB,aAAO;AAAA,QACH,KAAK,KAAK;AAAA,QACV,SAAS;AAAA;AAAA;AAAA,QAGT,SAAS,EAAE,gBAAgB,oBAAoB,QAAQ,uBAAuB;AAAA,QAC9E,aAAa;AAAA,MACjB;AAAA,IACJ;AACA,UAAM,IAAI,MAAM,6IACsE;AAAA,EAC1F;AAAA,EACA,KAAK,MAAM,QAAQ;AACf,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,EAAE,KAAK,SAAS,SAAS,YAAY,IAAI,KAAK,cAAc,IAAI;AACtE,aAAQ,MAAM,cAAc;AAAA,QACxB;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,aAAa,cAAc;AAAA,QAC3B,mBAAmB,iBAAgB;AAAA,QACnC,SAAS,KAAK;AAAA,QACd,cAAc,KAAK;AAAA,QACnB,eAAe,iBAAgB;AAAA,QAC/B;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA,EACA,gBAAgB,MAAM;AAClB,UAAM,UAAU,OAAO,OAAO,CAAC,GAAG,IAAI;AACtC,WAAO,QAAQ;AACf,QAAI,QAAQ,gBAAgB;AACxB,cAAQ,mBAAmB,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,QAAQ,gBAAgB,GAAG,EAAE,kBAAkB,oBAAoB,gBAAgB,QAAQ,eAAe,CAAC;AACtK,aAAO,QAAQ;AAAA,IACnB;AACA,WAAO;AAAA,EACX;AACJ;AAEA,gBAAgB,qBAAqB;AACrC,gBAAgB,sBAAsB;AACtC,gBAAgB,oBAAoB;AACpC,gBAAgB,6BAA6B;AAY7C,gBAAgB,qBAAqB;AACrC,gBAAgB,qBAAqB;AAAA,EACjC,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AACpB;AAEA,gBAAgB,kBAAkB;;;AClqB3B,SAAS,+BAA+B,GAAG;AAC9C,SAAO,OAAO,EAAE,cAAc;AAClC;AASO,IAAM,0BAAN,MAAM,yBAAwB;AAAA,EACjC,cAAc;AACV,SAAK,eAAe,IAAI,kBAAkB;AAAA,EAC9C;AAAA,EACA,IAAI,MAAM;AACN,WAAO,SAAS,yBAAwB,eAAe,KAAK,eAAe;AAAA,EAC/E;AAAA,EACA,UAAU;AACN,WAAO,KAAK;AAAA,EAChB;AAAA,EACA,cAAc;AACV,WAAO,yBAAwB;AAAA,EACnC;AAAA,EACA,QAAQ;AACJ,WAAO,CAAC,yBAAwB,YAAY;AAAA,EAChD;AAAA,EACA,UAAU,MAAM;AACZ,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI,IAAI;AACZ,UAAI,SAAS,UAAa,SAAS,yBAAwB;AACvD,eAAO;AACX,cAAQ,KAAM,OAAQ,MAAM,KAAK,KAAK,cAAc,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,EAAE,OAAS,QAAQ,OAAO,SAAS,KAAK;AAAA,IACxJ,CAAC;AAAA,EACL;AAAA,EACA,eAAe;AACX,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI,IAAI;AACZ,YAAM,UAAU,KAAM,OAAQ,MAAM,KAAK,KAAK,cAAc,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,EAAE,OAAS,QAAQ,OAAO,SAAS,KAAK;AAC5J,aAAO,CAAC,EAAE,MAAM,yBAAwB,cAAc,WAAW,MAAM,OAAO,CAAC;AAAA,IACnF,CAAC;AAAA,EACL;AACJ;AACA,wBAAwB,eAAe;AAkBhC,IAAM,4BAAN,MAAM,2BAA0B;AAAA,EACnC,YAAY,WAAW,aAAa;AAChC,SAAK,YAAY,oBAAI,IAAI;AAGzB,UAAM,OAAO,IAAI,IAAI,SAAS;AAC9B,+BAA0B,mBAAmB,MAAM,WAAW;AAC9D,SAAK,YAAY;AACjB,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,WAAW,aAAa;AAC9C,QAAI,UAAU,SAAS,GAAG;AACtB,YAAM,IAAI,MAAM,+DAA+D;AAAA,IACnF;AACA,QAAI,CAAC,UAAU,IAAI,WAAW,GAAG;AAC7B,YAAM,IAAI,MAAM,4CAA4C,WAAW,6BAA6B;AAAA,IACxG;AAAA,EACJ;AAAA,EACA,IAAI,MAAM;AACN,WAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAClC;AAAA,EACA,UAAU;AAEN,WAAO,KAAK,UAAU,IAAI,KAAK,YAAY;AAAA,EAC/C;AAAA,EACA,cAAc;AACV,WAAO,KAAK;AAAA,EAChB;AAAA,EACA,QAAQ;AACJ,WAAO,CAAC,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,EACpC;AAAA,EACA,UAAU,MAAM;AACZ,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,UAAI,IAAI;AACR,YAAM,WAAW,SAAS,SAAY,KAAK,QAAQ,IAAI,KAAK,UAAU,IAAI,IAAI;AAC9E,UAAI,CAAC;AACD,eAAO;AACX,cAAQ,KAAM,OAAQ,KAAK,SAAS,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,QAAQ,OAAS,QAAQ,OAAO,SAAS,KAAK;AAAA,IAC9I,CAAC;AAAA,EACL;AAAA,EACA,eAAe;AACX,WAAO,UAAU,MAAM,QAAQ,QAAQ,aAAa;AAChD,YAAM,UAAU,CAAC,GAAG,KAAK,UAAU,QAAQ,CAAC;AAC5C,aAAO,QAAQ,IAAI,QAAQ,IAAI,CAAC,OAAO,UAAU,MAAM,CAAC,EAAE,GAAG,QAAQ,WAAW,CAAC,MAAM,QAAQ,GAAG;AAC9F,YAAI,IAAI;AACR,eAAQ;AAAA,UACJ;AAAA,UACA,WAAW,SAAS,KAAK;AAAA,UACzB,SAAS,KAAM,OAAQ,KAAK,SAAS,eAAe,QAAQ,OAAO,SAAS,SAAS,GAAG,KAAK,QAAQ,OAAS,QAAQ,OAAO,SAAS,KAAK;AAAA,QAC/I;AAAA,MACJ,CAAC,CAAC,CAAC;AAAA,IACP,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAM,UAAU;AAChB,SAAK,UAAU,IAAI,MAAM,QAAQ;AACjC,SAAK,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAM;AACb,QAAI,CAAC,KAAK,UAAU,IAAI,IAAI,GAAG;AAC3B,YAAM,IAAI,MAAM,qDAAqD,IAAI,oCAA+B;AAAA,IAC5G;AACA,SAAK,eAAe;AACpB,SAAK,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,WAAW,UAAU,CAAC,GAAG;AAC5B,QAAI;AACJ,UAAM,OAAO,qBAAqB,MAAM,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,SAAS,CAAC;AAC9F,UAAM,eAAe,KAAK,QAAQ,aAAa,QAAQ,OAAO,SAAS,KAAK,KAAK;AACjF,+BAA0B,mBAAmB,MAAM,WAAW;AAC9D,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,OAAO;AAAA,EAChB;AAAA,EACA,UAAU,UAAU;AAChB,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM;AACT,WAAK,UAAU,OAAO,QAAQ;AAAA,IAClC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AACL,eAAW,YAAY,MAAM,KAAK,KAAK,SAAS;AAC5C,eAAS;AAAA,EACjB;AACJ;;;ACnQO,IAAM,oBAAiC,EAAE,SAAS,MAAM;AAAC,EAAE;AAgB3D,IAAM,qBAAN,MAAyB;AAAA;AAAA;AAAA;AAAA;AAAA,EAW9B,YAAY,QAAmC;AAV/C,SAAiB,cAAc,oBAAI,IAA6B;AAIhE,SAAQ,qBAAqB;AAO3B,SAAK,iBAAiB,IAAI,IAAI,QAAQ,kBAAkB,CAAC,CAAC;AAC1D,SAAK,qBACH,QAAQ,eAAe,OAAO,MAAM,OAAO,cAAe,QAAQ;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,gBAAsB;AAC5B,QAAI,KAAK,mBAAoB;AAC7B,SAAK,qBAAqB;AAC1B,UAAM,YAAY,OAAO,WAAW,eAAe,OAAO,qBAAqB;AAC/E,QAAI,KAAK,eAAe,SAAS,KAAK,CAAC,KAAK,sBAAsB,CAAC,UAAW;AAC9E,SAAK,UAAU,IAAI,iBAAiB,KAAK,mBAAmB,CAAC;AAC7D,SAAK,QAAQ,YAAY,CAAC,OAAO;AAC/B,YAAM,EAAE,MAAM,OAAO,IAAK,GAAG,QAAQ,CAAC;AACtC,UAAI,KAAM,MAAK,YAAY,MAAM,MAAM;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UACE,MACA,SACY;AAGZ,SAAK,cAAc;AACnB,QAAI,WAAW,KAAK,YAAY,IAAI,IAAc;AAClD,QAAI,CAAC,UAAU;AACb,iBAAW,oBAAI,IAAI;AACnB,WAAK,YAAY,IAAI,MAAgB,QAAQ;AAAA,IAC/C;AACA,UAAM,IAAI;AACV,aAAS,IAAI,CAAC;AACd,WAAO,MAAM,SAAU,OAAO,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAA+C,MAAS,QAAwC;AAC9F,SAAK,YAAY,MAAgB,MAAM;AACvC,QAAI,KAAK,eAAe,IAAI,IAAc,GAAG;AAC3C,WAAK,cAAc;AACnB,WAAK,SAAS,YAAY,EAAE,MAAM,OAAO,CAAC;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,MAAyC;AACxD,SAAK,eAAe,IAAI,IAAc;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAc;AACZ,SAAK,SAAS,MAAM;AACpB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,YAAY,MAAc,QAAuB;AACvD,SAAK,YAAY,IAAI,IAAI,GAAG,QAAQ,CAAC,YAAY,QAAQ,MAAM,CAAC;AAAA,EAClE;AACF;AAmBA,SAAS,wBAAwB,MAAsB;AAGrD,MAAI,OAAO,mBAAmB,YAAa,QAAO,GAAG,IAAI;AACzD,QAAM,MAAM,GAAG,IAAI;AACnB,MAAI,KAAK,eAAe,QAAQ,GAAG;AACnC,MAAI,CAAC,IAAI;AACP,SAAK,OAAO,WAAW;AACvB,mBAAe,QAAQ,KAAK,EAAE;AAAA,EAChC;AACA,SAAO,GAAG,IAAI,IAAI,EAAE;AACtB;AAkBO,IAAM,qBAAqB,IAAI,mBAAmB;AAAA,EACvD,gBAAgB,CAAC,cAAc,aAAa,mBAAmB,eAAe;AAAA;AAAA;AAAA;AAAA,EAI9E,oBAAoB,MAAM,wBAAwB,wBAAwB;AAC5E,CAAC;;;ACnMM,SAAS,oBACdC,WACA,cACA,WACY;AACZ,QAAM,WAAWA,UAAS,IAAI,YAAY;AAC1C,MAAI,CAAC,UAAU;AACb,UAAM,YAAYA,UAAS,MAAM,EAAE,KAAK,IAAI,KAAK;AACjD,UAAM,IAAI;AAAA,MACR,UAAU,SAAS,kCAAkC,YAAY,kBAAkB,SAAS;AAAA,IAC9F;AAAA,EACF;AACA,MAAI,CAAC,SAAS,MAAM;AAClB,UAAM,IAAI;AAAA,MACR,UAAU,SAAS,2BAA2B,YAAY;AAAA,IAC5D;AAAA,EACF;AACA,SAAO;AACT;AAYO,SAAS,6BACd,QACAA,WACM;AACN,QAAM,UAAU,oBAAI,IAAiB;AACrC,QAAM,OAAO,CAAC,UAA6B;AACzC,QAAI,QAAQ,IAAI,KAAK,EAAG;AACxB,YAAQ,IAAI,KAAK;AACjB,QAAI,OAAO,MAAM,aAAa,UAAU;AACtC,0BAAoBA,WAAU,MAAM,UAAU,MAAM,IAAI;AAAA,IAC1D;AACA,eAAW,OAAO,MAAM,aAAa,CAAC,EAAG,MAAK,GAAG;AAAA,EACnD;AACA,aAAW,QAAQ,OAAQ,MAAK,IAAI;AACtC;;;AC6CO,IAAM,wBAAoE;AAAA,EAC/E,cAAc;AAAA,EACd,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,6BAA6B;AAAA,EAC7B,qBAAqB;AAAA,EACrB,8BAA8B;AAAA;AAAA;AAAA,EAG9B,2BAA2B;AAAA,EAE3B,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,EAC1B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,+BAA+B;AAAA,EAC/B,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,6BAA6B;AAAA,EAE7B,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,oBAAoB;AACtB;AAuBA,IAAM,0BAA0B;AAQhC,IAAM,WAAW,oBAAI,IAA6B;AAS3C,SAAS,gBACd,KACA,MACA,QACM;AACN,MAAI,SAAS,SAAS,IAAI,GAAG;AAC7B,MAAI,CAAC,QAAQ;AACX,aAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE;AAC/B,aAAS,IAAI,KAAK,MAAM;AAAA,EAC1B;AACA,SAAO,OAAO,KAAK;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA,YAAY,sBAAsB,IAAI;AAAA,IACtC;AAAA,EACF,CAAC;AACD,SAAO,QAAQ;AACf,MAAI,OAAO,OAAO,SAAS,yBAAyB;AAMlD,UAAM,UAAU,OAAO,OAAO,UAAU,CAAC,MAAM,EAAE,eAAe,MAAM;AACtE,QAAI,YAAY,IAAI;AAClB,aAAO,OAAO,OAAO,SAAS,CAAC;AAAA,IACjC;AAAA,EACF;AACF;AAkBO,SAAS,gBACd,KACA,QACA,QACM;AACN,kBAAgB,KAAK,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC;AAC1D;AAQO,SAAS,gBACd,KACA,QACA,QACM;AACN,kBAAgB,KAAK,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC;AAC1D;AAGO,SAAS,cAAc,KAAuC;AACnE,SAAO,SAAS,IAAI,GAAG,GAAG,UAAU,CAAC;AACvC;AAWO,SAAS,gBAAgB,WAAmB,QAAoC;AACrF,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,SAAS,SAAS,IAAI,SAAS;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE;AAC/B,aAAS,IAAI,WAAW,MAAM;AAAA,EAChC;AACA,aAAW,SAAS,QAAQ;AAC1B,WAAO,OAAO,KAAK,EAAE,GAAG,OAAO,OAAO,OAAO,KAAK,CAAC;AACnD,WAAO,QAAQ;AAAA,EACjB;AAMA,MAAI,UAAU,OAAO,OAAO,SAAS;AACrC,MAAI,UAAU,GAAG;AACf,WAAO,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM;AAC1C,UAAI,UAAU,KAAK,EAAE,eAAe,QAAQ;AAC1C,mBAAW;AACX,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAOO,SAAS,aAAa,KAAmB;AAC9C,WAAS,OAAO,GAAG;AACrB;;;ACjTO,IAAMC,UAAS,aAAa,cAAc;;;ACyB1C,SAAS,yBAAyB,eAAiD;AACxF,QAAM,QAAiC,CAAC;AACxC,QAAM,YAAY,oBAAI,IAAqB;AAC3C,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,YAAY,oBAAI,IAAgB;AACtC,MAAI,WAAW;AAEf,QAAM,UAA8B;AAAA,IAClC;AAAA,IACA;AAAA,IACA,KAAQ,KAAa,SAA4B;AAC/C,UAAI,UAAU,IAAI,GAAG,EAAG,QAAO,UAAU,IAAI,GAAG;AAKhD,UAAI,UAAU;AACZ,QAAAC,QAAO;AAAA,UACL,4BAA4B,GAAG;AAAA,QACjC;AACA,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,QAAQ;AACtB,gBAAU,IAAI,KAAK,KAAK;AACxB,aAAO;AAAA,IACT;AAAA,IACA,SAAe;AAGb,iBAAW,YAAY,WAAW;AAChC,YAAI;AACF,mBAAS;AAAA,QACX,SAAS,GAAG;AACV,UAAAA,QAAO,MAAM,uDAAuD,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,UAAkC;AAC1C,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,UAAU,IAAsB;AAG9B,UAAI,UAAU;AACZ,WAAG;AACH;AAAA,MACF;AACA,gBAAU,IAAI,EAAE;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAgB;AACd,UAAI,SAAU;AACd,iBAAW;AACX,iBAAW,MAAM,WAAW;AAC1B,YAAI;AACF,aAAG;AAAA,QACL,SAAS,GAAG;AACV,UAAAA,QAAO,MAAM,+CAA+C,CAAC;AAAA,QAC/D;AAAA,MACF;AACA,gBAAU,MAAM;AAChB,gBAAU,MAAM;AAGhB,gBAAU,MAAM;AAAA,IAClB;AAAA,EACF;AACF;;;AC9EO,IAAM,qBAAqB;AAG3B,IAAM,qBAAqB;AAMlC,IAAM,yBAAyB;AA6G/B,SAAS,cAAc,SAAkC;AACvD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAYA,SAAS,aACP,QACA,MACA,SACA,SACA,YAOA,aAAa,GACL;AACR,QAAM,OAAO,WAAW,SAAS,SAAS;AAC1C,QAAM,MAAM,QAAQ,SAAS,eAAe,IAAI,QAAQ,EAAE,KAAK;AAC/D,QAAM,UAAU,aAAa,yBAAyB;AACtD,QAAM,SAAS,aAAa,IAAI,MAAM,UAAU,SAAS,eAAe,IAAI,KAAK,GAAG,KAAK;AACzF,SAAO,IAAI,IAAI,GAAG,GAAG,WAAM,IAAI,aAAa,OAAO,SAAS,MAAM,KAAK,cAAc,OAAO,CAAC,IAAI,OAAO;AAC1G;AAGA,SAAS,aAAa,SAAkC;AACtD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,OAAO,QAAQ,KAAK;AAAA,IAC7B,KAAK;AACH,aAAO,cAAc,QAAQ,EAAE;AAAA,IACjC;AACE,aAAO,QAAQ;AAAA,EACnB;AACF;AAEA,SAAS,oBAAoB,SAAiB,SAAyB;AACrE,SAAO,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,WAAW,sBAAsB,CAAC;AAC5E;AAgBA,SAAS,mBAAmB,MAAwC;AAClE,SAAO,SAAS,cAAc,SAAS;AACzC;AAyCO,SAAS,kBACd,SACA,UACA,KACA,aACe;AACf,MAAI,SAAS,SAAS,EAAG,QAAO;AAEhC,QAAM,aAAa,CAAC,UAClB,MAAM,QAAQ,MAAM,OAAO,EAAE,IAAI,MAAM,OAAO,KAAK,CAAC,MAAM,OAAO,EAAE;AASrE,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,cAAc,CAAC,CAAC;AAC9D,QAAM,OACJ,eAAe,IAAI,IAAI,YAAY,KAAK,MAAM,IAAI,YAAY,UAAU,IAAI;AAM9E,QAAM,cAAc,CAAC,UACnB,eAAe,KAAK,MAAM,aAAa;AAEzC,QAAM,cAAc,oBAAI,IAAoB;AAC5C,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,OAAO,SAAS;AACzB,QAAI,CAAC,IAAI,WAAW,OAAQ;AAC5B,eAAW,MAAM,IAAI,WAAW;AAC9B,eAAS,IAAI,GAAG,IAAI,GAAG,IAAI;AAC3B,YAAM,QAAQ,SAAS,IAAI,GAAG,EAAE;AAChC,UAAI,CAAC,SAAS,CAAC,YAAY,KAAK,EAAG;AACnC,iBAAW,KAAK,WAAW,KAAK,GAAG;AACjC,YAAI,EAAE,SAAS,aAAc,aAAY,IAAI,EAAE,IAAI,GAAG,EAAE;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,CACnB,YACA,OACA,SACY;AACZ,YAAQ,KAAK,MAAM;AAAA;AAAA;AAAA;AAAA,MAIjB,KAAK;AACH,eAAO,OAAO,MAAM,YAAY,KAAK;AAAA,MACvC,KAAK;AACH,eAAO,IAAI,OAAO,MAAM;AAAA,MAC1B,KAAK;AACH,eAAO,IAAI,gBAAgB,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA,MAI7C,KAAK;AACH,eAAO,IAAI,WAAW,MAAM,UAAU,KAAK,IAAI,gBAAgB,MAAM,UAAU;AAAA,MACjF;AACE,eAAO,YAAY,IAAI,KAAK,EAAE,MAAM;AAAA,IACxC;AAAA,EACF;AAUA,QAAM,aAAa,CACjB,YACA,UACgC;AAChC,QAAI,MAAM,aAAc,QAAO,MAAM;AACrC,UAAM,QAAQ,WAAW,KAAK,EAAE;AAAA,MAC9B,CAAC,OACE,mBAAmB,EAAE,IAAI,KAAK,YAAY,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;AAAA,IAC3F;AACA,QAAI,MAAO,OAAM,eAAe;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI,CAAC,QAAQ;AAE1B,QAAI,IAAI,WAAW,QAAQ;AACzB,UAAI,UAAU;AACd,YAAM,YAAY,IAAI,UAAU,IAAI,CAAC,OAAO;AAC1C,cAAM,QAAQ,SAAS,IAAI,GAAG,EAAE;AAChC,YAAI,CAAC,OAAO,OAAO,KAAM,QAAO;AAChC,cAAM,QAAQ,WAAW,GAAG,IAAI,KAAK;AACrC,YAAI,CAAC,MAAO,QAAO;AACnB,cAAM,UAAU,KAAK,UAAU,GAAG,QAAQ,CAAC,CAAC,EAAE;AAC9C,YAAI,UAAU,mBAAoB,QAAO;AACzC,kBAAU;AACV,cAAM,SAAS,MAAM,OAAO;AAa5B,cAAM,OAAgC;AAAA,UACpC,CAAC,kBAAkB,GACjB,WAAW,UAAU,WAAW,YAC5B,aAAa,QAAQ,GAAG,MAAM,OAAO,SAAS,WAAW,SAAS,IAClE,OAAO;AAAA,QACf;AACA,YAAI,CAAC,MAAM,cAAc;AACvB,gBAAM,eAAe;AACrB,gBAAM,UAAU,KAAK,UAAU,IAAI,EAAE;AACrC,sBAAY;AAAA,YACV,MAAM,MAAM;AAAA,YACZ,YAAY,GAAG;AAAA,YACf,MAAM,GAAG;AAAA,YACT,QAAQ;AAAA,YACR,SAAS,aAAa,KAAK;AAAA,YAC3B;AAAA,YACA,aAAa,oBAAoB,SAAS,OAAO;AAAA,UACnD,CAAC;AAAA,QACH;AACA,eAAO,EAAE,GAAG,IAAI,KAAK;AAAA,MACvB,CAAC;AACD,aAAO,UAAU,EAAE,GAAG,KAAK,UAAU,IAAI;AAAA,IAC3C;AAGA,QAAI,IAAI,YAAY;AAClB,YAAM,QAAQ,SAAS,IAAI,IAAI,WAAW,UAAU;AASpD,YAAM,UAAU,IAAI,WAAW,SAAS,UAAU;AAClD,YAAM,SAAS,IAAI,WAAW,eAAe,CAAC;AAI9C,YAAM,UAAU,UAAU,OAAO,OAAO,CAAC,GAAG,QAAQ,KAAK,IAAI,MAAM,UAAU,IAAI,CAAC;AAClF,YAAM,QAAQ,OAAO,OAAO,WACxB,WAAW,IAAI,WAAW,YAAY,KAAK,IAC3C;AACJ,UAAI,SAAS,SAAS,WAAW,oBAAoB;AACnD,cAAM,OAAO,SAAS,IAAI,IAAI,WAAW,UAAU,KAAK,IAAI,WAAW;AACvE,cAAM,SAAS,MAAM,OAAO;AAE5B,cAAM,UACJ,WAAW,UAAU,WAAW,YAC5B,aAAa,YAAY,MAAM,OAAO,SAAS,WAAW,WAAW,OAAO,MAAM,IAClF,OAAO;AACb,YAAI,CAAC,MAAM,kBAAkB;AAC3B,gBAAM,mBAAmB;AACzB,sBAAY;AAAA,YACV,MAAM,MAAM;AAAA,YACZ,YAAY,IAAI,WAAW;AAAA,YAC3B;AAAA,YACA,QAAQ;AAAA,YACR,SAAS,aAAa,KAAK;AAAA,YAC3B,SAAS,QAAQ;AAAA,YACjB,aAAa,oBAAoB,SAAS,QAAQ,MAAM;AAAA,UAC1D,CAAC;AAAA,QACH;AAIA,cAAM,EAAE,aAAa,SAAS,GAAG,aAAa,IAAI,IAAI;AACtD,eAAO,EAAE,GAAG,KAAK,YAAY,EAAE,GAAG,cAAc,QAAQ,EAAE;AAAA,MAC5D;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;;;ACxbA,SAAS,gBAAgB,KAA+B;AACtD,MAAI,IAAI,WAAW,QAAQ;AACzB,WAAO,EAAE,GAAG,KAAK,WAAW,IAAI,UAAU,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,MAAM,CAAC,EAAE,EAAE,EAAE;AAAA,EAC/E;AACA,MAAI,IAAI,YAAY;AAMlB,UAAM,EAAE,aAAa,SAAS,GAAG,aAAa,IAAI,IAAI;AACtD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,YAAY,EAAE,GAAG,cAAc,SAAS,sCAAsC;AAAA,IAChF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,yBAAyB,SAAwB,WAAkC;AACjG,SAAO,QAAQ,IAAI,CAAC,QAAQ;AAC1B,QAAI,CAAC,IAAI,aAAa,IAAI,cAAc,UAAW,QAAO;AAC1D,WAAO,gBAAgB,GAAG;AAAA,EAC5B,CAAC;AACH;AAMO,SAAS,gBAAgB,SAAiC,KAA4B;AAC3F,QAAM,SAAS,QAAQ,SAAS;AAChC,SAAO,QAAQ,IAAI,CAAC,KAAK,MAAO,IAAI,SAAS,gBAAgB,GAAG,IAAI,GAAI;AAC1E;AAKO,IAAM,+BAA+B;AAGrC,IAAM,kCAAkC;AAWxC,SAAS,kBAAkB,SAAgD;AAChF,MAAI,QAAQ,SAAS,+BAA+B,iCAAiC;AACnF,WAAO;AAAA,EACT;AACA,QAAM,SAAS,QAAQ,SAAS;AAChC,WAAS,IAAI,QAAQ,IAAI,GAAG,KAAK,GAAG;AAClC,QAAI,QAAQ,CAAC,EAAE,SAAS,QAAQ;AAC9B,aAAO,KAAK,kCAAkC,IAAI;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,wBAAwB,GAAwB;AACvD,UAAQ,EAAE,MAAM;AAAA,IACd,KAAK;AACH,aAAO,qBAAqB,EAAE,OAAO;AAAA,IACvC,KAAK;AACH,aAAO,EAAE,UAAU,SAAS,EAAE,OAAO,KAAK;AAAA,IAC5C,KAAK,aAAa;AAIhB,UAAI,EAAE,aAAa,aAAa;AAC9B,eAAO,EAAE,UAAU,aAAa,EAAE,OAAO,KAAK;AAAA,MAChD;AACA,UAAI,EAAE,aAAa,aAAa;AAC9B,eAAO,EAAE,UAAU,YAAY,EAAE,OAAO,KAAK;AAAA,MAC/C;AACA,UAAI,EAAE,WAAW,QAAQ;AACvB,cAAM,QAAQ,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACtD,eAAO,EAAE,UACL,cAAc,EAAE,OAAO,aAAa,KAAK,MACzC,qBAAqB,KAAK;AAAA,MAChC;AACA,aAAO,EAAE,UAAU,cAAc,EAAE,OAAO,KAAK;AAAA,IACjD;AAAA,IACA,KAAK;AACH,aAAO,EAAE,aAAa,gBAAgB,EAAE,WAAW,OAAO,KAAK;AAAA,IACjE;AACE,aAAO;AAAA,EACX;AACF;AASO,SAAS,6BAA6B,WAG3C;AACA,QAAM,aAAa,UAAU,IAAI,uBAAuB,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AACnF,QAAM,eACJ;AAIF,QAAM,cACJ;AAAA,EAA2B,UAAU;AAAA;AAAA;AAAA;AAGvC,SAAO,EAAE,cAAc,YAAY;AACrC;AAYO,SAAS,qBAAqB,SAAgD;AACnF,SAAO,QAAQ,IAAI,CAAC,MAAM;AACxB,QAAI,EAAE,SAAS,oBAAqB,QAAO;AAC3C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN,SACE;AAAA,EAA2B,EAAE,OAAO;AAAA;AAAA;AAAA;AAAA,MAGtC,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;;;ACpJO,SAAS,aAA6B;AAC3C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AACF;AAcO,SAAS,YAAY,OAA+B;AACzD,SACE,MAAM,sBAAsB,MAAM,kBAAkB,MAAM,mBAAmB,MAAM;AAEvF;AAWO,SAAS,SAAS,GAAmB,GAAmC;AAC7E,SAAO;AAAA,IACL,SAAS,EAAE,UAAU,EAAE;AAAA,IACvB,qBAAqB,EAAE,sBAAsB,EAAE;AAAA,IAC/C,iBAAiB,EAAE,kBAAkB,EAAE;AAAA,IACvC,kBAAkB,EAAE,mBAAmB,EAAE;AAAA,IACzC,cAAc,EAAE,eAAe,EAAE;AAAA,EACnC;AACF;AAqBO,SAAS,aAAa,GAA4C;AACvE,MACE,EAAE,QAAQ,QACV,EAAE,mBAAmB,QACrB,EAAE,eAAe,QACjB,EAAE,gBAAgB,QAClB,EAAE,mBAAmB,QACrB,EAAE,oBAAoB,MACtB;AACA,WAAO;AAAA,EACT;AACA,QAAM,kBAAkB,EAAE,mBAAmB;AAC7C,QAAM,mBAAmB,EAAE,oBAAoB;AAC/C,SAAO;AAAA,IACL,UAAU,EAAE,QAAQ,MAAM,EAAE,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,IAK/C,qBAAqB,KAAK,IAAI,IAAI,EAAE,eAAe,KAAK,kBAAkB,gBAAgB;AAAA,IAC1F;AAAA,IACA;AAAA,IACA,cAAc,EAAE,gBAAgB;AAAA,EAClC;AACF;AA6DO,SAAS,SAAS,UAAkD;AACzE,QAAM,QAAQ,WAAW;AACzB,aAAW,UAAU,KAAK;AAC1B,SAAO;AACT;AAGA,SAAS,QAAQ,MAAsB,MAA4B;AACjE,OAAK,WAAW,KAAK;AACrB,OAAK,uBAAuB,KAAK;AACjC,OAAK,mBAAmB,KAAK;AAC7B,OAAK,oBAAoB,KAAK;AAC9B,OAAK,gBAAgB,KAAK;AAC5B;AAOA,SAAS,WAAW,UAAkC,MAA4B;AAChF,aAAW,KAAK,UAAU;AAGxB,QAAI,EAAE,QAAQ,KAAM,MAAK,WAAW,EAAE;AACtC,QAAI,EAAE,mBAAmB,KAAM,MAAK,WAAW,EAAE;AAEjD,UAAM,YAAY,EAAE,mBAAmB;AACvC,UAAM,aAAa,EAAE,oBAAoB;AACzC,SAAK,mBAAmB;AACxB,SAAK,oBAAoB;AAKzB,SAAK,uBAAuB,KAAK,IAAI,IAAI,EAAE,eAAe,KAAK,YAAY,UAAU;AACrF,SAAK,gBAAgB,EAAE,gBAAgB;AAKvC,UAAM,SAAS,EAAE,YAAY;AAC7B,QAAI,OAAQ,SAAQ,MAAM,MAAM;AAEhC,eAAW,MAAM,EAAE,aAAa,CAAC,GAAG;AAClC,UAAI,GAAG,cAAe,YAAW,GAAG,eAAe,IAAI;AAAA,IACzD;AAAA,EACF;AACF;;;ACvMO,IAAM,mBAAmB,OAAO,UAAU;;;AC6GjD,IAAM,mBAAmB,CAAC,WAAuD;AAC/E,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,YAAa,OAAqC;AACxD,MAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,EAAG,QAAO;AAChE,QAAM,YAAY,UAAU;AAAA,IAC1B,CAAC,QAAQ,CAAC,CAAC,OAAO,OAAO,QAAQ,YAAa,IAA2B,SAAS;AAAA,EACpF;AACA,SAAO,YAAa,YAAsC;AAC5D;AAUA,IAAM,0BAA0B,CAAC,OAAoD;AAAA,EACnF,aAAa,EAAE;AAAA,EACf,MAAM,EAAE;AAAA,EACR,GAAI,EAAE,kBAAkB,OAAO,EAAE,gBAAgB,EAAE,eAAe,IAAI,CAAC;AAAA,EACvE,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,IAAI,CAAC;AAC3D;AAEA,IAAM,iBAAiB,CAAC,MAAsD;AAS5E,QAAM,SAAS,kBAAkB,EAAE,WAAW,KAAK,kBAAkB,EAAE,YAAY;AACnF,MAAI,EAAE,aAAa,QAAQ,EAAE,YAAY,QAAQ,CAAC,OAAQ,QAAO;AACjE,SAAO;AAAA,IACL,WAAW,EAAE;AAAA,IACb,UAAU,EAAE;AAAA,IACZ,aAAa,EAAE;AAAA,IACf,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA;AAAA;AAAA,IAG3B,GAAI,EAAE,wBAAwB,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,IAAI,CAAC;AAAA,EAC3F;AACF;AAEA,IAAM,8BAA8B;AACpC,IAAM,8BAA8B;AASpC,IAAM,6BAA6B;AACnC,IAAM,iCAAiC;AAKvC,IAAM,uBAAuB,iCAAiC;AAI9D,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAGnC,IAAM,8BAA8B;AACpC,IAAM,6BAA6B;AAYnC,IAAM,4BAAwD,oBAAI,IAAI;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,4BAA4B;AAGzC,IAAM,kCACJ;AA+MK,IAAM,aAAN,MAAM,oBAAmB,YAAgC;AAAA,EA+Z9D,YACmB,kBACjB,SAA2B,CAAC,GAC5B;AACA,UAAM;AAHW;AA/ZnB,SAAQ,UAAyB,CAAC;AAClC,SAAQ,OAAO;AAEf;AAAA,SAAQ,gBAAgB;AACxB,SAAQ,sBAAsB,oBAAI,IAUhC;AAUF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,sBAAsB,oBAAI,IAAsC;AAoExE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,mBAAmB,oBAAI,IAAsC;AAS9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,eAAe;AAOvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,UAAU;AAUlB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,oBAAoB;AAS5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,oBAAoB;AAG5B;AAAA,SAAQ,YAA8B,CAAC;AAEvC;AAAA,SAAQ,qBAAqB;AAE7B;AAAA,SAAQ,8BAA8B;AAMtC;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,yBAAyB,oBAAI,IAAY;AAO1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,oBAAoB,oBAAI,IAAY;AAQrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,uBAAuB,oBAAI,IAAY;AAIxD;AAAA,SAAQ,eAAyC,oBAAI,IAAI;AAezD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,aAAa;AAkCrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,wBAAwB;AAMhC;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,gBAAgC,CAAC;AAWzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,sBAAyC,CAAC;AAM3D;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,6BAA6B;AAErC;AAAA,SAAQ,kBAAkB;AAY1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,sBAAsB,IAAI,gBAAgB;AAS3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,iBAAiB,IAAI,gBAAgB;AAE7C;AAAA,SAAQ,gBAAgB;AA0DxB;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,wBAAwB,oBAAI,IAAwB;AAwB5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,sBAAsB,oBAAI,IAA2D;AAwC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,0BAA0B;AAWlC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,0BAA0B;AAuBlC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,wBAAwB;AAO9B,UAAM;AAAA,MACJ,eAAe,CAAC;AAAA,MAChB,kBAAkB,CAAC;AAAA,MACnB;AAAA,MACA;AAAA,MACA,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACF,IAAI;AACJ,SAAK,oBAAoB;AACzB,SAAK,qBAAqB;AAC1B,SAAK,aAAa;AAClB,SAAK,cAAc;AACnB,SAAK,iCAAiC;AACtC,SAAK,iCAAiC;AACtC,QAAI,OAAO,iBAAiB,YAAY;AACtC,WAAK,sBAAsB;AAC3B,WAAK,eAAe,CAAC;AAAA,IACvB,OAAO;AACL,WAAK,sBAAsB;AAC3B,WAAK,eAAe;AAAA,IACtB;AACA,QAAI,OAAO,oBAAoB,YAAY;AACzC,WAAK,yBAAyB;AAC9B,WAAK,kBAAkB,CAAC;AAAA,IAC1B,OAAO;AACL,WAAK,yBAAyB;AAC9B,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,eAAe;AACpB,SAAK,gBAAgB;AACrB,SAAK,oBAAoB;AACzB,SAAK,mBAAmB;AAUxB,QAAI,+BAA+B,KAAK,gBAAgB,GAAG;AACzD,WAAK,sBAAsB,KAAK,iBAAiB,UAAU,MAAM;AAC/D,aAAK,sBAAsB,MAAM;AACjC,aAAK,oBAAoB,MAAM;AAC/B,aAAK,2BAA2B;AAChC,aAAK,oBAAoB;AACzB,aAAK,uBAAuB;AAC5B,aAAK,6BAA6B;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,UAAgB;AACd,SAAK,oBAAoB,MAAM,IAAI,aAAa,gCAAgC,YAAY,CAAC;AAK7F,eAAW,UAAU,KAAK,oBAAoB,OAAO,EAAG,QAAO,QAAQ;AACvE,SAAK,oBAAoB,MAAM;AAI/B,SAAK,sBAAsB;AAC3B,SAAK,sBAAsB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAe;AACb,QAAI,CAAC,KAAK,KAAM;AAChB,SAAK,gBAAgB;AACrB,SAAK,eAAe,MAAM,IAAI,aAAa,qBAAqB,YAAY,CAAC;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAkB;AACxB,SAAK,gBAAgB;AACrB,SAAK,iBAAiB,IAAI,gBAAgB;AAC1C,UAAM,YAAY,KAAK,oBAAoB;AAC3C,QAAI,UAAU,SAAS;AACrB,WAAK,eAAe,MAAM,UAAU,MAAM;AAC1C,WAAK,0BAA0B;AAC/B;AAAA,IACF;AACA,UAAM,YAAY,MAAM,KAAK,eAAe,MAAM,UAAU,MAAM;AAClE,cAAU,iBAAiB,SAAS,WAAW,EAAE,MAAM,KAAK,CAAC;AAC7D,SAAK,0BAA0B,MAAM,UAAU,oBAAoB,SAAS,SAAS;AAAA,EACvF;AAAA;AAAA,EAGQ,UAAgB;AACtB,SAAK,0BAA0B;AAC/B,SAAK,0BAA0B;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBAAwC;AAC9C,QAAI,KAAK,eAAe;AACtB,MAAAC,QAAO,KAAK,oCAAoC;AAChD,WAAK,gBAAgB,EAAE,MAAM,gBAAgB,SAAS,WAAW,CAAC;AAAA,IACpE,OAAO;AACL,MAAAA,QAAO,KAAK,4CAA4C;AAAA,IAC1D;AACA,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,SACN,eACA,QACA,iBACkB;AAClB,QAAI,CAAC,cAAe,QAAO,EAAE,QAAQ,OAAO;AAG5C,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BQ,sBAAsB,MAGnB;AAIT,QAAI,KAAK,kCAAkC,KAAM,QAAO,KAAK;AAQ7D,QAAI,MAAM,yBAAyB,KAAM,QAAO;AAKhD,UAAM,UAAU,MAAM,cAClB,GAAG,KAAK,WAAW,sBACnB;AACJ,WAAO,kBAAkB,OAAO;AAAA,EAClC;AAAA,EAEA,sBACE,GACA,oBACkB;AAClB,QAAI,mBAAoB,MAAK,gBAAgB,kBAAkB;AAC/D,SAAK,0BAA0B;AAC/B,IAAAA,QAAO,MAAM,mCAAmC,CAAC;AACjD,oBAAgB,KAAK,YAAY,oBAAoB;AAAA,MACnD,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOf,QACE,kBAAkB,EAAE,WAAW,KAC/B,kBAAkB,EAAE,YAAY,KAChC,KAAK;AAAA,MACP,WAAW,EAAE;AAAA,MACb,UAAU,EAAE;AAAA,MACZ,YAAY,KAAK;AAAA,IACnB,CAAC;AACD,SAAK,gBAAgB,EAAE,MAAM,aAAa,SAAS,KAAK,sBAAsB,CAAC,EAAE,CAAC;AAClF,WAAO,KAAK,SAAS,oBAAoB,eAAe,CAAC,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,wBAAgC;AACtC,WAAO,KAAK,kCAAkC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,sBAAsB,GAA2C;AACvE,UAAM,SAAS,wBAAwB,CAAC;AACxC,SAAK,0BAA0B;AAC/B,SAAK,wBAAwB;AAC7B,IAAAA,QAAO,MAAM,4CAA4C,CAAC;AAC1D,oBAAgB,KAAK,YAAY,oBAAoB;AAAA,MACnD,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,QAAQ,kBAAkB,EAAE,WAAW,KAAK,KAAK;AAAA,MACjD,MAAM,EAAE;AAAA,MACR,gBAAgB,EAAE;AAAA,MAClB,cAAc,EAAE;AAAA,MAChB,YAAY,KAAK;AAAA,IACnB,CAAC;AACD,SAAK,gBAAgB,EAAE,MAAM,aAAa,SAAS,KAAK,sBAAsB,EAAE,CAAC;AACjF,WAAO,KAAK,SAAS,oBAAoB,QAAW,MAAM;AAAA,EAC5D;AAAA;AAAA,EAGA,OAAe,gBAAgB,QAAyD;AACtF,WAAO,OAAO,WAAW,SAAS,OAAO,gBAAgB;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,cAAc,QAMR;AACZ,UAAM,gBAAgB,YAAW,gBAAgB,MAAM;AACvD,QAAI,CAAC,cAAe,QAAO;AAC3B,QAAI,kBAAkB,oBAAoB;AACxC,aAAO,EAAE,cAAc;AAAA,IACzB;AAKA,UAAM,SAAS,OAAO,WAAW,SAAS,OAAO,SAAS;AAU1D,UAAM,SACJ,QAAQ,WAAW,KAAK,wBAAwB,SAAY,KAAK;AACnE,WAAO;AAAA,MACL;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,QAA2B;AAKpC,QAAI,OAAO,SAAS,KAAK,gBAAiB,MAAK,qBAAqB;AACpE,SAAK,eAAe,OAAO;AAC3B,QAAI,OAAO,OAAO,oBAAoB,YAAY;AAChD,WAAK,yBAAyB,OAAO;AAGrC,WAAK,kBAAkB,CAAC;AAAA,IAC1B,OAAO;AACL,WAAK,yBAAyB;AAC9B,WAAK,kBAAkB,OAAO,mBAAmB,CAAC;AAAA,IACpD;AACA,QAAI,OAAO,OAAO,iBAAiB,YAAY;AAC7C,WAAK,sBAAsB,OAAO;AAGlC,WAAK,eAAe,CAAC;AAAA,IACvB,OAAO;AACL,WAAK,sBAAsB;AAC3B,WAAK,eAAe,OAAO,gBAAgB,CAAC;AAAA,IAC9C;AACA,SAAK,gBAAgB,OAAO;AAC5B,SAAK,kBAAkB,OAAO;AAC9B,SAAK,cAAc,OAAO;AAI1B,SAAK,mBACH,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc,OAAO;AACvE,SAAK,mBAAmB,OAAO;AAC/B,SAAK,eAAe,IAAI,KAAK,OAAO,aAAa,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5E,SAAK,sBAAsB,OAAO;AAClC,SAAK,yBAAyB,OAAO;AACrC,SAAK,wBAAwB,OAAO;AACpC,SAAK,yBAAyB,OAAO;AACrC,SAAK,4BAA4B,OAAO;AACxC,SAAK,yBAAyB,OAAO;AACrC,SAAK,4BAA4B,OAAO;AACxC,SAAK,kBAAkB,OAAO;AAC9B,SAAK,yBAAyB,OAAO;AACrC,SAAK,sBAAsB,MAAM;AACjC,SAAK,2BAA2B;AAIhC,QAAI,OAAO,OAAO,aAAa,UAAU;AACvC,WAAK,sBAAsB,OAAO,UAAU,OAAO,IAAI;AAAA,IACzD;AAEA,SAAK,YAAY,CAAC;AAClB,SAAK,qBAAqB;AAI1B,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,6BACZ,UACA,MACA,UACiB;AACjB,QAAI,OAAO,KAAK,2BAA2B,YAAY;AACrD,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,uBAAuB;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,gBAAgB,OAAO,KAAK,KAAK,YAAY;AAAA,MAC/C,CAAC;AACD,aAAO,OAAO,WAAW,YAAY,OAAO,KAAK,EAAE,SAAS,IAAI,SAAS;AAAA,IAC3E,SAAS,GAAG;AACV,MAAAA,QAAO;AAAA,QACL,2CAA2C,QAAQ;AAAA,QACnD;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAgC;AAC9B,WAAO,KAAK,4BAA4B,KAAK,iBAAiB,YAAY;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBAAsB,MAAc,WAA+B;AACzE,UAAM,SAAS,KAAK,sBAAsB,IAAI,IAAI;AAClD,QAAI,OAAQ,QAAO;AACnB,UAAM,WAAW,oBAAoB,KAAK,kBAAkB,MAAM,SAAS;AAC3E,SAAK,sBAAsB,IAAI,MAAM,QAAQ;AAC7C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,uBAAuB,KAA+C;AAClF,QAAI;AACJ,QAAI;AACJ,QAAI,KAAK,wBAAwB,QAAW;AAC1C,iBAAW,KAAK,iBAAiB,QAAQ;AACzC,qBAAe,KAAK,iBAAiB,YAAY;AAAA,IACnD,OAAO;AACL,YAAM,OACJ,OAAO,KAAK,wBAAwB,aAChC,MAAM,KAAK,oBAAoB,GAAG,IAClC,KAAK;AACX,iBAAW,KAAK,sBAAsB,MAAM,KAAK,mBAAmB,WAAW;AAC/E,qBAAe;AAAA,IACjB;AACA,SAAK,2BAA2B;AAChC,UAAM,SAAS,MAAM,KAAK,yBAAyB,cAAc,QAAQ;AACzE,SAAK,oBAAoB,OAAO;AAChC,SAAK,uBAAuB,OAAO;AACnC,QAAI,iBAAiB,KAAK,4BAA4B;AACpD,WAAK,6BAA6B;AAClC,sBAAgB,KAAK,YAAY,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMpD,UAAU;AAAA,QACV,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,OAAO,KAAK;AAAA,MACd,CAAC;AACD,WAAK;AAAA,QACH,IAAI,YAA8B,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,EAAE,CAAC;AAAA,MAC1F;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,yBACZ,MACA,UACwD;AACxD,QAAI,KAAK,oBAAoB,IAAI,IAAI,EAAG,QAAO,KAAK,oBAAoB,IAAI,IAAI;AAChF,QAAI,SAAwD,CAAC;AAC7D,QAAI;AACF,YAAM,WAAW,MAAM,SAAS,YAAY;AAC5C,UAAI,UAAU;AACZ,iBAAS,EAAE,OAAO,SAAS,OAAO,UAAU,SAAS,SAAS;AAAA,MAChE;AAAA,IACF,QAAQ;AACN,eAAS,CAAC;AAAA,IACZ;AACA,SAAK,oBAAoB,IAAI,MAAM,MAAM;AACzC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,iBACZ,OACA,KACwB;AACxB,QAAI,UAAU,OAAW,QAAO;AAChC,WAAO,OAAO,UAAU,aACnB,MAAuD,GAAG,IAC3D;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAyD;AACvD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAuB;AACrB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAMc;AACZ,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,aACN,QACA,QACA,iBACM;AACN,QAAI,CAAC,KAAK,cAAc,KAAK,gBAAiB;AAG9C,SAAK,kBAAkB;AAAA,MACrB;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,2BAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAgD;AAC9C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,yBAAyD;AACvD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,yBAAyB,gBAAmD;AAClF,QAAI,eAAe,WAAW,EAAG;AAGjC,UAAM,aAAa,KAAK,IAAI,GAAG,KAAK,kBAAkB,CAAC;AACvD,UAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAI,SAAS;AACb,eAAW,QAAQ,gBAAgB;AACjC,UAAI;AACJ,UAAI,CAAC,KAAK,UAAU,SAAS,GAAG,GAAG;AAEjC,kBAAU;AACV,oBAAY,GAAG,UAAU,IAAI,MAAM;AACnC,qBAAa,IAAI,KAAK,WAAW,SAAS;AAAA,MAC5C,OAAO;AAEL,cAAM,CAAC,MAAM,GAAG,IAAI,IAAI,KAAK,UAAU,MAAM,GAAG;AAChD,cAAM,YAAY,aAAa,IAAI,IAAI,KAAK,GAAG,UAAU,IAAI,IAAI;AACjE,oBAAY,CAAC,WAAW,GAAG,IAAI,EAAE,KAAK,GAAG;AAAA,MAC3C;AACA,WAAK,cAAc,KAAK,EAAE,GAAG,MAAM,UAAU,CAAC;AAAA,IAChD;AACA,WAAO,KAAK,cAAc,SAAS,KAAK,kBAAkB;AACxD,WAAK,cAAc,MAAM;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,mBACN,sBACA,aACA,YACA,aACc;AACd,QAAI;AACJ,QAAI,KAAK,kBAAkB;AACzB,UAAI;AACF,wBAAgB,KAAK,iBAAiB;AAAA,MACxC,SAAS,GAAG;AAIV,wBAAgB,4BAA4B,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,MACxF;AAAA,IACF;AACA,UAAM,YAAY,OAAO,KAAK,eAAe;AAC7C,SAAK,mBAAmB;AACxB,UAAM,WAAyB;AAAA,MAC7B;AAAA,MACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,WAAW,KAAK;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,cAAc;AAAA,MACd;AAAA,MACA,WAAW,KAAK,gBAAgB,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,cAAc,KAAK,QAAQ;AAChC,QAAI,KAAK,cAAc,SAAS,KAAK,kBAAkB;AACrD,WAAK,cAAc,MAAM;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,4BAA4B,WAA6D;AACvF,SAAK,2BAA2B;AAAA,EAClC;AAAA,EAEA,aAAyC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAwC;AACtC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,qBAA+B;AAC7B,WAAO,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,EAC7C;AAAA,EAEA,MAAM,eACJ,SACAC,SACA,OACA,cACmB;AAInB,UAAM,kBAAkB,KAAK,iBAAiB,QAAQ;AACtD,QAAI,CAAC,gBAAgB,QAAQ;AAC3B,MAAAD,QAAO,KAAK,6DAA6D;AACzE,aAAO,CAAC;AAAA,IACV;AAEA,QAAI,eAAe;AACnB,QAAI,cAAc;AAElB,QAAI,cAAc,QAAQ;AACxB,YAAM,oBAAoB,aACvB,IAAI,CAAC,UAAU;AACd,cAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACtD,eAAO,KAAK,MAAM,IAAI,KAAK,MAAM,WAAW,MAAM,QAAQ,WAAW,KAAK,MAAM,UAAU;AAAA,MAC5F,CAAC,EACA,KAAK,IAAI;AACZ,qBAAe;AAAA,EAAkD,iBAAiB;AAElF,YAAM,eAAe,aAClB,QAAQ,CAAC,UAAU,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EACjD,OAAO,CAAC,OAAO,OAAO,SAAS,KAAK,QAAQ,KAAK,MAAM,KAAK,EAC5D,KAAK,IAAI;AACZ,oBAAc,eACV,6DAA6D,YAAY,MACzE;AAAA,IACN,WAAW,KAAK,iBAAiB;AAC/B,YAAM,YAAY,KAAK,gBAAgB,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,IAAI;AACzE,qBAAe,oCAAoC,KAAK,eAAe;AACvE,oBAAc,YAAY,2CAA2C,SAAS,MAAM;AAAA,IACtF;AAQA,UAAM,eACJ;AAGF,UAAM,oBACJ,gBAAgB,cACZ;AAAA;AAAA;AAAA,EAAuB,CAAC,cAAc,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA,iHAC7E;AAEN,UAAM,gBAAgBC,UAAS;AAAA;AAAA,wBAA6BA,OAAM,MAAM;AAExE,QAAI;AACJ,QAAI,QAAQ,WAAW,GAAG;AACxB,oBACE,oBAAoB,KAAK,0QAEzB,oBACA,gBACA;AAAA;AAAA;AAAA,YACa,KAAK;AAAA;AAAA;AAAA;AAAA,IAItB,OAAO;AACL,YAAM,sBAAsB,QACzB;AAAA,QACC,CAAC,OACE,EAAE,SAAS,UAAU,EAAE,SAAS,gBACjC,CAAC,EAAE,WAAW,UACd,CAAC,EAAE,YACH,CAAC,CAAC,EAAE,SAAS,KAAK;AAAA,MACtB,EACC,MAAM,CAAC,0BAA0B,EACjC,IAAI,CAAC,MAAM,GAAG,EAAE,SAAS,SAAS,SAAS,WAAW,KAAK,EAAE,OAAO,EAAE,EACtE,KAAK,IAAI;AAEZ,oBACE;AAAA,EAA2B,mBAAmB;AAAA;AAAA;AAAA,qGAE1B,KAAK,kHACZ,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC,oJAEnC,oBACA,gBACA;AAAA;AAAA;AAAA,YACa,KAAK;AAAA;AAAA;AAAA;AAAA,IAItB;AAEA,UAAM,OAAO,MAAM,gBAAgB,OAAQ,aAAa,EAAE,aAAa,CAAC;AAIxE,WACE,KACG,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAEnB,IAAI,CAAC,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC,EAE/C,IAAI,CAAC,MAAM,EAAE,QAAQ,0BAA0B,EAAE,EAAE,KAAK,CAAC,EAEzD,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,OAAO,CAAC,MAAM,CAAC,aAAa,KAAK,CAAC,CAAC,EACnC,OAAO,CAAC,MAAM,CAAC,mBAAmB,KAAK,CAAC,CAAC,EACzC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,CAAC,EAC9B,MAAM,GAAG,KAAK;AAAA,EAErB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAsB;AACpB,WAAO,kBAAkB,KAAK,OAAO,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,UAAuC;AAC3C,QAAI,KAAK,KAAM,QAAO;AACtB,UAAM,kBAAkB,KAAK,iBAAiB,QAAQ;AACtD,QAAI,CAAC,gBAAgB,QAAQ;AAC3B,MAAAD,QAAO,KAAK,iEAAiE;AAC7E,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,KAAK;AACrB,UAAM,MAAM,kBAAkB,OAAO;AACrC,QAAI,OAAO,KAAM,QAAO;AAExB,UAAM,YAAY,QAAQ,MAAM,GAAG,GAAG;AACtC,UAAM,OAAO,QAAQ,MAAM,GAAG;AAI9B,UAAM,EAAE,cAAc,YAAY,IAAI,6BAA6B,SAAS;AAI5E,UAAM,cACJ;AACF,QAAI;AACJ,QAAI;AACF,qBAAe,MAAM,gBAAgB,OAAQ,aAAa,EAAE,aAAa,CAAC,IAAI,KAAK,KAAK;AAAA,IAC1F,SAAS,GAAG;AACV,MAAAA,QAAO,KAAK,0CAA0C,aAAa,QAAQ,EAAE,UAAU,CAAC,EAAE;AAC1F,WAAK,gBAAgB,EAAE,MAAM,aAAa,SAAS,YAAY,CAAC;AAChE,aAAO;AAAA,IACT;AACA,QAAI,CAAC,aAAa;AAChB,MAAAA,QAAO,KAAK,qEAAqE;AACjF,WAAK,gBAAgB,EAAE,MAAM,aAAa,SAAS,YAAY,CAAC;AAChE,aAAO;AAAA,IACT;AAEA,QAAI;AACJ,aAAS,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC/C,UAAI,QAAQ,CAAC,EAAE,eAAe,MAAM;AAClC,uBAAe,QAAQ,CAAC,EAAE;AAC1B;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,MAAM,gBAAgB,YAAY;AACjD,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,UAAM,iBAA8B;AAAA,MAClC,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAKT,WAAW,UAAU,CAAC,GAAG,aAAa;AAAA,MACtC,YAAY;AAAA,QACV,gBAAgB,UAAU;AAAA,QAC1B,yBAAyB,UAAU,UAAU,SAAS,CAAC,GAAG;AAAA,QAC1D;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,eAAe,SAAS,SAAS;AAAA,MACnC;AAAA,IACF;AAEA,SAAK,YAAY,CAAC,gBAAgB,GAAG,IAAI,CAAC;AAC1C,WAAO;AAAA,EACT;AAAA,EAEA,SAAkB;AAChB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,4BACL,IACM;AACN,SAAK,2BAA2B;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAa,mBACX,eACA,MACA,SACY;AACZ,QAAI,KAAK,0BAA0B;AACjC,aAAO,KAAK,yBAA4B,eAAe,MAAM,OAAO;AAAA,IACtE;AACA,QAAI,KAAK,oBAAoB,OAAO,GAAG;AACrC,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AACA,UAAM,gBAAgB,OAAO,WAAW;AACxC,UAAM,2BAA2B,SAAS;AAC1C,UAAM,YAAY,SAAS;AAC3B,UAAM,eAAe,SAAS;AAC9B,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAK,oBAAoB,IAAI,eAAe;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,YAAY,2BAA2B,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKvD,eACE,aAAa,OACT,WAAW,MAAM;AACf,eAAK,mBAAmB,eAAe;AAAA,YACrC,QAAQ;AAAA,YACR,SAAS,+BAA+B,SAAS;AAAA,UACnD,CAA6B;AAAA,QAC/B,GAAG,SAAS,IACZ;AAAA,MACR,CAAC;AACD,sBAAgB,KAAK,YAAY,yBAAyB;AAAA,QACxD;AAAA,QACA,WAAW;AAAA,QACX,OAAO,KAAK;AAAA,MACd,CAAC;AAKD,WAAK,YAAY,QAAQ,yBAAyB,MAAS;AAC3D,UAAI,0BAA0B;AAC5B,aAAK;AAAA,UACH,IAAI,YAAY,qBAAqB;AAAA,YACnC,QAAQ,EAAE,eAAe,yBAAyB;AAAA,UACpD,CAAC;AAAA,QACH;AAAA,MACF;AAGA,WAAK,oBAAoB,IAAI,eAAe,yBAAyB,aAAa,CAAC;AACnF,WAAK,gBAAgB;AAAA,QACnB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBAAmB,eAAuB,QAAmB;AAClE,UAAM,cAAc,KAAK,oBAAoB,IAAI,aAAa;AAC9D,QAAI,aAAa;AAGf,UAAI,YAAY,cAAe,cAAa,YAAY,aAAa;AAuBrE,YAAM,uBAAwB,QAC1B;AACJ,UAAI,MAAM,QAAQ,oBAAoB,KAAK,qBAAqB,QAAQ;AACtE,cAAM,QAAS,KAAK,8BAA8B;AAClD,cAAM,iBAA8B,CAAC;AACrC,YAAI,YAAY;AAChB,YAAI,eAAe;AACnB,mBAAW,OAAO,sBAAsB;AAItC,cACE,CAAC,OACD,OAAO,QAAQ,YACf,OAAQ,IAA2B,SAAS,UAC5C;AACA;AAAA,UACF;AACA,gBAAM,QAAQ;AACd,cAAI,MAAM,SAAS,SAAS;AAC1B,kBAAM,EAAE,MAAM,OAAO,GAAG,MAAM,IAAI;AAClC,2BAAe,KAAK,KAA6B;AAAA,UACnD,WAAW,MAAM,SAAS,QAAQ;AAMhC,iBAAK,oBAAoB,KAAK;AAAA,cAC5B,GAAG;AAAA,cACH,WAAW,qBAAqB,KAAK,IAAI,SAAS;AAAA,YACpD,CAAC;AACD,yBAAa;AAAA,UACf,WAAW,MAAM,SAAS,WAAW;AACnC,4BAAgB;AAChB,iBAAK,oBAAoB,KAAK,KAAK;AAAA,UACrC;AAAA,QAMF;AACA,YAAI,eAAe,OAAQ,iBAAgB,KAAK,YAAY,cAAc;AAO1E,wBAAgB,KAAK,YAAY,+BAA+B;AAAA,UAC9D;AAAA,UACA;AAAA,UACA,QAAQ,EAAE,MAAM,WAAW,OAAO,eAAe,QAAQ,SAAS,aAAa;AAAA,QACjF,CAAC;AAAA,MACH;AACA,YAAM,MAAM,KAAK,QAAQ,UAAU,CAAC,MAAM,EAAE,aAAa,kBAAkB,aAAa;AACxF,UAAI,QAAQ,IAAI;AAId,cAAM,UACJ,OAAO,QAAQ,YAAY,YAC3B,OAAO,SAAS,OAAO,OAAO,KAC9B,OAAO,UAAU,IACb,OAAO,UACP;AACN,aAAK,QAAQ,GAAG,IAAI;AAAA,UAClB,GAAG,KAAK,QAAQ,GAAG;AAAA,UACnB,aAAa,EAAE,GAAG,KAAK,QAAQ,GAAG,EAAE,aAAc,UAAU,OAAO;AAAA,UACnE,GAAI,WAAW,OACX,EAAE,kBAAkB,KAAK,QAAQ,GAAG,EAAE,mBAAmB,KAAK,QAAQ,IACtE,CAAC;AAAA,QACP;AACA,aAAK;AAAA,UACH,IAAI,YAAwC,mBAAmB;AAAA,YAC7D,QAAQ,KAAK;AAAA,UACf,CAAC;AAAA,QACH;AAAA,MACF;AAQA,UAAI,OAAO,QAAQ,gBAAgB,YAAY,OAAO,YAAY,KAAK,GAAG;AACxE,aAAK,gBAAgB,EAAE,MAAM,kBAAkB,SAAS,OAAO,YAAY,CAAC;AAAA,MAC9E;AACA,UAAI,YAAY,YAAY;AAC1B,aAAK,cAAc,IAAI,YAAY,oBAAoB,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;AAAA,MACvF;AACA,sBAAgB,KAAK,YAAY,wBAAwB,EAAE,cAAc,CAAC;AAI1E,WAAK,YAAY,QAAQ,wBAAwB,MAAS;AAC1D,kBAAY,QAAQ,MAAM;AAC1B,WAAK,oBAAoB,OAAO,aAAa;AAG7C,WAAK,oBAAoB,IAAI,aAAa,GAAG,QAAQ;AACrD,WAAK,oBAAoB,OAAO,aAAa;AAAA,IAC/C,OAAO;AACL,MAAAA,QAAO,KAAK,uBAAuB,aAAa,aAAa;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,sBAAsB,eAAuD;AAClF,WAAO,KAAK,oBAAoB,IAAI,aAAa,GAAG;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,0BAA0B,SAAuB;AACvD,eAAW,iBAAiB,CAAC,GAAG,KAAK,oBAAoB,KAAK,CAAC,GAAG;AAChE,WAAK,mBAAmB,eAAe;AAAA,QACrC,QAAQ;AAAA,QACR;AAAA,MACF,CAA6B;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,YAAY,UAA+B;AAChD,SAAK,UAAU,CAAC,GAAG,QAAQ;AAC3B,SAAK;AAAA,MACH,IAAI,YAAwC,mBAAmB;AAAA,QAC7D,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,WAAmB,aAA2D;AAC9F,QAAI,KAAK,QAAS,CAAC,UAAU,KAAK,KAAK,CAAC,aAAa,OAAS,QAAO,EAAE,QAAQ,OAAO;AAEtF,SAAK,OAAO;AACZ,SAAK,UAAU;AAGf,SAAK,WAAW;AAChB,SAAK,qBAAqB;AAC1B,SAAK,kBAAkB;AACvB,SAAK,wBAAwB;AAC7B,SAAK,0BAA0B;AAC/B,SAAK,mBAAmB;AACxB,SAAK,wBAAwB;AAC7B,SAAK,0BAA0B;AAC/B,SAAK,wBAAwB;AAC7B,SAAK,gBAAgB,EAAE,MAAM,QAAQ,SAAS,WAAW,YAAY,CAAC;AACtE,SAAK,gBAAgB,KAAK,IAAI;AAC9B,oBAAgB,KAAK,YAAY,cAAc;AAAA,MAC7C,OAAO;AAAA,MACP,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,YAAY,QAAQ,mBAAmB,MAAS;AAGrD,QAAI,SAA2B,EAAE,QAAQ,OAAO;AAChD,QAAI;AACF,eAAS,MAAM,KAAK,YAAY,WAAW,WAAW;AACtD,aAAO;AAAA,IACT,SAAS,GAAG;AACV,MAAAA,QAAO,MAAM,qBAAqB,CAAC;AACnC,sBAAgB,KAAK,YAAY,aAAa;AAAA,QAC5C,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,MAAM,aAAa,QAAQ,EAAE,OAAO;AAAA,QACpC,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MACpD,CAAC;AACD,WAAK,gBAAgB;AAAA,QACnB,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AACD,eAAS,KAAK,SAAS,WAAW;AAClC,aAAO;AAAA,IACT,UAAE;AACA,sBAAgB,KAAK,YAAY,YAAY;AAAA,QAC3C,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK,IAAI,IAAI,KAAK;AAAA,MAChC,CAAC;AACD,WAAK,OAAO;AACZ,WAAK,QAAQ;AACb,WAAK,YAAY,QAAQ,iBAAiB,KAAK,cAAc,MAAM,CAAC;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BQ,oBACN,kBACA,cACA;AACA,WAAO;AAAA,MACL,oBAAoB,CAClB,eACA,MACA,YACe,KAAK,mBAAmB,eAAe,MAAM,OAAO;AAAA,MACrE,GAAI,KAAK,aAAa,OAAO,KAAK;AAAA,QAChC,iBAAiB,CACf,MACA,YAKA,KAAK,eAAkB,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,MAAM;AAIjE,cAAI,gBAAgB,MAAO,cAAa,OAAO,KAAK,KAAK;AACzD,iBAAO;AAAA,QACT,CAAC;AAAA,MACL;AAAA,MACA,kBAAkB,CAAC,WAA0B;AAC3C,YAAI,KAAK,oBAAoB;AAC3B,UAAAA,QAAO;AAAA,YACL,cAAc,KAAK,mBAAmB,SAAS;AAAA,UACjD;AACA;AAAA,QACF;AACA,aAAK,qBAAqB,EAAE,OAAO;AAGnC,aAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,cAAc,MAAY;AACxB,YAAI,KAAK,uBAAuB;AAC9B,UAAAA,QAAO;AAAA,YACL,cAAc,KAAK,mBAAmB,SAAS;AAAA,UACjD;AACA;AAAA,QACF;AACA,aAAK,wBAAwB;AAG7B,aAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,UAAU,MAAY;AAKpB,aAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,cAAc,CAAC,WAAiC;AAE9C,YAAI,CAAC,iBAAkB;AACvB,YAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,UAAU;AACtC,UAAAA,QAAO;AAAA,YACL,cAAc,KAAK,mBAAmB,SAAS;AAAA,UACjD;AACA;AAAA,QACF;AACA,cAAM,WAAW,MAAM,QAAQ,OAAO,EAAE,IAAI,OAAO,KAAK,CAAC,OAAO,EAAE;AAClE,cAAM,eAAe,CAAC,MACpB,GAAG,SAAS,eACR,OAAO,EAAE,OAAO,YAAY,EAAE,GAAG,SAAS,IAC1C,GAAG,SAAS,QACV,OAAO,EAAE,UAAU,YAAY,EAAE,SAAS,IAC1C,GAAG,SAAS,aAAa,GAAG,SAAS,cAAc,GAAG,SAAS;AACvE,YAAI,SAAS,WAAW,KAAK,CAAC,SAAS,MAAM,YAAY,GAAG;AAC1D,UAAAA,QAAO;AAAA,YACL,cAAc,KAAK,mBAAmB,SAAS;AAAA,UACjD;AACA;AAAA,QACF;AAGA,YAAI,KAAK,iBAAiB,IAAI,gBAAgB,GAAG;AAC/C,UAAAA,QAAO;AAAA,YACL,cAAc,KAAK,mBAAmB,SAAS;AAAA,UACjD;AACA;AAAA,QACF;AAGA,aAAK,iBAAiB,IAAI,kBAAkB;AAAA,UAC1C;AAAA,UACA,WAAW,KAAK;AAAA,UAChB,MAAM,KAAK;AAAA,UACX,YAAY,KAAK;AAAA,UACjB,YAAY,KAAK;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,eACZ,MACA,SAQC;AACD,UAAM,YAAY,KAAK,aAAa,IAAI,IAAI;AAC5C,QAAI,CAAC,WAAW;AACd,YAAM,YAAY,CAAC,GAAG,KAAK,aAAa,KAAK,CAAC,EAAE,KAAK,IAAI,KAAK;AAC9D,YAAM,IAAI;AAAA,QACR,cAAc,IAAI,yBAAyB,KAAK,eAAe,iBAAiB,SAAS;AAAA,MAC3F;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,YAAY,SAAS,UAAU,IAAI,WAAW,CAAC;AAK7D,UAAM,UAAU,KAAK,QAAQ,KAAK,QAAQ,SAAS,CAAC;AACpD,UAAM,cACJ,SAAS,SAAS,eAAe,QAAQ,WAAW,SAChD,KAAK,QAAQ,MAAM,GAAG,EAAE,IACxB,KAAK;AAEX,UAAM,kBACJ,cAAc,OAAO,gBAAgB,aAAa,UAAU,IAAI,CAAC,GAAG,WAAW;AAEjF,UAAM,kBAAiC,UACnC,CAAC,EAAE,MAAM,QAAQ,SAAS,wBAAwB,KAAK,UAAU,OAAO,CAAC,GAAG,CAAC,IAC7E,CAAC;AAEL,UAAM,kBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAI,UAAU,iBAAiB,CAAC;AAAA,IAClC;AAMA,UAAM,eAAe,OAAO,WAAW;AACvC,UAAM,kBAAkB,GAAG,KAAK,UAAU,SAAS,YAAY;AAC/D,UAAM,QAAQ,IAAI,YAAW,KAAK,kBAAkB;AAAA,MAClD,YAAY;AAAA;AAAA;AAAA,MAGZ,aAAa,KAAK;AAAA,IACpB,CAAC;AAGD,UAAM,eAAe;AAIrB,UAAM,eAAe,MAAM,MAAM,QAAQ;AACzC,QAAI,KAAK,oBAAoB,OAAO,SAAS;AAC3C,mBAAa;AAAA,IACf,OAAO;AACL,WAAK,oBAAoB,OAAO,iBAAiB,SAAS,cAAc,EAAE,MAAM,KAAK,CAAC;AAAA,IACxF;AACA,UAAM,WAAW,EAAE,GAAG,WAAW,eAAe,gBAAgB,CAAC;AAKjE,UAAM;AAAA,MACJ,CAAI,eAAuB,MAAW,SACpC,KAAK,mBAAsB,eAAe,MAAM,IAAI;AAAA,IACxD;AAEA,UAAM,eAAe,CAAC,MAAa;AACjC,WAAK;AAAA,QACH,IAAI,YAAY,6BAA6B;AAAA,UAC3C,QAAQ,EAAE,WAAW,UAAU,MAAM,SAAU,EAAiC,OAAO;AAAA,QACzF,CAAC;AAAA,MACH;AAAA,IACF;AAKA,UAAM,yBAAyB,CAAC,MAAa;AAC3C,WAAK;AAAA,QACH,IAAI,YAAY,oBAAoB,EAAE,QAAS,EAAkB,OAAO,CAAC;AAAA,MAC3E;AAAA,IACF;AACA,UAAM,iBAAiB,mBAAmB,YAAY;AACtD,UAAM,iBAAiB,oBAAoB,sBAAsB;AAEjE,UAAM,2BAA2B,SAAS;AAC1C,UAAM,kBAAkB,EAAE,MAAM,cAAc,yBAAyB;AAEvE,SAAK,cAAc,IAAI,YAAY,mBAAmB,EAAE,QAAQ,gBAAgB,CAAC,CAAC;AAIlF,oBAAgB,KAAK,YAAY,oBAAoB,EAAE,OAAO,KAAK,CAAC;AACpE,QAAI,WAAW;AACf,UAAM,aAAa,MAAM,YAAY,QAAQ,EAAE;AAC/C,QAAI;AACF,UAAI,aAAa,MAAM;AACrB,cAAM;AAAA,MACR,OAAO;AAIL,YAAI;AACJ,YAAI;AACF,gBAAM,gBAAgB,IAAI,QAAmB,CAAC,mBAAmB;AAC/D,4BAAgB,WAAW,MAAM,eAAe,SAAS,GAAG,SAAS;AAAA,UACvE,CAAC;AACD,gBAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,YAChC,WAAW,KAAK,MAAM,MAAe;AAAA,YACrC;AAAA,UACF,CAAC;AACD,cAAI,WAAW,WAAW;AACxB,uBAAW;AACX,kBAAM,QAAQ;AAQd,iBAAK,0BAA0B,cAAc,IAAI,qBAAqB,SAAS,KAAK;AACpF,kBAAM,WAAW,MAAM,MAAM,MAAS;AAAA,UACxC;AAAA,QACF,UAAE;AAEA,cAAI,cAAe,cAAa,aAAa;AAAA,QAC/C;AAAA,MACF;AAAA,IACF,UAAE;AACA,WAAK,oBAAoB,OAAO,oBAAoB,SAAS,YAAY;AACzE,YAAM,oBAAoB,mBAAmB,YAAY;AACzD,YAAM,oBAAoB,oBAAoB,sBAAsB;AAOpE,YAAM,QAAQ;AACd,WAAK,cAAc,IAAI,YAAY,kBAAkB,EAAE,QAAQ,gBAAgB,CAAC,CAAC;AAOjF,WAAK,yBAAyB,MAAM,iBAAiB,CAAC;AAMtD,YAAM,aAAa,KAAK,mBAAmB;AAC3C,YAAM,YAAY,cAAc,eAAe,EAC5C,OAAO,CAAC,MAAM,0BAA0B,IAAI,EAAE,IAAI,CAAC,EACnD,IAAI,CAAC,MAAM;AACV,cAAM,WAAW,EAAE,QAAQ;AAC3B,eAAO,EAAE,GAAG,GAAG,QAAQ,EAAE,GAAG,EAAE,QAAQ,UAAU,GAAG,UAAU,WAAM,YAAY,IAAI,GAAG,EAAE;AAAA,MAC1F,CAAC;AACH,sBAAgB,KAAK,YAAY,SAAS;AAC1C,mBAAa,eAAe;AAAA,IAC9B;AAEA,UAAM,QAAQ,MAAM,WAAW;AAE/B,QAAI,UAAU;AAIZ,sBAAgB,KAAK,YAAY,mBAAmB,EAAE,OAAO,MAAM,QAAQ,UAAU,CAAC;AACtF,aAAO,EAAE,SAAS,EAAE,IAAI,OAAO,QAAQ,UAAU,GAAG,MAAM;AAAA,IAC5D;AAEA,UAAM,aAAa,MAAM,sBAAsB;AAE/C,QAAI,YAAY;AACd,sBAAgB,KAAK,YAAY,sBAAsB,EAAE,OAAO,KAAK,CAAC;AACtE,aAAO,EAAE,SAAS,EAAE,IAAI,MAAM,QAAQ,WAAW,OAAY,GAAG,MAAM;AAAA,IACxE;AAQA,UAAM,UAAU,MAAM,mBAAmB;AACzC,UAAM,SAAS,SAAS,UAAU;AAKlC,oBAAgB,KAAK,YAAY,mBAAmB,EAAE,OAAO,MAAM,OAAO,CAAC;AAkB3E,QAAI,WAAW,oBAAoB;AACjC,WAAK,0BAA0B;AAC/B,WAAK,wBAAwB;AAC7B,WAAK,qBAAqB,SAAS;AAAA,IACrC;AAWA,QAAI,WAAW,oBAAoB;AACjC,WAAK,0BAA0B;AAC/B,WAAK,0BAA0B,SAAS;AAAA,IAC1C;AACA,WAAO,EAAE,SAAS,EAAE,IAAI,OAAO,OAAO,GAAG,MAAM;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBAAoB,iBAA4D;AACpF,QAAI,KAAK,KAAM,QAAO,EAAE,QAAQ,OAAO;AAEvC,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,qBAAqB;AAC1B,SAAK,kBAAkB;AACvB,SAAK,0BAA0B;AAC/B,SAAK,mBAAmB;AACxB,SAAK,wBAAwB;AAC7B,SAAK,0BAA0B;AAC/B,SAAK,wBAAwB;AAC7B,SAAK,gBAAgB,KAAK,IAAI;AAC9B,oBAAgB,KAAK,YAAY,cAAc;AAAA,MAC7C,OAAO;AAAA,MACP,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,YAAY,QAAQ,mBAAmB,MAAS;AAErD,QAAI,SAA2B,EAAE,QAAQ,OAAO;AAChD,QAAI;AACF,eAAS,MAAM,KAAK,YAAY,IAAI,QAAW,eAAe;AAC9D,aAAO;AAAA,IACT,SAAS,GAAG;AACV,MAAAA,QAAO,MAAM,qBAAqB,CAAC;AACnC,sBAAgB,KAAK,YAAY,aAAa;AAAA,QAC5C,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,MAAM,aAAa,QAAQ,EAAE,OAAO;AAAA,QACpC,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MACpD,CAAC;AACD,WAAK,gBAAgB;AAAA,QACnB,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AACD,eAAS,KAAK,SAAS,WAAW;AAClC,aAAO;AAAA,IACT,UAAE;AACA,sBAAgB,KAAK,YAAY,YAAY;AAAA,QAC3C,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK,IAAI,IAAI,KAAK;AAAA,MAChC,CAAC;AACD,WAAK,OAAO;AACZ,WAAK,QAAQ;AACb,WAAK,YAAY,QAAQ,iBAAiB,KAAK,cAAc,MAAM,CAAC;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,QAAQ,UAAwC;AACtD,UAAM,UAAU,KAAK,aAAa,QAAQ;AAC1C,WAAO,UAAY,QAAgB,gBAAgB,IAA6B;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,UAAkB,UAA4C;AACvF,UAAM,SAAS,YAAY,KAAK;AAChC,eAAW,CAAC,EAAE,OAAO,KAAK,OAAO,QAAQ,MAAM,GAAG;AAChD,YAAM,OAAQ,QAAgB,gBAAgB;AAC9C,UAAI,CAAC,KAAM;AAEX,UAAI,KAAK,SAAS,QAAQ,EAAG,QAAO,KAAK;AAEzC,YAAM,SAAS,KAAK,mBAAmB,UAAU,KAAK,QAAQ;AAC9D,UAAI,OAAQ,QAAO,KAAK;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,eAAe,UAAiC;AACtD,QAAI,KAAK,UAAU,WAAW,EAAG,QAAO;AACxC,UAAM,SAAS,KAAK,UAAU,KAAK,CAAC,MAAM,EAAE,iBAAiB,QAAQ,CAAC;AACtE,WAAO,SAAS,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,EAAE,WAAW;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,MAAgB,UAAwB;AAC/D,UAAM,gBAAgB,SAAS,QAAQ;AACvC,UAAM,UAAgC,CAAC;AACvC,UAAM,cAAgC,CAAC;AAEvC,QAAI,CAAC,KAAK,WAAW;AAEnB,iBAAW,OAAO,KAAK,iBAAiB;AACtC,YAAI,IAAI,SAAS,SAAU,SAAQ,KAAK,GAAG;AAAA,MAC7C;AACA,iBAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,KAAK,YAAY,GAAG;AAC/D,YAAI,SAAS,SAAU,aAAY,IAAI,IAAI;AAAA,MAC7C;AAAA,IACF;AAGA,YAAQ,KAAK,GAAG,KAAK,KAAK;AAC1B,WAAO,OAAO,aAAa,KAAK,QAAQ;AAGxC,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,aAAa,aAAa,QAAQ;AAAA,MAClC,YAAY,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,IAC/C,CAAC;AACD,gBAAY,aAAa,IAAI,YAA6B,KAAK,UAAU;AAEzE,SAAK,kBAAkB;AACvB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAGQ,SACN,UACA,MACA,MACA,kBACiB;AAGjB,eAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,YAAM,eAAe,KAAK,SAAS,GAAG;AACtC,UAAI,cAAc;AAChB,QAAAA,QAAO,MAAM,uCAAuC,QAAQ,aAAQ,GAAG,GAAG;AAE1E,aAAK,cAAc,QAAQ;AAC3B,aAAK,iBAAiB,MAAM,QAAQ;AACpC,aAAK,qBAAqB;AAC1B,cAAM,YACJ,OAAO,KAAK,GAAG,MAAM,YAAY,KAAK,GAAG,MAAM,OAC1C,KAAK,GAAG,IACT,CAAC;AACP,eAAO,aAAa,WAAW,KAAK,oBAAoB,gBAAgB,CAAC,EAAE;AAAA,UAAK,CAAC,MAC/E,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAGA,SAAK,cAAc,QAAQ;AAC3B,SAAK,iBAAiB,MAAM,QAAQ;AAEpC,UAAM,iBAAiB,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACnD,UAAM,gBAAgB,SAAS,QAAQ;AACvC,QAAI,UAAU,gBAAgB,QAAQ,0BAA0B,CAAC,GAAG,gBAAgB,aAAa,EAAE,KAAK,IAAI,CAAC;AAC7G,QAAI,KAAK,WAAY,YAAW,WAAW,KAAK,UAAU;AAC1D,eAAW,SAAS,aAAa;AACjC,WAAO,QAAQ,QAAQ,OAAO;AAAA,EAChC;AAAA,EAEQ,cAAc,UAAwB;AAC5C,SAAK,UAAU,KAAK;AAAA,MAClB;AAAA,MACA,qBAAqB,CAAC,GAAG,KAAK,eAAe;AAAA,MAC7C,kBAAkB,EAAE,GAAG,KAAK,aAAa;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,YAAoB;AAC1B,UAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAI,CAAC,MAAO,QAAO;AAEnB,SAAK,kBAAkB,MAAM;AAC7B,SAAK,eAAe,MAAM;AAE1B,UAAM,YAAY,KAAK,gBAAgB,IAAI,CAAC,MAAM,EAAE,IAAI;AACxD,WAAO,gBAAgB,MAAM,QAAQ,0BAA0B,UAAU,KAAK,IAAI,CAAC;AAAA,EACrF;AAAA;AAAA,EAGQ,8BAAsC;AAE5C,UAAM,cAA0B,CAAC;AACjC,eAAW,WAAW,OAAO,OAAO,KAAK,YAAY,GAAG;AACtD,YAAM,OAAQ,QAAgB,gBAAgB;AAC9C,UAAI,KAAM,aAAY,KAAK,IAAI;AAAA,IACjC;AAEA,QAAI,YAAY,WAAW,KAAK,KAAK,UAAU,WAAW,EAAG,QAAO;AAEpE,UAAM,QAAkB,CAAC,wBAAwB;AACjD,UAAM;AAAA,MACJ;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,YAAM,UAAU,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC;AACxD,YAAM;AAAA,QACJ,iCAAiC,QAAQ,QAAQ,sBAAsB,QAAQ,QAAQ;AAAA,MACzF;AAAA,IACF;AAEA,eAAW,QAAQ,aAAa;AAC9B,YAAM,KAAK,UAAK,KAAK,IAAI,KAAK,KAAK,WAAW,EAAE;AAAA,IAClD;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,YACZ,WACA,aACA,iBAC2B;AAC3B,QAAI,CAAC,KAAK,cAAc;AACtB,MAAAA,QAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe;AACnB,QAAI,qBAAmD;AACvD,QAAI,aAAa;AACjB,QAAI,oBAAoB;AACxB,QAAI,wBAAwB;AAI5B,QAAI,yBAAyB;AAK7B,QAAI,eAAe,CAAC,CAAC;AAWrB,QAAI;AACJ,QAAI,uBAAuB;AAE3B,WAAO,aAAa,KAAK,mBAAmB;AAC1C,oBAAc;AAId,WAAK,gBAAgB;AAKrB,UAAI,KAAK,eAAe,OAAO,SAAS;AACtC,eAAO,KAAK,oBAAoB;AAAA,MAClC;AAgBA,UAAI,KAAK,yBAAyB;AAChC,QAAAA,QAAO,MAAM,sEAAiE;AAC9E,wBAAgB,KAAK,YAAY,oBAAoB;AAAA,UACnD,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf,MAAM,KAAK,uBAAuB;AAAA,UAClC,KAAK;AAAA,UACL,YAAY,KAAK;AAAA,QACnB,CAAC;AACD,YAAI,KAAK,YAAY;AAMnB,eAAK,aAAa,oBAAoB,QAAW,KAAK,qBAAqB;AAAA,QAC7E,OAAO;AACL,eAAK,gBAAgB,EAAE,MAAM,aAAa,SAAS,KAAK,sBAAsB,EAAE,CAAC;AAAA,QACnF;AACA,eAAO,KAAK,SAAS,oBAAoB,QAAW,KAAK,qBAAqB;AAAA,MAChF;AACA,UAAI,KAAK,yBAAyB;AAChC,QAAAA,QAAO,MAAM,uEAAkE;AAC/E,wBAAgB,KAAK,YAAY,oBAAoB;AAAA,UACnD,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAUf,QAAQ,KAAK,kBAAkB;AAAA,UAC/B,KAAK;AAAA,UACL,YAAY,KAAK;AAAA,QACnB,CAAC;AACD,YAAI,KAAK,YAAY;AACnB,eAAK,aAAa,oBAAoB,KAAK,gBAAgB;AAAA,QAC7D,OAAO;AAKL,eAAK,gBAAgB;AAAA,YACnB,MAAM;AAAA,YACN,SAAS,KAAK,sBAAsB,KAAK,gBAAgB;AAAA,UAC3D,CAAC;AAAA,QACH;AAIA,eAAO,KAAK,SAAS,oBAAoB,KAAK,gBAAgB;AAAA,MAChE;AAEA,YAAM,YAAiC;AAAA,QACrC,WAAW,KAAK,mBAAmB;AAAA,QACnC,SAAS,KAAK;AAAA,QACd,WAAW,aAAa;AAAA,QACxB,QAAQ,KAAK,eAAe;AAAA,MAC9B;AAcA,UAAI;AACF,YAAI,KAAK,wBAAwB;AAE/B,eAAK,kBAAkB,MAAM,KAAK,uBAAuB,SAAS;AAAA,QACpE;AACA,YAAI,KAAK,qBAAqB;AAE5B,eAAK,eAAe,MAAM,KAAK,oBAAoB,SAAS;AAAA,QAC9D;AAAA,MACF,SAAS,GAAG;AACV,kCAA0B;AAC1B,YAAI,yBAAyB,6BAA6B;AACxD,UAAAA,QAAO;AAAA,YACL,yDAAyD,sBAAsB,IAAI,2BAA2B;AAAA,UAChH;AACA,wBAAc;AACd;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAMA,iBAAW,OAAO,KAAK,gBAAiB,MAAK,kBAAkB,IAAI,IAAI,IAAI;AAE3E,YAAM,uBACJ,OAAO,KAAK,iBAAiB;AAAA;AAAA,QAEzB,MAAM,KAAK,aAAa,SAAS;AAAA,UACjC,KAAK;AAMX,UAAI,OAAO,KAAK,gBAAgB,YAAY;AAE1C,aAAK,mBAAmB,MAAM,KAAK,YAAY,SAAS;AAAA,MAC1D;AAMA,YAAM,aAAa,KAAK,4BAA4B;AACpD,YAAM,aACJ,oBAAoB,IAChB,iJACA,wBAAwB,IACtB,wJACA;AACR,YAAM,wBAAwB,GAAG,UAAU,GAAG,UAAU;AASxD,YAAM,SAAS,qBAAqB;AAAA,QAClC,GAAI,KAAK,iBAAiB,CAAC;AAAA,QAC3B,GAAI,mBAAmB,CAAC;AAAA,MAC1B,CAAC;AACD,YAAM,cAAc,eAAe,KAAK,QAAQ,MAAM,GAAG,EAAE,IAAI,KAAK;AACpE,qBAAe;AAMf,YAAM,mBAAmB;AAAA,QACvB,CAAC,GAAG,WAAW;AAAA,QACf,KAAK;AAAA,QACL;AAAA,UACE,WAAW,KAAK;AAAA,UAChB,MAAM,KAAK;AAAA;AAAA;AAAA,UAGX,iBAAiB,CAAC,eAAe,aAAa,KAAK;AAAA;AAAA;AAAA,UAGnD,YAAY,CAAC,eAAe,aAAa,KAAK;AAAA,UAC9C,YAAY,KAAK;AAAA,QACnB;AAAA,QACA,CAAC,WAAW,gBAAgB,KAAK,YAAY,qBAAqB,MAAM;AAAA,MAC1E;AACA,YAAM,oBAAoB,qBAAqB,gBAAgB;AAC/D,YAAM,qBAAqB,KAAK,2BAC5B,KAAK,yBAAyB,iBAAiB,IAC/C;AACJ,YAAM,iBAAiB,CAAC,GAAG,QAAQ,GAAG,kBAAkB;AAMxD,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA;AAAA,QAEE,MAAM,QAAQ,IAAI;AAAA,UAChB,KAAK,iBAAyB,KAAK,wBAAwB,SAAS;AAAA,UACpE,KAAK,iBAAiC,KAAK,uBAAuB,SAAS;AAAA,UAC3E,KAAK,iBAA8B,KAAK,wBAAwB,SAAS;AAAA,UACzE,KAAK,iBAAyB,KAAK,wBAAwB,SAAS;AAAA,UACpE,KAAK,iBAAqC,KAAK,2BAA2B,SAAS;AAAA;AAAA;AAAA,UAGnF,uBACI,QAAQ,QAAQ,MAAS,IACzB,KAAK;AAAA,YACH,KAAK;AAAA,YACL;AAAA,UACF;AAAA,QACN,CAAC;AAAA;AACH,UAAI,CAAC,sBAAsB;AACzB,+BAAuB;AACvB,+BAAuB;AAAA,MACzB;AAMA,YAAM,eAAe,wBAAwB;AAC7C,YAAM,WAAW,CAAC,qBAAqB,qBAAqB,EACzD,IAAI,CAAC,UAAU,QAAQ,IAAI,KAAK,CAAC,EACjC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EAChC,KAAK,MAAM;AACd,YAAM,cAAc,WAChB;AAAA,EAAsB,QAAQ;AAAA,sBAC9B;AAKJ,YAAM,sBAAsB,uBAAuB,KAAK,aAAa,aAAa;AAElF,YAAM,eAAe,KAAK;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAQA,YAAM,mBAAmB;AACzB,YAAM,qBAAqB;AAC3B,qBAAe;AACf,2BAAqB;AAErB,YAAM,UAA8B;AAAA,QAClC;AAAA;AAAA,QAEA,OAAO,KAAK,gBAAgB,SAAS,KAAK,kBAAkB;AAAA,QAC5D,aAAa;AAAA;AAAA;AAAA,QAGb,QAAQ,KAAK,eAAe;AAAA,QAC5B,YAAY;AAAA;AAAA;AAAA,QAGZ,aAAa;AAAA;AAAA;AAAA,QAGb,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMb,gBAAgB;AAAA;AAAA,QAEhB;AAAA;AAAA;AAAA,QAGA,gBAAgB;AAAA;AAAA;AAAA,QAGhB,WAAW,KAAK;AAAA,MAClB;AAMA,YAAM,iBAAiB,MAAM,KAAK,uBAAuB,SAAS;AASlE,UAAI,KAAK,6BAA6B,QAAW;AAC/C,qBAAa,eAAe,KAAK;AAAA,MACnC;AACA,UAAI,KAAK,yBAAyB;AAChC,qBAAa,WAAW,KAAK;AAC/B,UAAI,KAAK,sBAAsB,OAAW,cAAa,QAAQ,KAAK;AAEpE,UAAI;AACJ,UAAI;AAEF,mBAAW,MAAM,eAAe,KAAM,gBAAgB,kBAAkB,OAAO;AAAA,MACjF,SAAS,GAAG;AACV,YAAI,aAAa,4BAA4B;AAC3C,+BAAqB;AACrB,cAAI,oBAAoB,uBAAuB;AAC7C,YAAAA,QAAO;AAAA,cACL,kDAAkD,iBAAiB,IAAI,qBAAqB;AAAA,YAC9F;AACA,4BAAgB,KAAK,YAAY,2BAA2B;AAAA,cAC1D,OAAO,KAAK;AAAA,cACZ,UAAU,KAAK;AAAA,cACf,SAAS;AAAA,cACT,aAAa;AAAA,cACb,eAAe,EAAE;AAAA,YACnB,CAAC;AACD,0BAAc;AACd;AAAA,UACF;AACA,UAAAA,QAAO,MAAM,0DAA0D;AACvE,0BAAgB,KAAK,YAAY,2BAA2B;AAAA,YAC1D,OAAO,KAAK;AAAA,YACZ,UAAU,KAAK;AAAA,YACf,UAAU;AAAA,YACV,eAAe,EAAE;AAAA,YACjB,YAAY,KAAK;AAAA,UACnB,CAAC;AACD,cAAI,KAAK,YAAY;AAEnB,iBAAK,aAAa,qBAAqB;AAAA,UACzC,OAAO;AACL,iBAAK,gBAAgB;AAAA,cACnB,MAAM;AAAA,cACN,SACE;AAAA,YACJ,CAAC;AAAA,UACH;AACA,iBAAO,KAAK,SAAS,yBAAyB;AAAA,QAChD;AAOA,YAAI,aAAa,wBAAwB;AACvC,UAAAA,QAAO,MAAM,0DAA0D,CAAC;AACxE,0BAAgB,KAAK,YAAY,sBAAsB;AAAA,YACrD,OAAO,KAAK;AAAA,YACZ,UAAU,KAAK;AAAA,YACf,OAAO,EAAE;AAAA,YACT,WAAW,EAAE;AAAA,YACb,cAAc,EAAE;AAAA,YAChB,OAAO,EAAE;AAAA,YACT,YAAY,KAAK;AAAA,UACnB,CAAC;AACD,cAAI,KAAK,YAAY;AAEnB,iBAAK,aAAa,oBAAoB;AAAA,UACxC,OAAO;AACL,iBAAK,gBAAgB;AAAA,cACnB,MAAM;AAAA,cACN,SACE;AAAA,YACJ,CAAC;AAAA,UACH;AACA,iBAAO,KAAK,SAAS,oBAAoB;AAAA,QAC3C;AAiBA,YAAI,aAAa,sBAAsB;AACrC,cAAI,KAAK,YAAY;AACnB,YAAAA,QAAO,MAAM,4CAA4C,CAAC;AAC1D,4BAAgB,KAAK,YAAY,oBAAoB;AAAA,cACnD,OAAO,KAAK;AAAA,cACZ,UAAU,KAAK;AAAA,cACf,QAAQ,kBAAkB,EAAE,WAAW,KAAK,KAAK;AAAA,cACjD,MAAM,EAAE;AAAA,cACR,gBAAgB,EAAE;AAAA,cAClB,cAAc,EAAE;AAAA,cAChB,YAAY;AAAA,YACd,CAAC;AAKD,kBAAM,SAAS,wBAAwB,CAAC;AACxC,iBAAK,aAAa,oBAAoB,QAAW,MAAM;AACvD,mBAAO,KAAK,SAAS,oBAAoB,QAAW,MAAM;AAAA,UAC5D;AACA,iBAAO,KAAK,sBAAsB,CAAC;AAAA,QACrC;AACA,YAAI,aAAa,sBAAsB;AAIrC,eAAK,0BAA0B;AAC/B,eAAK,mBAAmB,eAAe,CAAC;AAOxC,eAAK,wBAAwB;AAC7B,cAAI,KAAK,YAAY;AACnB,YAAAA,QAAO,MAAM,mCAAmC,CAAC;AACjD,4BAAgB,KAAK,YAAY,oBAAoB;AAAA,cACnD,OAAO,KAAK;AAAA,cACZ,UAAU,KAAK;AAAA,cACf,QACE,kBAAkB,EAAE,WAAW,KAC/B,kBAAkB,EAAE,YAAY,KAChC,KAAK;AAAA,cACP,WAAW,EAAE;AAAA,cACb,UAAU,EAAE;AAAA,cACZ,YAAY;AAAA,YACd,CAAC;AAID,iBAAK,aAAa,oBAAoB,KAAK,gBAAgB;AAC3D,mBAAO,KAAK,SAAS,oBAAoB,KAAK,gBAAgB;AAAA,UAChE;AACA,iBAAO,KAAK,sBAAsB,CAAC;AAAA,QACrC;AAMA,YAAI,aAAa,gBAAgB,EAAE,SAAS,gBAAgB;AAC1D,UAAAA,QAAO,MAAM,iCAAiC,CAAC;AAC/C,0BAAgB,KAAK,YAAY,aAAa;AAAA,YAC5C,OAAO,KAAK;AAAA,YACZ,UAAU,KAAK;AAAA,YACf,MAAM,EAAE;AAAA,YACR,SAAS,EAAE;AAAA,YACX,YAAY,KAAK;AAAA,UACnB,CAAC;AACD,cAAI,KAAK,YAAY;AAEnB,iBAAK,aAAa,SAAS;AAAA,UAC7B,OAAO;AACL,iBAAK,gBAAgB;AAAA,cACnB,MAAM;AAAA,cACN,SACE;AAAA,YACJ,CAAC;AAAA,UACH;AAGA,iBAAO,KAAK,SAAS,WAAW;AAAA,QAClC;AAMA,YAAI,aAAa,gBAAgB,EAAE,SAAS,cAAc;AACxD,iBAAO,KAAK,oBAAoB;AAAA,QAClC;AAIA,kCAA0B;AAC1B,YAAI,yBAAyB,6BAA6B;AACxD,UAAAA,QAAO;AAAA,YACL,mDAAmD,sBAAsB,IAAI,2BAA2B;AAAA,UAC1G;AACA,wBAAc;AACd;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAmBA,UAAI,SAAS,UAAU,UAAa,KAAK,sBAAsB,QAAW;AACxE,iBAAS,QAAQ,KAAK;AAAA,MACxB;AACA,UAAI,KAAK,yBAAyB,OAAW,UAAS,WAAW,KAAK;AACtE,UAAI,KAAK,6BAA6B,QAAW;AAC/C,iBAAS,eAAe,KAAK;AAAA,MAC/B;AAOA,mBAAa,QAAQ,aAAa,QAAQ;AAM1C,UAAI,SAAS,UAAU,OAAW,cAAa,QAAQ,SAAS;AAEhE,YAAM,iBAAiB,SAAS,WAAW,SAAS,WAAW;AAC/D,YAAM,kBAAkB,CAAC,SAAS,SAAS,KAAK,KAAK,CAAC,SAAS,WAAW;AAO1E,YAAM,YAAY,SAAS,cAAc,iBAAiB;AAE1D,UAAI,iBAAiB;AACnB,iCAAyB;AACzB,YAAI,CAAC,aAAa,wBAAwB,4BAA4B;AACpE,UAAAA,QAAO;AAAA,YACL,+CAA+C,qBAAqB,IAAI,0BAA0B;AAAA,UACpG;AACA,0BAAgB,KAAK,YAAY,kBAAkB;AAAA,YACjD,OAAO,KAAK;AAAA,YACZ,UAAU,KAAK;AAAA,YACf,SAAS;AAAA,YACT,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,YAKb,GAAG,SAAS;AAAA,UACd,CAAC;AACD,wBAAc;AACd;AAAA,QACF;AACA,cAAME,iBAAgB,YAAY,YAAY;AAC9C,QAAAF,QAAO;AAAA,UACL,YACI,+EACA;AAAA,QACN;AACA,wBAAgB,KAAK,YAAYE,gBAAe;AAAA,UAC9C,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf,UAAU;AAAA,UACV,YAAY,KAAK;AAAA,UACjB,GAAG,SAAS;AAAA,QACd,CAAC;AACD,YAAI,KAAK,YAAY;AACnB,eAAK,aAAa,YAAY,YAAY,gBAAgB;AAAA,QAC5D,OAAO;AACL,eAAK,gBAAgB;AAAA,YACnB,MAAM;AAAA,YACN,SAAS,YACL,qFACA;AAAA,UACN,CAAC;AAAA,QACH;AACA,eAAO,KAAK,SAASA,cAAa;AAAA,MACpC,OAAO;AAmBL,cAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAC/B,cAAM,cAAc;AAAA,UAClB,MAAM;AAAA,UACN,iBAAiB;AAAA,UACjB,aAAa;AAAA,UACb,cAAc;AAAA,UACd,iBAAiB;AAAA,UACjB,kBAAkB;AAAA,QACpB;AACA,YAAI,WAAW;AACb,eAAK,gBAAgB;AAAA,YACnB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,SAAS;AAAA,YACT,WAAW;AAAA,YACX,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AACA,YAAI,gBAAgB;AAElB,eAAK,gBAAgB;AAAA,YACnB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,WAAW;AAAA,YACX,UAAU;AAAA,UACZ,CAAC;AACD,eAAK,gBAAgB,EAAE,GAAG,MAAM,SAAS,GAAG,CAAC;AAAA,QAC/C,OAAO;AAGL,eAAK,gBAAgB,IAAI;AAAA,QAC3B;AAAA,MACF;AAIA,8BAAwB;AACxB,0BAAoB;AACpB,+BAAyB;AAEzB,UAAI,CAAC,SAAS,WAAW,QAAQ;AAC/B;AAAA,MACF;AAEA,YAAM,CAAC,WAAW,WAAW,IAAI,SAAS,UAAU;AAAA,QAClD,CAAC,KAAK,OAAO;AACX,cAAI,GAAG,SAAS,0BAA2B,KAAI,CAAC,EAAE,KAAK,EAAE;AAAA,cACpD,KAAI,CAAC,EAAE,KAAK,EAAE;AACnB,iBAAO;AAAA,QACT;AAAA,QACA,CAAC,CAAC,GAAG,CAAC,CAAC;AAAA,MACT;AAEA,YAAM,eAAe,oBAAI,IAQvB;AACF,YAAM,iBAAiB,oBAAI,IAAY;AAGvC,YAAM,eAAe,oBAAI,IAAY;AACrC,UAAI,sBAAsB;AAC1B,UAAI,sBAAsB;AAE1B,UAAI,UAAU,SAAS,GAAG;AAExB,cAAM,QAAQ;AAAA,UACZ,UAAU,IAAI,OAAO,OAAO;AAE1B,kBAAM,OAAO,KAAK,QAAQ,GAAG,IAAI;AACjC,gBAAI,MAAM;AACR,mBAAK,sBAAsB;AAC3B,kBAAI,KAAK,qBAAqB,KAAK,mBAAmB;AACpD,gBAAAF,QAAO;AAAA,kBACL,qCAAqC,KAAK,iBAAiB;AAAA,gBAC7D;AACA,6BAAa,IAAI,GAAG,IAAI;AAAA,kBACtB,YAAY,GAAG;AAAA,kBACf,SAAS,oCAAoC,KAAK,kBAAkB;AAAA,gBACtE,CAAC;AACD;AAAA,cACF;AACA,oBAAM,UAAU,MAAM,KAAK,SAAS,GAAG,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE;AACjE,2BAAa,IAAI,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,QAAQ,CAAC;AAEtD,4BAAc;AACd;AAAA,YACF;AAGA,gBAAI,GAAG,KAAK,WAAW,QAAQ,KAAK,KAAK,UAAU,SAAS,GAAG;AAC7D,oBAAM,cAAc,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,EAAE;AAC9D,kBAAI,GAAG,SAAS,SAAS,WAAW,IAAI;AACtC,qBAAK,sBAAsB;AAC3B,oBAAI,KAAK,qBAAqB,KAAK,mBAAmB;AACpD,+BAAa,IAAI,GAAG,IAAI;AAAA,oBACtB,YAAY,GAAG;AAAA,oBACf,SAAS,oCAAoC,KAAK,kBAAkB;AAAA,kBACtE,CAAC;AACD;AAAA,gBACF;AACA,sBAAM,UAAU,KAAK,UAAU;AAC/B,6BAAa,IAAI,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,QAAQ,CAAC;AACtD,8BAAc;AACd;AAAA,cACF;AAAA,YACF;AAGA,kBAAM,UAAU,KAAK,aAAa,GAAG,IAAI;AACzC,gBAAI,CAAC,SAAS;AACZ,oBAAM,iBAAiB,KAAK,mBAAmB,GAAG,IAAI;AACtD,kBAAI,gBAAgB;AAClB,gBAAAA,QAAO;AAAA,kBACL,yCAAyC,GAAG,IAAI,6BAAwB,cAAc;AAAA,gBACxF;AACA,gCAAgB,KAAK,YAAY,mBAAmB;AAAA,kBAClD,MAAM,GAAG;AAAA,kBACT,OAAO,KAAK;AAAA,kBACZ,MAAM;AAAA,kBACN,MAAM;AAAA,gBACR,CAAC;AACD,6BAAa,IAAI,GAAG,IAAI;AAAA,kBACtB,YAAY,GAAG;AAAA,kBACf,SAAS,IAAI,GAAG,IAAI,kDAAkD,cAAc,gBAAgB,cAAc;AAAA,gBACpH,CAAC;AAED,8BAAc;AACd;AAAA,cACF;AAUA,kBAAI,KAAK,kBAAkB,IAAI,GAAG,IAAI,GAAG;AACvC,qBAAK,+BAA+B;AACpC,sBAAM,aAAa,KAAK,eAAe,GAAG,IAAI;AAC9C,oBAAI;AACJ,oBAAI,YAAY;AACd,4BAAU,IAAI,GAAG,IAAI,iCAAiC,UAAU,8BAA8B,UAAU,sDAAsD,GAAG,IAAI;AACrK,kBAAAA,QAAO;AAAA,oBACL,qBAAqB,GAAG,IAAI,iCAAiC,UAAU,MAAM,KAAK,2BAA2B,IAAI,oBAAoB;AAAA,kBACvI;AAAA,gBACF,OAAO;AACL,4BAAU,IAAI,GAAG,IAAI,6JAAwJ,OAAO,KAAK,KAAK,YAAY,EAAE,KAAK,IAAI,KAAK,QAAQ;AAClO,kBAAAA,QAAO;AAAA,oBACL,2BAA2B,GAAG,IAAI,iFAA4E,KAAK,2BAA2B,IAAI,oBAAoB;AAAA,kBACxK;AAAA,gBACF;AACA,gCAAgB,KAAK,YAAY,mBAAmB;AAAA,kBAClD,MAAM,GAAG;AAAA,kBACT,OAAO,KAAK;AAAA,kBACZ,MAAM,aAAa,gBAAgB;AAAA,kBACnC,MAAM,cAAc;AAAA,kBACpB,aAAa,KAAK;AAAA,kBAClB,KAAK;AAAA,gBACP,CAAC;AAID,sBAAM,eAAe,aACjB,UACA,MAAM,KAAK,6BAA6B,GAAG,MAAM,SAAS,OAAO;AACrE,6BAAa,IAAI,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,SAAS,aAAa,CAAC;AACpE,+BAAe,IAAI,GAAG,EAAE;AACxB,6BAAa,IAAI,GAAG,EAAE;AACtB,qBAAK,uBAAuB,IAAI,GAAG,IAAI;AACvC,qBAAK,qBAAqB,IAAI,GAAG,IAAI;AACrC,oBAAI,KAAK,+BAA+B,sBAAsB;AAC5D,wCAAsB;AAAA,gBACxB;AACA;AAAA,cACF;AAGA,mBAAK,+BAA+B;AACpC,cAAAA,QAAO;AAAA,gBACL,+CAA+C,GAAG,IAAI,MAAM,KAAK,2BAA2B,IAAI,8BAA8B,uBAAuB,OAAO,KAAK,KAAK,YAAY,EAAE,KAAK,IAAI,KAAK,QAAQ;AAAA,cAC5M;AACA,8BAAgB,KAAK,YAAY,mBAAmB;AAAA,gBAClD,MAAM,GAAG;AAAA,gBACT,OAAO,KAAK;AAAA,gBACZ,MAAM;AAAA,gBACN,aAAa,KAAK;AAAA,gBAClB,KAAK;AAAA,gBACL,gBAAgB,OAAO,KAAK,KAAK,YAAY;AAAA,cAC/C,CAAC;AACD,oBAAM,iBAAiB,MAAM,KAAK;AAAA,gBAChC,GAAG;AAAA,gBACH;AAAA,gBACA,iBAAiB,GAAG,IAAI;AAAA,cAC1B;AACA,2BAAa,IAAI,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,SAAS,eAAe,CAAC;AACtE,6BAAe,IAAI,GAAG,EAAE;AACxB,mBAAK,uBAAuB,IAAI,GAAG,IAAI;AACvC,kBAAI,KAAK,+BAA+B,gCAAgC;AACtE,sCAAsB;AAAA,cACxB;AACA;AAAA,YACF;AAUA,kBAAM,eAA4C,EAAE,QAAQ,CAAC,EAAE;AAC/D,kBAAM,gBAAgB,MACpB,aAAa,OAAO,SAAS,aAAa,OAAO,KAAK,IAAI;AAC5D,gBAAI;AACF,oBAAM,SAAS,MAAM,QAAQ,GAAG,MAAM,KAAK,oBAAoB,GAAG,IAAI,YAAY,CAAC;AAOnF,oBAAM,eAAe,iBAAiB,MAAM;AAC5C,oBAAM,UAAU,eACZ,OAAQ,OAAiC,YAAY,WAClD,OAA+B,UAChC,KAAK,UAAU,EAAE,GAAI,QAAmB,aAAa,OAAU,CAAC,IAClE,OAAO,WAAW,WAChB,SACA,KAAK,UAAU,MAAM;AAC3B,2BAAa,IAAI,GAAG,IAAI;AAAA,gBACtB,YAAY,GAAG;AAAA,gBACf;AAAA,gBACA,GAAI,eAAe,EAAE,aAAa,aAAa,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,gBAIpD,eAAe,cAAc;AAAA,cAC/B,CAAC;AACD,oCAAsB;AAAA,YACxB,SAAS,GAAG;AACV,cAAAA,QAAO,MAAM,oBAAoB,GAAG,IAAI,aAAa,CAAC;AACtD,8BAAgB,KAAK,YAAY,eAAe;AAAA,gBAC9C,MAAM,GAAG;AAAA,gBACT,OAAO,KAAK;AAAA,gBACZ,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,cACpD,CAAC;AACD,2BAAa,IAAI,GAAG,IAAI;AAAA,gBACtB,YAAY,GAAG;AAAA;AAAA;AAAA,gBAGf,SAAS,eAAgB,EAAY,OAAO;AAAA;AAAA;AAAA;AAAA,gBAG5C,eAAe,cAAc;AAAA,cAC/B,CAAC;AACD,oCAAsB;AAAA,YACxB;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,qBAAqB;AACvB,aAAK,qBAAqB;AAC1B,aAAK,8BAA8B;AACnC,aAAK,uBAAuB,MAAM;AAClC,aAAK,qBAAqB,MAAM;AAAA,MAClC;AAGA,YAAM,WAAW,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,QAAQ;AAErD,iBAAW,MAAM,SAAS,WAAW;AACnC,YAAI,GAAG,SAAS,2BAA2B;AACzC,eAAK,gBAAgB;AAAA,YACnB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,YAAY,EAAE,YAAY,GAAG,IAAI,SAAS,gCAAgC;AAAA,UAC5E,CAAC;AAAA,QACH,OAAO;AACL,gBAAM,IAAI,aAAa,IAAI,GAAG,EAAE;AAChC,cAAI,GAAG;AAML,iBAAK,gBAAgB;AAAA,cACnB,MAAM;AAAA,cACN,SAAS;AAAA,cACT,YAAY;AAAA,gBACV,YAAY,EAAE;AAAA,gBACd,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA,gBAIX,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;AAAA,cACxD;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAIA,UAAI,WAAW;AACf,eAAS,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACpD,YAAI,KAAK,QAAQ,CAAC,EAAE,SAAS,eAAe,KAAK,QAAQ,CAAC,EAAE,WAAW,QAAQ;AAC7E,qBAAW;AACX;AAAA,QACF;AAAA,MACF;AACA,UAAI,aAAa,IAAI;AACnB,cAAM,QAAQ,KAAK,QAAQ,QAAQ;AACnC,cAAM,qBAAqB,OAAO,KAAK,KAAK,YAAY;AACxD,cAAM,iBAAiB,MAAM,UAAW,IAAI,CAAC,OAAO;AAClD,gBAAM,aACJ,CAAC,CAAC,KAAK,QAAQ,GAAG,IAAI;AAAA;AAAA,UAGtB,aAAa,IAAI,GAAG,EAAE,GAAG,SAAS,WAAW,cAAc;AAC7D,gBAAM,cAAc,aAAa,IAAI,GAAG,EAAE,GAAG,SAAS,WAAW,cAAc;AAC/E,gBAAM,YAAY,eAAe,IAAI,GAAG,EAAE;AAC1C,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,WAAW,aACN,SACD,cACG,UACD;AAAA;AAAA,YAEN,UAAU,CAAC,cAAc,CAAC,eAAe,SAAS,SAAS,IAAI,WAAW;AAAA,YAC1E,SAAS,aAAa;AAAA,YACtB,gBAAgB,YAAY,qBAAqB;AAAA;AAAA;AAAA,YAGjD,OAAO,aAAa,IAAI,GAAG,EAAE,KAAK;AAAA,YAClC,eAAe,aAAa,IAAI,GAAG,EAAE,GAAG;AAAA,UAC1C;AAAA,QACF,CAAC;AACD,aAAK,QAAQ,QAAQ,IAAI,EAAE,GAAG,OAAO,WAAW,eAAe;AAC/D,aAAK;AAAA,UACH,IAAI,YAAwC,mBAAmB;AAAA,YAC7D,QAAQ,KAAK;AAAA,UACf,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,qBAAqB;AACvB,QAAAA,QAAO;AAAA,UACL,mCAAmC,8BAA8B;AAAA,QACnE;AACA,cAAM,eAAe;AAAA,UACnB,GAAG,oBAAI,IAAI;AAAA,YACT,GAAG,KAAK;AAAA,YACR,IAAI,SAAS,aAAa,CAAC,GACxB,OAAO,CAAC,OAAO,eAAe,IAAI,GAAG,EAAE,CAAC,EACxC,IAAI,CAAC,OAAO,GAAG,IAAI;AAAA,UACxB,CAAC;AAAA,QACH;AAKA,cAAM,aAAa;AAAA,UACjB,GAAG,oBAAI,IAAI;AAAA,YACT,GAAG,KAAK;AAAA,YACR,IAAI,SAAS,aAAa,CAAC,GACxB,OAAO,CAAC,OAAO,aAAa,IAAI,GAAG,EAAE,CAAC,EACtC,IAAI,CAAC,OAAO,GAAG,IAAI;AAAA,UACxB,CAAC;AAAA,QACH;AACA,cAAM,oBAAoB,aAAa,OAAO,CAAC,MAAM,CAAC,WAAW,SAAS,CAAC,CAAC;AAC5E,wBAAgB,KAAK,YAAY,sBAAsB;AAAA,UACrD,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB,OAAO,KAAK,KAAK,YAAY;AAAA,UAC7C,YAAY,KAAK;AAAA,QACnB,CAAC;AACD,YAAI,KAAK,YAAY;AACnB,eAAK,aAAa,oBAAoB;AAAA,QACxC,OAAO;AACL,eAAK,gBAAgB;AAAA,YACnB,MAAM;AAAA,YACN,SACE;AAAA,UACJ,CAAC;AAAA,QACH;AACA,eAAO,KAAK,SAAS,oBAAoB;AAAA,MAC3C;AAEA,YAAM,oBAAoB,YAAY,CAAC;AACvC,UAAI,mBAAmB;AACrB,cAAM,EAAE,SAAS,gBAAgB,cAAc,IAAI,kBAAkB;AAIrE,eAAO,EAAE,QAAQ,iBAAiB,SAAS,cAAc;AAAA,MAC3D;AAIA,UAAI,KAAK,oBAAoB;AAC3B,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,IACF;AAIA,QAAI;AACJ,QAAI,cAAc,KAAK,mBAAmB;AACxC,MAAAA,QAAO,KAAK,mDAAmD;AAC/D,sBAAgB,KAAK,YAAY,kBAAkB;AAAA,QACjD,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK;AAAA,QACf;AAAA,QACA,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,MACnB,CAAC;AACD,UAAI,KAAK,YAAY;AACnB,aAAK,aAAa,gBAAgB;AAAA,MACpC,OAAO;AACL,aAAK,gBAAgB;AAAA,UACnB,MAAM;AAAA,UACN,SACE;AAAA,QACJ,CAAC;AAAA,MACH;AACA,sBAAgB;AAAA,IAClB;AAEA,WAAO,KAAK,SAAS,aAAa;AAAA,EACpC;AAAA,EAEQ,gBAAgB,SAA4B;AAClD,UAAM,SAAsB;AAAA,MAC1B,GAAG;AAAA;AAAA,MAEH,WAAW,QAAQ,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACvD,GAAI,KAAK,kBACL;AAAA,QACE,WAAW,KAAK;AAAA;AAAA,QAEhB,YAAY,KAAK;AAAA,MACnB,IACA,CAAC;AAAA,IACP;AACA,SAAK,UAAU,CAAC,GAAG,KAAK,SAAS,MAAM;AACvC,SAAK;AAAA,MACH,IAAI,YAAwC,mBAAmB;AAAA,QAC7D,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC1uHA,IAAM,uBAAuB;AAC7B,IAAM,oCAAoC;AAC1C,IAAM,6BAA6B;AAEnC,IAAM,kCAAkC;AAAA,EACtC,MAAM;AAAA,EACN,aACE;AAAA,EACF,YAAY;AAAA,IACV,MAAM;AAAA,IACN,UAAU,CAAC,WAAW,gBAAgB;AAAA,IACtC,YAAY;AAAA,MACV,SAAS;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,gBAAgB;AAAA,QACd,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAAoD;AACxE,SAAO,CAAC,MAAM;AAChB;AAEA,SAAS,WAAW,OAAkD;AACpE,SAAO,MAAM,aAAa;AAC5B;AAEA,SAAS,0BACP,UACA,aAC+B;AAC/B,QAAM,YAAY,YAAY,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,IAAI;AACnF,MAAI,OAAO,SAAS,iBAAiB,UAAU;AAC7C,WAAO,SAAS,aAAa,QAAQ,cAAc,SAAS;AAAA,EAC9D;AACA,MAAI,OAAO,SAAS,iBAAiB,YAAY;AAI/C,WAAO,SAAS;AAAA,EAClB;AACA,SAAO;AAAA;AAAA,EAAkI,SAAS;AAAA;AAAA;AACpJ;AASO,IAAM,sBAAN,cAAkC,YAAgC;AAAA,EAwDvE,YACmB,kBACA,QACjB,UAYI,CAAC,GACL;AACA,UAAM;AAhBW;AACA;AA9CnB;AAAA;AAAA;AAAA;AAAA,SAAiB,2BAA2B,IAAI,gBAAgB;AAMhE;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,YAAY;AAWpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,sBAAsB;AAO9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,kBAAiC;AAQzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,qBAAoC;AAQ5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,sBAA+C,CAAC;AAsBtD,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,0BACH,QAAQ,2BAA2B;AACrC,SAAK,oBAAoB,QAAQ,qBAAqB;AAKtD,iCAA6B,QAAQ,gBAAgB;AAIrD,SAAK,cAAc,OAAO,OAAO,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,qBAAqB;AACrF,UAAM,YAAY,OAAO,OAAO,UAAU;AAC1C,QAAI,UAAU,SAAS,GAAG;AACxB,MAAAG,QAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,UAAU,CAAC;AAC/B,SAAK,WAAW,cACZ,EAAE,GAAG,aAAa,cAAc,0BAA0B,aAAa,KAAK,WAAW,EAAE,IACzF;AAEJ,SAAK,aAAa,IAAI,WAAW,kBAAkB;AAAA,MACjD,mBAAmB,QAAQ;AAAA,MAC3B,mBAAmB,QAAQ;AAAA,MAC3B,kBAAkB,QAAQ;AAAA,MAC1B,YAAY,KAAK;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,wBAAwB,QAAQ;AAAA,IAClC,CAAC;AAGD,SAAK,WAAW,iBAAiB,mBAAmB,CAAC,MAAa;AAChE,WAAK,cAAc,IAAI,YAAY,mBAAmB,EAAE,QAAS,EAAkB,OAAO,CAAC,CAAC;AAAA,IAC9F,CAAC;AACD,SAAK,WAAW,iBAAiB,6BAA6B,CAAC,MAAa;AAC1E,WAAK;AAAA,QACH,IAAI,YAAY,6BAA6B,EAAE,QAAS,EAAkB,OAAO,CAAC;AAAA,MACpF;AAAA,IACF,CAAC;AACD,SAAK,WAAW,iBAAiB,mBAAmB,CAAC,MAAa;AAChE,WAAK,cAAc,IAAI,YAAY,mBAAmB,EAAE,QAAS,EAAkB,OAAO,CAAC,CAAC;AAAA,IAC9F,CAAC;AACD,SAAK,WAAW,iBAAiB,kBAAkB,CAAC,MAAa;AAC/D,WAAK,cAAc,IAAI,YAAY,kBAAkB,EAAE,QAAS,EAAkB,OAAO,CAAC,CAAC;AAAA,IAC7F,CAAC;AACD,SAAK,WAAW,iBAAiB,qBAAqB,CAAC,MAAa;AAClE,WAAK;AAAA,QACH,IAAI,YAAY,qBAAqB,EAAE,QAAS,EAAkB,OAAO,CAAC;AAAA,MAC5E;AAAA,IACF,CAAC;AACD,SAAK,WAAW,iBAAiB,oBAAoB,CAAC,MAAa;AACjE,WAAK;AAAA,QACH,IAAI,YAAY,oBAAoB,EAAE,QAAS,EAAkB,OAAO,CAAC;AAAA,MAC3E;AAAA,IACF,CAAC;AACD,SAAK,WAAW,iBAAiB,oBAAoB,CAAC,MAAa;AACjE,WAAK;AAAA,QACH,IAAI,YAAY,oBAAoB,EAAE,QAAS,EAAkB,OAAO,CAAC;AAAA,MAC3E;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,mBAAmB,eAAuB,QAAuB;AAC/D,SAAK,WAAW,mBAAmB,eAAe,MAAM;AAAA,EAC1D;AAAA,EAEA,sBAAsB,eAAuD;AAC3E,WAAO,KAAK,WAAW,sBAAsB,aAAa;AAAA,EAC5D;AAAA,EAEA,SAAkB;AAChB,WAAO,KAAK,WAAW,OAAO;AAAA,EAChC;AAAA;AAAA,EAGA,wBAAgC;AAC9B,WAAO,KAAK,WAAW,sBAAsB;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,MAA2B;AACxC,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,MAA2B;AACtC,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,YAAY,UAA+B;AACzC,SAAK,WAAW,YAAY,QAAQ;AAAA,EACtC;AAAA,EAEA,gBAAwC;AACtC,WAAO,KAAK,WAAW,WAAW;AAAA,EACpC;AAAA;AAAA,EAGA,UAAuC;AACrC,WAAO,KAAK,WAAW,QAAQ;AAAA,EACjC;AAAA;AAAA,EAGA,aAAsB;AACpB,WAAO,KAAK,WAAW,WAAW;AAAA,EACpC;AAAA;AAAA,EAGA,mBAAgD;AAC9C,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA,EAGA,yBAAyD;AACvD,WAAO,KAAK,WAAW,uBAAuB;AAAA,EAChD;AAAA,EAEA,MAAM,eACJ,SACAC,SACA,OACA,cACmB;AAGnB,UAAM,SAAS,KAAK,mBAAmB;AACvC,UAAM,aAAa,UAAU,aAAa,MAAM,IAAI,CAAC,MAAM,IAAI,KAAK;AACpE,UAAM,YAAY,WAAW,IAAI,CAAC,OAAO;AAAA,MACvC,MAAM,EAAE;AAAA,MACR,aAAa,EAAE;AAAA;AAAA;AAAA;AAAA,MAIf,OAAO,MAAM,QAAQ,EAAE,eAAe,IAAI,EAAE,kBAAkB,CAAC;AAAA,IACjE,EAAE;AACF,WAAO,KAAK,WAAW,eAAe,SAASA,SAAQ,OAAO,SAAS;AAAA,EACzE;AAAA,EAEA,MAAM,YAAY,OAAe,aAA2D;AAC1F,QAAI;AACF,aAAO,MAAM,KAAK,oBAAoB,OAAO,WAAW;AAAA,IAC1D,SAAS,GAAG;AAgBV,UAAI,aAAa,sBAAsB;AACrC,eAAO,KAAK,WAAW;AAAA,UACrB;AAAA,UACA,KAAK,sBACD,SACA;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,YACT,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,UACvC;AAAA,QACN;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,oBACZ,OACA,aAC2B;AAC3B,SAAK,YAAY;AACjB,SAAK,sBAAsB;AAC3B,UAAM,UAAU,KAAK,WAAW,WAAW;AAI3C,SAAK;AAAA,MACH,IAAI,YAAY,mBAAmB;AAAA,QACjC,QAAQ,CAAC,GAAG,SAAS,EAAE,MAAM,QAAQ,SAAS,OAAO,YAAY,CAAC;AAAA,MACpE,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,KAAK,mBAAmB;AACvC,QAAI,CAAC,OAAQ,MAAK,cAAc,IAAI,YAAY,qBAAqB,CAAC;AACtE,QAAI,eAAe,UAAW,MAAM,KAAK,SAAS,OAAO,SAAS,KAAK,WAAW;AAClF,QAAI,YAAY;AAChB,QAAI,WAAW;AACf,QAAI,iBAAiB;AACrB,QAAI,gBAAgB;AAEpB,QAAI;AAEJ,WAAO,MAAM;AAIX,UAAI,KAAK,UAAW;AAGpB,YAAM,KAAK,WAAW,YAAY;AAElC,UAAI;AACJ,UAAI,WAAW;AACb,cAAM,gBAA+B,iBACjC,CAAC,EAAE,MAAM,QAAQ,SAAS,kCAAkC,cAAc,GAAG,CAAC,IAC9E,CAAC;AAEL,iBAAS,MAAM,KAAK,WAAW,oBAAoB,aAAa;AAAA,MAClE,OAAO;AAKL,aAAK,sBAAsB;AAE3B,iBAAS,MAAM,KAAK,WAAW,YAAY,OAAO,WAAW;AAAA,MAC/D;AACA,mBAAa;AAMb,UAAI,KAAK,WAAW,yBAAyB,GAAG;AAE9C,cAAM,KAAK,mBAAmB;AAC9B;AAAA,MACF;AAIA,UAAI,OAAO,WAAW,mBAAmB,WAAW,YAAY,KAAK,QAAQ;AAC3E;AAAA,MACF;AAEA,kBAAY;AACZ,UAAI,WAAW,KAAK,aAAa;AAC/B,aAAK;AAAA,UACH;AAAA,QACF;AACA;AAAA,MACF;AAEA,uBAAiB,OAAO;AACxB,sBAAgB,OAAO;AACvB,kBAAY;AAEZ,YAAM,iBAAiB,KAAK,WAAW,WAAW;AAClD,WAAK,cAAc,IAAI,YAAY,qBAAqB,CAAC;AAEzD,qBAAe,MAAM,KAAK,SAAS,eAAe,cAAc;AAAA,IAClE;AAeA,WAAO,YAAY,WAAW,SAAS,aAAa,EAAE,QAAQ,OAAO;AAAA,EACvE;AAAA,EAEA,MAAM,oBAAoB,iBAA4D;AACpF,WAAO,KAAK,WAAW,oBAAoB,eAAe;AAAA,EAC5D;AAAA;AAAA,EAGA,wBAAwB,WAA0C;AAChE,SAAK,sBAAsB,EAAE,GAAG,UAAU;AAAA,EAC5C;AAAA;AAAA,EAGA,iBAA0C;AACxC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,WAAW,OAAmC;AAC1D,UAAM,gBAAgB,KAAK;AAC3B,UAAM,WAAW,CAAC,iBAAiB,cAAc,SAAS,MAAM;AAIhE,QAAI,UAAU;AACZ,sBAAgB,KAAK,YAAY,iBAAiB;AAAA,QAChD,MAAM,eAAe,QAAQ;AAAA,QAC7B,IAAI,MAAM;AAAA;AAAA,QAEV,UAAU,KAAK,oBAAoB,MAAM,IAAI,MAAM;AAAA,MACrD,CAAC;AAAA,IACH;AAKA,QAAI,YAAY,eAAe,cAAc;AAC3C,UAAI;AACF,cAAM,cAAc,aAAa;AAAA,UAC/B,WAAW,cAAc;AAAA,UACzB,YAAY,KAAK;AAAA,UACjB,QAAQ,KAAK,yBAAyB;AAAA,QACxC,CAAC;AAAA,MACH,SAAS,GAAG;AACV,QAAAD,QAAO,KAAK,sCAAsC,cAAc,IAAI,aAAa,CAAC;AAAA,MACpF;AAAA,IACF;AACA,QAAI,YAAY,MAAM,YAAY;AAIhC,YAAM,WAAW,KAAK,oBAAoB,MAAM,IAAI;AACpD,UAAI,aAAa,OAAW,QAAO,KAAK,oBAAoB,MAAM,IAAI;AACtE,UAAI;AACF,cAAM,MAAM,WAAW;AAAA,UACrB,WAAW,MAAM;AAAA,UACjB,YAAY,KAAK;AAAA,UACjB,mBAAmB,eAAe;AAAA,UAClC,QAAQ,KAAK,yBAAyB;AAAA,UACtC;AAAA,QACF,CAAC;AAAA,MACH,SAAS,GAAG;AACV,QAAAA,QAAO,KAAK,oCAAoC,MAAM,IAAI,aAAa,CAAC;AAAA,MAC1E;AAAA,IACF;AAEA,UAAM,oBAAoB,CAAC,EAAE,MAAM,cAAc,MAAM;AASvD,QAAI,YAAY,qBAAqB,KAAK,uBAAuB,MAAM,MAAM;AAC3E,WAAK,qBAAqB,MAAM;AAChC,WAAK,cAAc,IAAI,YAAY,sBAAsB,EAAE,QAAQ,MAAM,KAAK,CAAC,CAAC;AAAA,IAClF;AAWA,UAAM,aACJ,WAAW,KAAK,KAChB,KAAK,oBAAoB,QACzB,KAAK,uBAAuB,QAC5B;AAEF,QAAI,eAA4B;AAChC,QAAI,CAAC,YAAY;AACf,YAAM,gBAAgB,MAAM;AAC5B,qBAAe;AAAA,QACb,GAAG;AAAA,QACH,iBACE,OAAO,kBAAkB,aACrB,OAAO,QAA6B;AAAA,UAClC,GAAI,MAAM,cAAc,GAAG;AAAA,UAC3B;AAAA,QACF,IACA,CAAC,GAAI,iBAAiB,CAAC,GAAI,+BAA+B;AAAA,MAClE;AAAA,IACF;AAEA,QAAI,iBAAiB,cAAc,SAAS,MAAM,MAAM;AACtD,YAAM,aAAa,KAAK,WAAW,WAAW;AAC9C,WAAK,WAAW,YAAY;AAAA,QAC1B,GAAG;AAAA,QACH,EAAE,MAAM,gBAAgB,SAAS,MAAM,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,MACnF,CAAC;AAAA,IACH;AAEA,SAAK,WAAW,4BAA4B,CAAC,MAAM,yBAAyB,GAAG,MAAM,IAAI,CAAC;AAC1F,SAAK,WAAW,WAAW,YAAY;AACvC,SAAK,cAAc;AACnB,SAAK,cAAc,IAAI,YAAY,oBAAoB,CAAC;AACxD,SAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQ,MAAM,CAAC,CAAC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,qBAAoC;AAChD,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,MAAO;AACZ,QAAI,MAAM,cAAc;AACtB,UAAI;AACF,cAAM,MAAM,aAAa;AAAA,UACvB,WAAW,MAAM;AAAA,UACjB,YAAY,KAAK;AAAA,UACjB,QAAQ,KAAK,yBAAyB;AAAA,QACxC,CAAC;AAAA,MACH,SAAS,GAAG;AACV,QAAAA,QAAO,KAAK,8CAA8C,MAAM,IAAI,aAAa,CAAC;AAAA,MACpF;AAAA,IACF;AACA,SAAK,cAAc;AACnB,QAAI,KAAK,uBAAuB,MAAM;AACpC,WAAK,qBAAqB;AAC1B,WAAK,cAAc,IAAI,YAAY,sBAAsB,EAAE,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC5E;AACA,SAAK,cAAc,IAAI,YAAY,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC;AACvE,SAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,QAAQ,OAAU,CAAC,CAAC;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAe;AACb,SAAK,YAAY;AACjB,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAyB;AAC7B,UAAM,gBAAgB,KAAK;AAC3B,QAAI,eAAe,cAAc;AAC/B,UAAI;AACF,cAAM,cAAc,aAAa;AAAA,UAC/B,WAAW,cAAc;AAAA,UACzB,YAAY,KAAK;AAAA,UACjB,QAAQ,KAAK,yBAAyB;AAAA,QACxC,CAAC;AAAA,MACH,SAAS,GAAG;AACV,QAAAA,QAAO,KAAK,8CAA8C,cAAc,IAAI,aAAa,CAAC;AAAA,MAC5F;AAAA,IACF;AACA,SAAK,yBAAyB,MAAM;AAEpC,SAAK,WAAW,QAAQ;AACxB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAc,SACZ,OACA,SACA,cACsB;AAMtB,QAAI,KAAK,YAAY,WAAW,KAAK,CAAC,KAAK,UAAU;AACnD,aAAO,KAAK,YAAY,CAAC;AAAA,IAC3B;AACA,QAAI,KAAK,YAAY,WAAW,GAAG;AAOjC,UAAI,CAAC,KAAK,UAAU;AAClB,cAAM,WAAW,KAAK,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACzD,YAAI,SAAS,WAAW,GAAG;AACzB,iBAAO,SAAS,CAAC;AAAA,QACnB;AAAA,MACF;AACA,aAAO,KAAK,YAAY,EAAE,MAAM,aAAa,UAAU,KAAK;AAAA,IAC9D;AAEA,UAAM,YAAY,KAAK,YACpB,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,IAAI,WAAM,EAAE,WAAW,EAAE,EAClD,KAAK,IAAI;AAEZ,UAAM,iBAAiB,QACpB,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,WAAW,EACzD,MAAM,CAAC,KAAK,uBAAuB,EACnC,IAAI,CAAC,MAAM,GAAG,EAAE,SAAS,SAAS,SAAS,WAAW,KAAK,EAAE,OAAO,EAAE,EACtE,KAAK,IAAI;AAEZ,UAAM,mBACJ,gBAAgB,aAAa,YAAY,IACrC;AAAA;AAAA,oCAAyC,aAAa,IAAI,4FAA4F,aAAa,IAAI,kFACvK;AAEN,UAAM,mBAAmB;AAAA;AAAA;AAAA,EAAsX,SAAS,GAAG,gBAAgB,GAAG,iBAAiB;AAAA;AAAA;AAAA,EAA6B,cAAc,KAAK,EAAE;AAEjf,UAAM,cAAc;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,QACV,MAAM;AAAA,QACN,UAAU,CAAC,aAAa;AAAA,QACxB,YAAY;AAAA,UACV,aAAa;AAAA,YACX,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAMA,QAAI,gBAAgB;AAEpB,aAAS,UAAU,GAAG,WAAW,KAAK,mBAAmB,WAAW,GAAG;AACrE,UAAI;AACF,cAAM,UAA8B;AAAA,UAClC,cAAc;AAAA,UACd,OAAO,CAAC,WAAW;AAAA,QACrB;AAGA,cAAM,qBAAqB,KAAK,iBAAiB,QAAQ;AACzD,YAAI,CAAC,mBAAmB,MAAM;AAC5B,UAAAA,QAAO;AAAA,YACL;AAAA,UACF;AACA;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,mBAAmB,KAAK,CAAC,GAAG,OAAO,OAAO;AACjE,cAAM,KAAK,SAAS,YAAY,CAAC;AACjC,cAAM,QAAQ,IAAI,SAAS,iBAAkB,GAAG,KAAK,cAAyB;AAE9E,YAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,QAAQ;AACjD,iBAAO,KAAK,YAAY,KAAK;AAAA,QAC/B;AAEA,wBAAgB;AAChB;AAAA,MACF,SAAS,GAAG;AAOV,YAAI,aAAa,qBAAsB,OAAM;AAC7C,QAAAA,QAAO,KAAK,2CAA2C,UAAU,CAAC,YAAY,CAAC;AAC/E,YAAI,YAAY,KAAK,mBAAmB;AACtC,UAAAA,QAAO,MAAM,0EAA0E;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,SAAU,QAAO,KAAK;AAO/B,QAAI,eAAe;AACjB,YAAM,kBAAkB,KAAK,YAAY,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACrE,WAAK;AAAA,QACH,0DAA0D,eAAe;AAAA,MAC3E;AAAA,IACF;AACA,WAAO,KAAK,YAAY,CAAC;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,qBAA8C;AACpD,UAAM,OAAO,KAAK,sBAAsB,KAAK;AAC7C,QAAI,SAAS,KAAM,QAAO;AAC1B,UAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACrD,QAAI,CAAC,OAAO;AACV,MAAAA,QAAO;AAAA,QACL,sCAAsC,IAAI;AAAA,MAC5C;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,SAAuB;AACjD,UAAM,UAAU,KAAK,WAAW,WAAW;AAC3C,SAAK,WAAW,YAAY;AAAA,MAC1B,GAAG;AAAA,MACH,EAAE,MAAM,aAAa,SAAS,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,IACpE,CAAC;AACD,SAAK;AAAA,MACH,IAAI,YAAY,mBAAmB,EAAE,QAAQ,KAAK,WAAW,WAAW,EAAE,CAAC;AAAA,IAC7E;AAAA,EACF;AACF;;;AC9LO,SAAS,YAAyC,QAAc;AACrE,SAAO;AACT;;;ACrUA,SAAS,6BAA6B,OAAyB;AAC7D,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACzE,QAAI,OAAO,OAAO,QAAQ,YAAY,WAAW,OAAO,aAAa,OAAO,cAAc,KAAK;AAC7F,YAAM,IAAI;AAMV,YAAM,MAAM,EAAE,WAAW,CAAC;AAC1B,YAAM,EAAE,QAAQ,IAAI,OAAO,MAAM,GAAG,YAAY,IAAI;AACpD,aAAO,GAAG,IAAI;AAAA,QACZ,OAAO,EAAE;AAAA,QACT,SAAS;AAAA,QACT,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,KAAK,MAAM,EAAE,SACvB,SACA;AACN;AAaA,SAAS,yBAAyB,OAAyB;AACzD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACzE,WAAO,GAAG,IACR,OACA,OAAO,QAAQ,YACf,OAAQ,IAA2C,yBAAyB,aACvE,IAAgD,qBAAqB,IACtE;AAAA,EACR;AACA,SAAO;AACT;AAwBO,SAAS,eACd,SACA,UACA,MAAM,WACA;AACN,QAAM,WAAY,WAAmD,GAAG;AACxE,MAAI,aAAa,UAAa,aAAa,MAAM;AAC/C;AAAA,EACF;AACA,UAAQ,KAAK;AACb,UAAQ,MAAM,EAAE,OAAO,SAAS,CAAC;AACnC;AA2BO,SAAS,oBAAuB,MAAyC;AAC9E,MAAI;AAEJ,QAAM,gBAAgB,CAAC,aAAqC;AAC1D,eAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,UAAK,QAAgB,gBAAgB,GAAG;AACtC,cAAM,IAAI;AAAA,UACR,mBAAmB,KAAK,IAAI,WAAW,IAAI;AAAA,QAI7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,QAAM,gBAAkD,MAAM;AAC5D,UAAM,KAAK,KAAK;AAChB,QAAI,OAAO,OAAO,YAAY;AAC5B,aAAO,OAAO,QAA6B;AACzC,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,4BAA4B;AAAA,QAC1E;AACA,eAAO,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,MAC7B;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG;AAOH,QAAM,kBAAiD,KAAK,eACxD,YAAY;AACV,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,+BAA+B;AAAA,IAC7E;AACA,UAAM,WAAW,MAAM,KAAK,aAAc,KAAK;AAC/C,kBAAc,QAAQ;AACtB,WAAO;AAAA,EACT,IACA;AAEJ,QAAM,qBAAoD,KAAK,cAC3D,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,kCAAkC;AAAA,IAChF;AACA,WAAO,KAAK,YAAa,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,EAC5C,IACA;AAKJ,QAAM,kBACJ,OAAO,KAAK,aAAa,aACrB,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,+BAA+B;AAAA,IAC7E;AACA,WAAQ,KAAK,SAAwE;AAAA,MACnF,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,IACA,KAAK;AAIX,QAAM,qBACJ,OAAO,KAAK,gBAAgB,aACxB,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,kCAAkC;AAAA,IAChF;AACA,WAAQ,KAAK,YAA2E;AAAA,MACtF,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,IACA,KAAK;AAEX,QAAM,oBACJ,OAAO,KAAK,eAAe,aACvB,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,iCAAiC;AAAA,IAC/E;AACA,WACE,KAAK,WAGL,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,EACrB,IACA,KAAK;AAEX,QAAM,qBACJ,OAAO,KAAK,gBAAgB,aACxB,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,kCAAkC;AAAA,IAChF;AACA,WACE,KAAK,YACL,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,EACrB,IACA,KAAK;AAKX,QAAM,wBACJ,OAAO,KAAK,mBAAmB,aAC3B,OAAO,QAA6B;AAClC,QAAI,CAAC,MAAO,QAAO;AACnB,WACE,KAAK,eAGL,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,EACrB,IACA,KAAK;AAEX,QAAM,qBACJ,OAAO,KAAK,gBAAgB,aACxB,OAAO,QAA6B;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,kCAAkC;AAAA,IAChF;AACA,WAAQ,KAAK,YAA2E;AAAA,MACtF,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,IACA,KAAK;AAMX,QAAM,0BACJ,OAAO,KAAK,qBAAqB,aAC7B,OAAO,QAAQ;AACb,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AACA,WAAO,KAAK,iBAAkB,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,EACjD,IACA,KAAK;AAMX,QAAM,mBAAyD,KAAK,YAChE,OAAO,QAAmD;AACxD,QAAI,UAAU,OAAW,QAAO;AAChC,WAAO,KAAK,UAAW;AAAA,MACrB,WAAW,IAAI;AAAA,MACf,YAAY,IAAI;AAAA,MAChB,UAAU,IAAI;AAAA,MACd,aAAa,IAAI;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH,IACA;AAEJ,QAAM,OAAO;AAAA,IACX,MAAM,KAAK;AAAA,IACX,aAAa;AAAA,IACb,eAAe,KAAK;AAAA,IACpB,WAAW,KAAK;AAAA,IAChB,iBAAiB,KAAK;AAAA,IACtB,0BAA0B,KAAK;AAAA,IAC/B,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,qBAAqB,KAAK;AAAA,IAE1B,YAAY,OAAO,QAA+B;AAChD,cAAQ,MAAM,KAAK,KAAK,GAAG;AAM3B,UAAI,KAAK,cAAc;AACrB,cAAM,UAAU,MAAM,KAAK,aAAa,KAAK;AAC7C,sBAAc,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,cAAc,OAAO,QAA+B;AAClD,UAAI,UAAU,UAAa,KAAK,SAAS;AACvC,cAAM,KAAK,QAAQ,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,MACtC;AAIA,cAAQ;AAAA,IACV;AAAA,IAEA,cAAc,KAAK,eACf,OAAO,QAA6B;AAClC,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,mCAAmC;AAAA,MACjF;AACA,aAAO,KAAK,aAAc,EAAE,GAAG,KAAK,MAAM,CAAC;AAAA,IAC7C,IACA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMJ,kBAAkB,MAAM;AACtB,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO,KAAK,mBACR,KAAK,iBAAiB,KAAK,IAC3B,6BAA6B,KAAK;AAAA,IACxC;AAAA;AAAA;AAAA,IAIA,WAAW,MAAM;AACf,UAAI,UAAU,OAAW,QAAO;AAChC,aAAO,KAAK,YAAY,KAAK,UAAU,KAAK,IAAI,yBAAyB,KAAK;AAAA,IAChF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,KAAK;AAAA,IAClB,uBAAuB,KAAK;AAAA,EAC9B;AACF;;;ACtnBO,IAAM,wBAA6C;AAAA,EACxD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,cAAc;AAAA;AAAA;AAAA;AAAA;AAChB;AASO,IAAM,sBAA2C;AAAA,EACtD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,cAAc;AAChB;;;AC2CA,SAAS,SAAS,GAAyB;AACzC,SACE,EAAE,QAAQ,QACV,EAAE,mBAAmB,QACrB,EAAE,eAAe,QACjB,EAAE,gBAAgB,QAClB,EAAE,mBAAmB,QACrB,EAAE,oBAAoB;AAE1B;AAmCO,SAAS,UAAU,UAA8C;AACtE,SAAO,YAAY,UAAU,GAAG,MAAS;AAC3C;AAGA,SAAS,UACP,OACiG;AACjG,SAAO;AAAA,IACL,qBAAqB,MAAM;AAAA,IAC3B,iBAAiB,MAAM;AAAA,IACvB,kBAAkB,MAAM;AAAA,IACxB,cAAc,MAAM;AAAA,EACtB;AACF;AAEA,SAAS,YACP,UACA,OACA,YACY;AACZ,QAAM,OAAmB,CAAC;AAC1B,aAAW,KAAK,UAAU;AACxB,QAAI,SAAS,CAAC,GAAG;AACf,YAAM,kBAAkB,EAAE,mBAAmB;AAC7C,YAAM,mBAAmB,EAAE,oBAAoB;AAC/C,WAAK,KAAK;AAAA,QACR,QAAQ;AAAA,QACR,OAAO,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOT,UAAU,EAAE,aAAa,EAAE,QAAQ,cAAc,EAAE,KAAK,IAAI;AAAA,QAC5D,GAAI,EAAE,QAAQ,QAAQ,EAAE,SAAS,EAAE,KAAK;AAAA,QACxC,GAAI,EAAE,mBAAmB,QAAQ,EAAE,iBAAiB,EAAE,gBAAgB;AAAA;AAAA;AAAA;AAAA,QAItE,qBAAqB,KAAK,IAAI,IAAI,EAAE,eAAe,KAAK,kBAAkB,gBAAgB;AAAA,QAC1F;AAAA,QACA;AAAA,QACA,cAAc,EAAE,gBAAgB;AAAA,QAChC,GAAI,EAAE,aAAa,QAAQ,EAAE,WAAW,EAAE,UAAU;AAAA,QACpD,eAAe;AAAA,QACf,GAAI,cAAc,QAAQ,EAAE,WAAW;AAAA,MACzC,CAAC;AAAA,IACH;AAKA,UAAM,SAAS,EAAE,YAAY;AAC7B,QAAI,QAAQ;AACV,WAAK,KAAK;AAAA,QACR,QAAQ;AAAA,QACR,GAAI,OAAO,WAAW,QAAQ,EAAE,SAAS,OAAO,QAAQ;AAAA,QACxD,GAAG,UAAU,MAAM;AAAA,QACnB,GAAI,EAAE,aAAa,QAAQ,EAAE,WAAW,EAAE,UAAU;AAAA,QACpD,eAAe;AAAA,QACf,GAAI,cAAc,QAAQ,EAAE,WAAW;AAAA,MACzC,CAAC;AAAA,IACH;AAEA,eAAW,MAAM,EAAE,aAAa,CAAC,GAAG;AAClC,UAAI,GAAG,cAAe,MAAK,KAAK,GAAG,YAAY,GAAG,eAAe,QAAQ,GAAG,GAAG,EAAE,CAAC;AAAA,IACpF;AAAA,EACF;AACA,SAAO;AACT;;;ACvIO,SAAS,wBACd,UACA,SAAS,IACT,QAAQ,GACR,YACmB;AACnB,SAAO,SAAS,QAAQ,CAAC,MAAM;AAC7B,UAAM,aAAa,SAAS,GAAG,MAAM,WAAM,EAAE,aAAa,GAAG,KAAK,EAAE;AACpE,UAAM,aAAa,EAAE,WAAW,OAAO,CAAC,OAAO,GAAG,eAAe,MAAM,KAAK,CAAC;AAE7E,UAAM,QAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,GAAG;AAAA;AAAA;AAAA,MAGH,GAAI,WAAW,SAAS,KAAK;AAAA,QAC3B,WAAW,EAAE,UAAW;AAAA,UAAI,CAAC,OAC3B,GAAG,gBAAgB,EAAE,GAAG,IAAI,eAAe,OAAU,IAAI;AAAA,QAC3D;AAAA,MACF;AAAA;AAAA,MAEA,GAAI,QAAQ,KAAK;AAAA,QACf,WAAW;AAAA,QACX,cAAc,EAAE;AAAA,QAChB,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,QAAI,WAAW,WAAW,EAAG,QAAO,CAAC,KAAK;AAE1C,UAAM,UAAU,WAAW;AAAA,MAAQ,CAAC,OAClC,wBAAwB,GAAG,eAAgB,cAAc,IAAI,QAAQ,GAAG,GAAG,EAAE;AAAA,IAC/E;AACA,WAAO,CAAC,OAAO,GAAG,OAAO;AAAA,EAC3B,CAAC;AACH;;;ACpDO,SAAS,qBAAqB,OAIf;AACpB,QAAM,EAAE,eAAe,UAAU,WAAW,IAAI;AAKhD,MAAI;AACJ,MAAI,gBAAgB;AACpB,QAAM,QAAQ,cAAc,IAAI,CAAC,MAAM;AACrC,QAAI,EAAE,aAAa,IAAI;AACvB,QAAI,gBAAgB,QAAQ,iBAAiB,gBAAgB;AAC3D,qBAAe,sCAAiC,aAAa;AAAA,IAC/D,WAAW,gBAAgB,MAAM;AAC/B,uBAAiB;AACjB,sBAAgB,EAAE;AAAA,IACpB;AACA,WAAO,EAAE,MAAM,QAAiB,GAAG,GAAG,aAAa;AAAA,EACrD,CAAC;AAKD,QAAM,iBAAiB,wBAAwB,QAAQ;AACvD,QAAM,eAAe,WAAW,IAAI,CAAC,OAAO,EAAE,MAAM,SAAkB,GAAG,EAAE,EAAE;AAE7E,SAAO,CAAC,GAAG,gBAAgB,GAAG,OAAO,GAAG,YAAY;AACtD;;;ACqDA,SAAS,aAAa,OAAgC;AACpD,SAAO,SAAS,OAAO,MAAM,aAAa,EAAE,CAAC,KAAK,MAAM,aAAa,EAAE,KAAK,OAAO,MAAM,aAAa,EAAE,CAAC;AAC3G;AAIA,IAAM,YAAoC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,EAAE;AAG1E,IAAM,oBAAoB;AAqBnB,SAAS,iBAAiB,SAA4B,QAAqC;AAahG,QAAM,SAAS,oBAAI,IAAoB;AACvC,MAAI;AACJ,QAAM,WAA8B,CAAC;AACrC,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,SAAS,iBAAiB;AAClC,UAAI,CAAC,eAAe,MAAM,aAAa,QAAQ,WAAW,aAAa,KAAK;AAC1E,qBAAa;AAAA,MACf;AACA;AAAA,IACF;AACA,UAAM,KAAK,MAAM,SAAS,SAAS,aAAa,KAAK,IAAI,KAAK,UAAU,KAAK;AAC7E,UAAM,KAAK,OAAO,IAAI,EAAE;AACxB,QAAI,OAAO,QAAW;AAGpB,UAAI,MAAM,SAAS,CAAC,SAAS,EAAE,EAAE,MAAO,UAAS,EAAE,IAAI;AACvD;AAAA,IACF;AACA,WAAO,IAAI,IAAI,SAAS,MAAM;AAC9B,aAAS,KAAK,KAAK;AAAA,EACrB;AACA,WAAS,KAAK,CAAC,GAAG,MAAM;AACtB,UAAM,KAAK,EAAE,aAAa;AAC1B,UAAM,KAAK,EAAE,aAAa;AAC1B,QAAI,KAAK,GAAI,QAAO;AACpB,QAAI,KAAK,GAAI,QAAO;AACpB,YAAQ,UAAU,EAAE,IAAI,KAAK,sBAAsB,UAAU,EAAE,IAAI,KAAK;AAAA,EAC1E,CAAC;AAID,QAAM,UAAW,YAAY,MACzB;AACJ,SAAO,EAAE,QAAQ,cAAc,SAAS,cAAc,UAAU,MAAM,YAAY,KAAK;AACzF;AAmBO,SAAS,sBACd,QACA,OACmB;AACnB,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,eAAe,GAAG,KAAK;AACpE;",
|
|
4
|
+
"sourcesContent": ["/**\n * Node-safe headless entry point for the AI assistant driver stack (`@genesislcap/ai-assistant/chat-driver`).\n *\n * Re-exports ONLY the framework-agnostic pieces \u2014 {@link ChatDriver}, `OrchestratingDriver`, the\n * agent-config surface (`defineAgent`, `defineStatefulAgent`, and the config/input types), and the\n * activity-bus types/`NOOP_ACTIVITY_BUS` \u2014 WITHOUT the DOM/FAST component layer that the package's\n * main entry (`.`) pulls in via `main/main`. This lets a Node / CommonJS host (server, unit tests,\n * benches) construct and drive `ChatDriver` over `foundation-ai` providers with no jsdom and no\n * custom-element registration.\n *\n * Every module re-exported here is DOM-clean at import time (no `window`/`document`/`sessionStorage`\n * eval-time access, no `@genesislcap/web-core`). The activity bus is imported for its types and the\n * no-op default; its cross-tab `BroadcastChannel` is created lazily and only in a browser, so\n * pulling this entry into Node opens nothing.\n *\n * @packageDocumentation\n * @beta\n */\nexport * from './components/chat-driver';\nexport * from './components/orchestrating-driver';\nexport * from './channel/ai-activity-channel';\nexport * from './channel/ai-activity-bus';\nexport * from './config/config';\nexport * from './config/define-stateful-agent';\nexport * from './config/fallback-agents';\n\n// Provider-construction surface, re-exported from `@genesislcap/foundation-ai` so a headless\n// consumer builds its registry from the SAME bundled foundation-ai instance the driver uses. That\n// shared identity matters: `ChatDriver`'s malformed/truncated handling does `instanceof` on the\n// transports' error classes, so a second foundation-ai copy (a separate dep) would silently break\n// those checks. NAMED re-exports only \u2014 `export *` would drag in the FAST-DI module\n// (`@microsoft/fast-foundation` \u2192 `fast-element` \u2192 `document` at eval); by naming just these,\n// esbuild tree-shakes the DI module out and the bundle stays Node-loadable.\nexport {\n AnthropicProvider,\n AnthropicTransport,\n GeminiProvider,\n GeminiTransport,\n MutableAIProviderRegistry,\n // Supported-model allowlists \u2014 so a headless consumer validates a configured model id against\n // foundation-ai's REAL list instead of maintaining a parallel hardcoded copy that silently drifts\n // as the platform adds models (a valid new model would otherwise look like a misconfiguration).\n // GENC-1461, create PR #1644 review.\n SUPPORTED_ANTHROPIC_MODEL_IDS,\n SUPPORTED_GEMINI_MODEL_IDS,\n // The provider wall (GENC-1506). Re-exported for the same anti-drift reason as the model lists\n // above, and it matters more here because the other end of this contract is in ANOTHER REPO:\n // genesis-create's ai-service stamps `PROVIDER_REFUSED_CODE` onto its proxy responses and shows\n // `DEFAULT_PROVIDER_REFUSED_MESSAGE` on its own generation surfaces. Hand-copying either would\n // drift silently \u2014 a renamed code stops classifying, and a second copy of the sentence survives\n // the first reword. `ProviderRefusedError` is here so a headless caller can `instanceof` it\n // against the same bundled instance the driver throws from.\n DEFAULT_PROVIDER_REFUSED_MESSAGE,\n PROVIDER_REFUSED_CODE,\n ProviderRefusedError,\n isObservableAIProviderRegistry,\n // Request pricing. Re-exported HERE, not left to a direct `@genesislcap/foundation-ai`\n // import, for the same reason as everything above it: a headless host that adds its own\n // foundation-ai dependency gets a second copy, and the driver's malformed/truncated\n // handling does `instanceof` on the transports' error classes. Reaching the pricing\n // should not cost a consumer that guarantee.\n //\n // These take RAW provider usage rather than a `ChatMessage` \u2014 see the foundation-ai\n // module docs. They are for the path where nothing stamped a cost (a proxied or\n // server-side call holding a usage block); when a message already carries `cost`, use\n // it, because it was computed with the per-TTL cache split the message no longer has.\n ANTHROPIC_CACHE_READ_MULTIPLIER,\n ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER,\n ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER,\n anthropicRatesFor,\n anthropicTokenCost,\n GEMINI_CACHED_INPUT_MULTIPLIER,\n GEMINI_LONG_CONTEXT_THRESHOLD,\n geminiRatesFor,\n geminiTokenCost,\n // Resolves a model id to its vendor, so a caller holding only `message.model` can pick\n // between the two cost functions above without maintaining its own model\u2192vendor map.\n vendorOfModel,\n} from '@genesislcap/foundation-ai';\nexport type {\n // Re-exported alongside `sumUsage` below \u2014 a consumer that can call the function but cannot NAME\n // its return type has to restate the shape by hand, which is how the buckets get mis-summed.\n AggregateUsage,\n AIProvider,\n AIProviderRegistry,\n AnthropicModelId,\n CachePolicy,\n // The attachment union, so a headless caller can hand a screenshot to a model or return one\n // from a tool handler without restating the shape \u2014 and, more to the point, without missing\n // that the image arm's `kind` is REQUIRED and is the only thing the transports branch on.\n ChatAttachment,\n ChatFallback,\n ChatImageAttachment,\n ChatMessage,\n ChatRequestOptions,\n ChatTextAttachment,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n ChatToolResult,\n GeminiModelId,\n // Pricing input/output shapes, alongside the functions re-exported above \u2014 a caller that\n // can invoke them but cannot name their argument or result has to restate the shape by\n // hand, which is how the token buckets get mixed up between the two providers.\n AnthropicUsageRecord,\n GeminiUsageRecord,\n TokenCost,\n TokenCostBreakdown,\n TokenRates,\n} from '@genesislcap/foundation-ai';\n\n// Usage/cost summation. A headless consumer attributing spend to a run has no other route to it:\n// the transports' `getLifetimeCost()` is per-instance and lifetime-scoped, so a shared registry\n// makes it unattributable, and re-deriving cost from token counts is wrong in the one direction\n// that matters (`inputTokens` is total prompt size INCLUDING the cached part, so re-pricing charges\n// every cached token at full rate). `sumUsage` reads the per-request cost the transports already\n// stamped, and recurses into `toolCalls[].subAgentTrace` \u2014 where the entire spend of a delegating\n// agent lives \u2014 and into `compaction.rolledUpUsage`, which is spend whose messages no longer exist.\n// Both are invisible when omitted: the total is merely too low, which reads as a cheap run.\n//\n// `addUsage`/`emptyUsage` are the composition primitives for a conversation that CONTINUES across\n// rounds \u2014 see the guidance on `sumUsage` itself. `totalTokens` exists because the four buckets of\n// an `AggregateUsage` are disjoint and safe to add, which the per-message fields are NOT.\n//\n// `messageUsage` is the single-message projection of the same arithmetic \u2014 what ONE request\n// cost, in the same four-bucket shape. It is what prices a turn snapshot (see\n// `TurnSnapshot.usage`), and the reason a consumer needs it separately is that the response\n// to a *failed* attempt never reaches history, so `sumUsage` over the transcript cannot see\n// that spend at all.\nexport { addUsage, emptyUsage, messageUsage, sumUsage, totalTokens } from './utils/sum-usage';\n\n// Per-call projection, for the cases an aggregate cannot serve: usage rows for\n// per-project attribution, a cost dashboard, or auditing which turns came back\n// unpriced. `usageRows` is guaranteed to reconcile with `sumUsage` \u2014 including spend a\n// compaction banked, which has no message of its own and which a naive per-message walk\n// therefore drops while the total keeps it. Both take RAW history; `UsageRow` is\n// deliberately not a `ChatMessage`, so passing rows back into `sumUsage` (which recurses\n// itself, and would double-count) does not compile.\nexport { usageRows } from './utils/usage-rows';\nexport type { UsageRow } from './utils/usage-rows';\n\n// Debug-log harvesting (GENC-1461 unified diagnostics). A headless consumer collates its driver's\n// log \u2014 `buildTimelineEntries({ turnSnapshots: driver.getTurnSnapshots(), messages:\n// driver.getHistory(), metaEvents: getMetaEvents(sessionKey) })` \u2192 `DiagnosticEntry[]` \u2014 ships it to\n// the client, which folds it into the assistant's debug log via `InteractionResult.diagnostics`\n// (see `ChatDriver.getExternalDiagnostics`). `clearSession(sessionKey)` drops the per-request\n// meta-event bucket so the long-lived server process's module registry doesn't grow unbounded.\n// All three modules are DOM-clean, so the node entry stays Node-loadable.\nexport { clearSession, getMetaEvents } from './state/debug-event-log';\nexport type { MetaEvent } from './state/debug-event-log';\nexport { buildTimelineEntries } from './state/persistence/build-timeline-entries';\nexport type { TurnSnapshotLike } from './state/persistence/build-timeline-entries';\n// `withFreshMetaSnapshot` matters to a headless consumer that stitches a STORED stream: the\n// newest stored `meta-snapshot` is frozen at the last config-signature change, so its context\n// and cost figures are as old as that. Pass a fresh snapshot of your own through this before\n// `assembleDebugLog`, or state in your own output that the totals are historical.\nexport { assembleDebugLog, withFreshMetaSnapshot } from './state/persistence/diagnostics';\nexport type { DebugLog, DiagnosticEntry } from './state/persistence/diagnostics';\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nvar ownKeys = function(o) {\n ownKeys = Object.getOwnPropertyNames || function (o) {\n var ar = [];\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\n return ar;\n };\n return ownKeys(o);\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\n });\n }\n return path;\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __esDecorate,\n __runInitializers,\n __propKey,\n __setFunctionName,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n __rewriteRelativeImportExtension,\n};\n", "const noop = () => { };\n/**\n * Fan several `AbortSignal`s into one. The returned signal aborts as soon\n * as any input signal aborts, adopting that signal's `reason` \u2014 so callers can\n * distinguish, for example, a timeout (`TimeoutError`) from a user/lifecycle\n * cancellation (`AbortError`) by inspecting `signal.reason`. `undefined`\n * entries are ignored, letting callers pass optional signals directly.\n *\n * NOTE: the platform already provides exactly this \u2014 `AbortSignal.any([...])`\n * \u2014 but it is part of a newer spec than we target here. Our TypeScript config\n * is pinned to an older standard library (tsconfig `target: ES2015`,\n * `lib: [...ES2020]`), which predates `AbortSignal.any()`/`AbortSignal.timeout()`,\n * so those APIs are not in our typings (and have a narrower runtime-support\n * floor). This helper is the hand-rolled stand-in until the lib target is\n * raised, at which point this can be deleted in favour of `AbortSignal.any`.\n *\n * @example\n * const timeout = new AbortController();\n * const timer = setTimeout(\n * () => timeout.abort(new DOMException('Request timed out', 'TimeoutError')),\n * ms,\n * );\n * const { signal, dispose } = combineSignals([callerSignal, timeout.signal]);\n * try {\n * return await fetch(url, { signal });\n * } finally {\n * clearTimeout(timer);\n * dispose();\n * }\n */\nexport function combineSignals(signals) {\n const controller = new AbortController();\n const inputs = signals.filter((s) => s != null);\n // If any input is already aborted, adopt its reason immediately. Nothing to\n // wire up, so the disposer is a no-op.\n const preAborted = inputs.find((s) => s.aborted);\n if (preAborted) {\n controller.abort(preAborted.reason);\n return { signal: controller.signal, dispose: noop };\n }\n // `dispose` and `onAbort` reference each other; both are hoisted function\n // declarations so neither is read before it is initialised.\n function dispose() {\n for (const s of inputs) {\n s.removeEventListener('abort', onAbort);\n }\n }\n // `this` is the input signal the listener was attached to, so `this.reason`\n // is the reason of whichever signal aborted first.\n function onAbort() {\n controller.abort(this.reason);\n dispose();\n }\n for (const s of inputs) {\n s.addEventListener('abort', onAbort);\n }\n return { signal: controller.signal, dispose };\n}\n", "const LogLevels = {\n silent: Number.NEGATIVE_INFINITY,\n fatal: 0,\n error: 0,\n warn: 1,\n log: 2,\n info: 3,\n success: 3,\n fail: 3,\n ready: 3,\n start: 3,\n box: 3,\n debug: 4,\n trace: 5,\n verbose: Number.POSITIVE_INFINITY\n};\nconst LogTypes = {\n // Silent\n silent: {\n level: -1\n },\n // Level 0\n fatal: {\n level: LogLevels.fatal\n },\n error: {\n level: LogLevels.error\n },\n // Level 1\n warn: {\n level: LogLevels.warn\n },\n // Level 2\n log: {\n level: LogLevels.log\n },\n // Level 3\n info: {\n level: LogLevels.info\n },\n success: {\n level: LogLevels.success\n },\n fail: {\n level: LogLevels.fail\n },\n ready: {\n level: LogLevels.info\n },\n start: {\n level: LogLevels.info\n },\n box: {\n level: LogLevels.info\n },\n // Level 4\n debug: {\n level: LogLevels.debug\n },\n // Level 5\n trace: {\n level: LogLevels.trace\n },\n // Verbose\n verbose: {\n level: LogLevels.verbose\n }\n};\n\nfunction isPlainObject$1(value) {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {\n return false;\n }\n if (Symbol.iterator in value) {\n return false;\n }\n if (Symbol.toStringTag in value) {\n return Object.prototype.toString.call(value) === \"[object Module]\";\n }\n return true;\n}\n\nfunction _defu(baseObject, defaults, namespace = \".\", merger) {\n if (!isPlainObject$1(defaults)) {\n return _defu(baseObject, {}, namespace, merger);\n }\n const object = Object.assign({}, defaults);\n for (const key in baseObject) {\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = baseObject[key];\n if (value === null || value === void 0) {\n continue;\n }\n if (merger && merger(object, key, value, namespace)) {\n continue;\n }\n if (Array.isArray(value) && Array.isArray(object[key])) {\n object[key] = [...value, ...object[key]];\n } else if (isPlainObject$1(value) && isPlainObject$1(object[key])) {\n object[key] = _defu(\n value,\n object[key],\n (namespace ? `${namespace}.` : \"\") + key.toString(),\n merger\n );\n } else {\n object[key] = value;\n }\n }\n return object;\n}\nfunction createDefu(merger) {\n return (...arguments_) => (\n // eslint-disable-next-line unicorn/no-array-reduce\n arguments_.reduce((p, c) => _defu(p, c, \"\", merger), {})\n );\n}\nconst defu = createDefu();\n\nfunction isPlainObject(obj) {\n return Object.prototype.toString.call(obj) === \"[object Object]\";\n}\nfunction isLogObj(arg) {\n if (!isPlainObject(arg)) {\n return false;\n }\n if (!arg.message && !arg.args) {\n return false;\n }\n if (arg.stack) {\n return false;\n }\n return true;\n}\n\nlet paused = false;\nconst queue = [];\nclass Consola {\n options;\n _lastLog;\n _mockFn;\n /**\n * Creates an instance of Consola with specified options or defaults.\n *\n * @param {Partial<ConsolaOptions>} [options={}] - Configuration options for the Consola instance.\n */\n constructor(options = {}) {\n const types = options.types || LogTypes;\n this.options = defu(\n {\n ...options,\n defaults: { ...options.defaults },\n level: _normalizeLogLevel(options.level, types),\n reporters: [...options.reporters || []]\n },\n {\n types: LogTypes,\n throttle: 1e3,\n throttleMin: 5,\n formatOptions: {\n date: true,\n colors: false,\n compact: true\n }\n }\n );\n for (const type in types) {\n const defaults = {\n type,\n ...this.options.defaults,\n ...types[type]\n };\n this[type] = this._wrapLogFn(defaults);\n this[type].raw = this._wrapLogFn(\n defaults,\n true\n );\n }\n if (this.options.mockFn) {\n this.mockTypes();\n }\n this._lastLog = {};\n }\n /**\n * Gets the current log level of the Consola instance.\n *\n * @returns {number} The current log level.\n */\n get level() {\n return this.options.level;\n }\n /**\n * Sets the minimum log level that will be output by the instance.\n *\n * @param {number} level - The new log level to set.\n */\n set level(level) {\n this.options.level = _normalizeLogLevel(\n level,\n this.options.types,\n this.options.level\n );\n }\n /**\n * Displays a prompt to the user and returns the response.\n * Throw an error if `prompt` is not supported by the current configuration.\n *\n * @template T\n * @param {string} message - The message to display in the prompt.\n * @param {T} [opts] - Optional options for the prompt. See {@link PromptOptions}.\n * @returns {promise<T>} A promise that infer with the prompt options. See {@link PromptOptions}.\n */\n prompt(message, opts) {\n if (!this.options.prompt) {\n throw new Error(\"prompt is not supported!\");\n }\n return this.options.prompt(message, opts);\n }\n /**\n * Creates a new instance of Consola, inheriting options from the current instance, with possible overrides.\n *\n * @param {Partial<ConsolaOptions>} options - Optional overrides for the new instance. See {@link ConsolaOptions}.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n create(options) {\n const instance = new Consola({\n ...this.options,\n ...options\n });\n if (this._mockFn) {\n instance.mockTypes(this._mockFn);\n }\n return instance;\n }\n /**\n * Creates a new Consola instance with the specified default log object properties.\n *\n * @param {InputLogObject} defaults - Default properties to include in any log from the new instance. See {@link InputLogObject}.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n withDefaults(defaults) {\n return this.create({\n ...this.options,\n defaults: {\n ...this.options.defaults,\n ...defaults\n }\n });\n }\n /**\n * Creates a new Consola instance with a specified tag, which will be included in every log.\n *\n * @param {string} tag - The tag to include in each log of the new instance.\n * @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.\n */\n withTag(tag) {\n return this.withDefaults({\n tag: this.options.defaults.tag ? this.options.defaults.tag + \":\" + tag : tag\n });\n }\n /**\n * Adds a custom reporter to the Consola instance.\n * Reporters will be called for each log message, depending on their implementation and log level.\n *\n * @param {ConsolaReporter} reporter - The reporter to add. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n addReporter(reporter) {\n this.options.reporters.push(reporter);\n return this;\n }\n /**\n * Removes a custom reporter from the Consola instance.\n * If no reporter is specified, all reporters will be removed.\n *\n * @param {ConsolaReporter} reporter - The reporter to remove. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n removeReporter(reporter) {\n if (reporter) {\n const i = this.options.reporters.indexOf(reporter);\n if (i !== -1) {\n return this.options.reporters.splice(i, 1);\n }\n } else {\n this.options.reporters.splice(0);\n }\n return this;\n }\n /**\n * Replaces all reporters of the Consola instance with the specified array of reporters.\n *\n * @param {ConsolaReporter[]} reporters - The new reporters to set. See {@link ConsolaReporter}.\n * @returns {Consola} The current Consola instance.\n */\n setReporters(reporters) {\n this.options.reporters = Array.isArray(reporters) ? reporters : [reporters];\n return this;\n }\n wrapAll() {\n this.wrapConsole();\n this.wrapStd();\n }\n restoreAll() {\n this.restoreConsole();\n this.restoreStd();\n }\n /**\n * Overrides console methods with Consola logging methods for consistent logging.\n */\n wrapConsole() {\n for (const type in this.options.types) {\n if (!console[\"__\" + type]) {\n console[\"__\" + type] = console[type];\n }\n console[type] = this[type].raw;\n }\n }\n /**\n * Restores the original console methods, removing Consola overrides.\n */\n restoreConsole() {\n for (const type in this.options.types) {\n if (console[\"__\" + type]) {\n console[type] = console[\"__\" + type];\n delete console[\"__\" + type];\n }\n }\n }\n /**\n * Overrides standard output and error streams to redirect them through Consola.\n */\n wrapStd() {\n this._wrapStream(this.options.stdout, \"log\");\n this._wrapStream(this.options.stderr, \"log\");\n }\n _wrapStream(stream, type) {\n if (!stream) {\n return;\n }\n if (!stream.__write) {\n stream.__write = stream.write;\n }\n stream.write = (data) => {\n this[type].raw(String(data).trim());\n };\n }\n /**\n * Restores the original standard output and error streams, removing the Consola redirection.\n */\n restoreStd() {\n this._restoreStream(this.options.stdout);\n this._restoreStream(this.options.stderr);\n }\n _restoreStream(stream) {\n if (!stream) {\n return;\n }\n if (stream.__write) {\n stream.write = stream.__write;\n delete stream.__write;\n }\n }\n /**\n * Pauses logging, queues incoming logs until resumed.\n */\n pauseLogs() {\n paused = true;\n }\n /**\n * Resumes logging, processing any queued logs.\n */\n resumeLogs() {\n paused = false;\n const _queue = queue.splice(0);\n for (const item of _queue) {\n item[0]._logFn(item[1], item[2]);\n }\n }\n /**\n * Replaces logging methods with mocks if a mock function is provided.\n *\n * @param {ConsolaOptions[\"mockFn\"]} mockFn - The function to use for mocking logging methods. See {@link ConsolaOptions[\"mockFn\"]}.\n */\n mockTypes(mockFn) {\n const _mockFn = mockFn || this.options.mockFn;\n this._mockFn = _mockFn;\n if (typeof _mockFn !== \"function\") {\n return;\n }\n for (const type in this.options.types) {\n this[type] = _mockFn(type, this.options.types[type]) || this[type];\n this[type].raw = this[type];\n }\n }\n _wrapLogFn(defaults, isRaw) {\n return (...args) => {\n if (paused) {\n queue.push([this, defaults, args, isRaw]);\n return;\n }\n return this._logFn(defaults, args, isRaw);\n };\n }\n _logFn(defaults, args, isRaw) {\n if ((defaults.level || 0) > this.level) {\n return false;\n }\n const logObj = {\n date: /* @__PURE__ */ new Date(),\n args: [],\n ...defaults,\n level: _normalizeLogLevel(defaults.level, this.options.types)\n };\n if (!isRaw && args.length === 1 && isLogObj(args[0])) {\n Object.assign(logObj, args[0]);\n } else {\n logObj.args = [...args];\n }\n if (logObj.message) {\n logObj.args.unshift(logObj.message);\n delete logObj.message;\n }\n if (logObj.additional) {\n if (!Array.isArray(logObj.additional)) {\n logObj.additional = logObj.additional.split(\"\\n\");\n }\n logObj.args.push(\"\\n\" + logObj.additional.join(\"\\n\"));\n delete logObj.additional;\n }\n logObj.type = typeof logObj.type === \"string\" ? logObj.type.toLowerCase() : \"log\";\n logObj.tag = typeof logObj.tag === \"string\" ? logObj.tag : \"\";\n const resolveLog = (newLog = false) => {\n const repeated = (this._lastLog.count || 0) - this.options.throttleMin;\n if (this._lastLog.object && repeated > 0) {\n const args2 = [...this._lastLog.object.args];\n if (repeated > 1) {\n args2.push(`(repeated ${repeated} times)`);\n }\n this._log({ ...this._lastLog.object, args: args2 });\n this._lastLog.count = 1;\n }\n if (newLog) {\n this._lastLog.object = logObj;\n this._log(logObj);\n }\n };\n clearTimeout(this._lastLog.timeout);\n const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0;\n this._lastLog.time = logObj.date;\n if (diffTime < this.options.throttle) {\n try {\n const serializedLog = JSON.stringify([\n logObj.type,\n logObj.tag,\n logObj.args\n ]);\n const isSameLog = this._lastLog.serialized === serializedLog;\n this._lastLog.serialized = serializedLog;\n if (isSameLog) {\n this._lastLog.count = (this._lastLog.count || 0) + 1;\n if (this._lastLog.count > this.options.throttleMin) {\n this._lastLog.timeout = setTimeout(\n resolveLog,\n this.options.throttle\n );\n return;\n }\n }\n } catch {\n }\n }\n resolveLog(true);\n }\n _log(logObj) {\n for (const reporter of this.options.reporters) {\n reporter.log(logObj, {\n options: this.options\n });\n }\n }\n}\nfunction _normalizeLogLevel(input, types = {}, defaultLevel = 3) {\n if (input === void 0) {\n return defaultLevel;\n }\n if (typeof input === \"number\") {\n return input;\n }\n if (types[input] && types[input].level !== void 0) {\n return types[input].level;\n }\n return defaultLevel;\n}\nConsola.prototype.add = Consola.prototype.addReporter;\nConsola.prototype.remove = Consola.prototype.removeReporter;\nConsola.prototype.clear = Consola.prototype.removeReporter;\nConsola.prototype.withScope = Consola.prototype.withTag;\nConsola.prototype.mock = Consola.prototype.mockTypes;\nConsola.prototype.pause = Consola.prototype.pauseLogs;\nConsola.prototype.resume = Consola.prototype.resumeLogs;\nfunction createConsola(options = {}) {\n return new Consola(options);\n}\n\nexport { Consola, LogLevels, LogTypes, createConsola };\n", "import { createConsola as createConsola$1 } from './core.mjs';\nexport { Consola, LogLevels, LogTypes } from './core.mjs';\n\nclass BrowserReporter {\n options;\n defaultColor;\n levelColorMap;\n typeColorMap;\n constructor(options) {\n this.options = { ...options };\n this.defaultColor = \"#7f8c8d\";\n this.levelColorMap = {\n 0: \"#c0392b\",\n // Red\n 1: \"#f39c12\",\n // Yellow\n 3: \"#00BCD4\"\n // Cyan\n };\n this.typeColorMap = {\n success: \"#2ecc71\"\n // Green\n };\n }\n _getLogFn(level) {\n if (level < 1) {\n return console.__error || console.error;\n }\n if (level === 1) {\n return console.__warn || console.warn;\n }\n return console.__log || console.log;\n }\n log(logObj) {\n const consoleLogFn = this._getLogFn(logObj.level);\n const type = logObj.type === \"log\" ? \"\" : logObj.type;\n const tag = logObj.tag || \"\";\n const color = this.typeColorMap[logObj.type] || this.levelColorMap[logObj.level] || this.defaultColor;\n const style = `\n background: ${color};\n border-radius: 0.5em;\n color: white;\n font-weight: bold;\n padding: 2px 0.5em;\n `;\n const badge = `%c${[tag, type].filter(Boolean).join(\":\")}`;\n if (typeof logObj.args[0] === \"string\") {\n consoleLogFn(\n `${badge}%c ${logObj.args[0]}`,\n style,\n // Empty string as style resets to default console style\n \"\",\n ...logObj.args.slice(1)\n );\n } else {\n consoleLogFn(badge, style, ...logObj.args);\n }\n }\n}\n\nfunction createConsola(options = {}) {\n const consola2 = createConsola$1({\n reporters: options.reporters || [new BrowserReporter({})],\n prompt(message, options2 = {}) {\n if (options2.type === \"confirm\") {\n return Promise.resolve(confirm(message));\n }\n return Promise.resolve(prompt(message));\n },\n ...options\n });\n return consola2;\n}\nconst consola = createConsola();\n\nexport { consola, createConsola, consola as default };\n", "import { createConsola as createConsolaBrowser } from 'consola/browser';\nimport { LogLevels, createConsola as createConsolaCore, } from 'consola/core';\n/**\n * Used to set the logging level.\n *\n * @example Explicitly set the level of an imported package beyond the current runtime level.\n * ```ts\n * import { LogLevel } from '@genesislcap/foundation-logger';\n * import { logger as myPackageLogger } from 'my-package';\n * myPackageLogger.level = LogLevel.Error;\n * ```\n *\n * @public\n */\nexport { LogLevels } from 'consola/core';\n/**\n * The default logger options.\n * @public\n */\nexport const defaultLoggerOptions = {\n level: LogLevels.debug,\n};\n/**\n * Creates a logger with the given name and options.\n *\n * @example Create a logger in my-package/utils.\n * ```ts\n * import { createLogger } from '@genesislcap/foundation-logger';\n * export const logger = createLogger('my-package');\n * ```\n *\n * @example Using the logger within my-package.\n * ```ts\n * import { logger } from '../utils';\n * logger.debug(`Data retrieved from ${resourceName}`);\n * logger.info(this.toggled ? 'On' : 'Off');\n * logger.warn('Not available in this browser.');\n * ```\n *\n * @example Explicitly set the level of an imported package.\n * ```ts\n * import { logger as commsLogger } from '@genesislcap/foundation-comms';\n * import { LogLevel } from '@genesislcap/foundation-logger';\n * commsLogger.level = LogLevel.Warn;\n * ```\n *\n * @param name - The name to give the logger.\n * @param options - The options to use when creating the logger.\n * @returns The resulting logger.\n * @public\n */\nexport function createLogger(name, options = defaultLoggerOptions) {\n const createConsola = typeof window !== 'undefined' ? createConsolaBrowser : createConsolaCore;\n const logger = createConsola().withTag(name);\n if ((options === null || options === void 0 ? void 0 : options.level) !== undefined)\n logger.level = options.level;\n const typedLogger = logger;\n typedLogger.deprecated = (symbol, instruction = 'Consult docs for better alternative.', removalVersionTarget) => {\n typedLogger.warn(`Deprecated symbol used '${symbol}'. ${instruction}`, `${removalVersionTarget ? `Will be removed in version ${removalVersionTarget}.` : ''}`);\n };\n return typedLogger;\n}\n", "import { createLogger } from '@genesislcap/foundation-logger';\nexport const logger = createLogger('foundation-ai');\n", "import { logger } from '../utils';\nconst CLAUSE_SCHEMA = {\n type: 'object',\n properties: {\n field: { type: 'string', description: 'Field name from available metadata' },\n operator: {\n type: 'string',\n enum: [\n 'contains',\n 'equals',\n 'startsWith',\n 'endsWith',\n 'greaterThan',\n 'lessThan',\n 'greaterThanOrEqual',\n 'lessThanOrEqual',\n 'notEqual',\n 'dateIsToday',\n 'dateIsAfter',\n 'dateIsBefore',\n 'dateIsEqual',\n 'dateIsGreaterEqual',\n 'dateIsLessEqual',\n 'dateTimeIsAfter',\n 'dateTimeIsBefore',\n 'dateTimeIsGreaterEqual',\n 'dateTimeIsLessEqual',\n ],\n },\n value: {\n type: ['string', 'number', 'boolean', 'null'],\n description: 'Value for the clause; null for dateIsToday',\n },\n },\n required: ['field', 'operator', 'value'],\n additionalProperties: false,\n};\n/**\n * Standard JSON Schema for criteria interpretation output.\n * Used by Chrome Prompt API (responseConstraint) and other providers.\n *\n * @beta\n */\nexport const CRITERIA_JSON_SCHEMA = {\n type: 'object',\n properties: {\n groups: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n logic: {\n type: 'string',\n enum: ['and', 'or'],\n description: 'How clauses within the group are combined',\n },\n negated: {\n type: 'boolean',\n default: false,\n description: 'If true, negate the entire group',\n },\n clauses: {\n type: 'array',\n items: CLAUSE_SCHEMA,\n },\n },\n required: ['logic', 'negated', 'clauses'],\n additionalProperties: false,\n },\n },\n },\n required: ['groups'],\n additionalProperties: false,\n};\n/**\n * OpenAI-specific response_format wrapper for structured output.\n *\n * @beta\n */\nexport const OPENAI_CRITERIA_RESPONSE_FORMAT = {\n type: 'json_schema',\n json_schema: {\n name: 'criteria_interpretation',\n strict: true,\n schema: CRITERIA_JSON_SCHEMA,\n },\n};\nconst DEFAULT_SYSTEM_PROMPT = `You are a criteria builder. Convert natural language into structured search criteria.\nReturn a JSON object with a \"groups\" array. Each group has: logic (\"and\" or \"or\"), optional negated (boolean), and clauses (array).\nEach clause has: field (string), operator (from enum), value (string|number|boolean|null).\n- When the user says \"or\" (e.g. \"quantity 100 or price > 50\"), use a group with logic \"or\" and multiple clauses.\n- When the user says \"not\" or \"except\", set negated: true on the group.\n- When the user says \"and\" or lists conditions without \"or\", use logic \"and\".\nUse dateIsToday with value null for \"today\" queries. Use yyyyMMdd for dates, yyyyMMdd-HH:mm for datetimes.`;\n/**\n * Builds the system prompt for criteria interpretation.\n *\n * @beta\n */\nexport function buildCriteriaSystemPrompt(fields = [], customInstructions) {\n const fieldList = fields\n .map((f) => {\n var _a, _b, _c, _d;\n return typeof f === 'string'\n ? f\n : ((_d = (_c = (_b = (_a = f === null || f === void 0 ? void 0 : f.NAME) !== null && _a !== void 0 ? _a : f === null || f === void 0 ? void 0 : f.name) !== null && _b !== void 0 ? _b : f === null || f === void 0 ? void 0 : f.field) !== null && _c !== void 0 ? _c : f === null || f === void 0 ? void 0 : f.label) !== null && _d !== void 0 ? _d : '');\n })\n .filter(Boolean)\n .join(', ');\n const basePrompt = customInstructions !== null && customInstructions !== void 0 ? customInstructions : DEFAULT_SYSTEM_PROMPT;\n const fieldsLine = `Available fields: ${fieldList || 'unknown - use common field names like NAME, ID, DATE, etc.'}`;\n return `${basePrompt}\\n${fieldsLine}`;\n}\n/**\n * Builds the user prompt for criteria interpretation.\n *\n * @beta\n */\nexport function buildCriteriaUserPrompt(input) {\n return `Convert to criteria: \"${input}\"`;\n}\n/**\n * Parses the raw response text into CriteriaInterpretationResult.\n *\n * @beta\n */\nexport function parseCriteriaResponse(text) {\n if (!(text === null || text === void 0 ? void 0 : text.trim())) {\n logger.debug('parseCriteriaResponse: empty or null input');\n return null;\n }\n try {\n const parsed = JSON.parse(text);\n if (!(parsed === null || parsed === void 0 ? void 0 : parsed.groups) || !Array.isArray(parsed.groups)) {\n logger.debug('parseCriteriaResponse: missing or invalid groups in response');\n return null;\n }\n return {\n groups: parsed.groups,\n };\n }\n catch (e) {\n logger.debug('parseCriteriaResponse: invalid JSON', e);\n return null;\n }\n}\n", "import { __asyncDelegator, __asyncGenerator, __asyncValues, __await, __awaiter } from \"tslib\";\nimport { buildCriteriaSystemPrompt, buildCriteriaUserPrompt, CRITERIA_JSON_SCHEMA, parseCriteriaResponse, } from '../interactions';\nimport { logger } from '../utils';\n/**\n * Anthropic Claude AI provider. Uses {@link AnthropicTransport} to handle requests.\n * Implements criteria interpretation and multi-turn chat.\n *\n * @beta\n */\nexport class AnthropicProvider {\n constructor(config, transport) {\n this.transport = transport;\n this.criteriaInstructions = config.criteriaInstructions;\n }\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n const config = this.transport.getConfig();\n return { provider: 'anthropic', model: config.model, contextLimit: config.contextLimit };\n });\n }\n interpretCriteria(input, context) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const fields = (_a = context === null || context === void 0 ? void 0 : context.fields) !== null && _a !== void 0 ? _a : [];\n const systemPrompt = buildCriteriaSystemPrompt(fields, this.criteriaInstructions);\n const userPrompt = buildCriteriaUserPrompt(input);\n try {\n const raw = yield this.transport.sendStructuredPrompt({\n systemPrompt,\n userPrompt,\n responseSchema: CRITERIA_JSON_SCHEMA,\n });\n return parseCriteriaResponse(raw);\n }\n catch (e) {\n logger.error('AnthropicProvider interpretCriteria failed:', e);\n return null;\n }\n });\n }\n prompt(message, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const response = yield this.transport.sendChatMessage([], message, options);\n return response.content;\n });\n }\n chat(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.transport.sendChatMessage(history, userMessage, options);\n });\n }\n streamChat(history, userMessage, options) {\n return __asyncGenerator(this, arguments, function* streamChat_1() {\n if ('streamChatMessage' in this.transport &&\n typeof this.transport.streamChatMessage === 'function') {\n yield __await(yield* __asyncDelegator(__asyncValues(this.transport.streamChatMessage(history, userMessage, options))));\n }\n else {\n const msg = yield __await(this.transport.sendChatMessage(history, userMessage, options));\n yield yield __await({ delta: msg.content, done: true, toolCalls: msg.toolCalls });\n }\n });\n }\n}\n", "import { __awaiter } from \"tslib\";\n/**\n * Default no-op AI provider. Used when no provider is configured.\n * Components should check for capability support and show \"Configure AI\" state when appropriate.\n *\n * @beta\n */\nexport class DefaultAIProvider {\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n return { provider: 'none', model: '' };\n });\n }\n interpretCriteria(_input, _context) {\n return __awaiter(this, void 0, void 0, function* () {\n return null;\n });\n }\n}\n", "import { __asyncDelegator, __asyncGenerator, __asyncValues, __await, __awaiter } from \"tslib\";\nimport { buildCriteriaSystemPrompt, buildCriteriaUserPrompt, CRITERIA_JSON_SCHEMA, parseCriteriaResponse, } from '../interactions';\nimport { logger } from '../utils';\n/**\n * Gemini AI provider. Uses {@link GeminiTransport} to handle requests.\n * Implements criteria interpretation and multi-turn chat.\n *\n * @beta\n */\nexport class GeminiProvider {\n constructor(config, transport) {\n this.transport = transport;\n this.criteriaInstructions = config.criteriaInstructions;\n }\n getStatus() {\n return __awaiter(this, void 0, void 0, function* () {\n const config = this.transport.getConfig();\n return { provider: 'gemini', model: config.model, contextLimit: config.contextLimit };\n });\n }\n interpretCriteria(input, context) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const fields = (_a = context === null || context === void 0 ? void 0 : context.fields) !== null && _a !== void 0 ? _a : [];\n const systemPrompt = buildCriteriaSystemPrompt(fields, this.criteriaInstructions);\n const userPrompt = buildCriteriaUserPrompt(input);\n try {\n const raw = yield this.transport.sendStructuredPrompt({\n systemPrompt,\n userPrompt,\n responseSchema: CRITERIA_JSON_SCHEMA,\n });\n return parseCriteriaResponse(raw);\n }\n catch (e) {\n logger.error('GeminiProvider interpretCriteria failed:', e);\n return null;\n }\n });\n }\n prompt(message, options) {\n return __awaiter(this, void 0, void 0, function* () {\n const response = yield this.transport.sendChatMessage([], message, options);\n return response.content;\n });\n }\n chat(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n return this.transport.sendChatMessage(history, userMessage, options);\n });\n }\n streamChat(history, userMessage, options) {\n return __asyncGenerator(this, arguments, function* streamChat_1() {\n if ('streamChatMessage' in this.transport &&\n typeof this.transport.streamChatMessage === 'function') {\n yield __await(yield* __asyncDelegator(__asyncValues(this.transport.streamChatMessage(history, userMessage, options))));\n }\n else {\n // Fallback: non-streaming chat exposed as a single chunk\n const msg = yield __await(this.transport.sendChatMessage(history, userMessage, options));\n yield yield __await({ delta: msg.content, done: true, toolCalls: msg.toolCalls });\n }\n });\n }\n}\n", "/**\n * The AI-spend budget wall (GENC-1464 workstream C/D).\n *\n * Lives in its own module rather than beside `ResponseTruncatedError` in\n * `anthropic-transport.ts` because it is raised from `post-with-retry.ts`, which\n * both transports import \u2014 homing it in a transport would close an import cycle\n * (transport \u2192 post-with-retry \u2192 transport) that the repo's `circular` check\n * rejects.\n */\n/** The proxy's machine-readable rejection code for an exhausted AI budget. */\nexport const BUDGET_EXCEEDED_CODE = 'BUDGET_EXCEEDED';\n/**\n * Display name for each concrete AI vendor: the **single source** every\n * transport's `vendorLabel` is read from, and the only place a vendor's name is\n * spelled for a user.\n *\n * This map is the hinge of the per-vendor budget model (GENC-1464). A wall is\n * attributed to a vendor by reverse-looking-up the label the refused transport\n * stamped on its {@link BudgetExhaustedError} \u2014 so a label that drifts from this\n * map (a literal typo, a casing change, a new vendor added with a hardcoded\n * string) silently degrades every wall from that transport to \"unattributable\"\n * and re-locks the whole session instead of just that vendor. It fails safe, but\n * the feature quietly stops working, which is why the transports read their label\n * from here rather than restating it.\n *\n * The map has **two kinds of entry**, and the difference matters:\n *\n * - The {@link BUDGETED_VENDORS} \u2014 `anthropic` and `gemini` \u2014 reach the model\n * through the ai-service proxy, are metered by it, and stamp their label on a\n * {@link BudgetExhaustedError}. For these the label is both an attribution key\n * and display copy.\n * - `chrome` and `openai` are **display-only**. `ChromeProvider` talks to the\n * on-device Prompt API and the proxy refuses `openai` outright, so neither can\n * be refused for budget or stamp a label \u2014 but both report a `provider` from\n * `getStatus()`, which puts them in the assistant's reachable set, which is\n * what the blocked banner names when it tells a walled user where they can\n * still go (\"Switch to Chrome to keep going.\"). Dropping either entry would\n * print the raw type there.\n *\n * `'none'` is excluded deliberately: it is the \"no provider configured\" sentinel,\n * not a vendor, and nothing can be refused by it \u2014 nor switched to.\n *\n * @beta\n */\nexport const VENDOR_LABELS = Object.freeze({\n anthropic: 'Anthropic',\n gemini: 'Gemini',\n openai: 'OpenAI',\n chrome: 'Chrome',\n});\n/**\n * The vendors whose spend the ai-service proxy meters \u2014 i.e. the only vendors\n * that can raise a {@link BudgetExhaustedError}, and therefore the only ones a\n * 402's `otherVendorAvailable: false` is a statement about.\n *\n * Deliberately narrower than the keys of {@link VENDOR_LABELS}, and it must stay\n * exactly the proxy's own list \u2014 `VENDORS` in ai-service's `utils/aiVendor.js`.\n * A vendor listed here that the proxy does not meter gets walled by the\n * `otherVendorAvailable: false` sweep on a verdict that says nothing about it,\n * and if it is reachable, `blocked` then derives true and locks a composer with\n * headroom left.\n *\n * Two vendors are excluded for that reason:\n * - `chrome` runs on-device \u2014 no pot to exhaust, and free.\n * - `openai` is **not budgeted by the proxy**. ai-service rejects it up front\n * with `400 UNSUPPORTED_PROVIDER` (`SUPPORTED_PROVIDERS` in `aiVendor.js`), no\n * `MODEL_PRICING` row names it, and `otherVendorAvailable` is computed over\n * Anthropic and Gemini alone. So it can never raise a 402, and a 402 is never\n * a statement about it.\n *\n * @beta\n */\nexport const BUDGETED_VENDORS = Object.freeze([\n 'anthropic',\n 'gemini',\n]);\n/**\n * Whether this vendor's spend is metered by the proxy \u2014 see\n * {@link BUDGETED_VENDORS}.\n *\n * A HOST-FACING helper with, deliberately, no internal caller: the library's\n * own consumers iterate {@link BUDGETED_VENDORS} directly (structural, cannot\n * drift), while a host writing its own budget pre-flight or status surface\n * needs the membership test in predicate form. Kept exported for that use \u2014\n * genesis-create's pre-flight is the shape of consumer it exists for.\n *\n * @beta\n */\nexport const isBudgetedVendor = (vendor) => vendor != null && BUDGETED_VENDORS.includes(vendor);\n/** Reverse index of {@link VENDOR_LABELS}, lower-cased, built once. */\nconst VENDOR_TYPE_BY_LABEL = new Map(Object.entries(VENDOR_LABELS).map(([type, label]) => [\n label.toLowerCase(),\n type,\n]));\n/**\n * The {@link AIProviderType} behind a vendor label, or `undefined` for a label\n * no vendor claims.\n *\n * Case-insensitive and whitespace-tolerant, because the label travels as free\n * text on the wire (the driver contract carries `vendorLabel`, not the type) and\n * an unrecognised label must degrade to \"unattributable\" rather than to a wrong\n * attribution \u2014 blocking the wrong vendor is worse than blocking none.\n *\n * @beta\n */\nexport function vendorTypeOfLabel(label) {\n if (typeof label !== 'string')\n return undefined;\n return VENDOR_TYPE_BY_LABEL.get(label.trim().toLowerCase());\n}\n/**\n * HTTP status the ai-service proxy rejects an over-budget request with, in both\n * the legacy JSON mode (the response status) and the NDJSON framed mode (the\n * `status` on the terminal `err` frame).\n *\n * Deliberately **absent** from every transport's `RETRYABLE_STATUSES`: the budget\n * does not refill on a backoff ladder, so retrying only delays the inevitable\n * five times over.\n */\nexport const BUDGET_EXCEEDED_STATUS = 402;\n/**\n * The single copy shown to a user whose AI budget is gone \u2014 the transcript bubble\n * the chat driver appends, and the default text of the assistant's blocked banner.\n *\n * Deliberately **vendor-neutral**: the same bundle ships to white-labelled\n * deployments where \"contact Genesis\" is simply wrong. A host that wants\n * branded wording overrides both surfaces \u2014 the banner via\n * `FoundationAiAssistant.setBlocked(true, reason)`, the transcript bubble via\n * `ChatDriverConfig.budgetExhaustedMessage` \u2014 so neither is stuck with this\n * default while the other is customised.\n *\n * @beta\n */\nexport const DEFAULT_BUDGET_EXHAUSTED_MESSAGE = \"You've reached your AI usage limit. Contact your administrator to raise it.\";\n/**\n * Thrown when the AI-spend budget for the caller (user, tenant, or project) is\n * exhausted and the ai-service proxy refuses the request outright \u2014 HTTP `402`\n * with `code: 'BUDGET_EXCEEDED'`, in either the legacy JSON or the NDJSON framed\n * mode.\n *\n * This is a **terminal, non-transient** condition, in the same family as\n * `ResponseTruncatedError`: no amount of retrying clears it, because nothing\n * about the request is wrong. The budget has to be raised out-of-band before any\n * further call can succeed, so both the transport retry ladder and the driver's\n * transient-retry catch step aside for it and the failure surfaces immediately\n * as the `'budget-exhausted'` `TurnFailureReason`.\n *\n * `budgetUsd`/`spentUsd` are populated from the rejection body when the proxy\n * supplies them (the workstream-C contract does); they are optional because a\n * plain-text or truncated 402 from an older proxy still has to classify.\n *\n * @beta\n */\nexport class BudgetExhaustedError extends Error {\n constructor(\n /** Vendor label of the transport that was refused (e.g. `'Anthropic'`). */\n vendorLabel, \n /** The configured spend cap in USD, when the proxy reported one. */\n budgetUsd, \n /** Spend already booked against that cap in USD, when the proxy reported it. */\n spentUsd, \n /** The proxy's human-readable rejection message, when present. */\n detail, \n /**\n * The fields the proxy reports about the wider budget picture. An object\n * rather than two more positional arguments: the four above are already the\n * limit of what reads at a call site, and these two are set together or not\n * at all.\n */\n extra) {\n super(`${vendorLabel} request refused: the AI usage budget is exhausted` +\n (budgetUsd != null\n ? ` (spent ${spentUsd != null ? `$${spentUsd}` : 'an unknown amount'} of a $${budgetUsd} budget)`\n : '') +\n (detail ? `: ${detail}` : '') +\n '. Retrying will not clear this \u2014 the budget must be raised.');\n this.vendorLabel = vendorLabel;\n this.budgetUsd = budgetUsd;\n this.spentUsd = spentUsd;\n this.detail = detail;\n this.name = 'BudgetExhaustedError';\n this.otherVendorAvailable = extra === null || extra === void 0 ? void 0 : extra.otherVendorAvailable;\n this.serverVendor = extra === null || extra === void 0 ? void 0 : extra.serverVendor;\n }\n}\n/**\n * True for a budget rejection in either wire mode: the contracted `402`, or the\n * `BUDGET_EXCEEDED` code under **any** status.\n *\n * Both keys are load-bearing, and they are not redundant:\n *\n * - `status` is the key the workstream-C contract guarantees (\"402 always\"), and\n * the only one a plain-text or unparseable rejection carries.\n * - `code` is the cheap defence against that contract drifting. Nothing stops a\n * proxy from mapping the refusal onto `403` or `429` \u2014 and `429` is in *both*\n * transports' `RETRYABLE_STATUSES`, so a status-only check would hand the user\n * the exact bug GENC-1464 exists to fix: five doomed requests and ~31s of backoff\n * before an opaque failure. A well-formed `{ t: 'err', status: 429, code:\n * 'BUDGET_EXCEEDED' }` frame is accepted by `readFramedBody` (it only rejects a\n * non-numeric status), so this is a reachable shape, not a hypothetical one.\n *\n * The false-positive cost is a proxy sending `code: 'BUDGET_EXCEEDED'` on a\n * genuinely retryable failure \u2014 a shape the contract does not permit.\n *\n * Internal to the transports (unlike `BudgetExhaustedError`, which hosts branch\n * on): deliberately **not** re-exported from the package index.\n *\n * @internal\n */\nexport const isBudgetRejection = (status, code) => status === BUDGET_EXCEEDED_STATUS || code === BUDGET_EXCEEDED_CODE;\n/**\n * Best-effort JSON parse of an error body \u2014 `undefined` rather than a throw.\n * Shared by every caller that has to classify a rejection body before it knows\n * whether the body is JSON at all.\n *\n * @internal\n */\nexport const parseJsonOrUndefined = (text) => {\n try {\n return JSON.parse(text);\n }\n catch (_a) {\n return undefined;\n }\n};\n/**\n * Read the `code` field off an already-parsed rejection body, ignoring anything\n * that is not a string. Pairs with {@link isBudgetRejection} at the legacy call\n * sites, which have a parsed body rather than a typed frame.\n *\n * @internal\n */\nexport const codeOf = (payload) => {\n const code = payload === null || payload === void 0 ? void 0 : payload.code;\n return typeof code === 'string' ? code : undefined;\n};\n/** Narrow an unknown JSON value to a number, ignoring anything else. */\nconst numberOrUndefined = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n/** Narrow an unknown JSON value to a boolean, ignoring anything else. */\nconst booleanOrUndefined = (value) => typeof value === 'boolean' ? value : undefined;\n/** Narrow an unknown JSON value to a non-empty string, ignoring anything else. */\nconst stringOrUndefined = (value) => typeof value === 'string' && value.trim() !== '' ? value : undefined;\n/**\n * Build a {@link BudgetExhaustedError} from a rejection payload of either shape:\n * the legacy body `{ error, code, budgetUsd, spentUsd, vendor,\n * otherVendorAvailable }` or the framed err frame's `details` (the same fields\n * minus `error`) plus its top-level `error`.\n *\n * The fields read off the wire, and why each is here:\n *\n * | field | used for |\n * | ---------------------- | ----------------------------------------------------- |\n * | `budgetUsd` | the cap in the banner's figures |\n * | `spentUsd` | the spend in the banner's figures |\n * | `error` | the proxy's human-readable detail |\n * | `vendor` | attribution when the transport's own label is unclaimed |\n * | `otherVendorAvailable` | whether \"switch vendor\" is honest advice at all |\n *\n * Tolerant by design \u2014 a `402` classifies even when the payload is missing,\n * unparseable, or carries none of these. Each field is narrowed independently,\n * so a proxy that sends `null` for a figure it does not know (which the\n * ai-service side now does, in preference to a misleading `0`) still yields the\n * vendor and the availability verdict.\n */\nexport function budgetExhaustedFrom(vendorLabel, payload, fallbackDetail) {\n var _a, _b, _c, _d;\n const body = (typeof payload === 'object' && payload !== null ? payload : {});\n // The framed shape nests everything but `error` under `details`; the legacy\n // body has it all at the top level. Read both so one helper serves both call\n // sites.\n const details = (typeof body.details === 'object' && body.details !== null ? body.details : {});\n const detail = typeof body.error === 'string' ? body.error : fallbackDetail;\n return new BudgetExhaustedError(vendorLabel, (_a = numberOrUndefined(body.budgetUsd)) !== null && _a !== void 0 ? _a : numberOrUndefined(details.budgetUsd), (_b = numberOrUndefined(body.spentUsd)) !== null && _b !== void 0 ? _b : numberOrUndefined(details.spentUsd), detail, {\n otherVendorAvailable: (_c = booleanOrUndefined(body.otherVendorAvailable)) !== null && _c !== void 0 ? _c : booleanOrUndefined(details.otherVendorAvailable),\n serverVendor: (_d = stringOrUndefined(body.vendor)) !== null && _d !== void 0 ? _d : stringOrUndefined(details.vendor),\n });\n}\n", "/**\n * The PROVIDER wall (GENC-1506) \u2014 the upstream vendor refusing this account, as opposed to the\n * ai-service proxy refusing this user's own spend budget (`budget-exhausted-error.ts`, GENC-1464).\n *\n * The two are constantly confused, so state the difference once: a\n * {@link BudgetExhaustedError} means *we* declined to spend more on the caller's behalf and an\n * administrator can raise the cap; a {@link ProviderRefusedError} means *Anthropic or Google*\n * declined to serve the request at all, and no amount of budget-raising in our own system changes\n * that. Both are terminal, neither is retryable, and they need different people to fix them.\n *\n * Lives in its own module for the same reason its sibling does: it is raised from\n * `post-with-retry.ts`, which both transports import, so homing it in a transport would close an\n * import cycle the repo's `circular` check rejects.\n *\n * ## Scope: Anthropic only, deliberately\n *\n * Gemini is **not** classified here yet (GENC-1506, Matt's call 2026-08-18). It is not an oversight\n * and it is not because Gemini cannot fail this way \u2014 it is because Gemini's failure shapes are\n * genuinely different and only partly observed:\n *\n * - Google's paid tiers refuse a spend cap with `429 RESOURCE_EXHAUSTED`, which is **the same status\n * and the same message text** as an ordinary rate limit, and `429` is in\n * `GeminiTransport.RETRYABLE_STATUSES`. A prose probe there would classify routine rate limiting as\n * terminal and break the retry ladder \u2014 the exact inverse of the Anthropic situation below.\n * - The discriminator that *would* work is structural \u2014 `details[].QuotaFailure.violations[].quotaId`\n * names the limit's scope (`\u2026PerMinute\u2026` is retryable, per-day or spend-scoped is not) \u2014 but only\n * the per-minute free-tier value has been observed. Guessing the others is what this module's\n * history says not to do.\n * - Google's Prepay balance hitting $0 stops every key on the billing account at once, and its error\n * shape is neither documented nor observed.\n *\n * So {@link providerRefusalOf} dispatches on vendor and answers `undefined` for anything that is not\n * Anthropic. Adding Gemini later is a new branch, not a rewrite \u2014 which is why the vendor is a\n * parameter rather than an assumption.\n *\n * @packageDocumentation\n */\nimport { VENDOR_LABELS } from './budget-exhausted-error';\n/**\n * The proxy's machine-readable code for \"the upstream vendor refused this account\".\n *\n * Deliberately distinct from `BUDGET_EXCEEDED`: the ai-service proxy stamps this when it relays a\n * provider refusal, so the client can tell a relayed upstream fault from the proxy's own budget\n * verdict without inspecting the body at all.\n *\n * Exported from the package index \u2014 unlike its `BUDGET_EXCEEDED_CODE` sibling, which is internal \u2014\n * because the SERVER side of the contract lives in another repo (genesis-create's ai-service stamps\n * this code onto its proxy responses). A hand-copied string literal there would drift on the first\n * rename, and the drift would be silent: the client would simply stop classifying.\n *\n * @beta\n */\nexport const PROVIDER_REFUSED_CODE = 'PROVIDER_REFUSED';\n/**\n * The single sentence shown to a user whose provider has refused \u2014 the transcript bubble the chat\n * driver appends, and the string ai-service reuses for its own generation surfaces.\n *\n * **It names no cause, and that is the whole design.** Three constraints shaped it, and a rewrite\n * has to clear all three:\n *\n * 1. **It must not sound like a cap.** The user can often see their remaining AI spend in the same\n * UI, so *allowance / limit / quota / budget / usage / credit / balance* risk a visible\n * self-contradiction: a message saying there is nothing left, next to a figure showing there is.\n * \"isn't related to your account **or your usage**\" goes further than avoiding the words \u2014 it\n * pre-empts the user checking that figure and concluding the message is wrong.\n * 2. **It must not imply we cannot pay our bills.** *Billing / payment / funds / top up* all read as\n * an unpaid invoice. Naming no cause means there is nothing to be embarrassed by and nothing for\n * the user to contradict.\n * 3. **It must not promise self-healing.** Clearing this needs a human to act out of band, so\n * \"currently\" rather than \"temporarily\", and \"so it can be restored\" positively signals that\n * someone must do something.\n *\n * It is also true of **both** {@link ProviderRefusalKind}s unchanged, which is what makes one\n * sentence for two kinds honest rather than a fudge: for an expired key the provider *is* refusing,\n * it *is* unrelated to the user's own account and usage, they *can* do nothing, and support *can*\n * restore it.\n *\n * Vendor-neutral and deployment-neutral on purpose \u2014 the same bundle ships to white-labelled\n * deployments where naming a vendor, or naming Genesis, would be wrong. A host that wants different\n * wording sets `ChatDriverConfig.providerRefusedMessage`.\n *\n * @beta\n */\nexport const DEFAULT_PROVIDER_REFUSED_MESSAGE = \"AI requests are currently being refused by the provider. This isn't related to your account or \" +\n 'your usage and needs no action from you \u2014 please contact your support team so it can be restored.';\n/**\n * Thrown when the upstream provider refuses the request because of the state of the **account**\n * rather than anything about the request \u2014 see {@link ProviderRefusalKind}.\n *\n * Terminal and non-transient, in the same family as `ResponseTruncatedError` and\n * `BudgetExhaustedError`: retrying cannot clear it, because nothing about the request is wrong. So\n * both the transport retry ladder and the driver's transient-retry catch step aside for it and the\n * failure surfaces immediately as the `'provider-refused'` `TurnFailureReason`.\n *\n * @beta\n */\nexport class ProviderRefusedError extends Error {\n constructor(\n /** Vendor label of the transport that was refused (e.g. `'Anthropic'`). */\n vendorLabel, \n /** Which kind of refusal \u2014 drives the log and the operator's fix, never the user's message. */\n kind, \n /**\n * The provider's own HTTP status, when known.\n *\n * Diagnostic only, and deliberately not part of the classification contract: the observed spend\n * refusals arrive as `400` (not the `402 billing_error` the docs describe), so a consumer that\n * branched on this would be encoding one snapshot of provider behaviour.\n */\n upstreamStatus, \n /** The provider's own `error.type` (e.g. `'invalid_request_error'`, `'authentication_error'`). */\n upstreamType, \n /** The provider's human-readable message, verbatim, for the log. Never shown to the user. */\n detail) {\n super(`${vendorLabel} refused the request (${kind})` +\n (upstreamStatus != null ? ` \u2014 HTTP ${upstreamStatus}` : '') +\n (upstreamType ? ` ${upstreamType}` : '') +\n (detail ? `: ${detail}` : '') +\n '. Retrying will not clear this \u2014 the provider account must be fixed.');\n this.vendorLabel = vendorLabel;\n this.kind = kind;\n this.upstreamStatus = upstreamStatus;\n this.upstreamType = upstreamType;\n this.detail = detail;\n this.name = 'ProviderRefusedError';\n }\n}\n/**\n * Phrases that identify a spend refusal hiding inside Anthropic's **generic**\n * `invalid_request_error` bucket.\n *\n * Prose matching is not a shortcut here, it is the only handle available, and that is a measured\n * fact rather than an assumption. Both refusals we have captured arrive as `400` +\n * `invalid_request_error` with **no distinct type, no dedicated header and nothing else structural**:\n *\n * | Captured 2026-08-18 | Message |\n * | --- | --- |\n * | Credit balance at zero | `Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.` |\n * | Workspace usage cap | `You have reached your specified workspace API usage limits. You will regain access on 2026-09-01 at 00:00 UTC.` |\n *\n * A classifier keyed only on the documented `402 billing_error` signal would have matched **neither**\n * and shipped a non-fix. That is why this list exists.\n *\n * **Independent signals, not whole sentences.** A sentence list would need a new entry every time a\n * member is reworded, and would silently stop matching in the meantime. `credit balance` and\n * `usage limit` are each confirmed against a capture above; `spend limit` and the `insufficient \u2026`\n * form are unobserved and included as cheap tolerance for the same family.\n *\n * **False positives are near-impossible**, for a reason that is easy to miss: on a refused account\n * the spend check runs *before* request validation (verified \u2014 a deliberately malformed request on a\n * dry key still returned the credit message), so a genuine schema `400` is only observable on a\n * healthy account, where its message quotes field paths and matches nothing here.\n *\n * Deletable the day Anthropic gives this family its own `error.type`.\n */\nconst ANTHROPIC_SPEND_PHRASES = Object.freeze([\n /credit balance/i,\n /usage limit/i,\n /spend limit/i,\n /insufficient (credit|funds|balance)/i,\n]);\n/** Anthropic `error.type` values that are an auth refusal, straight from the documented table. */\nconst ANTHROPIC_AUTH_TYPES = Object.freeze([\n 'authentication_error',\n 'permission_error',\n]);\n/**\n * The inner `{ type, message }` of an Anthropic error envelope, from wherever it is on the wire.\n *\n * Two positions, both load-bearing, because the same refusal reaches us in two shapes:\n * - **direct API and legacy JSON proxy** \u2014 the envelope IS the body:\n * `{ type: 'error', error: { type, message } }`;\n * - **NDJSON framed proxy** \u2014 the envelope is nested under the err frame's `details`, while the\n * frame's own top-level `error` is a *string* (the proxy's summary).\n *\n * So reading only the top level would classify nothing on the browser path, and reading only\n * `details` would classify nothing on the server path. Mirrors how `budgetExhaustedFrom` reads both.\n */\nfunction anthropicErrorBody(payload) {\n var _a;\n const outer = typeof payload === 'object' && payload !== null ? payload : {};\n // Framed: `details` holds the upstream envelope. Legacy/direct: the body itself does.\n for (const candidate of [\n outer.error,\n (_a = outer.details) === null || _a === void 0 ? void 0 : _a.error,\n ]) {\n if (typeof candidate === 'object' && candidate !== null) {\n const { type, message } = candidate;\n return {\n type: typeof type === 'string' ? type : undefined,\n message: typeof message === 'string' ? message : undefined,\n };\n }\n }\n return undefined;\n}\n/**\n * A `kind` the caller stated explicitly, from either wire position, or `undefined`.\n *\n * Both positions are read for the same reason `anthropicErrorBody` reads two: a JSON body carries its\n * fields at the top level, while an NDJSON err frame nests everything but `error` under `details`.\n */\nfunction statedKind(payload) {\n const outer = (typeof payload === 'object' && payload !== null ? payload : {});\n const nested = (typeof outer.details === 'object' && outer.details !== null ? outer.details : {});\n for (const candidate of [outer.kind, nested.kind]) {\n if (candidate === 'auth' || candidate === 'spend')\n return candidate;\n }\n return undefined;\n}\n/**\n * The kind implied by the provider envelope's `type` alone \u2014 no prose, no status.\n *\n * Vendor-agnostic on purpose, so the explicit-code path can reuse it: by the time the proxy has\n * stamped `PROVIDER_REFUSED` it has already decided this is a refusal, and all that is left is which\n * kind \u2014 a question the relayed envelope answers without any vendor dispatch.\n */\nfunction kindFromEnvelopeType(payload) {\n const body = anthropicErrorBody(payload);\n if (!(body === null || body === void 0 ? void 0 : body.type))\n return undefined;\n if (ANTHROPIC_AUTH_TYPES.includes(body.type))\n return 'auth';\n // The documented billing signal. Unobserved by us \u2014 every real spend refusal we captured came\n // through the generic bucket \u2014 but it is in the errors table, so honour it.\n if (body.type === 'billing_error')\n return 'spend';\n return undefined;\n}\n/**\n * Classify a rejection as a provider refusal, or `undefined` for anything else.\n *\n * **Every trigger is a POSITIVE signal \u2014 status alone never classifies.** That is what keeps this\n * from stealing the proxy's own `402 BUDGET_EXCEEDED`: a bare `402` with no provider envelope\n * carries nothing this function recognises, so it falls through to the budget classification exactly\n * as it did before this module existed. A `402` that *does* carry an Anthropic envelope is a relayed\n * upstream fault and is claimed here \u2014 which is the collision GENC-1506 set out to close, closed by\n * ordering and positive detection rather than by loosening the budget predicate.\n *\n * @param vendor - which vendor's transport was refused. Anything but `'anthropic'` returns\n * `undefined` today; see this module's header for why Gemini is deliberately absent.\n * @param code - the proxy's machine-readable code, when there is one (`err` frame or JSON body).\n * @param payload - the parsed rejection body, or the parsed `err` frame.\n */\nexport function providerRefusalOf(vendor, code, payload) {\n var _a, _b;\n // The proxy's explicit signal wins over any body inspection, in any status. It is the one route\n // that needs no vendor knowledge at all \u2014 the proxy has already done the classifying.\n //\n // The KIND, though, still has to be worked out rather than assumed. Three sources, in descending\n // authority, because a caller that troubled to state the kind knows more than we can infer:\n //\n // 1. a stated `kind`, in EITHER wire position \u2014 top level on a JSON body, under `details` on an\n // err frame, since the framed protocol carries rejection metadata there (the same split\n // `anthropicErrorBody` and `budgetExhaustedFrom` already straddle);\n // 2. the provider envelope's own type, which the proxy relays in `details` whether or not it\n // states a kind \u2014 this is what our own ai-service proxy actually sends today;\n // 3. `spend`, as the last resort.\n //\n // Reading only position 1 and defaulting the rest was a real mis-attribution rather than a\n // hypothetical: our proxy stamps this code with the Anthropic envelope in `details` and no\n // top-level `kind`, so an `authentication_error` was being reported as `spend` \u2014 sending an\n // operator to top up an account when the actual fix is to rotate a credential. The user-facing\n // copy is identical either way, which is exactly why nothing on screen would have caught it.\n if (code === PROVIDER_REFUSED_CODE) {\n return (_b = (_a = statedKind(payload)) !== null && _a !== void 0 ? _a : kindFromEnvelopeType(payload)) !== null && _b !== void 0 ? _b : 'spend';\n }\n if (vendor !== 'anthropic')\n return undefined;\n // Structural first: documented types, no prose, and cheaper than the phrase scan. `401`/`403` are\n // absent from every RETRYABLE_STATUSES, so claiming them changes what the user is told and what the\n // log records \u2014 never the retry behaviour.\n const structural = kindFromEnvelopeType(payload);\n if (structural)\n return structural;\n // The generic bucket, gated on the phrase list. Deliberately NOT gated on status as well: the\n // captures were all `400`, and pinning that would encode one snapshot of provider behaviour when\n // the type plus the phrase is already specific enough.\n const body = anthropicErrorBody(payload);\n if ((body === null || body === void 0 ? void 0 : body.type) === 'invalid_request_error' && body.message) {\n const message = body.message;\n if (ANTHROPIC_SPEND_PHRASES.some((phrase) => phrase.test(message)))\n return 'spend';\n }\n return undefined;\n}\n/**\n * Build a {@link ProviderRefusedError} from a classified rejection, pulling the provider's own\n * status/type/message across for the log.\n *\n * `upstreamStatus` is passed in rather than read from the payload because the two wire modes carry it\n * differently (HTTP status vs the err frame's `status`), and the caller is the only one that knows\n * which it is looking at.\n */\nexport function providerRefusedFrom(vendorLabel, kind, upstreamStatus, payload, fallbackDetail) {\n var _a;\n const body = anthropicErrorBody(payload);\n return new ProviderRefusedError(vendorLabel, kind, upstreamStatus, body === null || body === void 0 ? void 0 : body.type, (_a = body === null || body === void 0 ? void 0 : body.message) !== null && _a !== void 0 ? _a : fallbackDetail);\n}\n/**\n * The {@link AIProviderType} a vendor label belongs to, for the classification call above.\n *\n * A thin wrapper over the label map rather than a reuse of `vendorTypeOfLabel`: this one is called\n * with the transport's OWN label, which is always a literal from {@link VENDOR_LABELS}, so an exact\n * match is correct and the case-insensitive, whitespace-tolerant lookup that the wire-borne label\n * needs would be misleading precision here.\n */\nexport function vendorOfTransportLabel(vendorLabel) {\n const entry = Object.entries(VENDOR_LABELS).find(([, label]) => label === vendorLabel);\n return entry === null || entry === void 0 ? void 0 : entry[0];\n}\n", "/** @beta */\nexport const SUPPORTED_GEMINI_MODEL_IDS = [\n 'gemini-2.5-pro',\n 'gemini-2.5-flash',\n 'gemini-2.5-flash-lite',\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/** @beta */\nexport const SUPPORTED_ANTHROPIC_MODEL_IDS = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-opus-4-7',\n 'claude-sonnet-5',\n 'claude-sonnet-4-6',\n 'claude-haiku-4-5-20251001',\n];\n/**\n * Which vendor a model id belongs to, or `undefined` when no supported provider claims it.\n *\n * @remarks\n * Derived from {@link SUPPORTED_ANTHROPIC_MODEL_IDS} and {@link SUPPORTED_GEMINI_MODEL_IDS},\n * so it cannot drift from them the way a hand-maintained map does \u2014 adding a model to an\n * allowlist is enough to teach this too.\n *\n * Exists because callers hold a **model id**, not a vendor. A usage ledger reads a message's\n * `model` and then has to pick the matching pricing function \u2014 `anthropicTokenCost` vs\n * `geminiTokenCost` \u2014 whose usage records are deliberately not interchangeable, because the\n * two providers disagree about whether the prompt figure includes the cached part. Without\n * this, every such caller writes its own model\u2192vendor map, which is the same duplication that\n * exporting the pricing removes.\n *\n * Returns `undefined` rather than falling back to a default vendor so an unrecognised model\n * is a decision the caller has to make out loud. Silently defaulting is precisely how an\n * unlisted model gets priced at some other tier's rates \u2014 a consumer has already had Haiku\n * billed at Sonnet rates that way.\n *\n * Takes a plain `string`, not a union: the interesting callers are reading a model id back\n * off a stored message or a config file, where it is untrusted text.\n *\n * @beta\n */\nexport function vendorOfModel(modelId) {\n if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(modelId))\n return 'anthropic';\n if (SUPPORTED_GEMINI_MODEL_IDS.includes(modelId))\n return 'gemini';\n return undefined;\n}\n", "/**\n * Normalise an image MIME type to the spelling both vendors accept.\n *\n * Only `image/jpg` \u2192 `image/jpeg` today. That is a rename, not a guess: it is the same format\n * under a label neither API recognises \u2014 Anthropic documents `image/jpeg`, `image/png`,\n * `image/gif` and `image/webp`, and rejects `image/jpg` with a 400. The alias is common enough\n * to be worth absorbing (anything deriving a type from a `.jpg` extension produces it), and the\n * cost of not absorbing it is a failed turn the user is waiting on.\n *\n * Deliberately NOT a validator. A genuinely unsupported type (`image/bmp`, `image/svg+xml`)\n * passes through untouched so the vendor's own error names it, rather than this function\n * inventing a substitute or throwing on input a future model tier might accept.\n *\n * Lives here rather than inline in each transport because it is one rule that must hold for\n * both; copied into two files it drifts the first time only one is updated.\n */\nexport function normalizeImageMime(mimeType) {\n return mimeType === 'image/jpg' ? 'image/jpeg' : mimeType;\n}\n/**\n * Strip a leading `data:` URL prefix from a base64 image payload, returning the bare bytes both\n * vendors' image blocks expect.\n *\n * {@link ChatImageAttachment.data} is documented as bare base64, but the natural browser way to\n * produce it \u2014 `FileReader.readAsDataURL` \u2014 yields `data:image/png;base64,\u2026`, and handed in\n * verbatim that prefix is a 400 on both APIs. This absorbs that one mistake: a\n * `data:<mime>;base64,` preamble (any or no mime) is removed; anything already bare passes\n * through untouched. Anchored and `;base64,`-terminated so it only ever removes a real data-URL\n * header, never a slice of the payload (base64 contains no comma).\n *\n * Like {@link normalizeImageMime} it is a normaliser, not a validator \u2014 it does not check that\n * the remainder is valid base64, and lives here for the same reason: one rule both transports\n * must share.\n */\nexport function stripImageDataUrl(data) {\n return data.replace(/^data:[^,]*;base64,/, '');\n}\n", "/**\n * Normalized-temperature anchor. Values at or below it scale into\n * `[0, providerDefault]`; values above it scale into `[providerDefault, providerMax]`.\n * So a normalized `0.5` maps to each provider's own default temperature.\n */\nconst DEFAULT_ANCHOR = 0.5;\n/**\n * Translate a provider-agnostic, normalized temperature into a provider's\n * native range, anchored on the provider's own default so the normalized scale\n * means the same thing everywhere:\n *\n * - `0` \u2192 `0` (fully deterministic),\n * - `0.5` \u2192 the provider's default temperature,\n * - `1` \u2192 the provider's maximum.\n *\n * Values between the anchors interpolate linearly within each half, so `< 0.5`\n * is \"more focused than default\" and `> 0.5` is \"more random than default\" on\n * every provider \u2014 even though the providers' native ranges differ (Anthropic\n * default/max `1`/`1`, Gemini `1`/`2`). Where a provider's default equals its\n * max (Anthropic), the upper half is flat: it cannot go hotter than its default.\n *\n * The input is clamped to `[0, 1]` before scaling, so an out-of-range value can\n * never produce a native temperature the provider would reject.\n */\nexport function scaleTemperature(normalized, { defaultTemp, maxTemp }) {\n const t = Math.min(Math.max(normalized, 0), 1);\n return t <= DEFAULT_ANCHOR\n ? (t / DEFAULT_ANCHOR) * defaultTemp\n : defaultTemp + ((t - DEFAULT_ANCHOR) / (1 - DEFAULT_ANCHOR)) * (maxTemp - defaultTemp);\n}\n/**\n * Provider-agnostic, normalized sampling-temperature presets in `0`\u2013`1` space \u2014\n * named handles for the values most callers actually want, so intent reads\n * better than a bare magnitude. Each maps through `scaleTemperature` to the\n * active provider's native range, so the same preset means the same intent\n * whichever provider services the turn:\n *\n * - `ChatTemperature.Deterministic` (`0`) \u2014 greedy/argmax sampling.\n * - `ChatTemperature.Focused` (`0.25`) \u2014 low but not greedy; precise tool calls\n * and extraction work where you still want a little slack.\n * - `ChatTemperature.Balanced` (`0.5`) \u2014 the provider's own default.\n * - `ChatTemperature.Creative` (`0.75`) \u2014 hotter than default, short of the ceiling.\n * - `ChatTemperature.Maximum` (`1`) \u2014 the hottest the active provider allows.\n *\n * (On a provider whose default equals its max \u2014 Anthropic \u2014 `Creative` and\n * `Maximum` coincide; see `scaleTemperature`.)\n *\n * @beta\n */\nexport const ChatTemperature = {\n Deterministic: 0,\n Focused: 0.25,\n Balanced: 0.5,\n Creative: 0.75,\n Maximum: 1,\n};\n", "/**\n * Per-request cost pricing for the models this package can call.\n *\n * @remarks\n * Extracted from the two transports' private cost paths so a host that prices\n * requests of its own \u2014 a server proxy, a usage ledger, a benchmark \u2014 computes the\n * same numbers instead of hand-copying the rate tables. Duplicated tables drift:\n * an unlisted model silently prices at whatever the copy's fallback is, and a\n * missing multiplier misprices every cached request.\n *\n * **Typed over raw provider usage, deliberately.** These take the token counts a\n * provider response reports, NOT `ChatMessage`/`AggregateUsage`. Two reasons:\n *\n * 1. `ChatMessage.cacheWriteTokens` is a single total, but Anthropic bills cache\n * writes per TTL (5-minute at 1.25\u00D7, 1-hour at 2\u00D7). The split exists only in\n * the provider response, so pricing from a message cannot be exact.\n * 2. The path that actually needs to compute a cost is the one where no transport\n * stamped one \u2014 a proxied or server-side call holding a raw usage block.\n *\n * When a `ChatMessage` already carries `cost`, use that; it was computed here at\n * request time with information the message no longer has. Re-deriving a cost\n * from a message's token fields is wrong in the expensive direction, because\n * `inputTokens` is total prompt size *including* the cached part.\n *\n * **What this model cannot express, by construction.** Everything here is\n * *per-request*: a function of the tokens one call consumed. Caching priced by\n * **elapsed time** does not fit, and no additional bucket would make it fit \u2014\n * Gemini's explicit context caching, for instance, charges an hourly storage fee\n * that accrues while you are making no requests at all. Nothing to attribute it to.\n *\n * A provider whose caching is billed that way needs a **separate ledger entry**,\n * recorded against a cache's lifetime rather than against a request, and summed\n * alongside these figures rather than inside them. Do not fold it into\n * {@link TokenCostBreakdown} \u2014 a storage fee divided across whatever requests\n * happened to occur is an invented number, and it would make two runs with\n * identical token usage report different costs for reasons neither run caused.\n *\n * The vendors also differ in shape more than they differ in rates, which is why\n * there is a function per provider rather than one with a normalised record:\n * Anthropic charges a premium for the cache *write* and lets you choose the TTL;\n * Gemini's implicit caching has no write charge at all; a provider with automatic,\n * non-configurable caching has neither a write bucket nor a TTL to record. The\n * shared vocabulary is the RESULT ({@link TokenCost}), not the input.\n */\n/** One million \u2014 the unit every published rate is quoted in. */\nconst TOKENS_PER_MILLION = 1000000;\n// ---------------------------------------------------------------------------\n// Anthropic\n// ---------------------------------------------------------------------------\n/**\n * Standard tier pricing per million tokens \u2014\n * https://docs.claude.com/en/docs/about-claude/pricing\n *\n * @beta\n */\nconst ANTHROPIC_PRICING = {\n 'claude-haiku-4-5-20251001': { promptPerMillion: 1, candidatePerMillion: 5 },\n // Fable 5 \u2014 Anthropic's most capable widely-released model; priced above Opus tier.\n 'claude-fable-5': { promptPerMillion: 10, candidatePerMillion: 50 },\n // Opus 4.7 / 4.8 \u2014 same $5 / $25 per MTok. Stated per model rather than shared through a\n // fall-through, so neither is ever \"whatever was left over\".\n 'claude-opus-4-8': { promptPerMillion: 5, candidatePerMillion: 25 },\n 'claude-opus-4-7': { promptPerMillion: 5, candidatePerMillion: 25 },\n // Sonnet 5 is $2 / $10 \u2014 its OWN tier, and CHEAPER than the older Sonnet 4.6 below.\n //\n // This launched as an introductory rate through 2026-08-31, and an earlier version of this\n // table deliberately charged the $3 / $15 standard rate instead, on the reasoning that the\n // introductory period would lapse. Anthropic has since confirmed $2 / $10 as the permanent\n // standard price and cancelled the scheduled increase, so that reasoning is dead and the old\n // figure over-charged every Sonnet 5 request by 50%.\n // https://platform.claude.com/docs/en/about-claude/pricing#model-pricing\n 'claude-sonnet-5': { promptPerMillion: 2, candidatePerMillion: 10 },\n // Sonnet 4.6 remains on the older $3 / $15 Sonnet tier \u2014 the newer model is the cheaper one.\n 'claude-sonnet-4-6': { promptPerMillion: 3, candidatePerMillion: 15 },\n};\n/**\n * Standard tier pricing per million tokens \u2014\n * https://docs.claude.com/en/docs/about-claude/pricing\n *\n * @remarks\n * Backed by a total {@link https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type | Record}\n * over `AnthropicModelId` rather than a chain of checks with a default. That is the whole\n * point: adding a model to `SUPPORTED_ANTHROPIC_MODEL_IDS` without pricing it becomes a\n * COMPILE error instead of a silent charge at whatever the fall-through happened to be \u2014 the\n * exact failure this module's header warns about, and one a consumer has already been bitten\n * by. The Gemini half of this file has always had the guarantee; this half now matches.\n *\n * @beta\n */\nexport function anthropicRatesFor(model) {\n return ANTHROPIC_PRICING[model];\n}\n/**\n * Prompt-cache pricing multipliers, applied to the model's base input rate\n * (`promptPerMillion`) \u2014 https://docs.claude.com/en/docs/build-with-claude/prompt-caching\n * Reads bill at ~0.1\u00D7 base input; writes bill by TTL \u2014 5-minute at ~1.25\u00D7 and 1-hour at 2\u00D7.\n * Both write TTLs are reachable (`CachePolicy.ttl` is `'5m' | '1h'`), so each TTL bucket is\n * costed from the response's per-TTL `cache_creation` breakdown rather than assuming one rate.\n *\n * @beta\n */\nexport const ANTHROPIC_CACHE_READ_MULTIPLIER = 0.1;\n/** @beta */\nexport const ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER = 1.25;\n/** @beta */\nexport const ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER = 2;\n/**\n * Cost one Anthropic request.\n *\n * @beta\n */\nexport function anthropicTokenCost(model, usage) {\n const { promptPerMillion, candidatePerMillion } = anthropicRatesFor(model);\n const m = TOKENS_PER_MILLION;\n // Split the creation total into its 1-hour portion and the 5-minute remainder and\n // cost each at its own rate. All buckets are multiples of the same base input rate,\n // so summing them stays correct whether or not caching was active (every cache\n // field is 0 when it wasn't).\n const cacheWrite5mTokens = Math.max(0, usage.cacheWriteTokens - usage.cacheWrite1hTokens);\n const promptCost = (usage.uncachedInputTokens / m) * promptPerMillion;\n const cacheReadCost = (usage.cacheReadTokens / m) * promptPerMillion * ANTHROPIC_CACHE_READ_MULTIPLIER;\n const cacheWriteCost = (cacheWrite5mTokens / m) * promptPerMillion * ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER +\n (usage.cacheWrite1hTokens / m) * promptPerMillion * ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER;\n const candidateCost = (usage.outputTokens / m) * candidatePerMillion;\n // Net saving vs no caching: the cache-read tokens would have cost full input price\n // (we paid ~0.1\u00D7 of that), while the write premium is an upfront cost that pays back\n // on later reads \u2014 so the net dips negative on a write-heavy request and climbs\n // positive as reads accrue.\n const cacheReadFull = (usage.cacheReadTokens / m) * promptPerMillion;\n const cacheWriteFull = (usage.cacheWriteTokens / m) * promptPerMillion;\n return {\n costUsd: promptCost + cacheReadCost + cacheWriteCost + candidateCost,\n savedUsd: cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost),\n breakdown: {\n promptUsd: promptCost,\n cacheReadUsd: cacheReadCost,\n cacheWriteUsd: cacheWriteCost,\n candidateUsd: candidateCost,\n },\n };\n}\n// ---------------------------------------------------------------------------\n// Gemini\n// ---------------------------------------------------------------------------\n/**\n * Prompt size (tokens) at or below which the standard pricing tier applies.\n * Above it, Gemini's long-context tier kicks in. Google applies a single tier\n * to the whole request based on prompt size \u2014 it is not a marginal/blended rate.\n *\n * @beta\n */\nexport const GEMINI_LONG_CONTEXT_THRESHOLD = 200000;\n/**\n * Cached / context-cache input tokens bill at a flat ~10% of the model's normal input\n * rate \u2014 consistent across models (flash $0.30\u2192$0.03, flash-lite $0.10\u2192$0.01,\n * pro $1.25\u2192$0.125). Source: https://ai.google.dev/gemini-api/docs/pricing.\n * (Explicit context caching also has an hourly storage fee; implicit caching \u2014 what the\n * transport relies on \u2014 has none, so only this read discount applies. There is no write\n * premium on this provider, which is why its savings figure is never negative.)\n *\n * @beta\n */\nexport const GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;\n/**\n * Paid Standard tier rates (USD per million tokens) \u2014\n * https://ai.google.dev/gemini-api/docs/pricing\n */\nconst GEMINI_PRICING = {\n 'gemini-2.5-flash-lite': {\n kind: 'flat',\n rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 },\n },\n 'gemini-2.5-flash': { kind: 'flat', rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },\n 'gemini-2.5-pro': {\n kind: 'tiered',\n standard: { promptPerMillion: 1.25, candidatePerMillion: 10.0 },\n longContext: { promptPerMillion: 2.5, candidatePerMillion: 15.0 },\n },\n 'gemini-3.1-flash-lite': {\n kind: 'flat',\n rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 },\n },\n 'gemini-3.5-flash': { kind: 'flat', rate: { promptPerMillion: 1.5, candidatePerMillion: 9.0 } },\n 'gemini-3.1-pro-preview': {\n kind: 'tiered',\n standard: { promptPerMillion: 2.0, candidatePerMillion: 12.0 },\n longContext: { promptPerMillion: 4.0, candidatePerMillion: 18.0 },\n },\n};\n/**\n * Resolve the per-million-token rates for a model given the request's prompt size,\n * selecting the long-context tier for tiered models when the prompt exceeds\n * {@link GEMINI_LONG_CONTEXT_THRESHOLD}.\n *\n * @remarks\n * `promptTokens` must be the **full** prompt size, cached slice included \u2014 the tier\n * is chosen on what was sent, not on what was billed at full rate. A mostly-cached\n * long prompt is still a long prompt.\n *\n * Unlike Anthropic's, this accessor is not a pure function of the model, which is\n * why there is no single `ratesFor(model)` across both providers.\n *\n * @beta\n */\nexport function geminiRatesFor(model, promptTokens) {\n const pricing = GEMINI_PRICING[model];\n if (pricing.kind === 'flat') {\n return pricing.rate;\n }\n return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;\n}\n/**\n * Cost one Gemini request.\n *\n * @beta\n */\nexport function geminiTokenCost(model, usage) {\n // The pricing TIER is chosen on the full prompt size, BEFORE the cache split.\n const { promptPerMillion, candidatePerMillion } = geminiRatesFor(model, usage.promptTokens);\n const m = TOKENS_PER_MILLION;\n const uncachedPromptTokens = Math.max(0, usage.promptTokens - usage.cachedTokens);\n const promptCost = (uncachedPromptTokens / m) * promptPerMillion;\n const cacheReadCost = (usage.cachedTokens / m) * promptPerMillion * GEMINI_CACHED_INPUT_MULTIPLIER;\n // Thinking tokens bill at the output rate, and are incurred whenever the model\n // thinks (always, on 2.5 Pro).\n const candidateCost = ((usage.candidateTokens + usage.thoughtTokens) / m) * candidatePerMillion;\n return {\n costUsd: promptCost + cacheReadCost + candidateCost,\n // Implicit caching has no write premium, so this is always >= 0.\n savedUsd: (usage.cachedTokens / m) * promptPerMillion - cacheReadCost,\n breakdown: {\n promptUsd: promptCost,\n cacheReadUsd: cacheReadCost,\n cacheWriteUsd: 0,\n candidateUsd: candidateCost,\n },\n };\n}\n", "import { __rest } from \"tslib\";\nimport { logger } from './logger';\n/** Keys whose value is a *map* of name \u2192 schema. */\nconst SCHEMA_MAP_KEYS = ['properties', 'patternProperties', '$defs', 'definitions'];\n/** Keys whose value is an *array* of schemas. */\nconst SCHEMA_LIST_KEYS = ['anyOf', 'oneOf', 'allOf', 'prefixItems'];\n/** Keys whose value is a single schema (or, for `items`, optionally a tuple of them). */\nconst SCHEMA_VALUE_KEYS = [\n 'items',\n 'not',\n 'additionalProperties',\n 'propertyNames',\n 'contains',\n];\nconst isPlainObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);\n/** Structural deep clone for JSON-Schema-shaped values (JSON-serialisable by definition). */\nfunction cloneValue(value) {\n if (Array.isArray(value))\n return value.map(cloneValue);\n if (isPlainObject(value)) {\n const out = {};\n for (const [k, v] of Object.entries(value))\n out[k] = cloneValue(v);\n return out;\n }\n return value;\n}\n/**\n * Deep-clone `node`, recursing into every nested schema and applying `transform`\n * to each node bottom-up. `path` is a JSON Pointer, passed to `transform` so it\n * can report *where* a change was made.\n *\n * **Never mutates the input.** Tool definitions are routinely module-level\n * constants shared across every turn, so in-place adaptation would corrupt them\n * for all subsequent requests.\n *\n * Recursion is keyword-directed rather than structural: only the keys above hold\n * schemas. A blind walk would descend into `enum` (an array of *values*),\n * `required` (an array of *names*), or `type` (which may be an array of type\n * names) and corrupt them.\n */\nfunction mapChildSchemas(node, visit, path) {\n const out = {};\n for (const [key, value] of Object.entries(node)) {\n const here = `${path}/${key}`;\n if (SCHEMA_MAP_KEYS.includes(key) && isPlainObject(value)) {\n out[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [\n name,\n isPlainObject(child) ? visit(child, `${here}/${name}`) : cloneValue(child),\n ]));\n }\n else if (SCHEMA_LIST_KEYS.includes(key) && Array.isArray(value)) {\n out[key] = value.map((child, i) => isPlainObject(child) ? visit(child, `${here}/${i}`) : cloneValue(child));\n }\n else if (SCHEMA_VALUE_KEYS.includes(key)) {\n if (isPlainObject(value))\n out[key] = visit(value, here);\n else if (Array.isArray(value))\n // Legacy tuple form of `items`.\n out[key] = value.map((child, i) => isPlainObject(child) ? visit(child, `${here}/${i}`) : cloneValue(child));\n else\n out[key] = cloneValue(value);\n }\n else {\n out[key] = cloneValue(value);\n }\n }\n return out;\n}\nfunction mapSchema(node, transform, path = '') {\n return transform(mapChildSchemas(node, (child, childPath) => mapSchema(child, transform, childPath), path), path);\n}\n// \u2500\u2500 Anthropic: enforcement (F6) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * Keywords Anthropic rejects outright when a tool is compiled for enforcement,\n * and which can be dropped without changing what the rest of the schema means.\n * Measured against `claude-opus-4-8` \u2014 see `docs/tool-schemas.md`.\n *\n * `minItems` is absent because it is only rejected above 1; it is handled below.\n */\nconst UNENFORCEABLE_KEYWORDS = [\n 'minimum',\n 'maximum',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'maxItems',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n];\n/**\n * Keywords Anthropic rejects that **cannot** be dropped, because removing them\n * would leave a node that means something entirely different (`oneOf` and `not`\n * carry the node's whole meaning; deleting `oneOf` leaves `{}`, which matches\n * anything).\n *\n * These are deliberately left in place so the request fails loudly rather than\n * silently enforcing a weaker schema than the caller wrote.\n */\nconst UNDROPPABLE_KEYWORDS = ['oneOf', 'not'];\n/**\n * Adapt a tool's `parameters` for Anthropic's decode-time enforcement.\n *\n * Two changes, both required by the provider:\n *\n * 1. `additionalProperties: false` on every object node. Anthropic rejects an\n * enforced schema without it (`For 'object' type, 'additionalProperties' must\n * be explicitly set to false`) \u2014 a closed key set is what makes the object's\n * grammar finite.\n * 2. Keywords that enforcement cannot express are removed. Numeric bounds and\n * most array constraints are *rejected* by the provider, so leaving them in\n * fails the whole request; dropping them keeps everything else enforced.\n *\n * `required` is deliberately untouched: a subset, an empty list, and an absent\n * key are all accepted, and an omitted-but-present property is still constrained.\n *\n * Note what is **not** stripped: `maxLength`/`minLength` are accepted and\n * silently ignored, so they survive as documentation but guarantee nothing \u2014\n * validate lengths yourself. `pattern` and `format` *are* enforced (shape only,\n * in `format`'s case) and are cheaper to compile than an unconstrained string.\n */\nexport function toEnforcedAnthropicSchema(parameters) {\n const stripped = [];\n const overridden = [];\n const undroppable = [];\n const schema = mapSchema(parameters, (node, path) => {\n for (const keyword of UNENFORCEABLE_KEYWORDS) {\n if (keyword in node) {\n delete node[keyword];\n stripped.push(`${path}/${keyword}`);\n }\n }\n // Only values other than 0 and 1 are rejected.\n if (typeof node.minItems === 'number' && node.minItems > 1) {\n delete node.minItems;\n stripped.push(`${path}/minItems`);\n }\n for (const keyword of UNDROPPABLE_KEYWORDS) {\n if (keyword in node)\n undroppable.push(`${path}/${keyword}`);\n }\n // An object node must be closed. `additionalProperties: true` is a direct\n // contradiction of the caller's own enforcement request, so it is overridden\n // rather than honoured \u2014 but loudly, since it changes what the schema admits.\n //\n // `type` may be an ARRAY containing `'object'` (a nullable object), which has\n // to close exactly like the scalar spelling. Testing `properties` alone is not\n // enough: a *property-less* `{type: ['object','null']}` would slip through and\n // then differ from `{type: 'object'}` in what it admits, purely because it is\n // nullable.\n const isObjectNode = node.type === 'object' ||\n (Array.isArray(node.type) && node.type.includes('object')) ||\n isPlainObject(node.properties);\n if (isObjectNode) {\n if (node.additionalProperties !== false) {\n if (node.additionalProperties !== undefined) {\n overridden.push(`${path}/additionalProperties`);\n }\n node.additionalProperties = false;\n }\n }\n return node;\n });\n return { schema, stripped, overridden, undroppable };\n}\n/**\n * Adapt a tool's `parameters` for enforcement and log what could not be carried\n * across. Thin wrapper over {@link toEnforcedAnthropicSchema} for transport use.\n *\n * Named as a **verb** to keep it distinct from the pure transform it wraps: this\n * one logs and returns only the schema, so a caller that wants to inspect what was\n * stripped or tightened wants `toEnforcedAnthropicSchema` instead. An earlier name\n * differed from it by word order alone, which made the two easy to confuse on\n * autocomplete despite returning different things. PR #2449 review.\n */\nexport function enforceAnthropicToolSchema(parameters, toolName) {\n const { schema, stripped, overridden, undroppable } = toEnforcedAnthropicSchema(parameters);\n if (stripped.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" requested schema enforcement; these keywords cannot ` +\n `be enforced and were removed \u2014 validate them yourself: ${stripped.join(', ')}`);\n }\n if (overridden.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" requested schema enforcement, which requires closed ` +\n `objects; \\`additionalProperties\\` was set to false at: ${overridden.join(', ')}. The tool ` +\n `now accepts fewer inputs than its schema declared.`);\n }\n if (undroppable.length) {\n logger.warn(`AnthropicTransport: tool \"${toolName}\" uses schema keywords enforcement cannot express ` +\n `(${undroppable.join(', ')}). They cannot be removed without changing the schema's meaning, ` +\n `so the request will be rejected. Rewrite them or drop enforceSchema for this tool.`);\n }\n return schema;\n}\n// \u2500\u2500 Gemini: dialect translation (F7) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * Keywords Gemini's function-declaration schema has no field for. They are\n * unknown-field parse errors, not unsupported features, so they must be removed\n * whatever the caller wrote. Measured against `gemini-3.5-flash`.\n */\nconst GEMINI_UNSUPPORTED_KEYWORDS = [\n 'additionalProperties',\n 'examples',\n 'multipleOf',\n 'patternProperties',\n // Both spellings of the definitions block. `$defs` would also fall to the\n // `$`-prefix sweep below, but the draft-07 spelling has no `$` and would\n // otherwise survive inlining and 400 the request \u2014 so list the pair together.\n '$defs',\n 'definitions',\n];\n/** Resolve a local JSON Pointer (`#/$defs/Name`) against the document root. */\nfunction resolvePointer(root, ref) {\n if (!ref.startsWith('#/'))\n return undefined;\n let current = root;\n for (const segment of ref.slice(2).split('/')) {\n if (!isPlainObject(current))\n return undefined;\n current = current[segment.replace(/~1/g, '/').replace(/~0/g, '~')];\n }\n return isPlainObject(current) ? current : undefined;\n}\n/**\n * Inline every local `$ref` against the root's `$defs`/`definitions`, because\n * Gemini has no field for either.\n *\n * A `$ref` that cannot be inlined \u2014 a cycle, a typo'd pointer, or an external\n * (non-`#/\u2026`) one \u2014 is left in place and collected in `unresolved`. It then\n * survives to the wire on purpose: `toGeminiSchema` exempts `$ref` from its\n * `$`-prefix sweep, so Gemini rejects the declaration instead of accepting a node\n * that constrains nothing. The collected pointers are logged, so the developer\n * reads which ref is at fault rather than decoding a provider error about a field\n * they never wrote.\n */\nfunction inlineRefs(root, node, seen, unresolved) {\n // Substitute *before* descending, so refs nested inside a resolved target are\n // themselves resolved. `seen` carries down that branch only, so the same\n // definition may legitimately appear twice in sibling positions.\n //\n // Loops rather than substituting once, because a target may ITSELF be a `$ref`\n // (an alias chain `A \u2192 B \u2192 C`). Stopping after one hop leaves a trailing `$ref`\n // that the sweep then deletes, collapsing the property to `{}` \u2014 the silent case\n // described above. Every hop joins `visited`, so a chain that turns back on\n // itself terminates instead of expanding forever.\n let current = node;\n let visited = seen;\n let ref = typeof current.$ref === 'string' ? current.$ref : undefined;\n while (ref && !visited.has(ref)) {\n const target = resolvePointer(root, ref);\n if (!target)\n break;\n const { $ref: _dropped } = current, siblings = __rest(current, [\"$ref\"]);\n current = Object.assign(Object.assign({}, cloneValue(target)), siblings);\n visited = new Set([...visited, ref]);\n ref = typeof current.$ref === 'string' ? current.$ref : undefined;\n }\n if (typeof current.$ref === 'string')\n unresolved.push(current.$ref);\n return mapChildSchemas(current, (child) => inlineRefs(root, child, visited, unresolved), '');\n}\n/**\n * Translate a JSON Schema into the OpenAPI 3.0 subset Gemini's function\n * declarations (and `responseSchema`) actually parse.\n *\n * This runs **unconditionally**, independently of any enforcement opt-in: Gemini\n * constrains tool arguments by default, so the only question here is whether the\n * declaration is *accepted at all*. Left untranslated, a schema with any nullable\n * column is a hard `400 Unknown name \"type\"` before the model runs.\n *\n * | JSON Schema | Gemini |\n * | --- | --- |\n * | `{\"type\": [\"integer\",\"null\"]}` | `{\"type\": \"integer\", \"nullable\": true}` |\n * | `{\"anyOf\": [{...}, {\"type\":\"null\"}]}` | the non-null branch, `nullable: true` |\n * | `{\"const\": \"X\"}` | `{\"enum\": [\"X\"]}` |\n * | `additionalProperties`, `examples`, `multipleOf` | removed |\n * | `$defs` / `$ref` | inlined, alias chains walked out |\n * | a `$ref` that cannot be inlined | **kept**, so the provider rejects it |\n * | any other `$`-prefixed keyword | removed |\n *\n * A type union that is not simply \"T or null\" (e.g. `[\"string\",\"integer\"]`) has\n * no OpenAPI equivalent and is left alone, so the provider rejects it rather\n * than us silently picking a branch.\n */\nexport function toGeminiSchema(parameters) {\n const unresolved = [];\n const inlined = inlineRefs(parameters, parameters, new Set(), unresolved);\n if (unresolved.length) {\n logger.warn(`GeminiTransport: these \\`$ref\\` pointers could not be inlined \u2014 a cycle, a typo, or an ` +\n `external ref: ${[...new Set(unresolved)].join(', ')}. They are left in the schema, so ` +\n `Gemini will reject this declaration; that is deliberate, because dropping them would ` +\n `send a node that constrains nothing.`);\n }\n const translated = mapSchema(inlined, (node) => {\n // `type: [T, \"null\"]` \u2192 `type: T, nullable: true`\n if (Array.isArray(node.type)) {\n const types = node.type.filter((t) => t !== 'null');\n if (types.length === 1 && node.type.length !== types.length) {\n node.type = types[0];\n node.nullable = true;\n }\n }\n // `anyOf: [X, {type:\"null\"}]` \u2192 X with `nullable: true`\n if (Array.isArray(node.anyOf)) {\n const branches = node.anyOf.filter(isPlainObject);\n const nonNull = branches.filter((b) => b.type !== 'null');\n if (branches.length === 2 && nonNull.length === 1) {\n const { anyOf: _dropped } = node, siblings = __rest(node, [\"anyOf\"]);\n return Object.assign(Object.assign(Object.assign({}, nonNull[0]), siblings), { nullable: true });\n }\n }\n if ('const' in node) {\n node.enum = [node.const];\n delete node.const;\n }\n for (const keyword of GEMINI_UNSUPPORTED_KEYWORDS)\n delete node[keyword];\n // Anything else `$`-prefixed (`$schema`, `$comment`, `$id`) is an unknown field\n // to Gemini and is dropped. `$ref` is deliberately EXEMPT: one that survives\n // inlining is a cycle, a typo, or an external pointer, and deleting it would\n // leave `{}` \u2014 a node Gemini accepts and does not constrain, which is the\n // silent widening this whole module exists to avoid. Left in place, the\n // declaration is rejected outright. Same choice as the genuine multi-type union\n // above: a schema that cannot be translated faithfully must fail rather than\n // quietly admit anything. PR #2449 review.\n for (const key of Object.keys(node)) {\n if (key.startsWith('$') && key !== '$ref')\n delete node[key];\n }\n return node;\n });\n return translated;\n}\n", "/**\n * Resolve the authoritative reason behind an abort-shaped rejection.\n *\n * Chromium/Firefox reject an aborted fetch/body read with the signal's\n * `reason`, but older WebKit rejects with a generic `AbortError` \u2014 which would\n * send a transport timeout down a caller's user-cancel path. Node and jsdom\n * test environments can raise the same shape as a plain `Error` rather than a\n * `DOMException`, so both are accepted (gated on the exact abort names).\n *\n * When `error` is abort-shaped the CALLER signal wins a same-tick tie: if the\n * user hits Stop in the same tick a stall/timeout fires, their intent takes\n * precedence, so the turn still routes to the user-cancel path and keeps its\n * \"Stopped.\" marker (first-cancel-wins, matching the pre-refactor behaviour).\n * A pure timeout \u2014 caller not aborted \u2014 still yields the timeout signal's\n * tagged `TimeoutError`, which is the WebKit fix. Anything not abort-shaped\n * passes through untouched.\n */\nexport function authoritativeAbortReason(error, timeoutSignal, callerSignal) {\n const abortShaped = (error instanceof DOMException || error instanceof Error) &&\n (error.name === 'AbortError' || error.name === 'TimeoutError');\n if (!abortShaped)\n return error;\n if (callerSignal === null || callerSignal === void 0 ? void 0 : callerSignal.aborted)\n return callerSignal.reason;\n if (timeoutSignal.aborted)\n return timeoutSignal.reason;\n return error;\n}\n", "/**\n * A `setTimeout`-based delay that rejects as soon as `signal` aborts, with the\n * signal's reason \u2014 so retry backoffs unwind immediately on a caller cancel or\n * dispose instead of waiting out the full wait. Resolves normally when `ms`\n * elapses first (the abort listener is detached, so a long-lived signal reused\n * across many delays does not accumulate dead listeners).\n */\nexport function abortableDelay(ms, signal) {\n return new Promise((resolve, reject) => {\n const abortReason = () => { var _a; return (_a = signal === null || signal === void 0 ? void 0 : signal.reason) !== null && _a !== void 0 ? _a : new DOMException('The operation was aborted.', 'AbortError'); };\n if (signal === null || signal === void 0 ? void 0 : signal.aborted) {\n reject(abortReason());\n return;\n }\n const onAbort = () => {\n clearTimeout(timer);\n reject(abortReason());\n };\n const timer = setTimeout(() => {\n signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n", "/**\n * Shared reader for the ai-service proxy's NDJSON heartbeat protocol (v1),\n * used by the server-proxied transports (Anthropic, Gemini). The proxy streams\n * `ping` frames while the upstream call runs and ends the body with exactly one\n * terminal `ok`/`err` frame, one JSON object per LF-terminated line.\n */\nimport { __awaiter } from \"tslib\";\n/** Cap on how much of a malformed proxy frame is quoted in the error message. */\nconst MALFORMED_FRAME_PREVIEW_CHARS = 120;\n/**\n * Read an NDJSON heartbeat body to its terminal frame. Buffers partial lines\n * across chunks, tolerates blank lines, and skips unknown frame types \u2014 pings\n * matter only as activity, which `onChunk` reports to the caller's stall\n * timer. An abort (stall timer or caller signal) rejects the pending `read()`\n * with the abort reason, which propagates to the caller's finally cleanup.\n * `vendorLabel` (e.g. `'Anthropic'`) prefixes the protocol-violation messages.\n *\n * `stallTimeout` (ms) arms a client-side backstop: the proxy's own pings re-arm\n * the caller's inactivity timer, so a proxy whose upstream has wedged but which\n * keeps pinging would never trip it. Each ping stamps `sinceLastEventMs` (time\n * since the last upstream event); when that exceeds `stallTimeout` we treat it\n * as a stall and throw the tagged `TimeoutError`, independent of the proxy\n * noticing its own stall. `<= 0` disables the backstop (inactivity detection off).\n */\nexport function readFramedBody(stream, onChunk, vendorLabel, stallTimeout) {\n return __awaiter(this, void 0, void 0, function* () {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n const malformedFrame = (line) => new Error(`${vendorLabel} proxy sent a malformed frame: ${line.slice(0, MALFORMED_FRAME_PREVIEW_CHARS)}`);\n const parseLine = (line) => {\n if (!line)\n return undefined;\n let parsed;\n try {\n parsed = JSON.parse(line);\n }\n catch (_a) {\n throw malformedFrame(line);\n }\n // JSON.parse also accepts null/scalars/arrays \u2014 a frame must be an object\n // (dereferencing `.t` on null would otherwise throw a raw TypeError).\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw malformedFrame(line);\n }\n const frame = parsed;\n if (frame.t === 'ok') {\n if (frame.body == null) {\n throw new Error(`${vendorLabel} proxy sent an ok frame without a body`);\n }\n return frame;\n }\n if (frame.t === 'err') {\n // The cast below promises a numeric status; hold the proxy to it rather\n // than letting `undefined` leak into the retry/status checks downstream.\n if (typeof frame.status !== 'number') {\n throw new Error(`${vendorLabel} proxy sent an err frame without a numeric status`);\n }\n return frame;\n }\n if (frame.t === 'ping') {\n // Client-side stall backstop: the proxy stamps how long its upstream has\n // been silent. Its pings keep the caller's inactivity timer alive, so\n // this is the only signal that catches a wedged upstream behind a proxy\n // that is itself still healthy. Surface the same tagged TimeoutError a\n // local inactivity fire would.\n if (stallTimeout > 0 &&\n typeof frame.sinceLastEventMs === 'number' &&\n frame.sinceLastEventMs > stallTimeout) {\n throw new DOMException(`${vendorLabel} request stalled: proxy reported ${frame.sinceLastEventMs}ms since the last upstream event (exceeds ${stallTimeout}ms)`, 'TimeoutError');\n }\n return undefined;\n }\n return undefined; // unknown frame types (forward compat)\n };\n try {\n for (;;) {\n // oxlint-disable-next-line no-await-in-loop -- sequential stream reads\n const { done, value } = yield reader.read();\n if (done)\n break;\n onChunk();\n buffer += decoder.decode(value, { stream: true });\n let newline = buffer.indexOf('\\n');\n while (newline !== -1) {\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n const frame = parseLine(line);\n if (frame)\n return frame;\n newline = buffer.indexOf('\\n');\n }\n }\n // Tolerate a final terminal frame missing its LF.\n const frame = parseLine((buffer + decoder.decode()).trim());\n if (frame)\n return frame;\n throw new Error(`${vendorLabel} proxy stream ended without a terminal frame`);\n }\n finally {\n // Stop the stream on early return, error, or abort; cancel rejects on an\n // already-errored stream, which is fine to ignore.\n void reader.cancel().catch(() => { });\n }\n });\n}\n", "/**\n * Server-supplied retry hints for the shared `postWithRetry` ladder (GENC-1506).\n *\n * ## Why this exists\n *\n * The ladder was `base * 2^attempt` \u2014 1s, 2s, 4s, 8s, 16s, **31s in total** \u2014 and it read neither the\n * HTTP `Retry-After` header nor Google's in-body `RetryInfo`. Measured against a real rate-limited\n * Gemini key (2026-08-18), the provider asked for **53s**:\n *\n * ```jsonc\n * {\"error\":{\"code\":429,\"status\":\"RESOURCE_EXHAUSTED\",\n * \"message\":\"\u2026 Please retry in 53.59713199s.\",\n * \"details\":[{\"@type\":\"type.googleapis.com/google.rpc.RetryInfo\",\"retryDelay\":\"53s\"}]}}\n * ```\n *\n * So a **legitimate** rate limit burned all five retries inside the window the provider had told us to\n * wait, then failed opaquely \u2014 every attempt after the first guaranteed to fail, and the user waiting\n * 31s to be told nothing useful. Honouring the hint turns five doomed requests into one that works.\n *\n * ## Scope note\n *\n * This is deliberately vendor-neutral and applies to **healthy traffic**, not just refusals. It is the\n * one part of GENC-1506 that changes timing on a path that is working: some failures that used to give\n * up after 31s will now wait longer before succeeding or failing. That is the correct behaviour and it\n * is what the server asked for, but it is why the ladder keeps its own tests and its own line in the\n * release notes rather than riding along silently inside a fix about error messages.\n *\n * @packageDocumentation\n */\n/**\n * Ceiling on a server-requested wait, per attempt.\n *\n * A hint is *advice from a remote party*, so it needs a bound: without one, a mistaken or hostile\n * `Retry-After: 86400` parks a turn for a day with no way out but a caller abort. 60s sits comfortably\n * above the largest value observed (53s) while keeping the worst case survivable.\n *\n * This caps each wait, and it is the ONLY per-attempt bound \u2014 the earlier claim that the exponential\n * ladder bounds a pathological sequence was simply wrong, because `resolveBackoffMs` takes the LARGER\n * of the two and the ladder tops out at `baseMs * 2 ** 4` (16s at the 1s base every transport uses). A\n * 60s hint therefore wins on every attempt and the ladder never contributes. That is what\n * {@link MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS} is for.\n */\nexport const MAX_SERVER_REQUESTED_BACKOFF_MS = 60000;\n/**\n * Ceiling on the server-requested wait across a WHOLE retry sequence.\n *\n * Without it the per-attempt cap is no real bound: five capped waits is five minutes, and nothing is\n * watching during them \u2014 the attempt's own timeout is cleared before each backoff, so a provider (or a\n * proxy in front of one) answering `Retry-After: 3600` five times parks the turn for the full five\n * minutes with a caller abort as the only way out.\n *\n * 120s is chosen so the case this module was written for still works untouched: the measured Gemini\n * hint was 53s, and two of those fit inside the budget with headroom. Past it we stop honouring hints\n * and fall back to the ladder, so a sequence of maximal 60s hints now totals ~151s (120s of honoured\n * excess plus the ladder's own 31s) rather than 300s.\n *\n * What it budgets is the EXCESS over the wait the ladder would have taken anyway \u2014 see\n * {@link serverBackoffSpentMs}. Budgeting the raw hint instead would let the ladder's own growth eat\n * the allowance late in a sequence, declining hints on the grounds of time we were always going to\n * spend.\n */\nexport const MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS = 120000;\n/** Anthropic's explicit retry verdict, which its own SDK honours. */\nconst SHOULD_RETRY_HEADER = 'x-should-retry';\n/** Both hint formats are expressed in seconds; every internal wait is in ms. */\nconst MS_PER_SECOND = 1000;\n/**\n * `true` only when the server has **explicitly** said not to retry.\n *\n * Absent means \"no opinion\" and must never be read as `true` \u2014 that asymmetry is measured, not\n * cautious: the captured Anthropic `401` carries no `x-should-retry` at all, while the captured\n * spend-refusal `400` carries `false`. Treating absence as a refusal to retry would silently disable\n * the ladder for every provider that does not send the header, Google included.\n */\nexport function shouldNotRetry(headers) {\n var _a;\n const value = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, SHOULD_RETRY_HEADER);\n return typeof value === 'string' && value.trim().toLowerCase() === 'false';\n}\n/**\n * The `Retry-After` header in ms, or `undefined`.\n *\n * Both documented forms are accepted \u2014 delta-seconds (`Retry-After: 53`) and an HTTP-date\n * (`Retry-After: Wed, 21 Oct 2026 07:28:00 GMT`) \u2014 because a proxy or CDN in front of the provider may\n * rewrite one into the other, and a silently unparsed hint is indistinguishable from no hint at all.\n * A date already in the past clamps to 0 rather than going negative.\n */\nexport function retryAfterMs(headers) {\n var _a;\n const raw = (_a = headers === null || headers === void 0 ? void 0 : headers.get) === null || _a === void 0 ? void 0 : _a.call(headers, 'retry-after');\n if (typeof raw !== 'string' || raw.trim() === '')\n return undefined;\n const seconds = Number(raw.trim());\n if (Number.isFinite(seconds))\n return Math.max(0, seconds * MS_PER_SECOND);\n const at = Date.parse(raw);\n if (Number.isNaN(at))\n return undefined;\n return Math.max(0, at - Date.now());\n}\n/**\n * Google's `google.rpc.RetryInfo.retryDelay` in ms, or `undefined`.\n *\n * Read from **two positions**, for the same reason the refusal classifier reads two: on the direct API\n * the body is Google's own (`{ error: { details: [...] } }`), while through the NDJSON framed proxy that\n * body is nested under the err frame's `details`. Reading one position only would honour the hint on\n * exactly one of the two paths.\n *\n * Matched on an `@type` **suffix** rather than the full URL: the type prefix is a Google-owned constant\n * that has no reason to change, but suffix-matching costs nothing and survives it if it does.\n */\nexport function retryInfoMs(payload) {\n const outer = typeof payload === 'object' && payload !== null ? payload : {};\n const framed = typeof outer.details === 'object' && outer.details !== null\n ? outer.details\n : undefined;\n for (const holder of [outer.error, framed === null || framed === void 0 ? void 0 : framed.error]) {\n const details = holder === null || holder === void 0 ? void 0 : holder.details;\n if (!Array.isArray(details))\n continue;\n for (const entry of details) {\n const type = entry === null || entry === void 0 ? void 0 : entry['@type'];\n if (typeof type !== 'string' || !type.endsWith('google.rpc.RetryInfo'))\n continue;\n const delay = entry === null || entry === void 0 ? void 0 : entry.retryDelay;\n // Protobuf Duration as JSON: a decimal number of seconds with an `s` suffix (\"53s\", \"1.5s\").\n if (typeof delay !== 'string')\n continue;\n const seconds = Number(delay.replace(/s$/, ''));\n if (Number.isFinite(seconds) && seconds >= 0)\n return seconds * MS_PER_SECOND;\n }\n }\n return undefined;\n}\n/**\n * How long to wait before the next attempt: never less than our own ladder, never less than the\n * server asked, never more than the ceiling.\n *\n * `max` rather than \"prefer the server's value\" is the point \u2014 a server asking for *less* than our\n * backoff must not be able to talk us into hammering it, which a naive \"honour the hint\" would do on\n * `Retry-After: 0`.\n *\n * @param attempt - zero-based attempt index, as the ladder counts them.\n * @param baseMs - the transport's backoff base; the ladder is `baseMs * 2^attempt`.\n * @param serverMs - the server's requested delay, when it supplied one.\n */\nexport function resolveBackoffMs(attempt, baseMs, serverMs, serverAllowanceMs = Number.POSITIVE_INFINITY) {\n const ladder = baseMs * Math.pow(2, attempt);\n if (serverMs == null || !Number.isFinite(serverMs))\n return ladder;\n // Three ceilings, all of which have to hold: what the server asked, the per-attempt cap, and\n // whatever is left of the sequence budget. An exhausted allowance clamps to 0, so the `max` below\n // returns the bare ladder and the sequence degrades to its pre-GENC-1506 behaviour rather than\n // stopping \u2014 a hint we decline to honour is not a reason to stop retrying.\n const honoured = Math.min(serverMs, MAX_SERVER_REQUESTED_BACKOFF_MS, Math.max(0, serverAllowanceMs));\n return Math.max(ladder, honoured);\n}\n/**\n * How much of the sequence budget a resolved wait consumed.\n *\n * Only the part attributable to the server counts: a wait the ladder would have taken anyway is not\n * the server's doing, so it must not eat the allowance \u2014 otherwise a long ladder late in a sequence\n * would exhaust the budget without a single hint having been honoured.\n */\nexport function serverBackoffSpentMs(resolvedMs, ladderMs) {\n return Math.max(0, resolvedMs - ladderMs);\n}\n", "import { __awaiter } from \"tslib\";\nimport { authoritativeAbortReason } from '../utils/abort-reason';\nimport { abortableDelay } from '../utils/abortable-delay';\nimport { combineSignals } from '../utils/combine-signals';\nimport { logger } from '../utils/logger';\nimport { budgetExhaustedFrom, codeOf, isBudgetRejection, parseJsonOrUndefined, } from './budget-exhausted-error';\nimport { readFramedBody } from './ndjson-frames';\nimport { providerRefusalOf, providerRefusedFrom, vendorOfTransportLabel } from './provider-refused';\nimport { MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS, resolveBackoffMs, retryAfterMs, retryInfoMs, serverBackoffSpentMs, shouldNotRetry, } from './retry-hints';\nconst MAX_RETRIES = 5;\n/**\n * POST with the shared retry ladder, wall-clock timeout, framed-mode stall\n * detection and abort-reason preservation. Returns the terminal `ok` frame body\n * (framed proxy) or the parsed JSON (legacy proxy / direct API) as `unknown` \u2014\n * the caller casts. Throws a tagged `TimeoutError` on a stall (local inactivity,\n * the proxy's `sinceLastEventMs` backstop, or an `UPSTREAM_STALLED` frame), the\n * caller's reason on a caller abort, or a plain `Error` otherwise.\n */\nexport function postWithRetry(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c, _d, _e, _f, _g;\n const { url, headers, body, credentials, vendorLabel, retryableStatuses, timeout, stallTimeout, backoffBaseMs, signal, } = options;\n // The vendor behind this transport's label, resolved once \u2014 the refusal classifier dispatches on\n // it, and it is the only vendor knowledge this envelope needs (GENC-1506).\n const vendor = vendorOfTransportLabel(vendorLabel);\n // Total time this sequence has spent waiting BEYOND its own ladder because a server asked it to.\n // The per-attempt cap alone is not a bound on the sequence \u2014 five capped waits is five minutes, with\n // no timer running through any of them \u2014 so the allowance is tracked here and spent down across\n // attempts. Per-call state, deliberately: a budget shared between concurrent requests would make one\n // request's hints silently shorten another's.\n let serverBackoffSpent = 0;\n // Exponential backoff between retries: base, 2\u00D7, 4\u00D7, 8\u00D7, 16\u00D7 \u2014 raised to whatever the server asked\n // for when it asked for more (GENC-1506; see `retry-hints`). Abortable on the CALLER signal only \u2014\n // the timeout is cleared before each backoff, so a caller cancel mid-wait unwinds immediately while\n // a timeout does not.\n const backoff = (attempt, serverMs) => {\n const ladderMs = backoffBaseMs * Math.pow(2, attempt);\n const allowanceMs = MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS - serverBackoffSpent;\n const waitMs = resolveBackoffMs(attempt, backoffBaseMs, serverMs, allowanceMs);\n serverBackoffSpent += serverBackoffSpentMs(waitMs, ladderMs);\n if (serverMs != null && waitMs > ladderMs) {\n // Logged because an honoured hint is otherwise indistinguishable from a hang: a silent 53s\n // pause in a log is the sort of thing someone spends an afternoon on.\n logger.warn(`${vendorLabel}Transport: honouring the server's requested retry delay (${Math.round(waitMs)}ms, asked ${Math.round(serverMs)}ms)`);\n }\n else if (serverMs != null && serverMs > ladderMs) {\n // The hint was declined, which is worth its own line: the wait about to happen is shorter than\n // the server asked for, and without this the log looks like the hint was never sent.\n logger.warn(`${vendorLabel}Transport: declining the server's requested retry delay (asked ${Math.round(serverMs)}ms; the ${MAX_TOTAL_SERVER_REQUESTED_BACKOFF_MS}ms sequence allowance is spent) \u2014 using the ladder's ${Math.round(waitMs)}ms`);\n }\n return abortableDelay(waitMs, signal);\n };\n // Sequential retries are intentional \u2014 each attempt depends on the previous response.\n /* oxlint-disable no-await-in-loop -- intentional sequential retries with backoff */\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {\n const timeoutController = new AbortController();\n // Which phase the request reached before the clock fired. A bare \"timed out\"\n // cannot distinguish \"the service never answered at all\" from \"it answered,\n // then produced no body\" \u2014 and those have completely different owners\n // (network/gateway vs the service itself). `fetch` resolves on HEADERS, so\n // the phase is knowable here and is the single most useful fact when the\n // only evidence available is a client-side log.\n // `performance.now()` (monotonic), not `Date.now()`: an NTP step or suspend/resume mid-request\n // would otherwise land a nonsense duration in the very message someone is reading to diagnose\n // a hang. Only differences are used, so the arbitrary time origin is irrelevant.\n const startedAt = performance.now();\n let headersAt;\n let responseCtype;\n const timedOutMessage = () => {\n const waited = Math.round(performance.now() - startedAt);\n if (headersAt === undefined) {\n return `${vendorLabel} request timed out after ${waited}ms \u2014 no response headers (the service never answered; nothing was received to stall on)`;\n }\n return `${vendorLabel} request timed out after ${waited}ms \u2014 headers arrived in ${Math.round(headersAt - startedAt)}ms (content-type: ${responseCtype !== null && responseCtype !== void 0 ? responseCtype : 'unknown'}) but no body followed`;\n };\n // Wall clock for connect/headers (and the whole body on the legacy JSON\n // path). The framed path swaps it for the inactivity timer below once the\n // heartbeat body starts streaming.\n let timeoutId = setTimeout(() => timeoutController.abort(new DOMException(timedOutMessage(), 'TimeoutError')), timeout);\n // Re-armed on every received chunk. With proxy pings every 5s it only fires\n // when the proxy/network actually dies \u2014 a framed body that keeps streaming\n // has no wall cap (max_tokens bounds generation; the proxy watches upstream).\n // A non-positive stallTimeout disables inactivity detection: leave the wall\n // clock armed as the only cap (and the sinceLastEventMs backstop stays off).\n const rearmStallTimer = () => {\n if (stallTimeout <= 0)\n return;\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => timeoutController.abort(new DOMException(`${vendorLabel} request stalled (no data for ${stallTimeout}ms)`, 'TimeoutError')), stallTimeout);\n };\n // Combine so BOTH the local timeout and an optional caller signal can abort\n // the fetch. A plain `signal ?? timeoutController.signal` would silently\n // disarm the timeout whenever a caller signal was supplied. The tagged\n // `TimeoutError` lets callers distinguish a timeout from a caller-initiated\n // cancellation by inspecting the abort reason.\n const { signal: combinedSignal, dispose } = combineSignals([signal, timeoutController.signal]);\n // The finally guards the WHOLE attempt \u2014 body reads included. Disarming on\n // headers alone left `response.json()` with no deadline and no caller abort.\n try {\n const response = yield fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: combinedSignal,\n credentials,\n });\n // Headers are in \u2014 record the phase so a later timeout can say so. Cheap and\n // unconditional: the value is only read when the clock actually fires.\n headersAt = performance.now();\n // Defensive: `headers` is optional on the Response-likes callers and tests supply, and a\n // diagnostic must never be the thing that breaks the request it is describing.\n responseCtype = (_c = (_b = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, 'content-type')) !== null && _c !== void 0 ? _c : undefined;\n if (!response.ok) {\n // One read of the error body per failing attempt \u2014 it feeds BOTH the\n // budget classification and the thrown message, and the response is\n // discarded either way. Note this means a retryable attempt now reads\n // the (small, proxy-authored) error body before backing off. That is the\n // price of the classification winning over the ladder in this branch as\n // well as the framed one; the attempt's wall-clock timer is still armed\n // and the read runs on the fetch's combined signal, so a pathological\n // non-terminating body times out rather than hanging.\n //\n // That timeout is a real behaviour change for a RETRYABLE status, and the\n // accepted cost of the symmetry: a 503 used to reach the ladder without\n // the body being touched, so a non-terminating one still backed off and\n // retried. Now the abort propagates out of `postWithRetry` instead.\n // Acceptable because these bodies are proxy-authored and small \u2014 if that\n // ever stops being true, read the body only when the status is\n // non-retryable or already budget-shaped.\n const errText = yield response.text();\n const parsed = parseJsonOrUndefined(errText);\n // The PROVIDER wall (GENC-1506) is classified BEFORE the budget wall, and the order is\n // load-bearing rather than arbitrary. `isBudgetRejection` treats a bare `402` as our own\n // budget verdict, and `402` is also Anthropic's documented `billing_error` status \u2014 so a\n // relayed upstream billing failure would otherwise be reported as the user's own spend cap,\n // locking their composer and sending them to an administrator to raise a limit that has\n // headroom. Every trigger in `providerRefusalOf` is a POSITIVE signal, so a bare `402` with\n // no provider envelope still falls through to the budget branch exactly as it always did.\n const refusal = providerRefusalOf(vendor, codeOf(parsed), parsed);\n if (refusal) {\n throw providerRefusedFrom(vendorLabel, refusal, response.status, parsed, errText || undefined);\n }\n // The budget wall (GENC-1464) wins over ANY status-based retry \u2014 the same\n // rule the framed branch below applies, now symmetric. It must be\n // classified BEFORE the ladder, not after it: 402 is absent from every\n // RETRYABLE_STATUSES today, but a proxy that maps the refusal onto a\n // retryable status (or a future set that includes 402) would otherwise\n // cost five doomed requests and ~31s of backoff before an opaque error \u2014\n // exactly the bug this classification exists to remove. Parsing is\n // best-effort: an unparseable or plain-text 402 still classifies, just\n // without the budget/spent figures.\n if (isBudgetRejection(response.status, codeOf(parsed))) {\n throw budgetExhaustedFrom(vendorLabel, parsed, errText || undefined);\n }\n // An explicit `x-should-retry: false` outranks our own retryable-status set (GENC-1506).\n // The provider knows things the status does not \u2014 a 429 it will keep refusing, say \u2014 and\n // Anthropic's own SDK honours this header. Absent means \"no opinion\", never `false`.\n const refusedRetry = shouldNotRetry(response.headers);\n if (retryableStatuses.includes(response.status) && !refusedRetry && attempt < MAX_RETRIES) {\n logger.warn(`${vendorLabel}Transport: retryable status ${response.status}, retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);\n clearTimeout(timeoutId); // this attempt is over \u2014 don't let its timer tick through the backoff\n // `||` not `??`: `retryAfterMs` returns 0 \u2014 not undefined \u2014 for `Retry-After: 0` and for an\n // HTTP-date already in the past, and a 0 carries nothing the ladder does not already have.\n // With `??` such a response would take the 0 and never read the in-body hint beside it.\n yield backoff(attempt, retryAfterMs(response.headers) || retryInfoMs(parsed));\n continue;\n }\n throw new Error(`${vendorLabel} request error ${response.status}: ${errText}`);\n }\n // The proxy streams NDJSON heartbeat frames when it supports them; an old\n // proxy ignores our Accept header and returns plain JSON, so branch on\n // what actually came back.\n if (((_e = (_d = response.headers) === null || _d === void 0 ? void 0 : _d.get('content-type')) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('application/x-ndjson')) &&\n response.body) {\n rearmStallTimer();\n const frame = yield readFramedBody(response.body, rearmStallTimer, vendorLabel, stallTimeout);\n if (frame.t === 'ok')\n return frame.body;\n // Classify a stall by `code` BEFORE the retryable-status ladder: a stall\n // paired with a retryable status must surface as the non-retried\n // TimeoutError, not get retried 5\u00D7 as that status.\n if (frame.code === 'UPSTREAM_STALLED') {\n // The proxy watchdog saw no upstream data \u2014 same tagged shape as a\n // local stall, so the driver's TimeoutError branch handles both.\n throw new DOMException(`${vendorLabel} request stalled: ${(_f = frame.error) !== null && _f !== void 0 ? _f : 'no upstream data'}`, 'TimeoutError');\n }\n // The budget wall, framed (GENC-1464) \u2014 the in-band twin of the 402 above,\n // through the same predicate, keyed on status OR code. Classified before\n // the retryable ladder for the same reason UPSTREAM_STALLED is: the\n // classification must win over any status-based retry. That ordering is\n // no longer unique to this branch \u2014 the legacy branch above now applies\n // the identical rule, so the two read as one policy rather than two.\n // The PROVIDER wall, framed (GENC-1506) \u2014 the in-band twin of the classification in the\n // legacy branch above, ahead of the budget wall for the same reason: the proxy relays an\n // upstream `402` faithfully, so a `billing_error` would otherwise be reported as the user's\n // own spend cap. On this path the upstream envelope rides in the frame's `details` while the\n // frame's own `error` is the proxy's summary string \u2014 `providerRefusalOf` reads both\n // positions, so the same classification serves the browser and the server.\n const framedRefusal = providerRefusalOf(vendor, frame.code, frame);\n if (framedRefusal) {\n throw providerRefusedFrom(vendorLabel, framedRefusal, frame.status, frame, frame.error);\n }\n if (isBudgetRejection(frame.status, frame.code)) {\n throw budgetExhaustedFrom(vendorLabel, frame);\n }\n // An in-band retryable status joins the same attempt/backoff ladder as\n // its HTTP-status equivalent (shared attempt counter). No `x-should-retry` to consult here \u2014\n // in framed mode the HTTP response is the proxy's own 200, so its headers say nothing about\n // the upstream attempt; the in-body `RetryInfo` is the only hint that survives the hop.\n if (retryableStatuses.includes(frame.status) && attempt < MAX_RETRIES) {\n logger.warn(`${vendorLabel}Transport: retryable status ${frame.status} (err frame), retrying (attempt ${attempt + 1}/${MAX_RETRIES})`);\n clearTimeout(timeoutId); // disarm the stall timer \u2014 the stream is done, only the backoff remains\n yield backoff(attempt, retryInfoMs(frame));\n continue;\n }\n throw new Error(`${vendorLabel} request error ${frame.status}: ${(_g = frame.error) !== null && _g !== void 0 ? _g : JSON.stringify(frame.details)}`);\n }\n return (yield response.json());\n }\n catch (e) {\n // Some engines reject an aborted read with a generic AbortError instead of\n // the signal's reason \u2014 rethrow the authoritative one so a timeout stays a\n // tagged TimeoutError rather than looking like a user cancel.\n throw authoritativeAbortReason(e, timeoutController.signal, signal);\n }\n finally {\n clearTimeout(timeoutId);\n dispose();\n }\n }\n /* oxlint-enable no-await-in-loop */\n throw new Error(`${vendorLabel} request failed: max retries exceeded`);\n });\n}\n", "import { __awaiter } from \"tslib\";\nimport { SUPPORTED_ANTHROPIC_MODEL_IDS, } from '../types';\nimport { normalizeImageMime, stripImageDataUrl } from '../utils/image-mime';\nimport { logger } from '../utils/logger';\nimport { scaleTemperature } from '../utils/temperature';\nimport { anthropicTokenCost } from '../utils/token-cost';\nimport { enforceAnthropicToolSchema } from '../utils/tool-schema';\nimport { VENDOR_LABELS } from './budget-exhausted-error';\nimport { postWithRetry } from './post-with-retry';\nconst ANTHROPIC_DIRECT_URL = 'https://api.anthropic.com/v1/messages';\nconst ANTHROPIC_API_VERSION = '2023-06-01';\nconst DEFAULT_MODEL = 'claude-haiku-4-5-20251001';\nconst DEFAULT_TIMEOUT = 300000; // healthy >200s generations observed at 128k max_tokens; wall clock is a last resort\nconst DEFAULT_STALL_TIMEOUT = 30000; // inactivity window on the framed proxy path; pings arrive every 5s\nconst DEFAULT_MAX_TOKENS = 4096;\n/** Anthropic's native default + ceiling temperature \u2014 https://docs.claude.com/en/api/messages */\nconst ANTHROPIC_DEFAULT_TEMPERATURE = 1;\nconst ANTHROPIC_MAX_TEMPERATURE = 1;\n/**\n * Map a provider-agnostic {@link ChatToolChoice} to Anthropic's `tool_choice`.\n * Returns undefined for the default (`'auto'`) so the request omits the field.\n */\nfunction toAnthropicToolChoice(choice) {\n if (!choice || choice === 'auto')\n return undefined;\n if (choice === 'required')\n return { type: 'any' };\n if (choice === 'none')\n return { type: 'none' };\n return { type: 'tool', name: choice.tool };\n}\n/**\n * Maximum input context window (tokens) per supported Claude model.\n * Source: https://docs.claude.com/en/docs/about-claude/models/overview\n */\nconst ANTHROPIC_CONTEXT_LIMITS = {\n 'claude-fable-5': 1000000,\n 'claude-opus-4-8': 1000000,\n 'claude-opus-4-7': 1000000,\n 'claude-sonnet-5': 1000000,\n 'claude-sonnet-4-6': 1000000,\n 'claude-haiku-4-5-20251001': 200000,\n};\n/**\n * Tool name used to coerce JSON-schema output from the model when the caller\n * provided a `responseSchema`. The transport forces `tool_choice` to this tool\n * and surfaces the `input` field as the structured response.\n */\nconst STRUCTURED_OUTPUT_TOOL_NAME = 'emit_structured_response';\n/** Beta flag enabling the server-side `fallbacks` request parameter (refusal rescue). */\nconst SERVER_SIDE_FALLBACK_BETA = 'server-side-fallback-2026-06-01';\nfunction assertSupportedAnthropicModel(model) {\n if (!SUPPORTED_ANTHROPIC_MODEL_IDS.includes(model)) {\n throw new Error(`AnthropicTransport: unsupported model \"${model}\". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(', ')}.`);\n }\n}\n/**\n * Models that reject non-default sampling parameters (`temperature`/`top_p`/`top_k`) with a 400 \u2014\n * the Opus 4.7+ / Sonnet 5 / Fable 5 generation. Sonnet 4.6 and Haiku 4.5 still accept them.\n */\nfunction rejectsSamplingParams(model) {\n return (model === 'claude-fable-5' ||\n model === 'claude-opus-4-8' ||\n model === 'claude-opus-4-7' ||\n model === 'claude-sonnet-5');\n}\n/**\n * Whether the model enforces structured output natively via decode-time `output_config.format`\n * (json_schema). True for Fable 5, Opus 4.8, Sonnet 5, and Haiku 4.5; false for Opus 4.7 and\n * Sonnet 4.6, which fall back to the forced-tool approach on the one-shot path. `output_config`\n * composes with a live `tools` array, so no tool-vs-schema gating is needed on this provider.\n */\nfunction supportsNativeStructuredOutput(model) {\n return (model === 'claude-fable-5' ||\n model === 'claude-opus-4-8' ||\n model === 'claude-sonnet-5' ||\n model === 'claude-haiku-4-5-20251001');\n}\n/**\n * Whether a model accepts `thinking: {type:'adaptive'}` at all. Everything from the 4.6\n * generation on does; Haiku 4.5 does not, and asking for it there is a 400 rather than a\n * no-op \u2014 so a caller's `'auto'` degrades to the model default instead of failing the turn.\n */\nfunction supportsAdaptiveThinking(model) {\n return model !== 'claude-haiku-4-5-20251001';\n}\n/**\n * Models that think **unconditionally** \u2014 `{type:'disabled'}` is a 400, not a no-op. The same\n * constraint exists on the other provider (Gemini 2.5 Pro), so this is a property of flagship\n * reasoning models rather than an Anthropic quirk; see `ChatThinkingPolicy`.\n */\nfunction thinkingIsMandatory(model) {\n return model === 'claude-fable-5';\n}\n/**\n * Extended-thinking posture for a request, given the model and the caller's\n * {@link ChatThinkingPolicy} for this turn.\n *\n * **`policy === undefined` is the per-model default, and is a distinct third state** \u2014 not a\n * synonym for either value. It reproduces exactly what this function returned before the option\n * existed, so an agent that leaves `thinkingPolicy` unset (or whose resolver returns `undefined`\n * on a given turn) is priced and behaves identically to before:\n *\n * - Sonnet 5 and Fable 5 \u2192 adaptive thinking with `display:'summarized'`, regardless of\n * `tool_choice`. First-party has no forced-tool-vs-thinking restriction (that's Bedrock-only),\n * and \"adaptive\" self-regulates (the model thinks little on trivial turns on its own), so there\n * is no reason to special-case forced tool calls. `display:'summarized'` means the reasoning\n * summary is always returned \u2014 billed regardless, with the host's toggle deciding only\n * *visibility*. Hiding the steps saves no money; `'off'` is what saves money.\n * - Every other model (Opus 4.8/4.7, Sonnet 4.6, Haiku) \u2192 `thinking` omitted, so it runs WITHOUT\n * thinking on the chat path (their adaptive thinking is opt-in). The older \"forced tool +\n * thinking is incompatible\" restriction therefore never applies to them \u2014 you cannot hit it\n * when thinking is off.\n *\n * An explicit policy overrides that default, **clamped to what the model can actually honour**\n * so a policy can never turn a turn into a 400:\n *\n * - `'off'` on a mandatory-thinking model (Fable 5) \u2192 left at its default. Requesting `disabled`\n * there is a 400; the caller is told once via {@link AnthropicTransport} rather than losing\n * the turn.\n * - `'auto'` on a model without adaptive support (Haiku) \u2192 omitted, i.e. its default.\n *\n * `'off'` is expressed as an *omission* on models that already default to no thinking, rather\n * than an explicit `{type:'disabled'}`: the two are equivalent on the wire there, and omitting\n * keeps the request identical to the one those models have always received.\n */\nfunction anthropicThinking(model, policy) {\n const defaultsToThinking = model === 'claude-sonnet-5' || thinkingIsMandatory(model);\n const adaptive = { type: 'adaptive', display: 'summarized' };\n if (policy === 'off') {\n // Cannot be turned off \u2014 keep the model's default rather than 400 the turn.\n if (thinkingIsMandatory(model))\n return adaptive;\n // Already off by default: omitting and disabling are the same request.\n return defaultsToThinking ? { type: 'disabled' } : undefined;\n }\n if (policy === 'auto') {\n return supportsAdaptiveThinking(model) ? adaptive : undefined;\n }\n // A graded level asks for reasoning DEPTH, which on Anthropic is `output_config.effort`\n // riding alongside adaptive thinking (see `anthropicEffort`). Asking for a depth on a model\n // with no adaptive support leaves it at its default rather than 400ing the turn.\n if (policy !== undefined) {\n return supportsAdaptiveThinking(model) ? adaptive : undefined;\n }\n // policy === undefined \u2192 the per-model default, unchanged.\n return defaultsToThinking ? adaptive : undefined;\n}\n/**\n * Whether the model accepts `output_config.effort`.\n *\n * An allow-list, and deliberately the same generation {@link supportsNativeStructuredOutput}\n * treats as new, minus Haiku: `effort` and `format` share the one `output_config` container, so\n * the two gates must agree on which models understand it. `output_config` arrived with the\n * Fable 5 / Opus 4.8 / Sonnet 5 generation \u2014 Opus 4.7 and Sonnet 4.6 predate it and 400 on a\n * field inside it, so a graded policy is dropped for them (they run their default posture, with a\n * one-time warning from {@link AnthropicTransport}) rather than forwarded into a failed turn.\n *\n * Haiku 4.5 is the lone asymmetry with `supportsNativeStructuredOutput`, which lists it: Haiku\n * took `output_config.format` but not `.effort`, and has no adaptive thinking for effort to ride\n * on anyway (`anthropicEffort` also gates on {@link supportsAdaptiveThinking}). An allow-list is\n * the safe default for a \"send-it-and-400\" parameter \u2014 a newly added model gets no `effort` until\n * it is confirmed to accept it.\n */\nfunction supportsEffort(model) {\n return model === 'claude-fable-5' || model === 'claude-opus-4-8' || model === 'claude-sonnet-5';\n}\n/**\n * `output_config.effort` for a graded policy.\n *\n * An exhaustive `Record`, not a condition chain: adding a member to {@link ChatThinkingLevel}\n * then fails to compile here instead of silently falling through to the model default, which is\n * the failure mode this mapping is most likely to acquire.\n *\n * `'minimal'` clamps UP to `low` \u2014 Anthropic's ladder starts there. `xhigh` is deliberately\n * unreachable; see {@link ChatThinkingPolicy}.\n */\nconst ANTHROPIC_EFFORT = {\n minimal: 'low',\n low: 'low',\n medium: 'medium',\n high: 'high',\n max: 'max',\n};\nfunction anthropicEffort(model, policy) {\n if (policy === undefined || policy === 'auto' || policy === 'off')\n return undefined;\n if (!supportsEffort(model) || !supportsAdaptiveThinking(model))\n return undefined;\n return ANTHROPIC_EFFORT[policy];\n}\n/**\n * Key under which this transport stashes its round-trip state on a tool call's\n * provider-neutral `providerMetadata` bag. Private to AnthropicTransport.\n */\nconst ANTHROPIC_PROVIDER_KEY = 'anthropic';\n/**\n * Thrown when a response was cut off at the output-token limit (Anthropic\n * `stop_reason: 'max_tokens'`, Gemini `finishReason: 'MAX_TOKENS'`) in a way\n * that leaves nothing safe to keep. Both transports raise it when the truncated\n * turn carries tool calls: the model ran out of its output-token budget\n * mid-stream, so the cut-off call's arguments are incomplete or untrustworthy\n * (e.g. a `vfs_write` whose `content` never finished serializing) \u2014 rather than\n * hand a corrupt tool call to the caller, which silently runs with missing args\n * and tends to be retried into an identical wall, the failure is loud and\n * diagnosable. The Gemini transport also raises it when truncation leaves no\n * usable answer text (a blank or thinking-only response), which would otherwise\n * be misclassified \u2014 and pointlessly retried \u2014 as an \"empty\" response.\n *\n * It is deterministic: re-issuing the same request hits the same cap. The remedy\n * is to raise the provider's `maxTokens` where configurable (see\n * {@link AnthropicAIConfig.maxTokens}) or to split the work into smaller\n * outputs \u2014 not to retry verbatim.\n *\n * Shared by both transports; it lives here with the transport that introduced it.\n *\n * @beta\n */\nexport class ResponseTruncatedError extends Error {\n constructor(\n /** The model that produced the truncated response. */\n model, \n /**\n * The `max_tokens` cap the request was sent with, when the transport sends\n * one (Anthropic). Undefined when no explicit cap was requested and the\n * model's own output-token limit applied instead (Gemini).\n */\n maxTokens, \n /** Output tokens generated before truncation, when the usage block is present. */\n outputTokens, \n /** Names of the tool call(s) on the truncated turn (the last is the cut-off one). */\n toolNames) {\n super(`Response truncated at ${maxTokens != null ? `the max_tokens cap (${maxTokens})` : \"the model's output-token limit\"} for model ${model}` +\n (toolNames.length > 0 ? ` while emitting tool call(s): ${toolNames.join(', ')}` : '') +\n '. The output exceeds the per-response limit \u2014 raise the provider maxTokens (where configurable) or split the work into smaller outputs.');\n this.model = model;\n this.maxTokens = maxTokens;\n this.outputTokens = outputTokens;\n this.toolNames = toolNames;\n this.name = 'ResponseTruncatedError';\n }\n}\n/**\n * Transport for Anthropic Claude. Calls the Messages API directly when `apiKey`\n * is provided, otherwise falls back to a server-proxy endpoint (if `serverEndpoint`\n * is configured).\n *\n * Implements `AITransport` (structured prompt via tool-forcing) and `ChatTransport`\n * (multi-turn chat).\n *\n * @beta\n */\nexport class AnthropicTransport {\n /**\n * Warn once when a requested policy is silently clamped, in EITHER direction \u2014 which is what\n * `ChatThinkingPolicy` promises callers. Both directions cost the caller something they asked\n * for and would otherwise get no signal about: `'off'` on a model that always thinks keeps\n * billing reasoning as output, and `'auto'` on a model without adaptive support means an agent\n * that asked to reason quietly does not. (Gemini's twin deliberately stays silent on `'auto'`,\n * but only because dynamic thinking is already the default there; Haiku defaults to none, so\n * the same silence would hide a real difference.)\n */\n warnIfThinkingUnclampable(policy) {\n if (this.warnedThinkingClamped)\n return;\n const message = this.clampWarning(policy);\n if (!message)\n return;\n this.warnedThinkingClamped = true;\n logger.warn(message);\n }\n /**\n * The warning for a policy this model cannot honour, or `undefined` when it can.\n *\n * An exhaustive `switch` with a `never` check rather than a condition chain: a new\n * {@link ChatThinkingPolicy} member must be considered HERE or the build fails. The condition\n * chain this replaced would have let every graded level clamp in silence, which is the one\n * outcome the type's own docs promise callers never happens.\n */\n clampWarning(policy) {\n switch (policy) {\n case undefined:\n return undefined;\n case 'off':\n return thinkingIsMandatory(this.model)\n ? `AnthropicTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} always thinks and rejects an explicit disable. Reasoning tokens are still billed as output; switch model if you need them gone.`\n : undefined;\n case 'auto':\n return supportsAdaptiveThinking(this.model)\n ? undefined\n : `AnthropicTransport: thinkingPolicy 'auto' ignored \u2014 ${this.model} does not support adaptive thinking, so this turn runs without reasoning. Use a Sonnet or Opus tier if the agent needs it.`;\n case 'minimal':\n case 'low':\n case 'medium':\n case 'high':\n case 'max':\n if (!supportsAdaptiveThinking(this.model) || !supportsEffort(this.model)) {\n return `AnthropicTransport: thinkingPolicy '${policy}' ignored \u2014 ${this.model} predates output_config.effort, so this turn runs at its default posture. Use Opus 4.8, Sonnet 5, or Fable 5 to set reasoning depth.`;\n }\n // A clamp WITHIN the supported ladder is documented on the type (Anthropic has no\n // 'minimal'), costs nothing, and would be noise on every turn of a vision loop.\n return undefined;\n default: {\n const exhaustive = policy;\n return exhaustive;\n }\n }\n }\n constructor(config = {}) {\n var _a, _b, _c, _d;\n /**\n * Estimated USD cost accumulated across every successful request on this\n * transport instance. Convenience accessor for non-chat consumers\n * (telemetry, debug overlays). The main chat UI sums per-message `cost`\n * fields instead so its session total stays attributed to chat turns only.\n */\n this.lifetimeCostUsd = 0;\n /**\n * Estimated USD saved by prompt caching vs paying full input price, accumulated across\n * every request. Net of cache-write premiums, so it can be briefly negative before reads\n * accrue. Surfaced alongside `getLifetimeCost`.\n */\n this.lifetimeSavingsUsd = 0;\n /**\n * Whether we have already told the caller their `thinkingPolicy: 'off'` cannot be honoured\n * on this model. Latched, because it would otherwise fire on every turn of a tool loop.\n */\n this.warnedThinkingClamped = false;\n /**\n * Serving-model ids already reported as unrecognised. Per-id rather than a single flag, so a\n * second unknown model is still announced. See {@link AnthropicTransport.servingModel}.\n */\n this.warnedUnknownServingModels = new Set();\n const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL;\n assertSupportedAnthropicModel(model);\n this.model = model;\n if (model === 'claude-sonnet-5') {\n logger.warn('AnthropicTransport: using claude-sonnet-5 \u2014 standard Sonnet tier, higher cost than Haiku, and adaptive thinking runs by default so reasoning tokens add to output cost. Use for stronger reasoning or agent tasks.');\n }\n else if (model === 'claude-sonnet-4-6') {\n logger.warn('AnthropicTransport: using claude-sonnet-4-6 \u2014 higher cost than Haiku; use for stronger reasoning or agent tasks.');\n }\n else if (model === 'claude-opus-4-7' || model === 'claude-opus-4-8') {\n logger.warn(`AnthropicTransport: using ${model} \u2014 significantly higher cost; reserve for tasks where Sonnet reliability is insufficient.`);\n }\n else if (model === 'claude-fable-5') {\n logger.warn('AnthropicTransport: using claude-fable-5 \u2014 Anthropic\\'s most capable model, priced above Opus tier ($10 / $50 per MTok) with thinking always on. Reserve for the hardest reasoning/long-horizon work. Requires \u226530-day data retention (unavailable under ZDR) and may return stop_reason \"refusal\"; pair with an Opus 4.8 fallback.');\n }\n this.timeout = (_b = config.timeout) !== null && _b !== void 0 ? _b : DEFAULT_TIMEOUT;\n this.stallTimeout = (_c = config.stallTimeout) !== null && _c !== void 0 ? _c : DEFAULT_STALL_TIMEOUT;\n this.apiKey = config.apiKey;\n this.serverEndpoint = config.serverEndpoint;\n this.maxTokens = (_d = config.maxTokens) !== null && _d !== void 0 ? _d : DEFAULT_MAX_TOKENS;\n }\n getConfig() {\n return {\n provider: 'anthropic',\n model: this.model,\n contextLimit: ANTHROPIC_CONTEXT_LIMITS[this.model],\n };\n }\n /** Estimated USD cost accumulated across every successful request on this transport instance. */\n getLifetimeCost() {\n return this.lifetimeCostUsd;\n }\n /** Estimated USD saved by prompt caching (net of write premiums) across this instance. */\n getLifetimeSavings() {\n return this.lifetimeSavingsUsd;\n }\n /** Reset the lifetime cost + savings counters. Intended for chat-clear / new-session flows. */\n resetLifetimeCost() {\n this.lifetimeCostUsd = 0;\n this.lifetimeSavingsUsd = 0;\n }\n // \u2500\u2500 AITransport (structured prompt) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendStructuredPrompt(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n const { systemPrompt, userPrompt, responseSchema } = options;\n const messages = [{ role: 'user', content: userPrompt }];\n const body = {\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n };\n if (systemPrompt)\n body.system = systemPrompt;\n // Prefer native decode-time enforcement (`output_config.format`) where the model supports it \u2014\n // the answer comes back as ordinary text conforming to the schema. On models without native\n // support (Opus 4.7, Sonnet 4.6), fall back to the legacy pattern: a tool whose `input_schema`\n // is the schema, forced via `tool_choice`, with the structured payload read from its `tool_use`.\n const useNative = responseSchema != null && supportsNativeStructuredOutput(this.model);\n const useForcedTool = responseSchema != null && !useNative;\n if (useNative) {\n body.output_config = Object.assign(Object.assign({}, body.output_config), { format: { type: 'json_schema', schema: responseSchema } });\n }\n else if (useForcedTool) {\n body.tools = [\n {\n name: STRUCTURED_OUTPUT_TOOL_NAME,\n description: 'Emit the structured response that matches the required schema.',\n input_schema: responseSchema,\n },\n ];\n body.tool_choice = { type: 'tool', name: STRUCTURED_OUTPUT_TOOL_NAME };\n }\n // Sonnet 5 runs adaptive thinking by default; disable it for one-shot prompts \u2014 the reasoning\n // would be billed but discarded. Fable 5 runs thinking unconditionally (cannot be disabled \u2014 a\n // 400), so it is left on; its summary is simply unused here. Not routed through\n // `anthropicThinking`: this path wants the summary suppressed rather than returned, so a\n // clamped Fable 5 must keep omitting the field rather than opting into `display:'summarized'`.\n if (this.model === 'claude-sonnet-5')\n body.thinking = { type: 'disabled' };\n const response = yield this.post(body);\n if (useForcedTool) {\n const toolUse = ((_a = response.content) !== null && _a !== void 0 ? _a : []).find((b) => b.type === 'tool_use' && b.name === STRUCTURED_OUTPUT_TOOL_NAME);\n return toolUse ? JSON.stringify((_b = toolUse.input) !== null && _b !== void 0 ? _b : {}) : '';\n }\n // Native structured output and plain prompts both return the answer as text.\n return ((_c = response.content) !== null && _c !== void 0 ? _c : [])\n .filter((b) => b.type === 'text')\n .map((b) => b.text)\n .join('');\n });\n }\n // \u2500\u2500 ChatTransport (multi-turn chat) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendChatMessage(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c, _d, _e;\n // The models this request could actually be served by \u2014 the configured one plus any\n // fallback target. Needed when replaying reasoning: a signature is only valid for the\n // model that produced it, so stored blocks are replayed only when their producer is\n // still reachable on THIS request. See `reasoningToReplay`.\n const reachableModels = new Set([\n this.model,\n ...((_a = options === null || options === void 0 ? void 0 : options.fallbacks) !== null && _a !== void 0 ? _a : []).map((f) => f.model),\n ]);\n const messages = this.toAnthropicMessages(history, userMessage, options === null || options === void 0 ? void 0 : options.attachments, reachableModels);\n const body = {\n model: this.model,\n // Per-turn override wins over the instance default; see ChatRequestOptions.maxTokens.\n max_tokens: (_b = options === null || options === void 0 ? void 0 : options.maxTokens) !== null && _b !== void 0 ? _b : this.maxTokens,\n messages,\n };\n if (options === null || options === void 0 ? void 0 : options.systemPrompt)\n body.system = options.systemPrompt;\n if ((_c = options === null || options === void 0 ? void 0 : options.tools) === null || _c === void 0 ? void 0 : _c.length) {\n // `enforceSchema` is a per-tool opt-in, and the provider compiles per tool:\n // an unenforced tool is never compiled and costs nothing against the\n // compilation limits, so marking one tool in a large surface is legitimate.\n // Enforcement additionally requires `additionalProperties: false` on every\n // object node, which the adapter adds (see `enforceAnthropicToolSchema` in\n // `utils/tool-schema.ts` for what it strips and what it tightens).\n body.tools = options.tools.map((t) => (Object.assign({ name: t.name, description: t.description, input_schema: t.enforceSchema\n ? enforceAnthropicToolSchema(t.parameters, t.name)\n : t.parameters }, (t.enforceSchema ? { strict: true } : {}))));\n }\n // Map the requested tool-call mode to Anthropic's tool_choice \u2014 only\n // meaningful when tools exist. `'required'`/`{ tool }` force a tool call so\n // a turn can only end via one (e.g. a sub-agent's completion tool).\n if ((_d = body.tools) === null || _d === void 0 ? void 0 : _d.length) {\n const toolChoice = toAnthropicToolChoice(options === null || options === void 0 ? void 0 : options.toolChoice);\n if (toolChoice)\n body.tool_choice = toolChoice;\n }\n // Extended thinking. Adaptive regardless of `tool_choice` \u2014 first-party has no\n // forced-tool-vs-thinking restriction (that's Bedrock-only) and adaptive self-regulates on\n // mechanical turns. The per-turn `thinkingPolicy` overrides the per-model default; an\n // undefined policy reproduces it exactly (see `anthropicThinking`).\n this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n const thinking = anthropicThinking(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n if (thinking)\n body.thinking = thinking;\n // Reasoning DEPTH rides in `output_config.effort`, a different field from `thinking`.\n // MERGED, never assigned: structured output writes `format` into the same object further\n // down, and either write clobbering the other is silent \u2014 the request stays valid, it just\n // quietly stops doing one of the two things it was asked to do.\n const effort = anthropicEffort(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n if (effort)\n body.output_config = Object.assign(Object.assign({}, body.output_config), { effort });\n // Normalized [0,1] temperature \u2192 Anthropic's native range, anchored so 0.5 maps to its default.\n // (Default == max here, so the upper half is flat.) Skipped in two cases:\n //\n // - models that reject sampling params outright (Opus 4.7+ / Sonnet 5 / Fable 5), where\n // sending `temperature` is a 400 whether or not thinking is on;\n // - ANY model with thinking enabled, because temperature is incompatible with thinking on\n // the models that still accept sampling params. Sonnet 4.6 is the live case: it takes a\n // temperature happily until `thinkingPolicy: 'auto'` turns thinking on, at which point\n // `{ thinkingPolicy: 'auto', temperature: 0 }` \u2014 an entirely reasonable agent config \u2014\n // becomes an invalid request. The thinking posture wins; temperature is dropped.\n const thinkingEnabled = (thinking === null || thinking === void 0 ? void 0 : thinking.type) === 'adaptive';\n if ((options === null || options === void 0 ? void 0 : options.temperature) != null && !rejectsSamplingParams(this.model) && !thinkingEnabled) {\n body.temperature = scaleTemperature(options.temperature, {\n defaultTemp: ANTHROPIC_DEFAULT_TEMPERATURE,\n maxTemp: ANTHROPIC_MAX_TEMPERATURE,\n });\n }\n // Structured output: constrain the final text answer to the caller's JSON schema via\n // decode-time `output_config.format`. Composes with a live `tools` array \u2014 the model still\n // calls tools through the turn and conforms its closing answer to the schema. Applied only on\n // models that support it natively; elsewhere the schema is dropped here (the caller keeps a\n // prompt-instruction + validator fallback). No beta header needed.\n if ((options === null || options === void 0 ? void 0 : options.responseSchema) && supportsNativeStructuredOutput(this.model)) {\n body.output_config = Object.assign(Object.assign({}, body.output_config), { format: { type: 'json_schema', schema: options.responseSchema } });\n }\n // Refusal fallback chain (e.g. Fable 5 \u2192 Opus 4.8). Sent as the server-side `fallbacks`\n // param; `post` adds the required beta header when this is present. A refused turn is\n // re-run on the next model in one round trip.\n if ((_e = options === null || options === void 0 ? void 0 : options.fallbacks) === null || _e === void 0 ? void 0 : _e.length) {\n body.fallbacks = options.fallbacks.map((f) => f.maxTokens != null ? { model: f.model, max_tokens: f.maxTokens } : { model: f.model });\n }\n // Place prompt-cache breakpoints per the resolved policy (no-op for `'default'`/absent).\n if (options === null || options === void 0 ? void 0 : options.cachePolicy) {\n this.applyCacheControl(body, options.cachePolicy);\n }\n // Inject never-stored tail context AFTER the cache breakpoints, so this per-turn volatile\n // block stays outside the cached prefix. The caller has already framed it.\n if (options === null || options === void 0 ? void 0 : options.tailContext) {\n this.appendTailContext(body, options.tailContext);\n }\n const response = yield this.post(body, options === null || options === void 0 ? void 0 : options.signal);\n return this.fromAnthropicResponse(response, body.max_tokens);\n });\n }\n /**\n * Place prompt-cache breakpoints on the outgoing request per the resolved {@link CachePolicy}.\n * A breakpoint is `cache_control: {type:'ephemeral'}` on a content block / tool / system block;\n * the API caches the byte-exact prefix up to it. Below a model's minimum cacheable prefix the\n * marker is silently ignored (no error), so placing one is always safe.\n *\n * Render order is tools \u2192 system \u2192 messages, so a breakpoint's cached prefix covers everything\n * before it:\n * - `'tools'` \u2014 last tool (caches the tool block; survives a later system-prompt change).\n * - `'prompt'` \u2014 system block (caches tools + system); falls back to the last tool when there\n * is no system prompt.\n * - `'history'` \u2014 last stored message block (caches tools + system + the whole stored history),\n * keeping the system-tier breakpoint as a cheaper fallback. The injected, never-stored tail\n * context (if any) sits after this and is intentionally left uncached.\n */\n applyCacheControl(body, policy) {\n var _a, _b;\n if (policy.scope === 'default')\n return;\n const cacheControl = policy.ttl === '1h' ? { type: 'ephemeral', ttl: '1h' } : { type: 'ephemeral' };\n if (policy.scope === 'tools') {\n if ((_a = body.tools) === null || _a === void 0 ? void 0 : _a.length) {\n body.tools[body.tools.length - 1].cache_control = cacheControl;\n }\n return;\n }\n // 'prompt' and 'history' both cache through the system prompt. A breakpoint on the (single)\n // system block caches tools + system together; with no system prompt, fall back to the last\n // tool \u2014 the furthest stable prefix available.\n if (typeof body.system === 'string' && body.system.length > 0) {\n body.system = [{ type: 'text', text: body.system, cache_control: cacheControl }];\n }\n else if ((_b = body.tools) === null || _b === void 0 ? void 0 : _b.length) {\n body.tools[body.tools.length - 1].cache_control = cacheControl;\n }\n if (policy.scope === 'history') {\n const lastMessage = body.messages[body.messages.length - 1];\n if (lastMessage && Array.isArray(lastMessage.content) && lastMessage.content.length > 0) {\n lastMessage.content[lastMessage.content.length - 1].cache_control = cacheControl;\n }\n }\n }\n /**\n * Append never-stored tail context (already framed by the caller) as the final block of the\n * outbound messages. Called AFTER `applyCacheControl`, so any `'history'` breakpoint sits\n * on the last *stored* block and this per-turn volatile block stays outside the cached prefix.\n * At a model-call the last message is user-role; if not (defensive), start a fresh user turn.\n */\n appendTailContext(body, tailContext) {\n const block = { type: 'text', text: tailContext };\n const lastMessage = body.messages[body.messages.length - 1];\n if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'user' && Array.isArray(lastMessage.content)) {\n lastMessage.content.push(block);\n }\n else {\n body.messages.push({ role: 'user', content: [block] });\n }\n }\n /**\n * Logs the per-call cost breakdown, accumulates the lifetime running total,\n * and returns the per-call total so the caller can attach it to the response\n * message.\n */\n logTokenUsage(model, promptTokens, candidateTokens, cacheReadTokens, cacheCreationTokens, cacheCreation1hTokens) {\n // The arithmetic and the rate table live in `utils/token-cost` so a host pricing\n // its own requests \u2014 a server proxy, a usage ledger \u2014 uses the same numbers\n // instead of a hand-copied table that drifts. This method keeps only what is\n // instance-scoped: the lifetime accumulators and the log.\n const { costUsd, savedUsd, breakdown } = anthropicTokenCost(model, {\n uncachedInputTokens: promptTokens,\n outputTokens: candidateTokens,\n cacheReadTokens,\n cacheWriteTokens: cacheCreationTokens,\n cacheWrite1hTokens: cacheCreation1hTokens,\n });\n this.lifetimeCostUsd += costUsd;\n this.lifetimeSavingsUsd += savedUsd;\n const dp = AnthropicTransport.COST_DECIMAL_PLACES;\n console.log(`--- Anthropic Token Usage (${model}) ---`);\n console.log(`Prompt Tokens: ${promptTokens} ($${breakdown.promptUsd.toFixed(dp)})`);\n console.log(`Cache Read: ${cacheReadTokens} ($${breakdown.cacheReadUsd.toFixed(dp)})`);\n console.log(`Cache Write: ${cacheCreationTokens} ($${breakdown.cacheWriteUsd.toFixed(dp)})`);\n console.log(`Candidate Tokens: ${candidateTokens} ($${breakdown.candidateUsd.toFixed(dp)})`);\n console.log(`Total Cost: $${costUsd.toFixed(dp)}`);\n console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);\n console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);\n console.log('--------------------------');\n return costUsd;\n }\n /**\n * Convert the internal `ChatMessage[]` history into Anthropic's message format.\n *\n * Anthropic alternates strictly `user` / `assistant`. Tool calls are emitted by\n * the assistant as `tool_use` blocks; the corresponding `tool_result` blocks\n * must appear in the *next* user message and reference the tool by `tool_use_id`.\n * Consecutive same-role turns are merged by the API but we merge here to keep\n * the payload tidy.\n */\n toAnthropicMessages(history, userMessage, attachments, reachableModels = new Set([this.model])) {\n var _a, _b, _c, _d;\n const messages = [];\n const pushBlock = (role, block) => {\n const last = messages[messages.length - 1];\n if (last && last.role === role && Array.isArray(last.content)) {\n last.content.push(block);\n return;\n }\n messages.push({ role, content: [block] });\n };\n /**\n * Split attachments by kind. Images are emitted BEFORE the accompanying text (the order\n * Anthropic's vision guidance specifies); text attachments keep their existing position\n * AFTER it, so a turn with no images produces a byte-identical request to before.\n *\n * Branches on `kind`, never on `mimeType` \u2014 see {@link ChatImageAttachment}.\n */\n const splitAttachments = (atts) => {\n const images = [];\n const texts = [];\n for (const att of atts) {\n if (att.kind === 'image') {\n images.push({\n type: 'image',\n source: {\n type: 'base64',\n media_type: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n });\n }\n else {\n texts.push({ type: 'text', text: `[File: ${att.name}]\\n${att.content}` });\n }\n }\n return { images, texts };\n };\n for (const msg of history) {\n if (msg.role === 'system' ||\n msg.role === 'system-event' ||\n msg.role === 'synthetic-user' ||\n msg.role === 'compacted-summary' ||\n msg.category === 'reasoning' ||\n msg.category === 'narration' ||\n msg.thinking // legacy pre-split sessions\n )\n continue;\n if (msg.toolResult) {\n const resultImages = (_a = msg.toolResult.attachments) !== null && _a !== void 0 ? _a : [];\n pushBlock('user', {\n type: 'tool_result',\n tool_use_id: msg.toolResult.toolCallId,\n // Bare string when there are no images \u2014 the historical shape, byte for byte.\n content: resultImages.length\n ? [\n // Text block only when there IS text. A handler can return an image with no\n // caption (`{ content: '', attachments: [img] }` \u2014 the mainline vision-agent\n // \"just look at this\" shape), and Anthropic 400s an empty text block, live and on\n // replay. Guarded like every user-turn path; the array is then image-only.\n ...(msg.toolResult.content\n ? [{ type: 'text', text: msg.toolResult.content }]\n : []),\n ...resultImages.map((att) => ({\n type: 'image',\n source: {\n type: 'base64',\n media_type: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n })),\n ]\n : msg.toolResult.content,\n });\n continue;\n }\n if ((_b = msg.toolCalls) === null || _b === void 0 ? void 0 : _b.length) {\n // Reasoning first, then text, then the calls \u2014 the order the model produced them,\n // which is the order the API validates. A tool-use loop is one assistant turn, so\n // resuming it requires the thinking that led to the call to still be present and\n // byte-identical. Replayed from the first call's stashed blocks (see\n // `AnthropicToolCallState`), never rebuilt from the display summary.\n for (const block of this.reasoningToReplay(msg.toolCalls[0], reachableModels)) {\n pushBlock('assistant', block);\n }\n if (msg.content) {\n pushBlock('assistant', { type: 'text', text: msg.content });\n }\n for (const tc of msg.toolCalls) {\n pushBlock('assistant', {\n type: 'tool_use',\n id: tc.id,\n name: tc.name,\n input: (_c = tc.args) !== null && _c !== void 0 ? _c : {},\n });\n }\n continue;\n }\n const role = msg.role === 'user' ? 'user' : 'assistant';\n if (role === 'user' && ((_d = msg.attachments) === null || _d === void 0 ? void 0 : _d.length)) {\n const { images, texts } = splitAttachments(msg.attachments);\n for (const image of images)\n pushBlock(role, image);\n // Guarded like the live turn below: an image-only message has empty `content`, and\n // Anthropic 400s an empty text block. Unguarded, such a turn succeeded when sent and\n // then failed on REPLAY \u2014 the nastiest shape of this bug, and \"image, no caption\" is\n // mainline input for a vision agent.\n if (msg.content)\n pushBlock(role, { type: 'text', text: msg.content });\n for (const text of texts)\n pushBlock(role, text);\n }\n else if (msg.content) {\n pushBlock(role, { type: 'text', text: msg.content });\n }\n }\n if (userMessage || (attachments === null || attachments === void 0 ? void 0 : attachments.length)) {\n const { images, texts } = splitAttachments(attachments !== null && attachments !== void 0 ? attachments : []);\n for (const image of images)\n pushBlock('user', image);\n if (userMessage) {\n pushBlock('user', { type: 'text', text: userMessage });\n }\n for (const text of texts)\n pushBlock('user', text);\n }\n return messages;\n }\n /**\n * The blocks to replay ahead of a tool call \u2014 fallback boundaries then reasoning, or none.\n *\n * A `signature` is only valid for the model that produced it, so reasoning captured under a\n * *different* model is normally dropped: an agent that varies `provider` by state can switch\n * models mid-loop, and replaying the old model's signatures would send blocks the new one\n * cannot verify.\n *\n * Two ways the producer can be the model that will validate:\n *\n * 1. **It is the model we are asking for.** `state.model === this.model` \u2014 the ordinary case.\n * 2. **Sticky routing will send this conversation back to it.** After a conversation falls\n * back, later requests carrying `fallbacks` go straight to the model that served, without\n * re-running the one that declined. That is what makes a fallback producer's reasoning\n * replayable at all (Fable 5 configured, Opus 4.8 serving \u2014 the pairing this transport's\n * own constructor warning recommends). But it holds only while the conversation continues\n * under the SAME request configuration, which is why `requestedModel` is compared rather\n * than just checking the chain for the producer.\n *\n * That second condition is deliberately narrow. Chain membership alone is too weak: a\n * fallback target is only *contingently* the server, so an agent that switches `provider` to\n * a model whose own chain happens to contain the old producer would replay foreign\n * signatures to whichever model actually answers. Requiring the requested model to be\n * unchanged separates \"this conversation is still going\" from \"we are somewhere else now\".\n *\n * State captured before `requestedModel` existed falls back to condition 1 alone, which is\n * the conservative branch \u2014 it can drop reasoning, never misdirect it.\n *\n * Boundaries themselves are always echoed: keeping them in place is the documented rule, and\n * with no thinking blocks around them they are inert rather than harmful.\n */\n reasoningToReplay(firstCall, reachableModels) {\n var _a, _b, _c;\n const state = (_a = firstCall.providerMetadata) === null || _a === void 0 ? void 0 : _a[ANTHROPIC_PROVIDER_KEY];\n if (!state)\n return [];\n const boundaries = (_b = state.fallbacks) !== null && _b !== void 0 ? _b : [];\n const stickyToProducer = state.requestedModel === this.model && reachableModels.has(state.model);\n const vouched = state.model === this.model || stickyToProducer;\n return [...boundaries, ...(vouched ? ((_c = state.reasoning) !== null && _c !== void 0 ? _c : []) : [])];\n }\n /**\n * The model that actually served this response.\n *\n * A server-side `fallbacks` chain re-runs a declined request on another model and\n * names it in the response's top-level `model`. Pricing must follow that, not the\n * model we asked for: a Fable 5 request served by Opus 4.8 costed at Fable's\n * $10/$50 instead of $5/$25 doubles that part of the bill.\n *\n * An unrecognised model id is NOT priced at a guessed rate \u2014 that is precisely how\n * a consumer ended up billing Haiku at Sonnet rates. It warns and falls back to the\n * configured model, which is at least a figure someone chose.\n */\n servingModel(response) {\n const served = response.model;\n if (!served || served === this.model)\n return this.model;\n if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(served)) {\n return served;\n }\n // Latched per id: this is reached once per response AND once per fallback-chain attempt, so\n // an unrecognised model would otherwise repeat on every iteration of every turn for the\n // session's life \u2014 burying the one message the operator needs at exactly the moment cost\n // reporting has gone wrong. Keyed by id so a second unknown model still gets its own line.\n if (!this.warnedUnknownServingModels.has(served)) {\n this.warnedUnknownServingModels.add(served);\n logger.warn(`AnthropicTransport: response was served by \"${served}\", which is not a known model \u2014 ` +\n `pricing it at the configured \"${this.model}\" rate instead of guessing. The reported ` +\n `cost for this request may be wrong; add the model to SUPPORTED_ANTHROPIC_MODEL_IDS.`);\n }\n return this.model;\n }\n /**\n * Whether a fallback-chain attempt is a refusal that was **not billed**.\n *\n * Anthropic does not charge for a refusal that arrives before any output: the token counts\n * still appear in `usage`, but they are not on the bill. Pricing them anyway turns the\n * fallback undercount this reducer was written to fix into an overcount \u2014 the documented\n * example declines with `input_tokens: 535, output_tokens: 0`, which is real money at\n * Fable 5's prompt rate.\n *\n * A **mid-output** refusal *is* billed for the input and whatever it streamed, so output\n * tokens are the discriminator rather than the refusal itself.\n *\n * Declined attempts appear as `type: 'message'`; the attempt that served the turn is\n * `type: 'fallback_message'`. The serving entry is normally billable \u2014 except when every\n * model in the chain declined, where the last entry is both the serving one and a refusal,\n * which `lastAndRefused` covers.\n *\n * Also called for a response with no chain at all, as `isUnbilledRefusal({}, usage, refused)`:\n * a direct request that was declined has no `iterations` array, and the same rule applies to\n * it. That is in fact the common case \u2014 `iterations` only appears when `fallbacks` was\n * configured.\n */\n isUnbilledRefusal(attempt, usage, lastAndRefused) {\n var _a;\n if (((_a = usage.output_tokens) !== null && _a !== void 0 ? _a : 0) > 0)\n return false;\n return attempt.type === 'message' || lastAndRefused;\n }\n /** Cost one attempt's usage block at `model`'s rates, logging and banking it. */\n costAttempt(model, usage) {\n var _a, _b, _c, _d, _e, _f;\n const cacheRead = (_a = usage.cache_read_input_tokens) !== null && _a !== void 0 ? _a : 0;\n // 1-hour writes bill at 2\u00D7 vs 1.25\u00D7 for 5-min, so read the per-TTL breakdown when present\n // and let the cost path split the buckets. Fall back to the flat total (treated as 5-min)\n // when the breakdown is absent.\n const breakdown = usage.cache_creation;\n const cacheCreation1h = (_b = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _b !== void 0 ? _b : 0;\n const cacheCreation = (_c = usage.cache_creation_input_tokens) !== null && _c !== void 0 ? _c : (breakdown ? ((_d = breakdown.ephemeral_5m_input_tokens) !== null && _d !== void 0 ? _d : 0) + cacheCreation1h : 0);\n return this.logTokenUsage(model, (_e = usage.input_tokens) !== null && _e !== void 0 ? _e : 0, (_f = usage.output_tokens) !== null && _f !== void 0 ? _f : 0, cacheRead, cacheCreation, cacheCreation1h);\n }\n fromAnthropicResponse(response, \n /** The cap ACTUALLY sent this turn \u2014 a per-turn `maxTokens` overrides the instance one. */\n effectiveMaxTokens = this.maxTokens) {\n var _a, _b, _c, _d, _e, _f, _g;\n let inputTokens;\n let outputTokens;\n let cacheReadTokens;\n let cacheWriteTokens;\n let cost;\n const servingModel = this.servingModel(response);\n if (response.usage) {\n const uncachedInput = (_a = response.usage.input_tokens) !== null && _a !== void 0 ? _a : 0;\n const cacheRead = (_b = response.usage.cache_read_input_tokens) !== null && _b !== void 0 ? _b : 0;\n const breakdown = response.usage.cache_creation;\n const cacheCreation1h = (_c = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _c !== void 0 ? _c : 0;\n const cacheCreation = (_d = response.usage.cache_creation_input_tokens) !== null && _d !== void 0 ? _d : (breakdown ? ((_e = breakdown.ephemeral_5m_input_tokens) !== null && _e !== void 0 ? _e : 0) + cacheCreation1h : 0);\n // Top-level `usage` describes only the attempt that produced this message. When a\n // fallback chain ran, the ATTEMPTS BEFORE IT were billed too \u2014 a mid-output decline\n // bills for what it streamed \u2014 and they may have run on a different model at a\n // different rate. Cost each attempt at its own model and sum; the token fields\n // below still describe the serving attempt, which is what the message's content is.\n const attempts = response.usage.iterations;\n if (attempts === null || attempts === void 0 ? void 0 : attempts.length) {\n const refused = response.stop_reason === 'refusal';\n cost = attempts.reduce((total, attempt, index) => {\n var _a;\n const usage = (_a = attempt.usage) !== null && _a !== void 0 ? _a : attempt;\n if (this.isUnbilledRefusal(attempt, usage, index === attempts.length - 1 && refused)) {\n return total;\n }\n // An omitted `model` means the attempt ran on the model we ASKED for \u2014 which on a\n // chain turn is precisely not the one that served it. Defaulting to `servingModel`\n // here would price a declining Fable 5 attempt at Opus 4.8's $5/$25 instead of\n // $10/$50: half its real cost, in the same silent-undercount direction this reducer\n // exists to fix.\n const model = attempt.model ? this.servingModel({ model: attempt.model }) : this.model;\n return total + this.costAttempt(model, usage);\n }, 0);\n }\n else if (this.isUnbilledRefusal({}, response.usage, response.stop_reason === 'refusal')) {\n // A refusal with no chain behind it \u2014 the model was called directly, declined before\n // producing anything, and was not charged. The `iterations` branch above only sees\n // this when `fallbacks` was configured; most refusals arrive here instead, so pricing\n // this path is the difference between an occasional phantom charge and a routine one.\n cost = 0;\n }\n else {\n cost = this.costAttempt(servingModel, response.usage);\n }\n // Report TOTAL prompt size (uncached + cache read + cache write) so `inputTokens` means\n // \"prompt tokens\" consistently whether or not caching was active \u2014 matching Gemini's\n // `promptTokenCount`, which already includes cached tokens. Cost (above) reflects the\n // cache discount; this field is the size, not the bill.\n inputTokens = uncachedInput + cacheRead + cacheCreation;\n // The two cache buckets BREAK DOWN the prompt total above rather than adding\n // to it, so a consumer derives uncached input by subtracting them. Reported\n // even when zero: \"this provider measured the split and it was 0\" is distinct\n // from \"this provider reports no split at all\" (undefined).\n cacheReadTokens = cacheRead;\n cacheWriteTokens = cacheCreation;\n if (response.usage.output_tokens != null) {\n outputTokens = response.usage.output_tokens;\n }\n }\n const blocks = (_f = response.content) !== null && _f !== void 0 ? _f : [];\n const toolCalls = [];\n const thoughtParts = [];\n const textParts = [];\n // Raw reasoning blocks, kept verbatim for wire replay. Distinct from `thoughtParts`,\n // which is the readable text for display \u2014 that copy is lossy (no signature) and must\n // never be what goes back to the API.\n const reasoningBlocks = [];\n // A server-side fallback splits the turn: everything before the LAST `fallback` block was\n // produced by a model that then declined. Its reasoning and client tool calls must be\n // dropped when echoing the turn \u2014 they belong to a model that is no longer answering, and\n // their signatures are not valid for the one that is. Replaying blocks from both sides of\n // the boundary is a rejected request, not a degraded one. Absent a fallback (the normal\n // case) this is -1, so every block counts as post-boundary and nothing changes.\n const fallbackIndex = blocks.map((b) => b.type).lastIndexOf('fallback');\n const fallbackBlocks = blocks.filter((b) => b.type === 'fallback');\n for (const [index, block] of blocks.entries()) {\n const postBoundary = index > fallbackIndex;\n if (block.type === 'tool_use') {\n // A pre-boundary client tool call was abandoned with the declined attempt; echoing it\n // would ask the serving model to own a call it never made.\n if (postBoundary) {\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: (_g = block.input) !== null && _g !== void 0 ? _g : {},\n });\n }\n }\n else if (block.type === 'thinking') {\n if (postBoundary)\n reasoningBlocks.push(block);\n thoughtParts.push(block.thinking);\n }\n else if (block.type === 'redacted_thinking') {\n // No readable text by design \u2014 replayable but never displayable.\n if (postBoundary)\n reasoningBlocks.push(block);\n }\n else if (block.type === 'text') {\n textParts.push(block.text);\n }\n }\n // Attach the turn's reasoning to the FIRST tool call, which is where it is replayed\n // from: the blocks precede the whole `tool_use` group in the assistant message, not\n // each call individually. Stored only when a tool call exists \u2014 without one the turn\n // ends and there is nothing to resume, so the blocks have no further wire role. The\n // boundary marker travels with them so it can be re-emitted in position, which is what\n // the API validates the surrounding thinking blocks against.\n if (toolCalls.length > 0 && (reasoningBlocks.length > 0 || fallbackBlocks.length > 0)) {\n const state = {\n reasoning: reasoningBlocks,\n model: servingModel,\n requestedModel: this.model,\n };\n if (fallbackBlocks.length > 0)\n state.fallbacks = fallbackBlocks;\n toolCalls[0].providerMetadata = Object.assign(Object.assign({}, toolCalls[0].providerMetadata), { [ANTHROPIC_PROVIDER_KEY]: state });\n }\n // A `max_tokens` stop means the response was cut off mid-stream. For a turn\n // carrying tool calls this is fatal: the final tool call's argument JSON was\n // truncated before it closed, so its args are incomplete and the call cannot\n // be run. Raise rather than return a corrupt tool call (which would run with\n // missing args and get retried into the same wall). Usage/cost is already\n // logged above, so the spent tokens are still accounted for on this instance.\n if (response.stop_reason === 'max_tokens' && toolCalls.length > 0) {\n throw new ResponseTruncatedError(this.model, effectiveMaxTokens, outputTokens, toolCalls.map((tc) => tc.name));\n }\n // Reasoning (extended-thinking summary) and answer/narration travel in separate channels:\n // `content` is the answer text, `reasoning` is the summary. The driver splits them into\n // separate category-tagged messages. (Previously `thoughtParts.join('') || textParts.join('')`\n // put reasoning in `content` and DROPPED the answer text whenever thinking was present.)\n const reasoning = thoughtParts.join('') || undefined;\n const base = toolCalls.length > 0\n ? { role: 'assistant', content: textParts.join(''), reasoning, toolCalls }\n : { role: 'assistant', content: textParts.join(''), reasoning };\n if (inputTokens != null)\n base.inputTokens = inputTokens;\n if (outputTokens != null)\n base.outputTokens = outputTokens;\n if (cacheReadTokens != null)\n base.cacheReadTokens = cacheReadTokens;\n if (cacheWriteTokens != null)\n base.cacheWriteTokens = cacheWriteTokens;\n if (cost != null)\n base.cost = cost;\n // The model that actually answered \u2014 which is NOT the configured one when a\n // fallback chain served the request. Stamped here rather than left to the driver,\n // which only knows what was asked for; a usage ledger attributing spend to the\n // requested model would misattribute every fallback-served turn.\n base.model = servingModel;\n // Surface a non-standard stop reason for observability and parity with the\n // Gemini transport's `responseMeta.finishReason`. A text-only `max_tokens`\n // stop yields partial-but-legible content, so it is returned (not raised) with\n // the truncation flagged \u2014 the caller can decide what to do with it.\n if (response.stop_reason === 'max_tokens') {\n base.responseMeta = { finishReason: 'max_tokens' };\n }\n // A `refusal` stop means safety classifiers declined the request (Fable 5 and other\n // recent models). Content is empty (pre-output) or partial (mid-stream) \u2014 return it\n // rather than crash on an assumed non-empty block, and flag the reason so the driver\n // (or a server-side `fallbacks` chain) can respond deterministically instead of\n // retrying into the same wall. Usage/cost is already logged above.\n if (response.stop_reason === 'refusal') {\n base.responseMeta = { finishReason: 'refusal' };\n }\n return base;\n }\n buildEndpoint() {\n if (this.apiKey) {\n return {\n url: ANTHROPIC_DIRECT_URL,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': ANTHROPIC_API_VERSION,\n // Anthropic blocks browser-origin requests by default. This header is the\n // documented opt-in (equivalent to the SDK's `dangerouslyAllowBrowser`).\n 'anthropic-dangerous-direct-browser-access': 'true',\n },\n credentials: 'omit',\n };\n }\n if (this.serverEndpoint) {\n return {\n url: this.serverEndpoint,\n // Opt in to the proxy's NDJSON heartbeat framing. An old proxy ignores\n // this and returns plain JSON \u2014 see the Content-Type branch in `post`.\n headers: { 'Content-Type': 'application/json', Accept: 'application/x-ndjson' },\n credentials: 'include',\n };\n }\n throw new Error('AnthropicTransport: no API key or server endpoint configured. ' +\n 'Set ANTHROPIC_API_KEY in your .env or pass apiKey/serverEndpoint in AnthropicAIConfig.');\n }\n post(body, signal) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const { url, headers, credentials } = this.buildEndpoint();\n // The server-side `fallbacks` param is gated behind a beta flag; add it per-request only\n // when a fallback chain is set (the param without the header is a 400, and vice-versa is fine).\n const requestHeaders = ((_a = body.fallbacks) === null || _a === void 0 ? void 0 : _a.length)\n ? Object.assign(Object.assign({}, headers), { 'anthropic-beta': [headers['anthropic-beta'], SERVER_SIDE_FALLBACK_BETA]\n .filter(Boolean)\n .join(',') }) : headers;\n return (yield postWithRetry({\n url,\n headers: requestHeaders,\n body,\n credentials,\n vendorLabel: VENDOR_LABELS.anthropic,\n retryableStatuses: AnthropicTransport.RETRYABLE_STATUSES,\n timeout: this.timeout,\n stallTimeout: this.stallTimeout,\n backoffBaseMs: AnthropicTransport.BACKOFF_BASE_MS,\n signal,\n }));\n });\n }\n}\n// \u2500\u2500 Private helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nAnthropicTransport.TOKENS_PER_MILLION = 1000000;\nAnthropicTransport.COST_DECIMAL_PLACES = 6;\nAnthropicTransport.RATE_LIMIT_STATUS = 429;\nAnthropicTransport.SERVICE_UNAVAILABLE_STATUS = 503;\nAnthropicTransport.OVERLOADED_STATUS = 529;\nAnthropicTransport.RETRYABLE_STATUSES = [\n AnthropicTransport.RATE_LIMIT_STATUS,\n AnthropicTransport.SERVICE_UNAVAILABLE_STATUS,\n AnthropicTransport.OVERLOADED_STATUS,\n];\n// Base backoff for the shared retry ladder (1s, 2s, 4s, 8s, 16s).\nAnthropicTransport.BACKOFF_BASE_MS = 1000;\n", "// \u2500\u2500 MALFORMED_FUNCTION_CALL repair \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Gemini occasionally returns `finishReason: \"MALFORMED_FUNCTION_CALL\"` when it\n// has actually produced a complete, correct tool call but serialised it as a\n// Python statement instead of the API's structured format, e.g.\n//\n// print(default_api.vfs_edit(new_string = \"\u2026\", old_string = \"\u2026\", path = \"\u2026\", replace_all = true))\n//\n// The intended call is fully present in `candidates[0].finishMessage`. Rather\n// than throw and burn a ChatDriver retry (a full re-roll that may regenerate\n// something worse, or malform again), we parse the call back out and hand it to\n// the transport as a normal structured tool call \u2014 unwrapping a wrong envelope,\n// not guessing. The parser is deliberately fail-closed: on ANY ambiguity it\n// returns null and the transport falls back to throwing\n// `MalformedFunctionCallError`, leaving today's retry behaviour unchanged. It\n// never returns a half-parsed call.\nconst MALFORMED_CALL_ANCHOR = 'default_api.';\nconst PRINT_WRAPPER_RE = /print\\(\\s*$/;\nconst UNICODE_ESCAPE_DIGITS = 4;\nconst HEX_ESCAPE_DIGITS = 2;\nconst HEX_RADIX = 16;\n/**\n * Recursive-descent scanner for a single Python-style `default_api.<tool>(...)`\n * call. Walks the string character by character so that delimiters (commas,\n * parens, quotes, brackets, newlines) appearing *inside* string-literal\n * arguments don't prematurely terminate parsing. Throws on the first unexpected\n * token; callers treat any throw as \"not confidently parseable\".\n */\nclass MalformedFunctionCallParser {\n constructor(src) {\n this.src = src;\n this.pos = 0;\n }\n parse() {\n const anchor = this.src.indexOf(MALFORMED_CALL_ANCHOR);\n if (anchor === -1)\n this.bail();\n // Tolerate an enclosing `print(` wrapper (the observed Python form) or a\n // bare call. Any other preamble (e.g. \"Malformed function call: \") is\n // ignored \u2014 we only anchor on `default_api.`.\n const wrapped = PRINT_WRAPPER_RE.test(this.src.slice(0, anchor));\n this.pos = anchor;\n const call = this.parseCall();\n this.skipWhitespace();\n if (wrapped) {\n this.expect(')');\n this.skipWhitespace();\n }\n // Strict: nothing may follow the call. In particular a second\n // `default_api.` (batched calls) bails rather than silently dropping work.\n if (this.pos !== this.src.length)\n this.bail();\n return call;\n }\n parseCall() {\n this.expectLiteral(MALFORMED_CALL_ANCHOR);\n const name = this.readIdentifier();\n this.expect('(');\n const args = this.parseKwargs();\n this.expect(')');\n return { name, args };\n }\n parseKwargs() {\n const args = {};\n for (;;) {\n this.skipWhitespace();\n // Empty arg list, or a tolerated trailing comma before the closing paren.\n if (this.peek() === ')')\n break;\n const key = this.readIdentifier();\n this.skipWhitespace();\n this.expect('=');\n this.skipWhitespace();\n const value = this.parseValue();\n if (Object.prototype.hasOwnProperty.call(args, key))\n this.bail();\n args[key] = value;\n this.skipWhitespace();\n const next = this.peek();\n if (next === ',') {\n this.pos += 1;\n continue;\n }\n if (next === ')')\n break;\n this.bail();\n }\n return args;\n }\n parseValue() {\n const ch = this.peek();\n if (ch === '\"' || ch === \"'\")\n return this.readString();\n if (ch === '-' || ch === '+' || this.isDigit(ch))\n return this.readNumber();\n if (/[A-Za-z]/.test(ch))\n return this.readBareword();\n // Unhandled value form (e.g. a list `[\u2026]` or dict `{\u2026}`) \u2014 bail.\n return this.bail();\n }\n readString() {\n const quote = this.src[this.pos];\n this.pos += 1; // opening quote\n let out = '';\n for (;;) {\n if (this.pos >= this.src.length)\n this.bail(); // unterminated \u2192 truncation guard\n const c = this.src[this.pos];\n this.pos += 1;\n if (c === quote)\n return out; // closing quote\n if (c === '\\\\') {\n out += this.readEscape();\n continue;\n }\n out += c;\n }\n }\n readEscape() {\n if (this.pos >= this.src.length)\n this.bail();\n const e = this.src[this.pos];\n this.pos += 1;\n switch (e) {\n case 'n':\n return '\\n';\n case 't':\n return '\\t';\n case 'r':\n return '\\r';\n case 'b':\n return '\\b';\n case 'f':\n return '\\f';\n case '\\\\':\n return '\\\\';\n case '\"':\n return '\"';\n case \"'\":\n return \"'\";\n case '/':\n return '/';\n case 'u':\n return this.readHexCodepoint(UNICODE_ESCAPE_DIGITS);\n case 'x':\n return this.readHexCodepoint(HEX_ESCAPE_DIGITS);\n default:\n // Unknown escape \u2014 refuse rather than risk a silent mis-decode.\n return this.bail();\n }\n }\n readHexCodepoint(digits) {\n const hex = this.src.slice(this.pos, this.pos + digits);\n if (hex.length !== digits || !/^[0-9a-fA-F]+$/.test(hex))\n this.bail();\n this.pos += digits;\n return String.fromCharCode(parseInt(hex, HEX_RADIX));\n }\n readNumber() {\n const start = this.pos;\n if (this.peek() === '-' || this.peek() === '+')\n this.pos += 1;\n while (this.pos < this.src.length && /[0-9.eE+-]/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n const value = Number(this.src.slice(start, this.pos));\n if (!Number.isFinite(value))\n this.bail();\n return value;\n }\n readBareword() {\n const word = this.readIdentifier();\n switch (word) {\n case 'true':\n case 'True':\n return true;\n case 'false':\n case 'False':\n return false;\n // Python serialises an omitted/optional kwarg as `None` (and sometimes a\n // JSON-ish `null`); decode both to `null` rather than bailing the whole call.\n case 'null':\n case 'None':\n return null;\n default:\n return this.bail();\n }\n }\n readIdentifier() {\n const start = this.pos;\n if (!/[A-Za-z_]/.test(this.peek()))\n this.bail();\n while (this.pos < this.src.length && /[A-Za-z0-9_]/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n return this.src.slice(start, this.pos);\n }\n isDigit(ch) {\n return ch >= '0' && ch <= '9';\n }\n peek() {\n return this.pos < this.src.length ? this.src[this.pos] : '';\n }\n skipWhitespace() {\n while (this.pos < this.src.length && /\\s/.test(this.src[this.pos])) {\n this.pos += 1;\n }\n }\n expect(ch) {\n if (this.src[this.pos] !== ch)\n this.bail();\n this.pos += 1;\n }\n expectLiteral(literal) {\n if (this.src.slice(this.pos, this.pos + literal.length) !== literal)\n this.bail();\n this.pos += literal.length;\n }\n bail() {\n throw new Error('MalformedFunctionCallParser: unexpected token');\n }\n}\n/**\n * Attempts to recover a structured tool call from a Gemini\n * `MALFORMED_FUNCTION_CALL` `finishMessage`. Returns the parsed call only when\n * it parses cleanly AND its tool name is one of the offered tools; otherwise\n * returns null so the caller can fall back to the existing retry path.\n */\nexport function repairMalformedFunctionCall(finishMessage, offeredToolNames) {\n if (!finishMessage)\n return null;\n let call;\n try {\n call = new MalformedFunctionCallParser(finishMessage).parse();\n }\n catch (_a) {\n return null;\n }\n if (!offeredToolNames.has(call.name))\n return null;\n return call;\n}\n", "import { __awaiter } from \"tslib\";\nimport { SUPPORTED_GEMINI_MODEL_IDS, } from '../types';\nimport { normalizeImageMime, stripImageDataUrl } from '../utils/image-mime';\nimport { logger } from '../utils/logger';\nimport { scaleTemperature } from '../utils/temperature';\nimport { geminiTokenCost } from '../utils/token-cost';\nimport { toGeminiSchema } from '../utils/tool-schema';\nimport { ResponseTruncatedError } from './anthropic-transport';\nimport { VENDOR_LABELS } from './budget-exhausted-error';\nimport { repairMalformedFunctionCall } from './gemini-malformed-call';\nimport { postWithRetry } from './post-with-retry';\nconst GEMINI_DIRECT_URL = (model) => `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;\nconst DEFAULT_MODEL = 'gemini-2.5-flash-lite';\nconst DEFAULT_TIMEOUT = 300000; // healthy >200s generations observed at 128k max_tokens; wall clock is a last resort\nconst DEFAULT_STALL_TIMEOUT = 30000; // inactivity window on the framed proxy path; pings arrive every 5s\n/**\n * Maximum input context window (tokens) per supported Gemini model.\n * Source: https://ai.google.dev/gemini-api/docs/models\n */\nconst GEMINI_CONTEXT_LIMITS = {\n 'gemini-2.5-pro': 1048576,\n 'gemini-2.5-flash': 1048576,\n 'gemini-2.5-flash-lite': 1048576,\n 'gemini-3.5-flash': 1048576,\n 'gemini-3.1-flash-lite': 1048576,\n 'gemini-3.1-pro-preview': 1048576,\n};\n/** Gemini's native default + ceiling temperature \u2014 https://ai.google.dev/gemini-api/docs */\nconst GEMINI_DEFAULT_TEMPERATURE = 1;\nconst GEMINI_MAX_TEMPERATURE = 2;\n/**\n * Map a provider-agnostic {@link ChatToolChoice} to Gemini's `toolConfig`.\n * Returns undefined for the default (`'auto'`) so the request omits the field.\n */\nfunction toGeminiToolConfig(choice) {\n if (!choice || choice === 'auto')\n return undefined;\n if (choice === 'required')\n return { functionCallingConfig: { mode: 'ANY' } };\n if (choice === 'none')\n return { functionCallingConfig: { mode: 'NONE' } };\n return { functionCallingConfig: { mode: 'ANY', allowedFunctionNames: [choice.tool] } };\n}\nfunction assertSupportedGeminiModel(model) {\n if (!SUPPORTED_GEMINI_MODEL_IDS.includes(model)) {\n throw new Error(`GeminiTransport: unsupported model \"${model}\". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(', ')}.`);\n }\n}\n/**\n * Per-model warnings emitted on construction. flash-lite tiers are the cheap\n * default and warn-free; higher-cost, frontier, and preview models flag their\n * trade-offs so callers don't pick them by accident.\n */\nconst GEMINI_MODEL_WARNINGS = {\n 'gemini-2.5-flash': 'GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.',\n 'gemini-2.5-pro': 'GeminiTransport: using gemini-2.5-pro \u2014 significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.',\n 'gemini-3.5-flash': 'GeminiTransport: using gemini-3.5-flash \u2014 frontier model, materially higher cost than flash-lite; use for harder reasoning or agent tasks.',\n 'gemini-3.1-pro-preview': 'GeminiTransport: using gemini-3.1-pro-preview \u2014 PREVIEW model (no stability guarantee, may be withdrawn) with significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.',\n};\n/**\n * Gemini's `thinkingConfig` for a turn, given the model and the caller's\n * {@link ChatThinkingPolicy}.\n *\n * `includeThoughts` is about what is **returned**, not what is billed, and stays on for every\n * posture that thinks \u2014 a thinking-only turn would otherwise surface as blank, and the thought\n * summary is what `logTokenUsage` reconciles its thinking-token accounting against.\n *\n * `thinkingBudget` is the posture itself: `0` off, `-1` model-decides. **Omitting it is the third\n * state** and is what an undefined policy sends \u2014 the model's own default, exactly the request\n * shape this transport issued before the option existed.\n *\n * Only the flash tiers can actually be turned off. `gemini-2.5-pro` always thinks (its minimum\n * budget is 128; `0` is rejected), which is the same constraint Anthropic's Fable 5 has \u2014 so a\n * clamp here is the norm across providers, not a Gemini quirk. The 3.x tiers moved to a\n * `thinkingLevel` enum instead of a numeric budget, and a graded {@link ChatThinkingPolicy} now\n * maps onto it (GENC-1508) \u2014 the \"wire it through once per-tier support is confirmed\" this\n * comment used to defer. The 2.5 tiers keep the budget dialect and ignore graded levels rather\n * than being sent an enum they do not take: a clamp costs money, but a guess costs a 400 on a\n * turn the user is waiting for.\n */\nconst GEMINI_THINKING_DISABLEABLE = [\n 'gemini-2.5-flash',\n 'gemini-2.5-flash-lite',\n];\n/** Tiers that accept `generationConfig.mediaResolution`. Gemini 3 only, like `thinkingLevel`. */\nconst GEMINI_MEDIA_RESOLUTION_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/** The tiers that take `thinkingConfig.thinkingLevel` rather than a numeric `thinkingBudget`. */\nconst GEMINI_THINKING_LEVEL_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\n/**\n * Graded policy \u2192 Gemini `thinkingLevel`. Exhaustive `Record` for the same reason as the\n * Anthropic table: a new level must be mapped here or the build fails.\n *\n * `'max'` clamps DOWN to `high` \u2014 Gemini's ladder stops there. See {@link ChatThinkingPolicy}.\n */\nconst GEMINI_THINKING_LEVEL = {\n minimal: 'minimal',\n low: 'low',\n medium: 'medium',\n high: 'high',\n max: 'high',\n};\n/**\n * Tiers that accept only the coarse `low` / `high` pair rather than the full four-level enum.\n *\n * Currently EVERY `thinkingLevel` tier. The Gemini 3 line did not ship `minimal` and `medium`\n * across every tier at once, and this file's own doctrine is that an unverified enum value is\n * worse than a coarser one \u2014 \"a clamp costs money, but a guess costs a 400 on a turn the user is\n * waiting for\". `low`/`high` are the pair confirmed across the line, so the fine levels fold onto\n * their nearer neighbour here rather than being forwarded on faith to a tier that may 400 on\n * them. Remove a tier from this list once its support for the full enum has been OBSERVED, not\n * assumed \u2014 `GEMINI_THINKING_LEVEL`'s finer mapping then takes effect for it immediately.\n */\nconst GEMINI_COARSE_LEVEL_TIERS = [\n 'gemini-3.5-flash',\n 'gemini-3.1-flash-lite',\n 'gemini-3.1-pro-preview',\n];\nconst GEMINI_COARSE_LEVEL = {\n minimal: 'low',\n low: 'low',\n medium: 'high',\n high: 'high',\n};\nconst isGradedLevel = (p) => p !== undefined && p !== 'auto' && p !== 'off';\nfunction geminiThinkingConfig(model, policy) {\n if (isGradedLevel(policy) && GEMINI_THINKING_LEVEL_TIERS.includes(model)) {\n const level = GEMINI_THINKING_LEVEL[policy];\n return {\n includeThoughts: true,\n thinkingLevel: GEMINI_COARSE_LEVEL_TIERS.includes(model) ? GEMINI_COARSE_LEVEL[level] : level,\n };\n }\n if (policy === 'off' && GEMINI_THINKING_DISABLEABLE.includes(model)) {\n // No reasoning to return once there is none to bill for.\n return { includeThoughts: false, thinkingBudget: 0 };\n }\n if (policy === 'auto' && GEMINI_THINKING_DISABLEABLE.includes(model)) {\n return { includeThoughts: true, thinkingBudget: -1 };\n }\n // Undefined policy, or a model whose posture we cannot safely set: the default.\n return { includeThoughts: true };\n}\n/**\n * Token accepted by the Gemini 3 API in place of a real `thoughtSignature` to\n * skip signature validation. Used when replaying a tool call whose signature\n * belongs to a different model (a mid-execution model switch) or was never\n * captured: the step's first function call still needs *a* signature to pass\n * validation, but a foreign signature can't be honoured.\n * Source: https://ai.google.dev/gemini-api/docs/thought-signatures\n */\nconst SKIP_SIGNATURE = 'skip_thought_signature_validator';\n/**\n * Key under which this transport stashes its round-trip state on a tool call's\n * provider-neutral `providerMetadata` bag. Private to GeminiTransport.\n */\nconst GEMINI_PROVIDER_KEY = 'gemini';\n/**\n * Split attachments into image parts and text parts.\n *\n * Images are emitted BEFORE the accompanying text part; text attachments keep their existing\n * position AFTER it, so a turn carrying no images serialises byte-identically to before this\n * existed. Branches on `kind`, never on `mimeType` \u2014 a TEXT attachment can carry an image mime\n * (any pre-GENC-1508 persisted session does; see `ChatImageAttachment`).\n */\nfunction splitAttachmentParts(atts) {\n const imageParts = [];\n const textParts = [];\n for (const att of atts) {\n if (att.kind === 'image') {\n imageParts.push({\n inlineData: {\n mimeType: normalizeImageMime(att.mimeType),\n data: stripImageDataUrl(att.data),\n },\n });\n }\n else {\n textParts.push({ text: `[File: ${att.name}]\\n${att.content}` });\n }\n }\n return { imageParts, textParts };\n}\n/**\n * Thrown when Gemini returns a `MALFORMED_FUNCTION_CALL` finish reason,\n * typically because the model tried to batch multiple tool calls using\n * Python-style syntax instead of the proper API format.\n *\n * @beta\n */\nexport class MalformedFunctionCallError extends Error {\n constructor(finishMessage) {\n super('Gemini returned MALFORMED_FUNCTION_CALL');\n this.finishMessage = finishMessage;\n this.name = 'MalformedFunctionCallError';\n }\n}\n/**\n * Transport for Gemini. Calls the Gemini REST API directly when `apiKey` is\n * provided, otherwise falls back to a server-proxy endpoint (if `serverEndpoint`\n * is configured).\n *\n * Implements `AITransport` (structured prompt) and `ChatTransport` (multi-turn chat).\n *\n * @beta\n */\nexport class GeminiTransport {\n /**\n * Warn once when a requested policy cannot be honoured on this model \u2014 a *cost* decision the\n * caller made that the wire silently reversed, so they hear about it, but only once, not per\n * turn. Two shapes reach here (the Anthropic twin warns on the same two):\n *\n * - `'off'` on a tier that can't disable thinking \u2014 only the flash tiers accept a zero thinking\n * budget; everything else keeps paying for reasoning it was told to stop. (`'auto'` is NOT this\n * case: it is already what an omitted budget produces on every model here, so warning it was\n * \"ignored\" would be false and would spend the one warning the genuine cases need.)\n * - A graded depth (`minimal`\u2026`max`) on a 2.5 tier \u2014 those speak the numeric-budget dialect,\n * not the Gemini 3 `thinkingLevel` enum, so the level is dropped and the turn runs at the\n * default posture. Without this, a caller asking for `high` on `gemini-2.5-pro` and quietly\n * getting the default is left to wonder why.\n */\n warnIfThinkingUnclampable(policy) {\n if (this.warnedThinkingClamped) {\n return;\n }\n if (policy === 'off' && !GEMINI_THINKING_DISABLEABLE.includes(this.model)) {\n this.warnedThinkingClamped = true;\n logger.warn(`GeminiTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} runs its default thinking posture and takes no budget we can safely set. Reasoning tokens are still billed at the candidate rate; use a flash tier if you need them gone.`);\n return;\n }\n if (isGradedLevel(policy) && !GEMINI_THINKING_LEVEL_TIERS.includes(this.model)) {\n this.warnedThinkingClamped = true;\n logger.warn(`GeminiTransport: thinkingPolicy '${policy}' ignored \u2014 ${this.model} takes a numeric thinking budget, not the graded 'thinkingLevel' the Gemini 3 tiers use, so this turn runs at its default reasoning posture. Use a Gemini 3 tier to set reasoning depth.`);\n }\n }\n constructor(config = {}) {\n var _a, _b, _c;\n /**\n * Estimated USD cost accumulated across every successful request on this\n * transport instance. Convenience accessor for non-chat consumers\n * (telemetry, debug overlays). The main chat UI sums per-message `cost`\n * fields instead so its session total stays attributed to chat turns only.\n */\n this.lifetimeCostUsd = 0;\n /**\n * Estimated USD saved by context caching vs paying full input price, accumulated across\n * every request. Gemini implicit caching has no write premium, so this is always \u2265 0.\n * Surfaced alongside `getLifetimeCost`.\n */\n this.lifetimeSavingsUsd = 0;\n /**\n * Whether we have already told the caller their `thinkingPolicy` cannot be honoured on this\n * model. Latched, because it would otherwise fire on every turn of a tool loop.\n */\n this.warnedThinkingClamped = false;\n const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL;\n assertSupportedGeminiModel(model);\n this.model = model;\n const warning = GEMINI_MODEL_WARNINGS[model];\n if (warning) {\n logger.warn(warning);\n }\n this.timeout = (_b = config.timeout) !== null && _b !== void 0 ? _b : DEFAULT_TIMEOUT;\n this.stallTimeout = (_c = config.stallTimeout) !== null && _c !== void 0 ? _c : DEFAULT_STALL_TIMEOUT;\n this.apiKey = config.apiKey;\n this.serverEndpoint = config.serverEndpoint;\n }\n getConfig() {\n return {\n provider: 'gemini',\n model: this.model,\n contextLimit: GEMINI_CONTEXT_LIMITS[this.model],\n };\n }\n /** Estimated USD cost accumulated across every successful request on this transport instance. */\n getLifetimeCost() {\n return this.lifetimeCostUsd;\n }\n /** Estimated USD saved by context caching across this instance (implicit caching \u2192 always \u2265 0). */\n getLifetimeSavings() {\n return this.lifetimeSavingsUsd;\n }\n /** Reset the lifetime cost + savings counters. Intended for chat-clear / new-session flows. */\n resetLifetimeCost() {\n this.lifetimeCostUsd = 0;\n this.lifetimeSavingsUsd = 0;\n }\n // \u2500\u2500 AITransport (structured prompt) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendStructuredPrompt(options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a;\n const { systemPrompt, userPrompt, responseSchema } = options;\n const contents = [];\n if (systemPrompt) {\n contents.push({ role: 'user', parts: [{ text: systemPrompt }] });\n contents.push({ role: 'model', parts: [{ text: 'Understood.' }] });\n }\n contents.push({ role: 'user', parts: [{ text: userPrompt }] });\n const response = yield this.post({ model: this.model, contents, responseSchema });\n return (_a = response === null || response === void 0 ? void 0 : response.content) !== null && _a !== void 0 ? _a : '';\n });\n }\n // \u2500\u2500 ChatTransport (multi-turn chat) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n sendChatMessage(history, userMessage, options) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n // NOTE: `options.cachePolicy` is intentionally NOT read here. Gemini 2.5+ does *implicit*\n // caching automatically and always-on \u2014 it caches as much of the stable request prefix as it\n // can on every call, regardless of the policy's `scope` (including `'default'`). We issue no\n // explicit `cachedContent`, so there is no request-side field to set; the only lever is\n // keeping the prefix byte-stable (a consumer concern). The cached tokens that come back are\n // priced in `logTokenUsage` via `cachedContentTokenCount`. See `CachePolicy` docs.\n const contents = this.toGeminiContents(history, userMessage, options === null || options === void 0 ? void 0 : options.attachments);\n // Never-stored tail context as a trailing user content (after the stable prefix). Verified\n // valid even directly after a functionResponse content. The caller has already framed it.\n if (options === null || options === void 0 ? void 0 : options.tailContext) {\n contents.push({ role: 'user', parts: [{ text: options.tailContext }] });\n }\n // Gemini's function declarations are an OpenAPI 3.0 subset, not JSON Schema,\n // so the canonical dialect is translated on the way out. This is unconditional\n // and unrelated to `ChatToolDefinition.enforceSchema`: Gemini already\n // constrains arguments by default, and the only question here is whether the\n // declaration parses at all. Untranslated, any nullable column is a hard 400.\n const tools = ((_a = options === null || options === void 0 ? void 0 : options.tools) === null || _a === void 0 ? void 0 : _a.length)\n ? [\n {\n functionDeclarations: options.tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: toGeminiSchema(t.parameters),\n })),\n },\n ]\n : undefined;\n const systemInstruction = (options === null || options === void 0 ? void 0 : options.systemPrompt)\n ? { role: 'system', parts: [{ text: options.systemPrompt }] }\n : undefined;\n // Map the requested tool-call mode to Gemini's toolConfig \u2014 only meaningful\n // when functions are declared. NOTE: forcing (`ANY` / allowedFunctionNames)\n // can make the model batch calls in Python-ish syntax \u2192\n // `MALFORMED_FUNCTION_CALL`, which `fromGeminiResponse` repairs in place when\n // it can confidently parse the call (see `repairMalformedFunctionCall`),\n // falling back to the caller's retry otherwise.\n const toolConfig = tools ? toGeminiToolConfig(options === null || options === void 0 ? void 0 : options.toolChoice) : undefined;\n // Thinking posture for this turn. By default (no `thinkingPolicy`) this asks only for thought\n // summaries, so the model's official reasoning is returned and a thinking-only turn surfaces\n // *something* rather than going silently blank \u2014 see `logTokenUsage` for the thinking-token\n // accounting it lets us capture. A policy adds an explicit `thinkingBudget` where the model\n // supports one; Gemini 2.5 Pro always thinks regardless. See `geminiThinkingConfig`.\n this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);\n const generationConfig = { thinkingConfig: geminiThinkingConfig(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy) };\n // Per-turn output ceiling; see ChatRequestOptions.maxTokens for why the instance default\n // is not enough. Omitted when unset, so an unchanged caller sends an unchanged body.\n if ((options === null || options === void 0 ? void 0 : options.maxTokens) != null) {\n generationConfig.maxOutputTokens = options.maxTokens;\n }\n // Image fidelity, from the FIRST image attachment that states a preference. Gemini bills\n // image tokens by resolution, so this is a real cost lever \u2014 and it is the one thing on\n // ChatImageAttachment that Anthropic has no equivalent for, where the only lever is the\n // pixels you send. Deliberately not synthesised into an Anthropic knob.\n const resolutionHint = [\n ...((_b = options === null || options === void 0 ? void 0 : options.attachments) !== null && _b !== void 0 ? _b : []),\n ...history.flatMap((m) => { var _a; return (_a = m.attachments) !== null && _a !== void 0 ? _a : []; }),\n // Tool-result images too: `ChatToolResult.attachments` is typed ChatImageAttachment[], so\n // `detail` is offerable there, and a render handed back by a tool is the whole point of\n // the tool-result image path. Omitting this source made the field silently inert there.\n ...history.flatMap((m) => { var _a, _b; return (_b = (_a = m.toolResult) === null || _a === void 0 ? void 0 : _a.attachments) !== null && _b !== void 0 ? _b : []; }),\n ].find((att) => att.kind === 'image' && att.detail);\n // Gated by tier for the same reason thinkingLevel is: a clamp costs money, a guess costs a\n // 400. Note it is per-REQUEST, so the first stated preference governs every image in the\n // turn \u2014 there is no per-image control on the wire.\n if ((resolutionHint === null || resolutionHint === void 0 ? void 0 : resolutionHint.kind) === 'image' &&\n resolutionHint.detail &&\n GEMINI_MEDIA_RESOLUTION_TIERS.includes(this.model)) {\n generationConfig.mediaResolution = `MEDIA_RESOLUTION_${resolutionHint.detail.toUpperCase()}`;\n }\n // Normalized [0,1] temperature \u2192 Gemini's native range, anchored so 0.5\n // maps to its default (native 1) and 1 to its ceiling (native 2).\n if ((options === null || options === void 0 ? void 0 : options.temperature) != null) {\n generationConfig.temperature = scaleTemperature(options.temperature, {\n defaultTemp: GEMINI_DEFAULT_TEMPERATURE,\n maxTemp: GEMINI_MAX_TEMPERATURE,\n });\n }\n // Names of the tools offered this turn \u2014 used to validate a repaired\n // malformed call against the real tool surface before accepting it.\n const offeredToolNames = new Set(((_c = options === null || options === void 0 ? void 0 : options.tools) !== null && _c !== void 0 ? _c : []).map((t) => t.name));\n // Structured output (native JSON mode). Gemini 3 can combine it with function calling;\n // Gemini 2.x cannot, so on 2.x apply the schema only on a pure structured turn (no tools) and\n // otherwise drop it (the caller keeps a prompt-instruction + validator fallback). Passed as a\n // top-level `responseSchema` that `toDirectPayload` maps to `generationConfig.responseMimeType`\n // + `responseSchema` on the direct path (the proxy forwards it).\n const schemaCoexistsWithTools = this.model.startsWith('gemini-3');\n const applyResponseSchema = (options === null || options === void 0 ? void 0 : options.responseSchema) != null && (!tools || schemaCoexistsWithTools);\n const response = yield this.post(Object.assign({ model: this.model, contents,\n tools,\n systemInstruction,\n toolConfig,\n generationConfig }, (applyResponseSchema\n ? { responseSchema: toGeminiSchema(options.responseSchema) }\n : {})), options === null || options === void 0 ? void 0 : options.signal);\n return this.fromGeminiResponse(response, offeredToolNames, generationConfig.maxOutputTokens);\n });\n }\n /**\n * Logs the per-call cost breakdown, accumulates the lifetime running total,\n * and returns the per-call total so the caller can attach it to the response\n * message.\n */\n logTokenUsage(promptTokens, candidateTokens, thoughtTokens, cachedTokens) {\n // The arithmetic, the rate table and the long-context tiering rule live in\n // `utils/token-cost` so a host pricing its own requests uses the same numbers\n // instead of a hand-copied table that drifts. This method keeps only what is\n // instance-scoped: the lifetime accumulators and the log.\n const { costUsd, savedUsd, breakdown } = geminiTokenCost(this.model, {\n promptTokens,\n candidateTokens,\n thoughtTokens,\n cachedTokens,\n });\n this.lifetimeCostUsd += costUsd;\n this.lifetimeSavingsUsd += savedUsd;\n const dp = GeminiTransport.COST_DECIMAL_PLACES;\n console.log(`--- Gemini Token Usage (${this.model}) ---`);\n console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${breakdown.promptUsd.toFixed(dp)} + $${breakdown.cacheReadUsd.toFixed(dp)})`);\n console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${breakdown.candidateUsd.toFixed(dp)})`);\n console.log(`Total Cost: $${costUsd.toFixed(dp)}`);\n console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);\n console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);\n console.log('--------------------------');\n return costUsd;\n }\n toGeminiContents(history, userMessage, attachments) {\n var _a, _b, _c, _d;\n const contents = [];\n // Gemini requires functionResponse.name to match the original functionCall.name.\n // Our internal IDs are UUIDs, so build a lookup from ID \u2192 function name as we go.\n const toolCallNameById = new Map();\n for (const msg of history) {\n if (msg.role === 'system' ||\n msg.role === 'system-event' ||\n msg.role === 'synthetic-user' ||\n msg.role === 'compacted-summary' ||\n msg.category === 'reasoning' ||\n msg.category === 'narration' ||\n msg.thinking // legacy pre-split sessions\n )\n continue;\n const role = msg.role === 'user' ? 'user' : 'model';\n if (msg.toolResult) {\n const fnName = (_a = toolCallNameById.get(msg.toolResult.toolCallId)) !== null && _a !== void 0 ? _a : msg.toolResult.toolCallId;\n contents.push({\n role: 'user',\n parts: [\n {\n functionResponse: {\n name: fnName,\n response: { content: msg.toolResult.content },\n },\n },\n ],\n });\n // Images ride in their OWN following user content rather than inside\n // `functionResponse.response`. That field is a protobuf Struct and per-tier support for\n // media nested in it is unverified; a separate content is plainly legal and costs an\n // extra content entry. Only emitted when the tool actually returned images, so a\n // result without them is byte-identical to before.\n const resultImages = (_b = msg.toolResult.attachments) !== null && _b !== void 0 ? _b : [];\n if (resultImages.length) {\n contents.push({\n role: 'user',\n parts: resultImages.map((att) => ({\n inlineData: { mimeType: normalizeImageMime(att.mimeType), data: att.data },\n })),\n });\n }\n }\n else if ((_c = msg.toolCalls) === null || _c === void 0 ? void 0 : _c.length) {\n for (const tc of msg.toolCalls) {\n toolCallNameById.set(tc.id, tc.name);\n }\n contents.push({\n role: 'model',\n parts: msg.toolCalls.map((tc, i) => {\n var _a;\n const part = { functionCall: { name: tc.name, args: tc.args } };\n const state = (_a = tc.providerMetadata) === null || _a === void 0 ? void 0 : _a[GEMINI_PROVIDER_KEY];\n // A signature is only valid for the model that produced it. Replay\n // the real one only when the producing model matches this request's\n // model; on a mid-execution model switch (or when none was captured)\n // put the skip token on the step's first call so validation passes.\n // Parallel sibling calls (i > 0) carry no signature, matching what\n // Gemini emits.\n const sig = (state === null || state === void 0 ? void 0 : state.model) === this.model ? state.thoughtSignature : undefined;\n if (sig) {\n part.thoughtSignature = sig;\n }\n else if (i === 0) {\n part.thoughtSignature = SKIP_SIGNATURE;\n }\n return part;\n }),\n });\n }\n else if (role === 'user' && ((_d = msg.attachments) === null || _d === void 0 ? void 0 : _d.length)) {\n const { imageParts, textParts } = splitAttachmentParts(msg.attachments);\n // Empty text parts are dropped, not sent \u2014 see the Anthropic twin. An image-only\n // message has no caption to carry.\n contents.push({\n role: 'user',\n parts: [...imageParts, ...(msg.content ? [{ text: msg.content }] : []), ...textParts],\n });\n }\n else {\n contents.push({ role, parts: [{ text: msg.content }] });\n }\n }\n const { imageParts, textParts } = splitAttachmentParts(attachments !== null && attachments !== void 0 ? attachments : []);\n if (userMessage || imageParts.length || textParts.length) {\n contents.push({\n role: 'user',\n parts: [...imageParts, ...(userMessage ? [{ text: userMessage }] : []), ...textParts],\n });\n }\n return contents;\n }\n /**\n * Map Gemini's `usageMetadata` onto the provider-agnostic usage fields, pricing\n * the call as a side effect (`logTokenUsage`). Returns an empty object when the\n * response carries no usage \u2014 every field is optional, so an absent count stays\n * `undefined` rather than being reported as a measured 0.\n *\n * Split out of `fromGeminiResponse` because it is self-contained bookkeeping\n * that reads better alone \u2014 and because folding it inline pushed that method\n * past the complexity ceiling.\n */\n usageFromGemini(usageMetadata) {\n var _a, _b, _c, _d, _e, _f;\n if (!usageMetadata)\n return {};\n const usage = usageMetadata;\n const cost = this.logTokenUsage((_a = usage.promptTokenCount) !== null && _a !== void 0 ? _a : 0, (_b = usage.candidatesTokenCount) !== null && _b !== void 0 ? _b : 0, (_c = usage.thoughtsTokenCount) !== null && _c !== void 0 ? _c : 0, (_d = usage.cachedContentTokenCount) !== null && _d !== void 0 ? _d : 0);\n return {\n inputTokens: usage.promptTokenCount,\n // Thinking tokens are generated output, billed at the candidate rate, but\n // reported in a field disjoint from `candidatesTokenCount`. Fold them into the\n // provider-agnostic `outputTokens` so it reflects the true generated total \u2014\n // matching Anthropic, whose `output_tokens` already includes them. Left\n // `undefined` only when the provider reported neither count.\n outputTokens: usage.candidatesTokenCount != null || usage.thoughtsTokenCount != null\n ? ((_e = usage.candidatesTokenCount) !== null && _e !== void 0 ? _e : 0) + ((_f = usage.thoughtsTokenCount) !== null && _f !== void 0 ? _f : 0)\n : undefined,\n thoughtsTokens: usage.thoughtsTokenCount,\n // Gemini reports cache HITS only \u2014 implicit caching bills no separate write, so\n // `cacheWriteTokens` is left unset rather than 0 (there is no write bucket to\n // measure, which is not the same as measuring 0). Already counted inside\n // `promptTokenCount`, so this breaks that total down rather than adding to it.\n cacheReadTokens: usage.cachedContentTokenCount,\n cost,\n };\n }\n fromGeminiResponse(response, offeredToolNames = new Set(), \n /**\n * The per-turn cap actually sent, when one was. Left `undefined` on the default path so a\n * truncation still reports \"the model's output-token limit\" \u2014 which is the truth when no\n * `maxOutputTokens` was set, and a lie the moment one is.\n */\n effectiveMaxTokens) {\n var _a, _b, _c, _d;\n const { inputTokens, outputTokens, thoughtsTokens, cacheReadTokens, cost } = this.usageFromGemini(response.usageMetadata);\n const candidates = response === null || response === void 0 ? void 0 : response.candidates;\n const firstCandidate = candidates === null || candidates === void 0 ? void 0 : candidates[0];\n const parts = (_b = (_a = firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.content) === null || _a === void 0 ? void 0 : _a.parts) !== null && _b !== void 0 ? _b : [];\n const toolCalls = [];\n const thoughtParts = [];\n const textParts = [];\n for (const part of parts) {\n if (part.functionCall) {\n // Stash the reasoning signature (and the producing model) so it can be\n // replayed on the next request \u2014 Gemini 3 requires the first function\n // call of each step to carry its signature or the request 400s. The\n // API only returns a signature on the first of a set of parallel calls.\n const state = { model: this.model };\n if (part.thoughtSignature) {\n state.thoughtSignature = part.thoughtSignature;\n }\n toolCalls.push({\n id: crypto.randomUUID(),\n name: part.functionCall.name,\n args: (_c = part.functionCall.args) !== null && _c !== void 0 ? _c : {},\n providerMetadata: { [GEMINI_PROVIDER_KEY]: state },\n });\n }\n else if (part.thought && part.text) {\n thoughtParts.push(part.text);\n }\n else if (part.text) {\n textParts.push(part.text);\n }\n }\n // Gemini sometimes flags MALFORMED_FUNCTION_CALL when it produced a complete\n // tool call but serialised it as a Python statement. Recover it in place\n // when we can parse it with full confidence (its `parts` are empty in this\n // case, so the repaired call flows through the normal token/cost handling\n // below); otherwise throw so the ChatDriver retry takes over.\n if ((firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.finishReason) === 'MALFORMED_FUNCTION_CALL') {\n const repaired = repairMalformedFunctionCall(firstCandidate.finishMessage, offeredToolNames);\n if (!repaired) {\n throw new MalformedFunctionCallError(firstCandidate.finishMessage);\n }\n toolCalls.push({ id: crypto.randomUUID(), name: repaired.name, args: repaired.args });\n }\n // The model's official thinking (thought-summary parts, returned because we set\n // `thinkingConfig.includeThoughts`) travels in its OWN channel, distinct from the answer /\n // tool-call narration: `content` carries the answer text, `reasoning` carries the summary. The\n // driver splits them into separate category-tagged messages (reasoning vs narration) so each has\n // its own visibility toggle and log category. Final answers surface only the answer text; the\n // reasoning summary rides `reasoning` and is deliberately not promoted to be the answer.\n const reasoning = thoughtParts.join('');\n const narration = textParts.join('');\n const base = toolCalls.length > 0\n ? { role: 'assistant', content: narration, reasoning: reasoning || undefined, toolCalls }\n : { role: 'assistant', content: narration, reasoning: reasoning || undefined };\n // Blank / non-STOP finishes are the recurring failure mode (especially empty\n // STOP on 2.5 Pro). Log the full shape so the cause is legible from the\n // breakdown rather than inferred. MALFORMED is excluded \u2014 it has its own\n // repair/throw path above.\n const finishReason = firstCandidate === null || firstCandidate === void 0 ? void 0 : firstCandidate.finishReason;\n const isBlank = toolCalls.length === 0 && !reasoning && !narration;\n if (isBlank ||\n (finishReason && finishReason !== 'STOP' && finishReason !== 'MALFORMED_FUNCTION_CALL')) {\n this.logAbnormalResponse(response, {\n finishReason,\n functionCallParts: toolCalls.length,\n thoughtParts: thoughtParts.length,\n textParts: textParts.length,\n });\n }\n this.guardMaxTokensTruncation(finishReason, toolCalls, narration, outputTokens, effectiveMaxTokens);\n if (inputTokens != null)\n base.inputTokens = inputTokens;\n if (outputTokens != null)\n base.outputTokens = outputTokens;\n if (cacheReadTokens != null)\n base.cacheReadTokens = cacheReadTokens;\n if (cost != null)\n base.cost = cost;\n // Surface the provider diagnostic on the message so the driver can fold it\n // into the debug-log meta events (the console log above is dev-only). Only\n // when there's signal \u2014 a finish reason, thinking tokens, or a block reason.\n const blockReason = (_d = response.promptFeedback) === null || _d === void 0 ? void 0 : _d.blockReason;\n if (finishReason != null || thoughtsTokens != null || blockReason != null) {\n base.responseMeta = {\n finishReason,\n thoughtsTokens,\n parts: {\n functionCall: toolCalls.length,\n thought: thoughtParts.length,\n text: textParts.length,\n },\n blockReason,\n };\n }\n return base;\n }\n /**\n * Raises {@link ResponseTruncatedError} when a `MAX_TOKENS` finish left nothing\n * safe to keep. A MAX_TOKENS finish means generation was cut off at the\n * output-token limit (no explicit cap is requested, so this is the model's own\n * output ceiling \u2014 which thinking tokens share). Truncation is DETERMINISTIC:\n * re-issuing the identical request hits the same limit, so it must not fall\n * through to the caller's empty-response retry. Mirrors the Anthropic\n * transport's contract: with tool calls the cut-off call's args can't be\n * trusted, and with no usable answer text (blank or thinking-only) there is\n * nothing to keep either \u2014 the typed truncation error is raised for both.\n * Partial answer TEXT is instead returned by `fromGeminiResponse`, flagged via\n * `responseMeta.finishReason`, for the caller to decide. Usage/cost is logged\n * before this check runs, so the spent tokens stay accounted for.\n */\n guardMaxTokensTruncation(finishReason, toolCalls, narration, outputTokens, \n /** The per-turn cap sent, when one was \u2014 so the error names the cap it actually hit. */\n effectiveMaxTokens) {\n if (finishReason !== 'MAX_TOKENS')\n return;\n // A truncated text-only answer is partial but legible \u2014 keep it (the driver's\n // emptiness rule is `!content.trim()`, so whitespace-only does NOT count).\n if (toolCalls.length === 0 && narration.trim() !== '')\n return;\n throw new ResponseTruncatedError(this.model, effectiveMaxTokens, outputTokens, toolCalls.map((tc) => tc.name));\n }\n /**\n * Log the full shape of a blank or non-STOP response so its cause is legible\n * without re-deriving it: a thinking-only STOP (substantial `thoughtsTokenCount`,\n * ~0 `candidatesTokenCount`) vs a content block (`SAFETY` / `RECITATION`) vs a\n * token cap (`MAX_TOKENS`) vs a prompt-level block (top-level\n * `promptFeedback.blockReason`). On 2.5 Pro \u2014 which always thinks \u2014 a blank\n * STOP carrying substantial thought tokens is the \"thought, then stopped\n * without answering\" signature.\n */\n logAbnormalResponse(response, parsed) {\n var _a, _b, _c;\n const usage = ((_a = response.usageMetadata) !== null && _a !== void 0 ? _a : {});\n const candidate = (_c = (_b = response.candidates) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : {};\n logger.warn('GeminiTransport: blank/non-STOP response', {\n model: this.model,\n finishReason: parsed.finishReason,\n finishMessage: candidate.finishMessage,\n parts: {\n total: parsed.functionCallParts + parsed.thoughtParts + parsed.textParts,\n functionCall: parsed.functionCallParts,\n thought: parsed.thoughtParts,\n text: parsed.textParts,\n },\n usage: {\n promptTokenCount: usage.promptTokenCount,\n candidatesTokenCount: usage.candidatesTokenCount,\n thoughtsTokenCount: usage.thoughtsTokenCount,\n totalTokenCount: usage.totalTokenCount,\n },\n promptFeedback: response.promptFeedback,\n safetyRatings: candidate.safetyRatings,\n citationMetadata: candidate.citationMetadata,\n });\n }\n buildEndpoint(body) {\n if (this.apiKey) {\n return {\n url: `${GEMINI_DIRECT_URL(this.model)}?key=${this.apiKey}`,\n payload: this.toDirectPayload(body),\n headers: { 'Content-Type': 'application/json' },\n credentials: 'omit',\n };\n }\n if (this.serverEndpoint) {\n return {\n url: this.serverEndpoint,\n payload: body,\n // Opt in to the proxy's NDJSON heartbeat framing. An old proxy ignores\n // this and returns plain JSON \u2014 see the Content-Type branch in `post`.\n headers: { 'Content-Type': 'application/json', Accept: 'application/x-ndjson' },\n credentials: 'include',\n };\n }\n throw new Error('GeminiTransport: no API key or server endpoint configured. ' +\n 'Set GEMINI_API_KEY in your .env or pass apiKey/serverEndpoint in GeminiAIConfig.');\n }\n post(body, signal) {\n return __awaiter(this, void 0, void 0, function* () {\n const { url, payload, headers, credentials } = this.buildEndpoint(body);\n return (yield postWithRetry({\n url,\n headers,\n body: payload,\n credentials,\n vendorLabel: VENDOR_LABELS.gemini,\n retryableStatuses: GeminiTransport.RETRYABLE_STATUSES,\n timeout: this.timeout,\n stallTimeout: this.stallTimeout,\n backoffBaseMs: GeminiTransport.BACKOFF_BASE_MS,\n signal,\n }));\n });\n }\n toDirectPayload(body) {\n const payload = Object.assign({}, body);\n delete payload.model;\n if (payload.responseSchema) {\n payload.generationConfig = Object.assign(Object.assign({}, payload.generationConfig), { responseMimeType: 'application/json', responseSchema: payload.responseSchema });\n delete payload.responseSchema;\n }\n return payload;\n }\n}\n// \u2500\u2500 Private helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nGeminiTransport.TOKENS_PER_MILLION = 1000000;\nGeminiTransport.COST_DECIMAL_PLACES = 6;\nGeminiTransport.RATE_LIMIT_STATUS = 429;\nGeminiTransport.SERVICE_UNAVAILABLE_STATUS = 503;\n/**\n * 502 BAD_GATEWAY is a cleanly transient fault from an intermediate proxy or load\n * balancer fronting the API \u2014 back off and retry it alongside 429/503.\n *\n * Deliberately NOT retried: 500 INTERNAL and 504 DEADLINE_EXCEEDED. Google documents\n * both as also carrying a deterministic cause (\"input context is too long\" / \"prompt\n * too large to process in time\"); re-issuing the identical request just re-hits the\n * same wall and burns the whole backoff ladder \u2014 the same deterministic-retry trap\n * this transport avoids for MAX_TOKENS, and especially wasteful on the large-context\n * agent path. They fail fast instead.\n */\nGeminiTransport.BAD_GATEWAY_STATUS = 502;\nGeminiTransport.RETRYABLE_STATUSES = [\n GeminiTransport.RATE_LIMIT_STATUS,\n GeminiTransport.SERVICE_UNAVAILABLE_STATUS,\n GeminiTransport.BAD_GATEWAY_STATUS,\n];\n// Base backoff for the shared retry ladder (1s, 2s, 4s, 8s, 16s).\nGeminiTransport.BACKOFF_BASE_MS = 1000;\n", "import { __awaiter } from \"tslib\";\nimport { AnthropicProvider } from './providers/anthropic-provider';\nimport { ChromeProvider } from './providers/chrome-provider';\nimport { DefaultAIProvider } from './providers/default-provider';\nimport { GeminiProvider } from './providers/gemini-provider';\nimport { OpenAIProvider } from './providers/openai-provider';\nimport { AnthropicTransport } from './transports/anthropic-transport';\nimport { ChromePromptTransport } from './transports/chrome-prompt-transport';\nimport { GeminiTransport } from './transports/gemini-transport';\nimport { ServerOpenAITransport } from './transports/server-openai-transport';\nimport { SUPPORTED_ANTHROPIC_MODEL_IDS, SUPPORTED_GEMINI_MODEL_IDS, } from './types';\nimport { logger } from './utils';\nimport { isAIFeatureEnabled } from './utils/feature-flags';\nfunction isChromeConfig(config) {\n return 'providerType' in config && config.providerType === 'chrome';\n}\nfunction isGeminiConfig(config) {\n return 'providerType' in config && config.providerType === 'gemini';\n}\nfunction isAnthropicConfig(config) {\n return 'providerType' in config && config.providerType === 'anthropic';\n}\nfunction isServerAIConfig(config) {\n return !!config.provider;\n}\n/**\n * Creates an AIProvider from config.\n * Uses ChromeProvider when providerType is 'chrome'.\n * Uses OpenAIProvider with ServerOpenAITransport when provider is set (server-only).\n * Otherwise returns DefaultAIProvider.\n * When the AI feature flag is disabled (?feature.ai), always returns DefaultAIProvider.\n *\n * @beta\n */\nexport function createAIProvider(config) {\n if (!isAIFeatureEnabled()) {\n logger.warn('createAIProvider: AI feature flag disabled, using DefaultAIProvider');\n return new DefaultAIProvider();\n }\n if (config && isChromeConfig(config)) {\n logger.debug('createAIProvider: using ChromeProvider');\n return new ChromeProvider(config);\n }\n if (config && isGeminiConfig(config)) {\n logger.debug('createAIProvider: using GeminiProvider');\n const transport = new GeminiTransport({\n model: config.model,\n timeout: config.timeout,\n stallTimeout: config.stallTimeout,\n serverEndpoint: config.serverEndpoint,\n apiKey: config.apiKey,\n });\n return new GeminiProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n if (config && isAnthropicConfig(config)) {\n logger.debug('createAIProvider: using AnthropicProvider');\n const transport = new AnthropicTransport({\n model: config.model,\n timeout: config.timeout,\n stallTimeout: config.stallTimeout,\n serverEndpoint: config.serverEndpoint,\n apiKey: config.apiKey,\n maxTokens: config.maxTokens,\n });\n return new AnthropicProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n if (config && isServerAIConfig(config)) {\n if (config.provider !== 'openai') {\n logger.warn('createAIProvider: only openai server provider supported for now, using default');\n return new DefaultAIProvider();\n }\n logger.debug('createAIProvider: using OpenAIProvider (server proxy)');\n const transport = new ServerOpenAITransport({\n model: config.model,\n timeout: config.timeout,\n });\n return new OpenAIProvider({ criteriaInstructions: config.criteriaInstructions }, transport);\n }\n logger.debug('createAIProvider: using DefaultAIProvider');\n return new DefaultAIProvider();\n}\n/**\n * Resolves AI config, optionally preferring Chrome when available.\n * Use before registering AIProvider. Server URL is derived from API_HOST.\n * Returns null when the AI feature flag is disabled (?feature.ai).\n *\n * @beta\n */\nexport function resolveAIConfig() {\n return __awaiter(this, arguments, void 0, function* (options = {}) {\n if (!isAIFeatureEnabled()) {\n logger.warn('resolveAIConfig: AI feature flag disabled');\n return null;\n }\n const { provider = 'openai', model, preferChrome = true } = options;\n if (preferChrome) {\n const transport = new ChromePromptTransport();\n const availability = yield transport.getAvailability();\n if (availability === 'available' ||\n availability === 'downloadable' ||\n availability === 'downloading') {\n return { providerType: 'chrome' };\n }\n logger.warn('resolveAIConfig: Chrome not available', availability);\n }\n if (provider === 'gemini') {\n const geminiModel = model !== null && model !== void 0 ? model : 'gemini-2.5-flash-lite';\n if (!SUPPORTED_GEMINI_MODEL_IDS.includes(geminiModel)) {\n throw new Error(`resolveAIConfig: unsupported Gemini model \"${geminiModel}\". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(', ')}.`);\n }\n return { providerType: 'gemini', model: geminiModel };\n }\n if (provider === 'anthropic') {\n const anthropicModel = model !== null && model !== void 0 ? model : 'claude-haiku-4-5-20251001';\n if (!SUPPORTED_ANTHROPIC_MODEL_IDS.includes(anthropicModel)) {\n throw new Error(`resolveAIConfig: unsupported Anthropic model \"${anthropicModel}\". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(', ')}.`);\n }\n return { providerType: 'anthropic', model: anthropicModel };\n }\n return { provider, model: model !== null && model !== void 0 ? model : 'gpt-4o-mini' };\n });\n}\n/**\n * Feature-detects an {@link ObservableAIProviderRegistry}. Returns `true` when\n * `r` exposes a `subscribe` method \u2014 i.e. it can notify on runtime changes \u2014\n * and `false` for the immutable built-ins.\n *\n * @beta\n */\nexport function isObservableAIProviderRegistry(r) {\n return typeof r.subscribe === 'function';\n}\n/**\n * Built-in fallback registry. Resolved by the DI container when no host has\n * registered an {@link (AIProviderRegistry:interface)}. Holds a single\n * `DefaultAIProvider` (no-op) under the name `'default'`, preserving the\n * \"no host registration \u2192 assistant inert\" behavior.\n *\n * @internal\n */\nexport class EmptyAIProviderRegistry {\n constructor() {\n this.noopProvider = new DefaultAIProvider();\n }\n get(name) {\n return name === EmptyAIProviderRegistry.DEFAULT_NAME ? this.noopProvider : undefined;\n }\n default() {\n return this.noopProvider;\n }\n defaultName() {\n return EmptyAIProviderRegistry.DEFAULT_NAME;\n }\n names() {\n return [EmptyAIProviderRegistry.DEFAULT_NAME];\n }\n getStatus(name) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n if (name !== undefined && name !== EmptyAIProviderRegistry.DEFAULT_NAME)\n return null;\n return (_c = (yield ((_b = (_a = this.noopProvider).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : null;\n });\n }\n listStatuses() {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b, _c;\n const status = (_c = (yield ((_b = (_a = this.noopProvider).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : null;\n return [{ name: EmptyAIProviderRegistry.DEFAULT_NAME, isDefault: true, status }];\n });\n }\n}\nEmptyAIProviderRegistry.DEFAULT_NAME = 'default';\n/**\n * Map-backed registry built by {@link registerAIProviders}. Preserves the\n * insertion order of `providers` for {@link (AIProviderRegistry:interface).names}\n * and {@link (AIProviderRegistry:interface).listStatuses}.\n *\n * Mutable and observable: a host that holds a reference can rebind names,\n * change the default, or atomically replace the whole mapping at runtime via\n * {@link MutableAIProviderRegistry.set}, {@link MutableAIProviderRegistry.setDefault}\n * and {@link MutableAIProviderRegistry.update}, and subscribe to be told when\n * any of those happen. This is the substrate for runtime provider switching:\n * the DI token resolves one stable instance, and consumers re-resolve their\n * cached providers when {@link MutableAIProviderRegistry.subscribe | subscribe}\n * fires. A registry that is never mutated behaves identically to an immutable\n * one, so existing single-registration callers are unaffected.\n *\n * @beta\n */\nexport class MutableAIProviderRegistry {\n constructor(providers, defaultName) {\n this.listeners = new Set();\n // Defensive copy so external mutation of the caller's Map can't desync the\n // registry from its own invariants. Validate the copy we will actually keep.\n const next = new Map(providers);\n MutableAIProviderRegistry.assertValidMapping(next, defaultName);\n this.providers = next;\n this._defaultName = defaultName;\n }\n /**\n * The mapping invariant shared by construction and\n * {@link MutableAIProviderRegistry.update}: at least one provider, and the\n * resolved default name must be one of the keys. Throws\n * with the same messages from both call sites. Validates the finalized map, so\n * callers normalize/copy and resolve the default name first, then validate.\n */\n static assertValidMapping(providers, defaultName) {\n if (providers.size === 0) {\n throw new Error('MutableAIProviderRegistry: at least one provider is required.');\n }\n if (!providers.has(defaultName)) {\n throw new Error(`MutableAIProviderRegistry: default name \"${defaultName}\" not present in providers.`);\n }\n }\n get(name) {\n return this.providers.get(name);\n }\n default() {\n // Construction and every mutator guarantee this lookup succeeds.\n return this.providers.get(this._defaultName);\n }\n defaultName() {\n return this._defaultName;\n }\n names() {\n return [...this.providers.keys()];\n }\n getStatus(name) {\n return __awaiter(this, void 0, void 0, function* () {\n var _a, _b;\n const provider = name === undefined ? this.default() : this.providers.get(name);\n if (!provider)\n return null;\n return (_b = (yield ((_a = provider.getStatus) === null || _a === void 0 ? void 0 : _a.call(provider)))) !== null && _b !== void 0 ? _b : null;\n });\n }\n listStatuses() {\n return __awaiter(this, void 0, void 0, function* () {\n const entries = [...this.providers.entries()];\n return Promise.all(entries.map((_a) => __awaiter(this, [_a], void 0, function* ([name, provider]) {\n var _b, _c;\n return ({\n name,\n isDefault: name === this._defaultName,\n status: (_c = (yield ((_b = provider.getStatus) === null || _b === void 0 ? void 0 : _b.call(provider)))) !== null && _c !== void 0 ? _c : null,\n });\n })));\n });\n }\n /**\n * Rebind (or add) a single name. Rebinding an existing name preserves its\n * position in `names()`; a new name is appended. Notifies subscribers.\n */\n set(name, provider) {\n this.providers.set(name, provider);\n this.notify();\n }\n /**\n * Change the default provider. Throws if `name` is not currently registered.\n * Notifies subscribers.\n */\n setDefault(name) {\n if (!this.providers.has(name)) {\n throw new Error(`MutableAIProviderRegistry: cannot set default to \"${name}\" \u2014 not present in providers.`);\n }\n this._defaultName = name;\n this.notify();\n }\n /**\n * Atomically replace the whole mapping (and optionally the default) in one\n * step, then notify subscribers once. Applies the same validation as the\n * constructor: an empty mapping throws, and the resolved default must be\n * present. When `options.default` is omitted the current default name is\n * retained (and must still exist in the new mapping).\n */\n update(providers, options = {}) {\n var _a;\n const next = providers instanceof Map ? new Map(providers) : new Map(Object.entries(providers));\n const nextDefault = (_a = options.default) !== null && _a !== void 0 ? _a : this._defaultName;\n MutableAIProviderRegistry.assertValidMapping(next, nextDefault);\n this.providers = next;\n this._defaultName = nextDefault;\n this.notify();\n }\n subscribe(listener) {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n /**\n * Fire every listener once. Iterates a snapshot so a listener that\n * unsubscribes (or subscribes) during notification doesn't perturb the\n * in-flight iteration.\n */\n notify() {\n for (const listener of Array.from(this.listeners))\n listener();\n }\n}\n", "import type { AgenticActivityEvents } from './ai-activity-channel';\n\n/**\n * Configuration for {@link AgenticActivityBus}.\n *\n * @beta\n */\nexport interface AgenticActivityBusConfig {\n /** Events that should also be forwarded via BroadcastChannel to other tabs. */\n crossTabEvents?: (keyof AgenticActivityEvents)[];\n /** BroadcastChannel name. Only used when crossTabEvents is non-empty. */\n channelName?: string;\n /**\n * Lazy alternative to {@link AgenticActivityBusConfig.channelName}: called the first\n * time a cross-tab channel is actually needed, in a browser only. Deferring the name\n * computation keeps side effects (e.g. `sessionStorage` reads) out of module-eval and\n * off the non-browser path. Ignored if `channelName` is also set.\n */\n channelNameFactory?: () => string;\n}\n\ntype AnyHandler = (detail: any) => void;\n\n/**\n * Minimal activity-bus surface the drivers depend on. `ChatDriver`/`OrchestratingDriver`\n * only ever *publish* \u2014 accepting this narrow interface (rather than importing the module\n * singleton) lets a headless/server or unit-test host omit the bus entirely, so no live\n * `BroadcastChannel` is ever opened on that path. See {@link NOOP_ACTIVITY_BUS}.\n *\n * @beta\n */\nexport interface ActivityBus {\n publish<K extends keyof AgenticActivityEvents>(type: K, detail: AgenticActivityEvents[K]): void;\n}\n\n/**\n * No-op {@link ActivityBus}. The default when no bus is injected (Node, tests, headless\n * server use) \u2014 publishing goes nowhere and nothing is left open to tear down.\n *\n * @beta\n */\nexport const NOOP_ACTIVITY_BUS: ActivityBus = { publish: () => {} };\n\n/**\n * Typed in-process event bus for AI assistant activity events.\n *\n * Dispatches events synchronously to all local subscribers in the same JS module instance\n * (i.e. the same browser tab). Events listed in `crossTabEvents` are additionally forwarded\n * via a shared `BroadcastChannel` so that other tabs on the same origin receive them.\n *\n * @remarks\n * The pre-instantiated {@link agenticActivityBus} singleton covers all platform use cases.\n * App developers can extend the event map using TypeScript declaration merging on\n * {@link AgenticActivityEvents} and subscribe/publish custom events without any platform changes.\n *\n * @beta\n */\nexport class AgenticActivityBus {\n private readonly subscribers = new Map<string, Set<AnyHandler>>();\n private readonly crossTabEvents: Set<string>;\n private readonly channelNameFactory?: () => string;\n private channel?: BroadcastChannel;\n private channelInitialised = false;\n\n /**\n * @param config - Optional configuration. Omit to create an in-memory-only bus.\n * @beta\n */\n constructor(config?: AgenticActivityBusConfig) {\n this.crossTabEvents = new Set(config?.crossTabEvents ?? []);\n this.channelNameFactory =\n config?.channelName != null ? () => config.channelName! : config?.channelNameFactory;\n }\n\n /**\n * Lazily open the cross-tab `BroadcastChannel` on first use. Deferred (rather than\n * created in the constructor) so that importing this module, or constructing the bus\n * off-browser (Node, tests, headless server), never opens a live channel or reads\n * `sessionStorage` \u2014 both would keep a Node event loop alive and hang the process.\n * Cross-tab forwarding is inherently browser-only, so channel creation is gated on a\n * browser environment; elsewhere the bus stays purely in-process.\n */\n private ensureChannel(): void {\n if (this.channelInitialised) return;\n this.channelInitialised = true;\n const inBrowser = typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined';\n if (this.crossTabEvents.size === 0 || !this.channelNameFactory || !inBrowser) return;\n this.channel = new BroadcastChannel(this.channelNameFactory());\n this.channel.onmessage = (ev) => {\n const { type, detail } = (ev.data ?? {}) as { type?: string; detail?: unknown };\n if (type) this.notifyLocal(type, detail);\n };\n }\n\n /**\n * Subscribe to an event. Returns an unsubscribe function \u2014 call it in\n * `disconnectedCallback` to avoid memory leaks.\n *\n * @beta\n */\n subscribe<K extends keyof AgenticActivityEvents>(\n type: K,\n handler: (detail: AgenticActivityEvents[K]) => void,\n ): () => void {\n // Open the cross-tab channel (browser only) so this subscriber receives events\n // forwarded from other tabs; no-op off-browser.\n this.ensureChannel();\n let handlers = this.subscribers.get(type as string);\n if (!handlers) {\n handlers = new Set();\n this.subscribers.set(type as string, handlers);\n }\n const h = handler as AnyHandler;\n handlers.add(h);\n return () => handlers!.delete(h);\n }\n\n /**\n * Publish an event to all local subscribers and, if configured, to other tabs\n * via BroadcastChannel.\n *\n * @beta\n */\n publish<K extends keyof AgenticActivityEvents>(type: K, detail: AgenticActivityEvents[K]): void {\n this.notifyLocal(type as string, detail);\n if (this.crossTabEvents.has(type as string)) {\n this.ensureChannel();\n this.channel?.postMessage({ type, detail });\n }\n }\n\n /**\n * Add an event type to the cross-tab forwarding set at runtime.\n * Must be called before the first {@link AgenticActivityBus.publish} of that event type.\n *\n * @beta\n */\n addCrossTabEvent(type: keyof AgenticActivityEvents): void {\n this.crossTabEvents.add(type as string);\n }\n\n /**\n * Close the underlying BroadcastChannel. Call once on application teardown if needed.\n *\n * @beta\n */\n close(): void {\n this.channel?.close();\n this.channel = undefined;\n }\n\n private notifyLocal(type: string, detail: unknown): void {\n this.subscribers.get(type)?.forEach((handler) => handler(detail));\n }\n}\n\n/**\n * Returns a `BroadcastChannel` name that is scoped to the current tab and any popout windows\n * it opens, while remaining isolated from unrelated tabs on the same origin.\n *\n * **How it works:**\n * A UUID is generated once and stored in `sessionStorage`. `sessionStorage` persists across\n * page refreshes (so the channel name stays stable after an F5), but is cleared when the tab\n * is closed. Crucially, when a page opens a child window via `window.open()`, the browser\n * initialises the new window's `sessionStorage` as a copy of the opener's \u2014 so the child\n * inherits the same UUID and therefore the same channel name.\n *\n * Result:\n * - **Same tab + its `window.open()` popouts** share one channel \u2192 events flow as intended.\n * - **Independent tabs** (opened from the address bar, bookmarks, or links) each get a fresh\n * `sessionStorage` and therefore a distinct channel \u2192 no cross-talk between unrelated app\n * instances on the same origin.\n */\nfunction getTabScopedChannelName(base: string): string {\n // Belt-and-braces: this only runs in a browser (see `ensureChannel`), but guard anyway\n // so a direct call off-browser never throws a `sessionStorage is not defined` ReferenceError.\n if (typeof sessionStorage === 'undefined') return `${base}-nostorage`;\n const key = `${base}-tab-id`;\n let id = sessionStorage.getItem(key);\n if (!id) {\n id = crypto.randomUUID();\n sessionStorage.setItem(key, id);\n }\n return `${base}-${id}`;\n}\n\n/**\n * Pre-instantiated singleton event bus for AI assistant activity.\n *\n * - `halo-start` / `halo-stop` are forwarded via a tab-scoped `BroadcastChannel` so that\n * popout windows opened from this tab show halo animations, while remaining isolated from\n * unrelated tabs on the same origin (tab-scoped channel name).\n * - `tool-loop-start` / `tool-loop-end` are cross-tab for the same reason: they describe the\n * assistant's lifecycle (a turn beginning / ending), and the most common subscribers\n * (workspace transitions, post-turn deferred recomputation, UI gates tied to the assistant\n * being idle) need the event regardless of whether the user is interacting with the chat\n * in the main tab or a popout window. Tab-local-only telemetry can subscribe and filter.\n * - `chat-popout` / `chat-popin` are in-memory only \u2014 they must only affect the tab where the\n * user clicked.\n *\n * @beta\n */\nexport const agenticActivityBus = new AgenticActivityBus({\n crossTabEvents: ['halo-start', 'halo-stop', 'tool-loop-start', 'tool-loop-end'],\n // Lazy: the tab-scoped name (and its `sessionStorage` read) is computed on first\n // cross-tab use in a browser, not at module-eval \u2014 so importing this module is\n // side-effect-free and Node/test-safe.\n channelNameFactory: () => getTabScopedChannelName('foundation-ai-activity'),\n});\n", "import type { AIProvider, AIProviderRegistry } from '@genesislcap/foundation-ai';\nimport type { AgentConfig } from './config';\n\n/**\n * Resolve a provider name against the registry and assert it implements\n * `chat()` \u2014 the capability the chat tool-loop depends on. Throws with a\n * message naming the agent so misconfigured agents are easy to track down.\n *\n * Used by both the up-front static walk in `OrchestratingDriver` and by\n * `ChatDriver`'s per-turn resolver for function-form `provider` values.\n *\n * @internal\n */\nexport function resolveChatProvider(\n registry: AIProviderRegistry,\n providerName: string,\n agentName: string,\n): AIProvider {\n const provider = registry.get(providerName);\n if (!provider) {\n const available = registry.names().join(', ') || '(none)';\n throw new Error(\n `Agent \"${agentName}\" references unknown provider \"${providerName}\". Registered: ${available}`,\n );\n }\n if (!provider.chat) {\n throw new Error(\n `Agent \"${agentName}\" resolved to provider \"${providerName}\" which does not implement chat().`,\n );\n }\n return provider;\n}\n\n/**\n * Walk an agent tree (including nested `subAgents`) and validate every static\n * `provider: string` against the registry. Function-form `provider` values are\n * deferred \u2014 they validate on first resolution inside the driver.\n *\n * Throws on the first failure, with the same message shape produced by\n * {@link resolveChatProvider}.\n *\n * @internal\n */\nexport function validateStaticAgentProviders(\n agents: AgentConfig[],\n registry: AIProviderRegistry,\n): void {\n const visited = new Set<AgentConfig>();\n const walk = (agent: AgentConfig): void => {\n if (visited.has(agent)) return;\n visited.add(agent);\n if (typeof agent.provider === 'string') {\n resolveChatProvider(registry, agent.provider, agent.name);\n }\n for (const sub of agent.subAgents ?? []) walk(sub);\n };\n for (const root of agents) walk(root);\n}\n", "/**\n * Module-level append-only timeline of meta/lifecycle events, keyed by session\n * identity (the same `stateKey` space used by the driver registry and the\n * session store).\n *\n * Why a module registry rather than the redux store or the driver:\n * - **Survives the pop-in/pop-out element churn.** A single session can be\n * emitted from up to two element instances (an `expand` bubble + a `collapse`\n * panel) sharing one driver; keying by `stateKey` unifies them into one\n * timeline.\n * - **Survives driver rebuilds.** The driver is torn down and recreated when the\n * host swaps the agents array (see `agentsChanged` / `deleteDriver`), so a\n * driver-owned buffer would lose the timeline mid-session. The `stateKey`\n * outlives the driver.\n * - **Stays out of redux reactivity.** These appends never drive the UI, so\n * there's no reason to pay immutable-reducer cost or flood the Redux DevTools\n * action log with debug noise.\n *\n * Surfaced in `getDebugLog().timeline`, merged chronologically with messages and\n * turn snapshots. Ring-buffered \u2014 the oldest non-`high` events are evicted first\n * while `high`-importance failure events are retained \u2014 so a long-lived session\n * stays bounded in normal use without ever dropping a failure signal.\n *\n * @internal\n */\n\nimport type { TurnFailureReason } from '@genesislcap/foundation-ai';\n\n/**\n * Catalogue of meta event names. This is the documented surface \u2014 extend it as\n * new events are wired in (Tier 2/3 lifecycle, interaction, provider events).\n */\nexport type MetaEventType =\n // Element lifecycle + window placement\n | 'assistant.connected'\n | 'assistant.disconnected'\n | 'assistant.popout'\n | 'assistant.popin'\n // Driver lifecycle / wiring\n | 'driver.created'\n | 'driver.wired'\n | 'driver.unwired'\n // Turn lifecycle\n | 'state.changed'\n | 'turn.start'\n | 'turn.end'\n | 'turn.retry'\n | 'turn.error'\n | 'tool.failed'\n | 'tool.unresolved'\n | 'subagent.started'\n | 'subagent.completed'\n | 'subagent.failed'\n // Routing / providers\n | 'agent.handoff'\n | 'agent.pinned'\n | 'agent.unpinned'\n | 'provider.selected'\n // Blocking interactions\n | 'interaction.requested'\n | 'interaction.resolved'\n | 'interaction.external-cost'\n | 'interaction.external-cost-dropped'\n // External / unified diagnostics (GENC-1461) \u2014 an out-of-band engine's log folded into this session\n | 'external-diagnostics.folded'\n // Context / cost\n | 'context.updated'\n | 'context.threshold-crossed'\n | 'context.compacted'\n | 'context.condensed'\n // UI + input\n | 'panel.toggled'\n | 'attachment.added'\n | 'file.read-failed'\n | 'suggestions.failed'\n // Session lifecycle (GENC-1351)\n | 'session.cleared'\n | 'session.switched'\n | 'session.switch-deferred'\n | 'persistence.toggled'\n | 'persistence.saved'\n | 'persistence.save-failed'\n | 'persistence.suppressed'\n | 'persistence.not-resumable'\n | 'persistence.restored'\n | 'persistence.restore-orphan';\n\n/**\n * How much a reader should care about an event \u2014 lets a consumer (or an AI\n * agent) filter the timeline: skip `low` UI/bookkeeping noise, skim `normal`\n * session flow, or jump straight to `high` problem/limit signals when triaging.\n */\nexport type MetaEventImportance = 'high' | 'normal' | 'low';\n\n/**\n * Importance is intrinsic to the event *type*, not the instance, so it's\n * defined once here and stamped automatically by {@link recordMetaEvent} \u2014 call\n * sites never pass it. The `Record` is exhaustive: adding a `MetaEventType`\n * without a level here is a compile error.\n *\n * - `high` \u2014 failures and hard limits you almost always want to see.\n * - `normal` \u2014 meaningful session flow you read to follow what happened.\n * - `low` \u2014 frequent UI / bookkeeping noise, usually safe to skip.\n */\nexport const META_EVENT_IMPORTANCE: Record<MetaEventType, MetaEventImportance> = {\n 'turn.error': 'high',\n 'tool.failed': 'high',\n 'subagent.failed': 'high',\n 'file.read-failed': 'high',\n 'suggestions.failed': 'high',\n 'context.threshold-crossed': 'high',\n 'context.compacted': 'high',\n 'persistence.restore-orphan': 'high',\n // A save that did not land is silent data loss in progress: the transcript on screen\n // is no longer backed by the store, and every later turn widens the gap. GENC-1511.\n 'persistence.save-failed': 'high',\n\n 'assistant.connected': 'normal',\n 'assistant.disconnected': 'normal',\n 'assistant.popout': 'normal',\n 'assistant.popin': 'normal',\n 'driver.created': 'normal',\n 'state.changed': 'normal',\n 'turn.start': 'normal',\n 'turn.end': 'normal',\n 'turn.retry': 'normal',\n 'tool.unresolved': 'normal',\n 'subagent.started': 'normal',\n 'subagent.completed': 'normal',\n 'agent.handoff': 'normal',\n 'agent.pinned': 'normal',\n 'agent.unpinned': 'normal',\n 'provider.selected': 'normal',\n 'interaction.requested': 'normal',\n 'interaction.resolved': 'normal',\n // Bookkeeping about an already-finished turn; interesting when reconciling a session total.\n 'interaction.external-cost': 'normal',\n // Spend that was billed but could NOT be recorded (the message was trimmed/condensed away, or\n // the value was not real spend). 'high': it is the one way the session total goes quietly\n // wrong, so it must stand out when reconciling.\n 'interaction.external-cost-dropped': 'high',\n 'external-diagnostics.folded': 'normal',\n 'session.cleared': 'normal',\n 'session.switched': 'low',\n 'session.switch-deferred': 'low',\n 'persistence.restored': 'normal',\n 'persistence.suppressed': 'normal',\n 'persistence.not-resumable': 'normal',\n\n 'driver.wired': 'low',\n 'driver.unwired': 'low',\n 'context.updated': 'low',\n 'context.condensed': 'low',\n 'panel.toggled': 'low',\n 'persistence.toggled': 'low',\n 'persistence.saved': 'low',\n 'attachment.added': 'low',\n};\n\n/** One entry in the meta-event timeline. */\nexport interface MetaEvent {\n /** Monotonic counter across the session's lifetime (does not reset on driver rebuild). */\n index: number;\n /** ISO timestamp, matching the format used elsewhere in the debug log. */\n timestamp: string;\n /** Event name \u2014 see {@link MetaEventType}. */\n type: MetaEventType;\n /** How much to care about this event \u2014 see {@link META_EVENT_IMPORTANCE}. */\n importance: MetaEventImportance;\n /** Optional structured payload. */\n detail?: Record<string, unknown>;\n}\n\n/**\n * Soft ring-buffer cap. Once exceeded, the oldest *non-`high`* event is evicted;\n * `high`-importance events (failures and hard limits) are never dropped \u2014 they're\n * the whole reason the log exists. So a buffer dominated by `high` events is\n * allowed to float above this cap rather than lose a failure signal; in normal\n * use the frequent `low`/`normal` events keep it near the cap. Entries are cheap.\n */\nconst DEFAULT_MAX_META_EVENTS = 800;\n\ninterface MetaEventBuffer {\n events: MetaEvent[];\n /** Next index to assign \u2014 kept separate from `events.length` so it stays monotonic after eviction. */\n next: number;\n}\n\nconst registry = new Map<string, MetaEventBuffer>();\n\n/**\n * Append a meta event to the timeline for `key`. Once the buffer exceeds\n * {@link DEFAULT_MAX_META_EVENTS}, evicts the oldest *non-`high`* event;\n * `high`-importance events are never evicted. An empty `key` is bucketed under\n * `''`, matching how drivers/stores handle an absent session identity, so\n * callers never need to guard.\n */\nexport function recordMetaEvent(\n key: string,\n type: MetaEventType,\n detail?: Record<string, unknown>,\n): void {\n let buffer = registry.get(key);\n if (!buffer) {\n buffer = { events: [], next: 0 };\n registry.set(key, buffer);\n }\n buffer.events.push({\n index: buffer.next,\n timestamp: new Date().toISOString(),\n type,\n importance: META_EVENT_IMPORTANCE[type],\n detail,\n });\n buffer.next += 1;\n if (buffer.events.length > DEFAULT_MAX_META_EVENTS) {\n // Drop the oldest event that isn't `high` importance. `high` events\n // (failures/limits) are retained even past the cap \u2014 losing a failure\n // signal is worse than briefly exceeding the buffer size. If every retained\n // event is `high` (all-failures session), nothing is evicted and the buffer\n // grows; in practice frequent `low`/`normal` events keep it bounded.\n const evictAt = buffer.events.findIndex((e) => e.importance !== 'high');\n if (evictAt !== -1) {\n buffer.events.splice(evictAt, 1);\n }\n }\n}\n\n/**\n * Why a turn failed or was retried \u2014 stamped as `detail.reason` on `turn.error`\n * and `turn.retry` events, and (since PTC-0) surfaced at the driver's loop\n * boundary via {@link ChatDriverResult.failureReason}. Re-exported from\n * `@genesislcap/foundation-ai` \u2014 where it lives alongside `ChatDriverResult` so\n * the boundary field and this log surface can never drift apart \u2014 under its\n * historical name so existing importers are unaffected. Enumerated so the set\n * stays in sync with the README and call sites can't drift to ad-hoc strings.\n */\nexport type { TurnFailureReason };\n\n/**\n * Record a turn-ending failure (`turn.error`, importance `high`). The `reason`\n * is typed so the high-importance triage surface stays consistent; pass any\n * diagnostic specifics (attempt counts, offending tool names, etc.) in `detail`.\n */\nexport function recordTurnError(\n key: string,\n reason: TurnFailureReason,\n detail?: Record<string, unknown>,\n): void {\n recordMetaEvent(key, 'turn.error', { reason, ...detail });\n}\n\n/**\n * Record a recoverable retry *within* a turn (`turn.retry`, importance `normal`)\n * \u2014 e.g. one malformed/empty attempt that will be retried, as distinct from the\n * final attempt that bails out as a `turn.error`. Include `attempt`/`maxAttempts`\n * in `detail` so the timeline shows which try this was.\n */\nexport function recordTurnRetry(\n key: string,\n reason: TurnFailureReason,\n detail?: Record<string, unknown>,\n): void {\n recordMetaEvent(key, 'turn.retry', { reason, ...detail });\n}\n\n/** Returns the meta-event timeline for `key`, or an empty array if none recorded. */\nexport function getMetaEvents(key: string): ReadonlyArray<MetaEvent> {\n return registry.get(key)?.events ?? [];\n}\n\n/**\n * Merge pre-built meta events into the timeline for `targetKey`, **preserving each\n * event's original `timestamp`** (so it interleaves chronologically on export)\n * while re-indexing onto the target buffer's monotonic counter. Used to fold a\n * sub-agent's harvested events into the parent session \u2014 see\n * `ChatDriver.invokeSubAgent`. Unlike {@link recordMetaEvent} it does not stamp a\n * fresh timestamp; the same non-`high` eviction policy is applied once after the\n * batch so the buffer stays bounded.\n */\nexport function mergeMetaEvents(targetKey: string, events: readonly MetaEvent[]): void {\n if (events.length === 0) return;\n let buffer = registry.get(targetKey);\n if (!buffer) {\n buffer = { events: [], next: 0 };\n registry.set(targetKey, buffer);\n }\n for (const event of events) {\n buffer.events.push({ ...event, index: buffer.next });\n buffer.next += 1;\n }\n // Evict oldest non-`high` events until back under the cap \u2014 same policy as\n // recordMetaEvent; `high` events (failures/limits) are never dropped. Single\n // pass: take the overflow count, then drop that many of the oldest non-`high`\n // events in order (if there aren't enough non-`high`, the buffer floats above\n // the cap rather than losing a failure signal).\n let toEvict = buffer.events.length - DEFAULT_MAX_META_EVENTS;\n if (toEvict > 0) {\n buffer.events = buffer.events.filter((e) => {\n if (toEvict > 0 && e.importance !== 'high') {\n toEvict -= 1;\n return false;\n }\n return true;\n });\n }\n}\n\n/**\n * Drop the entire timeline for `key`. Used to discard a sub-agent's transient\n * per-invocation session once its events have been harvested into the parent, so\n * the module registry doesn't accumulate one orphaned bucket per sub-agent run.\n */\nexport function clearSession(key: string): void {\n registry.delete(key);\n}\n\n/**\n * Human/agent-facing guide emitted as the first key of the exported debug log,\n * so whoever opens the JSON (often an AI agent) knows how to read it without\n * reverse-engineering the shape. Kept here next to the event catalogue it\n * describes \u2014 but proximity alone demonstrably did NOT keep the two in sync\n * (`refusal` was missing from both reason lists for a whole release), so\n * `debug-event-log.test.ts` now asserts that every `TurnFailureReason` and every\n * `SubAgentFailureReason` is named here, and fails the build when one is added\n * without a matching sentence. Enumerations below read as exhaustive and WILL be\n * trusted by an agent reading the JSON \u2014 keep them so.\n */\nexport const DEBUG_LOG_README: readonly string[] = [\n 'This is an exported debug log for the Genesis AI assistant. Read it top-to-bottom.',\n \"`sessionUsage` is what this session spent: `costUsd` (USD, provider-reported per request and summed, cache discounts already applied) plus the four TOKEN BUCKETS \u2014 `uncachedInputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `outputTokens`. Those four are disjoint and safe to add up for a total-tokens figure; the per-message fields further down are NOT (see kind:'message'). Each bucket bills at a different rate \u2014 cache reads a fraction of uncached input, cache writes a premium, output highest \u2014 so a big token count against a small cost means the prompt was mostly cache hits, not a missing charge. It covers sub-agent turns and spend a compaction banked, so for the CONVERSATION it is the authoritative total: prefer it over re-summing the timeline, which can be short by whatever the ring buffers evicted. The same figures appear under `meta.context`. It is as current as the snapshot it came from: the assistant's own download stamps a fresh one, but a log stitched by another tool can carry an older one \u2014 compare `meta.timestamp` with the last timeline entry, and if it is well behind, read these totals as historical and fall back to summing the timeline. One scope caveat: it is derived from the transcript, so it excludes billed calls that produced no message (a blank or refused attempt that was retried \u2014 see kind:'turn'.`usage`). Summing the turns can therefore come out HIGHER than this, and the difference is exactly that discarded spend, not a double-count.\",\n \"What 'session' means for those figures: the CURRENT conversation under this session key (a host-supplied per-project id, or the element id + header title when the host supplies none) \u2014 which is not necessarily everything in `timeline`. It is re-derived from the live transcript, so it spans page loads only when the chat is being remembered, and a Clear resets it to zero. `timeline` is append-only regardless: it keeps every page load and the pre-Clear conversation, with the session.cleared event as the boundary. So on a long-lived log, read these totals as the latest conversation's and the earlier sections as history \u2014 not as a total of the whole file.\",\n '`timeline` is the entire session as one array, already sorted chronologically by `timestamp` (ISO 8601). Every entry has a `kind`.',\n 'Timestamps are millisecond-resolution; entries that share the same millisecond are ordered by a fixed kind rank (event, then turn, then message), which is a heuristic and may not reflect exact causal order within that millisecond \u2014 e.g. a user message and the turn it triggered, or a final assistant message and its turn.end event, can appear in either order depending on whether they landed in the same millisecond. Read the logical structure of a turn rather than over-interpreting the micro-ordering of co-timestamped entries of different kinds.',\n \"kind:'message' \u2014 the conversation. `role` is user/assistant/tool/system-event/synthetic-user; `agentName` says which agent produced it; `toolCalls`/`toolResult`/`interaction` carry tool and widget activity; `inputTokens`/`outputTokens`/`cost` are per-message LLM usage, where `inputTokens` is the WHOLE prompt for that request and `cacheReadTokens`/`cacheWriteTokens` BREAK IT DOWN rather than add to it \u2014 uncached input is `inputTokens` minus those two, and adding the cache fields to `inputTokens` counts the prompt twice. The cache fields are absent on providers that report no cache split (Gemini reports reads only, since implicit caching bills no write) and on messages persisted before they existed, so read them as 0 when missing. Each bucket bills at a different rate \u2014 cache reads a fraction of uncached input, cache writes a premium, output highest \u2014 so a large token count at a small cost means the prompt was mostly cache hits. `externalCostUsd` is any non-LLM cost a widget reported for its own external service calls (folded into the session cost total alongside `cost`). On model-produced assistant messages, `model` is the concrete model id that generated it (e.g. 'gemini-2.5-flash-lite') and `providerName` is the registry slot it resolved under (e.g. a tier name like 'high'/'low', or the default); together they attribute the message \u2014 and any tool calls it carries \u2014 to an exact model even across a mid-session vendor/tier switch, where one slot name can map to different models before and after the switch. Both are undefined on any entry that is NOT an LLM response: non-assistant roles (user/tool/system-event) and 'synthetic-user' echoes; assistant interaction/widget entries (empty content carrying an `interaction` \u2014 a rendered widget, not a model turn); driver-authored assistant fallbacks (the timeout, repeated-malformed-call, and empty-response apology messages); and messages restored from a session persisted before these fields existed. One partial case: on a genuine model turn whose provider exposes no `getStatus` (or reports no model), `providerName` is still set but `model` alone is undefined. A 'synthetic-user' message is a display-only echo of an interaction outcome (e.g. the answer a widget reported): it renders on the user's side of the chat and `agentName` is the agent that created it, but it is never sent to the LLM \u2014 so it has no matching 'turn' and the model learns the outcome only from the corresponding tool result.\",\n \"Sub-agent messages appear inline. When a tool delegates to a sub-agent (via `requestSubAgent`), the sub-agent's whole conversation \u2014 its own assistant/tool messages, each with their own `content`/`thinking`/`toolCalls`/`toolResult` and per-message `model`/`providerName`/`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheWriteTokens`/`cost` \u2014 is hoisted into the timeline as ordinary kind:'message' entries, interleaved by timestamp right after the tool call that spawned them (so you read the delegation top-to-bottom). A hoisted entry is marked: `subAgentDepth` is its delegation depth (1 for a sub-agent, 2 for a sub-agent's sub-agent, \u2026), `subAgentOf` is the id of the parent tool call that spawned it (correlates it back even when two sub-agents run in one parent turn), `subAgentName` is the sub-agent's own name, and `agentName` is rewritten to a `\\\"<parent> \u203A <sub-agent>\\\"` breadcrumb (composing when nested, e.g. `\\\"UI Builder \u203A Planner \u203A Grounding\\\"`). The sub-agent's per-LLM-call snapshots also surface as kind:'turn' entries with an N-M `turnIndex`, and subagent.started/completed (or subagent.failed) events bracket the run. Per-message `cost` on hoisted entries is already part of the session total (it is summed from the un-flattened history), so summing the top-level timeline does NOT double-count.\",\n \"kind:'turn' \u2014 one LLM call. `turnIndex` is a string: a top-level turn is the bare counter ('0', '1', \u2026); a sub-agent's turns are numbered under the parent turn that activated them ('3-1', '3-2', \u2026, and a nested sub-agent contributes '3-2-1', \u2026), and `agentName` names the agent that ran the turn. `systemPrompt` and `toolNames` are what the model saw. A systemPrompt of '<repeated \u2014 identical to turn N>' was byte-identical to turn N and de-duplicated; the full prompt is shown whenever it changes (often because a stateful agent advanced), so prompt evolution is visible.\",\n \"kind:'turn'.`model`/`providerName`/`provider` \u2014 which model ran that call: the concrete model id, the registry slot it resolved under (a tier name like 'high'/'low', or the default), and the vendor. Recorded per CALL, so an agent whose `provider` selector varies by state \u2014 a flow that plans on a high tier and executes on a low one \u2014 has every step attributed, including calls that produced no message. `model` is the SERVING model where the provider reports one, so a turn answered by a server-side fallback names the model that answered rather than the one requested; it always matches the `model` on the message that call produced. Absent when the provider exposes no `getStatus` and the transport stamped nothing.\",\n \"kind:'turn'.`usage` \u2014 what that ONE call cost, in the same four-bucket + `costUsd` shape as `sessionUsage`. Absent while a call is in flight and on providers that report no usage. This is the SAME money as the message the call produced, not extra money: never add turn usage to message usage, and read a turn plus its message as one charge. Its distinct value is the calls that produced NO message \u2014 a blank or refused response is billed and then discarded before the retry, so the turn entry is the only record of that spend, and a turn with `usage` but no message after it is exactly that. `costUsd: 0` alongside a nonzero token count means the provider reported no price, not that the call was free.\",\n \"kind:'turn'.`agentSnapshot` \u2014 the active agent's own view of its internal state, captured at that turn. An agent opts into this by exposing a `getDebugSnapshot()` that returns JSON-serializable per-state info; stateful/flow agents wire it automatically, so you can watch a flow advance turn-by-turn (e.g. current step, cursor, collected fields, pending changes). Absent for agents that don't expose one.\",\n \"kind:'event' \u2014 a meta/lifecycle event. `type` names it (see below); `detail` carries structured data. `detail.placement` is the emitting UI instance: 'bubble' (collapsed), 'panel' (popped-out), or 'standalone'.\",\n \"Each 'event' also has an `importance`: 'high' (failures/limits \u2014 turn.error, tool.failed, subagent.failed, file.read-failed, suggestions.failed, context.threshold-crossed), 'normal' (session flow \u2014 connects, turns, retries, handoffs, agent/provider changes, interactions, sub-agent start/complete), or 'low' (skippable UI/bookkeeping noise \u2014 panel.toggled, attachment.added, driver.wired/unwired, context.updated, context.condensed). To skim, ignore importance:'low'; to triage a failure, filter to importance:'high' then read the nearby messages and turns. A 'high' turn.error is often preceded by one or more 'normal' turn.retry events for the same reason \u2014 read them together to see how many attempts were made before bailing. 'message' and 'turn' entries carry no importance \u2014 they are the substance, always read them.\",\n 'Event types: assistant.connected/disconnected (mount + placement + whether the session was created or restored), assistant.popout/popin (window placement), driver.created/wired/unwired (which driver is live and why it stops/starts responding across a popout), state.changed (idle\u2194loading), turn.start/turn.end (turn boundary; turn.end carries durationMs), turn.retry (a recoverable in-turn retry \u2014 detail.reason plus attempt/maxAttempts; for malformed calls also finishMessage; for empty responses also the provider finishReason + thoughtsTokens + parts breakdown), turn.error (a turn failed or hit a guardrail \u2014 detail.reason is one of exception/malformed-function-call/empty-response/unknown-tool-limit/max-iterations/response-truncated/refusal/budget-exhausted/provider-refused, plus reason-specific diagnostics: attempts (for empty-response also finishReason + thoughtsTokens + a parts breakdown, distinguishing a thinking-only STOP from a truly empty turn), finishMessage, for response-truncated the model + maxTokens + outputTokens + tools, unknownTools (split into staleTools \u2014 real earlier this activation but retired by the current state or hidden behind an open exclusive fold \u2014 and hallucinatedTools \u2014 never advertised) + availableTools, iterations + limit, for budget-exhausted the budgetUsd + spentUsd figures reported by the proxy plus the resolved vendor, for provider-refused the kind (spend|auth) plus the upstream status and error type \u2014 the vendor refusing the ACCOUNT rather than us refusing to spend, so the remedy is a top-up or a key rotation rather than a raised cap, and the kind is the only place that distinction survives because the user-facing copy is deliberately cause-free, or name + message for exceptions), tool.failed (a tool threw), tool.unresolved (the model called a tool that could not be dispatched \u2014 detail.kind is folded/fold-hidden/stale/unknown, plus tool + agent and, for the counted kinds, the consecutive streak; the recurring lead-up to an unknown-tool-limit turn.error), subagent.started/completed/failed (the lifecycle of a `requestSubAgent` delegation \u2014 detail.agent names the sub-agent; these bracket the sub-agent turns that appear as kind:turn entries with an N-M `turnIndex`; subagent.failed also carries detail.reason, one of max_iterations/malformed_tool_call/empty_response/unknown_tool_limit/timeout/response_truncated/refusal/budget_exhausted/provider_refused; budget_exhausted and provider_refused are both terminal for the PARENT turn too \u2014 the parent stops rather than calling the model again into the same wall), agent.handoff (routing; from=null is the initial activation), agent.pinned/unpinned (forced routing), provider.selected (the resolved provider for the upcoming turns \u2014 detail.provider is the registry SLOT/tier name, detail.model the concrete model behind it and detail.vendor its vendor; emitted only when the slot CHANGES, so read the per-turn `model` for the model of any given call rather than assuming the nearest event still applies), interaction.requested/resolved (blocking user widgets \u2014 explain quiet gaps; note that when a sub-agent opens a widget, detail.agent \u2014 and the agentName on the interaction message \u2014 is the HOST agent that owns the widget, NOT the sub-agent that asked, because widgets render and resolve on the host driver), context.updated/threshold-crossed (token + cost), context.condensed (a stale tool payload was collapsed out of the model-bound history by a `condenseWhen` declaration on the tool \u2014 detail.tool + toolCallId, target args|response, trigger (superseded:<key> or age:<n>), stubLen, and an estimated tokensSaved; stored history and this log keep the FULL payload, so the model-visible slice at any point is the full history minus the condensations recorded up to then), panel.toggled, attachment.added, file.read-failed, suggestions.failed.',\n 'Sub-agent meta events: a sub-agent\\'s own turn.retry/turn.error/tool.failed/tool.unresolved events are merged into this same timeline, tagged with `detail.subAgent` \u2014 a `\"<parent> \u203A <sub-agent>\"` breadcrumb that composes when nested (e.g. `\"UI Builder \u203A Planner \u203A Grounding\"`) \u2014 and interleaved by their original timestamps within the subagent.started\u2192completed/failed bracket. These are the per-attempt/per-failure signals that do NOT appear among the sub-agent\\'s (hoisted) messages: a malformed/empty attempt that gets retried produces no message, and the stale-vs-hallucinated split and streak counts live only on the event. A sub-agent\\'s high-volume, message-derivable events (turn.start/turn.end, provider.selected, context.updated) are intentionally NOT merged \u2014 read its hoisted messages for model/tokens/cost and turn-by-turn activity, and the bracketing subagent.* events for the run\\'s span.',\n \"`meta` holds context captured at export time: agentSummary (full agent configs), context (active model, contextTokens/contextLimit/contextUsagePercent for the last call, and the session totals \u2014 sessionCostUsd, sessionTokensConsumed, and the four-bucket sessionUsage lifted to the top of this log), activeDebugSnapshot (the active agent's `getDebugSnapshot()` taken fresh at export \u2014 reflects state NOW, which may have advanced beyond the last turn's agentSnapshot), debug (optional host-supplied debug state), host, and the export timestamp.\",\n 'Note the two different scopes in `meta.context`: `contextTokens` is the prompt size of the LAST call (against `contextLimit`, the model context window), while `sessionUsage`/`sessionTokensConsumed` are cumulative BILLED throughput. Every turn resends the conversation, so the cumulative figure counts each turn\u2019s prompt again in the next turn\u2019s and is expected to dwarf the context size \u2014 that is not double-counting.',\n 'To debug a failure: find the last turn.error or tool.failed, then read upward for the user message, the turn(s), and the agent/provider/state events that led into it.',\n];\n\n/**\n * Removes all entries. Exposed for test isolation only \u2014 not part of the\n * public API.\n *\n * @internal\n */\nexport function clearMetaEventRegistry(): void {\n registry.clear();\n}\n", "import { createLogger } from '@genesislcap/foundation-logger';\n\nexport const logger = createLogger('ai-assistant');\n", "import type { InteractionContext } from '../types/interaction-context';\nimport { logger } from '../utils/logger';\n\n/**\n * A created {@link InteractionContext} plus the host-only `dispose` handle. The\n * driver keeps the handle (so it can tear the context down on resolve/evict) and\n * hands only `context` to the widget \u2014 widgets must not dispose their own context.\n *\n * @internal\n */\nexport interface InteractionContextHandle {\n readonly context: InteractionContext;\n /**\n * Run every registered `onDispose` callback once (in registration order), then\n * clear listeners. Idempotent. Called by the driver from `resolveInteraction`\n * and on driver teardown \u2014 never on element unmount.\n */\n dispose(): void;\n}\n\n/**\n * Create a live, per-interaction context (GENC-1390). Framework-agnostic: the\n * `subscribe`/`notify` pair is a plain observer set, not FAST reactivity. See\n * {@link InteractionContext} for the lifetime/semantics contract.\n *\n * @internal\n */\nexport function createInteractionContext(interactionId: string): InteractionContextHandle {\n const state: Record<string, unknown> = {};\n const onceCache = new Map<string, unknown>();\n const listeners = new Set<() => void>();\n const disposers = new Set<() => void>();\n let disposed = false;\n\n const context: InteractionContext = {\n interactionId,\n state,\n once<T>(key: string, factory: () => T): T | null {\n if (onceCache.has(key)) return onceCache.get(key) as T;\n // Interaction already ended (resolve/timeout/evict): refuse to run the factory.\n // A resource created here would leak \u2014 dispose has already run every `onDispose`\n // and won't run again. Return null so a stray late call (e.g. an async callback\n // that lands after a `timeoutMs` timeout) degrades instead of crashing or leaking.\n if (disposed) {\n logger.warn(\n `InteractionContext.once(\"${key}\") called after dispose; not creating a resource on an ended interaction.`,\n );\n return null;\n }\n const value = factory();\n onceCache.set(key, value);\n return value;\n },\n notify(): void {\n // A Set tolerates a listener unsubscribing mid-walk (matches\n // interaction-panel-session's forEach); a throwing subscriber must not stop the rest.\n for (const listener of listeners) {\n try {\n listener();\n } catch (e) {\n logger.error('InteractionContext subscriber threw during notify()', e);\n }\n }\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n onDispose(fn: () => void): void {\n // Late registration after the interaction already ended: run immediately so\n // callers never leak a resource by registering a beat too late.\n if (disposed) {\n fn();\n return;\n }\n disposers.add(fn);\n },\n };\n\n return {\n context,\n dispose(): void {\n if (disposed) return;\n disposed = true;\n for (const fn of disposers) {\n try {\n fn();\n } catch (e) {\n logger.error('InteractionContext onDispose callback threw', e);\n }\n }\n disposers.clear();\n listeners.clear();\n // Release memoised `once` values (sockets, timers, service handles) for GC \u2014 the resources\n // themselves are closed via their `onDispose`, but drop the references too.\n onceCache.clear();\n },\n };\n}\n", "import type { ChatMessage, CondensePolicy, CondenseTrigger } from '@genesislcap/foundation-ai';\n\n/**\n * Tool-context condensation: collapse stale tool payloads out of the history\n * sent to the model, while leaving stored history untouched.\n *\n * The driver owns the registry (tool handlers populate it via `condenseWhen`)\n * and the cadence (this runs before every provider call). This module owns the\n * pure application: given the registry + the current loop iteration, produce a\n * rewritten copy of the history with stale args/results replaced by stubs. Kept\n * pure (no driver/session state, no logging) so it unit-tests in isolation \u2014\n * the one-time `context.condensed` signal is delivered via an `onCondensed`\n * callback rather than reaching into the debug-event log directly.\n *\n * @packageDocumentation\n */\n\n/**\n * Below this serialized size a tool payload isn't worth condensing \u2014 the stub\n * would save little and cost a breadcrumb. A driver-level floor so the public\n * `condenseWhen` API needs no per-policy threshold field.\n */\nexport const CONDENSE_MIN_CHARS = 1000;\n\n/** Key the collapsed args are stored under \u2014 a tool-call's args must stay a Record. */\nexport const CONDENSED_ARGS_KEY = 'condensed';\n\n/**\n * Rough chars-per-token divisor for the `tokensSaved` estimate. No tokenizer is\n * available in this stack; ~4 chars/token is the usual English approximation.\n */\nconst APPROX_CHARS_PER_TOKEN = 4;\n\n/**\n * A `condenseWhen` policy registered against a tool-call id, with its age clock\n * and report-once flags. The driver holds these in a `Map<toolCallId, \u2026>`;\n * {@link applyCondensation} reads them and flips the `reported*` flags so the\n * `context.condensed` signal fires once per payload, not once per provider call.\n */\nexport interface RegisteredCondensePolicy {\n policy: CondensePolicy;\n /**\n * Monotonic model-call sequence (`modelCallSeq`) when `condenseWhen` was called\n * \u2014 the origin of the age clock. Driver-lifetime and NOT reset per turn, so age\n * is measured consistently across turn boundaries (the field name is historical;\n * it is not the per-turn loop iteration).\n */\n iteration: number;\n /** Turn (`sendMessage`) sequence when the call was made \u2014 the `turnEnd` clock. */\n turn: number;\n /** Agent-activation sequence when the call was made \u2014 the `agentEnd` clock. */\n activation: number;\n /** App-controlled phase epoch when the call was made \u2014 the `phaseEnd` clock. */\n phaseEpoch: number;\n /** `context.condensed` already emitted for the args payload (fire-once). */\n reportedArgs?: boolean;\n /** `context.condensed` already emitted for the response payload (fire-once). */\n reportedResponse?: boolean;\n /**\n * The first trigger to fire for this call, latched on the pass it fired.\n *\n * \"Fired\", not \"collapsed\": it is written during trigger resolution, before the\n * per-payload size floor is applied, so an entry whose payloads are all below the floor\n * can latch without anything ever rendering. That is deliberate and safe \u2014 both payloads\n * of a call resolve off the same clocks in the same pass, so they can never disagree\n * about which trigger fired, and a payload's size is fixed for the life of the call\n * (condensation never touches stored history), so a below-floor payload can never later\n * become a large one under a stale reason.\n *\n * Trigger resolution picks the first LISTED trigger that is *currently* true, so without\n * this it re-evaluates on every provider call and can change after the collapse: with the\n * usual `on: [{superseded}, {agentEnd}]`, a payload collapsed at `agentEnd` silently\n * re-resolves to `superseded` as soon as a newer call on the same key lands. Any stub that\n * embeds the reason (`pointer` does) is then rewritten \u2014 an in-place history mutation that\n * invalidates the prompt cache from that position a second time, for a payload that had\n * already collapsed. Latching keeps the rendered stub stable, which is sound because a\n * collapse is monotonic and never reverts, so the first trigger to fire is the correct\n * one to keep.\n */\n firedTrigger?: CondenseTrigger;\n}\n\n/**\n * The driver's live state at the moment of a provider call \u2014 the clocks every\n * trigger is evaluated against. Passed by the driver; kept as an interface so the\n * transform stays a pure function of (history, policies, clocks).\n */\nexport interface CondenseContext {\n /** Monotonic model-call sequence now \u2014 the `age` clock. */\n modelCall: number;\n /** Monotonic turn (`sendMessage`) sequence now \u2014 the `turnEnd` clock. */\n turn: number;\n /** Whether the agent activation that made a call has since ended \u2014 the `agentEnd` clock. */\n activationEnded: (activation: number) => boolean;\n /**\n * Whether a later phase epoch is current than the one a call was made in \u2014 the\n * `phaseEnd` clock. True once `endPhase()` has been called since the call.\n */\n phaseEnded: (phaseEpoch: number) => boolean;\n /**\n * Collapse in batches of this many model-calls instead of continuously. A positive\n * integer; decimals are floored and anything below `1` becomes `1`. Omit (or `1`) to\n * collapse as soon as a trigger fires, which is the historical behaviour.\n *\n * Condensation rewrites a payload *in place*, so the model-bound history is not\n * append-only and every prompt-cache entry written before the rewrite is invalidated\n * from that position on. Collapsing the moment each trigger fires therefore breaks the\n * cache on nearly every call of a re-read loop \u2014 the case condensation exists to\n * contain. Batching holds the collapse set still between boundaries so the prefix is\n * append-only in between, trading up to `batchCalls` calls' worth of extra context for\n * one cache break per batch instead of one per call.\n *\n * `agentEnd` and `phaseEnd` are exempt and still collapse as they fire: they mark a\n * discontinuity that invalidates the cached prefix anyway, so deferring them would hold\n * stale payloads longer for nothing.\n */\n batchCalls?: number;\n}\n\n/**\n * Structured detail for a `context.condensed` meta-event. The index signature\n * lets it satisfy `recordMetaEvent`'s `Record<string, unknown>` detail param\n * while the named fields stay strictly typed.\n */\nexport interface CondensedEventDetail {\n [key: string]: unknown;\n /** Tool-loop iteration the collapsed call was made on. */\n turn: number;\n toolCallId: string;\n tool: string;\n target: 'args' | 'response';\n /** Human-readable trigger, e.g. `superseded:Foo.tsx` or `age:3`. */\n trigger: string;\n /** Length of the replacement stub. */\n stubLen: number;\n /** Estimated input tokens saved this collapse (char/4 \u2014 no tokenizer in-stack). */\n tokensSaved: number;\n}\n\n/** Short human-readable reason for the stub text, per fired trigger. */\nfunction triggerReason(trigger: CondenseTrigger): string {\n switch (trigger.kind) {\n case 'age':\n return 'aged out';\n case 'turnEnd':\n return 'turn ended';\n case 'agentEnd':\n return 'agent finished';\n case 'phaseEnd':\n return 'phase ended';\n default:\n return 'superseded';\n }\n}\n\n/**\n * Framework-generated stub, shared by `pointer` and `drop`. Names the tool, the superseded key\n * (the only surviving identifier once args are elided \u2014 the model cannot otherwise tell WHICH\n * file a collapsed `vfs_write` wrote) and the original size.\n *\n * `restorable` is the ONLY difference between the two modes: `pointer` promises that re-calling\n * reproduces the content and is valid solely for idempotent tools; `drop` makes no such promise\n * and must not carry the clause. Identifying information is not what separates them \u2014 a stub too\n * bare to say what the call did is how GENC-1494 started.\n */\nfunction condenseStub(\n target: 'args' | 'response',\n tool: string,\n trigger: CondenseTrigger,\n origLen: number,\n restorable: boolean,\n /**\n * Images elided alongside the text. Reported separately because the model reads this stub as\n * fact: folding base64 bytes into the char count would tell it a 15KB render was \"~15447\n * chars\" of prose. One variable cannot be both the size FLOOR (bytes, correctly) and a\n * model-facing description (characters).\n */\n imageCount = 0,\n): string {\n const what = target === 'args' ? 'args' : 'result';\n const key = trigger.kind === 'superseded' ? ` ${trigger.by}` : '';\n const restore = restorable ? '; re-call to restore' : '';\n const images = imageCount > 0 ? ` + ${imageCount} image${imageCount === 1 ? '' : 's'}` : '';\n return `[${tool}${key} \u2014 ${what} elided, ~${origLen} chars${images} (${triggerReason(trigger)})${restore}]`;\n}\n\n/** Stable label for the `context.condensed` meta-event's `trigger` field. */\nfunction triggerLabel(trigger: CondenseTrigger): string {\n switch (trigger.kind) {\n case 'age':\n return `age:${trigger.turns}`;\n case 'superseded':\n return `superseded:${trigger.by}`;\n default:\n return trigger.kind; // 'turnEnd' | 'agentEnd' | 'phaseEnd'\n }\n}\n\nfunction estimateTokensSaved(origLen: number, stubLen: number): number {\n return Math.max(0, Math.ceil((origLen - stubLen) / APPROX_CHARS_PER_TOKEN));\n}\n\n/**\n * Whether a trigger marks a genuine discontinuity rather than firing continuously, and so is\n * exempt from batching.\n *\n * `agentEnd` advances only when the active agent's name changes (or a sub-agent completes /\n * the agent is released), which swaps the system prompt and tool definitions \u2014 those render\n * before the messages, so the cached prefix is invalidated at that point regardless. `phaseEnd`\n * is the app declaring the same kind of boundary explicitly, and falls back to `agentEnd`.\n * Deferring either to the next batch would buy no cache and only hold stale payloads longer.\n *\n * The rest fire continuously (`superseded`, `age`) or at a point where the history is otherwise\n * append-only (`turnEnd` \u2014 a new turn appends a user message, leaving the previous entry live),\n * so batching them is exactly where the cache is won.\n */\nfunction marksDiscontinuity(kind: CondenseTrigger['kind']): boolean {\n return kind === 'agentEnd' || kind === 'phaseEnd';\n}\n\n/**\n * Collapse stale tool payloads (declared via `condenseWhen`) out of the\n * model-bound history. Pure over the `history` array \u2014 it emits new message\n * objects and never mutates the input messages (mirroring the agent-masking\n * transform). It DOES, however, write two latches onto the matching `policies`\n * entry the first time a payload collapses, both because the collapse itself\n * re-runs before every provider call: the `reported*` flag (the report-once gate\n * that keeps `onCondensed` firing once per (tool call, payload)) and\n * `firedTrigger` (which pins the reason so a reason-bearing stub is rendered\n * once and never rewritten).\n *\n * Triggers (a policy may list several via `on: Trigger[]` \u2014 the FIRST to fire\n * collapses the payload; all are monotonic, so the collapse never reverts):\n * - `superseded` \u2014 among all registered calls sharing a `by` key, the LAST in\n * history order survives; every earlier one's targeted payload collapses. A\n * re-call with the same key becomes the new survivor and re-arms the rest.\n * - `age` \u2014 the result is first visible one model-call after the call, so `turns`\n * is how many model-calls may see the full result before it collapses\n * (fires when `modelCall \u2212 callModelCall > turns`): `turns: 1` is seen once,\n * then collapses. The clock is monotonic across turns.\n * - `turnEnd` \u2014 collapses once the turn (`sendMessage`) that made the call has\n * ended (fires when `turn > callTurn`): full for the rest of that request,\n * gone on every later one.\n * - `agentEnd` \u2014 collapses once the agent activation that made the call has ended\n * (a swap to another agent, or `releaseAgent`/`completeSubAgent`): kept across\n * all of the agent's turns, dropped when its flow finishes.\n * - `phaseEnd` \u2014 collapses once the app advances its phase epoch via `endPhase()`\n * after the call (a sub-`agentEnd` boundary the author declares), OR at\n * `agentEnd` as a backstop if no boundary is ever declared.\n *\n * The tool-call/result envelope is never removed (providers reject orphaned\n * calls/results) \u2014 only the args object or the result content is replaced.\n *\n * @param history - The to-model history copy to rewrite (not mutated).\n * @param policies - The driver's registry, keyed by tool-call id. Its entries'\n * `reported*` flags are flipped as payloads first collapse.\n * @param ctx - The driver's live clocks (model-call / turn / agent-activation).\n * @param onCondensed - Invoked once per payload at its full\u2192stub transition.\n */\nexport function applyCondensation(\n history: ChatMessage[],\n policies: Map<string, RegisteredCondensePolicy>,\n ctx: CondenseContext,\n onCondensed: (detail: CondensedEventDetail) => void,\n): ChatMessage[] {\n if (policies.size === 0) return history;\n\n const triggersOf = (entry: RegisteredCondensePolicy): CondenseTrigger[] =>\n Array.isArray(entry.policy.on) ? entry.policy.on : [entry.policy.on];\n\n // One pass: resolve supersession survivors and a toolCallId \u2192 tool-name\n // lookup. For each `superseded` key the LAST call in history order survives.\n // The name lookup lets a tool message (which carries only an id) name its tool\n // in stubs and events.\n // Batch boundary: the collapse set is resolved as of this model-call and stays put\n // until the next boundary, so the prefix is append-only in between. `batchCalls` of 1\n // (the default) makes this `ctx.modelCall` \u2014 i.e. no batching.\n const batchCalls = Math.max(1, Math.floor(ctx.batchCalls ?? 1));\n const asOf =\n batchCalls === 1 ? ctx.modelCall : Math.floor(ctx.modelCall / batchCalls) * batchCalls;\n // A call made after the boundary is invisible to this pass in BOTH directions: it\n // cannot supersede an older call (which would collapse the older payload early), and\n // it cannot itself collapse (which would elide the very result just fetched). Unbatched,\n // the boundary is the live clock and this gate is off entirely \u2014 a call registered on\n // the current model-call is still eligible, as it always was.\n const withinBatch = (entry: RegisteredCondensePolicy): boolean =>\n batchCalls === 1 || entry.iteration <= asOf;\n\n const latestByKey = new Map<string, string>();\n const nameById = new Map<string, string>();\n for (const msg of history) {\n if (!msg.toolCalls?.length) continue;\n for (const tc of msg.toolCalls) {\n nameById.set(tc.id, tc.name);\n const entry = policies.get(tc.id);\n if (!entry || !withinBatch(entry)) continue;\n for (const t of triggersOf(entry)) {\n if (t.kind === 'superseded') latestByKey.set(t.by, tc.id);\n }\n }\n }\n\n const triggerFires = (\n toolCallId: string,\n entry: RegisteredCondensePolicy,\n trig: CondenseTrigger,\n ): boolean => {\n switch (trig.kind) {\n // Result first visible one model-call after the call, so collapse one call\n // past the last allowed view: turns:1 \u2192 seen once, then gone. Monotonic\n // clock, so this holds across turn boundaries too.\n case 'age':\n return asOf - entry.iteration > trig.turns;\n case 'turnEnd':\n return ctx.turn > entry.turn;\n case 'agentEnd':\n return ctx.activationEnded(entry.activation);\n // Fires when the app advanced the phase epoch since the call \u2014 OR, as a\n // backstop, when the whole activation has ended, so a phase boundary that\n // is never declared still collapses at `agentEnd` rather than never.\n case 'phaseEnd':\n return ctx.phaseEnded(entry.phaseEpoch) || ctx.activationEnded(entry.activation);\n default:\n return latestByKey.get(trig.by) !== toolCallId; // superseded by a newer call\n }\n };\n\n // The first listed trigger that fires \u2014 drives the collapse, the stub reason,\n // and the event label. `undefined` means the payload stays full.\n //\n // Latched on first fire (see `firedTrigger`): re-resolving on every pass lets the reason\n // change under a payload that has already collapsed, which rewrites any reason-bearing stub\n // and costs a second cache break. Both payloads of a call share the latch \u2014 they are\n // evaluated in the same pass off the same clocks, so they never disagree about which\n // trigger fired; only the size floor decides whether each one renders.\n const firstFired = (\n toolCallId: string,\n entry: RegisteredCondensePolicy,\n ): CondenseTrigger | undefined => {\n if (entry.firedTrigger) return entry.firedTrigger;\n const fired = triggersOf(entry).find(\n (t) =>\n (marksDiscontinuity(t.kind) || withinBatch(entry)) && triggerFires(toolCallId, entry, t),\n );\n if (fired) entry.firedTrigger = fired;\n return fired;\n };\n\n return history.map((msg) => {\n // Tool-call ARGS live on the assistant message.\n if (msg.toolCalls?.length) {\n let changed = false;\n const toolCalls = msg.toolCalls.map((tc) => {\n const entry = policies.get(tc.id);\n if (!entry?.policy.args) return tc;\n const fired = firstFired(tc.id, entry);\n if (!fired) return tc;\n const origLen = JSON.stringify(tc.args ?? {}).length;\n if (origLen < CONDENSE_MIN_CHARS) return tc;\n changed = true;\n const result = entry.policy.args;\n // Args must stay a Record, so every mode stashes its stub under a single key.\n // Spread `tc` so providerMetadata (e.g. the Gemini reasoning signature that must\n // round-trip) and UI fields survive.\n //\n // GENC-1494: `drop` used to collapse args to a bare `{}`. That is indistinguishable\n // from a call the model made with NO arguments, and the model reads its own history\n // as fact: a ui-builder run saw its elided `vfs_write` calls as `vfs_write {}` beside\n // a live `{\"status\":\"buffered\",\"path\":\"\u2026\"}` result, concluded it was calling the tool\n // without content, and burned two hours re-writing files that were already correct.\n // A bare marker is not enough either \u2014 it still fails to say WHICH file the call\n // wrote, since `path` went with the args. So `drop` renders the same identifying stub\n // as `pointer`, minus only the restore promise it cannot honour.\n const args: Record<string, unknown> = {\n [CONDENSED_ARGS_KEY]:\n result === 'drop' || result === 'pointer'\n ? condenseStub('args', tc.name, fired, origLen, result === 'pointer')\n : result.replaceWith,\n };\n if (!entry.reportedArgs) {\n entry.reportedArgs = true;\n const stubLen = JSON.stringify(args).length;\n onCondensed({\n turn: entry.iteration,\n toolCallId: tc.id,\n tool: tc.name,\n target: 'args',\n trigger: triggerLabel(fired),\n stubLen,\n tokensSaved: estimateTokensSaved(origLen, stubLen),\n });\n }\n return { ...tc, args };\n });\n return changed ? { ...msg, toolCalls } : msg;\n }\n\n // The tool RESULT lives on the tool message.\n if (msg.toolResult) {\n const entry = policies.get(msg.toolResult.toolCallId);\n // Defensive `?? 0` for restored/malformed history \u2014 `content` is typed\n // `string`, but a 0-length payload is simply below the floor and skipped.\n //\n // Attachment bytes COUNT toward the floor (GENC-1508). An image-bearing result is\n // typically a few words of text \u2014 \"rendered the mockup\" \u2014 plus ~15KB of base64, so\n // sizing on `content` alone leaves it permanently under CONDENSE_MIN_CHARS and the\n // image rides every subsequent turn. That is the exact payload condensation exists\n // to shed, so it must be what is measured.\n const textLen = msg.toolResult.content?.length ?? 0;\n const images = msg.toolResult.attachments ?? [];\n // Bytes gate the FLOOR (an image result is a few words of text plus ~15KB of base64, so\n // sizing on text alone would never condense it); `textLen` and the image count are what\n // the model is told. See condenseStub.\n const origLen = textLen + images.reduce((n, att) => n + (att.data?.length ?? 0), 0);\n const fired = entry?.policy.response\n ? firstFired(msg.toolResult.toolCallId, entry)\n : undefined;\n if (entry && fired && origLen >= CONDENSE_MIN_CHARS) {\n const tool = nameById.get(msg.toolResult.toolCallId) ?? msg.toolResult.toolCallId;\n const result = entry.policy.response!; // `fired` is only set when response is declared\n // Kept non-empty \u2014 Anthropic rejects empty tool_result content.\n const content =\n result === 'drop' || result === 'pointer'\n ? condenseStub('response', tool, fired, textLen, result === 'pointer', images.length)\n : result.replaceWith;\n if (!entry.reportedResponse) {\n entry.reportedResponse = true;\n onCondensed({\n turn: entry.iteration,\n toolCallId: msg.toolResult.toolCallId,\n tool,\n target: 'response',\n trigger: triggerLabel(fired),\n stubLen: content.length,\n tokensSaved: estimateTokensSaved(origLen, content.length),\n });\n }\n // `attachments` is dropped, not spread through: the stub says the payload was\n // elided, and leaving the images attached would make that a lie AND shed none of\n // the bytes the condensation was performed to shed.\n const { attachments: _elided, ...restOfResult } = msg.toolResult;\n return { ...msg, toolResult: { ...restOfResult, content } };\n }\n }\n\n return msg;\n });\n}\n", "import type { ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * Masks the tool-specific payload of a single message \u2014 clears tool call args\n * and replaces tool result content with a placeholder. Used when passing history\n * to an agent that should not see another agent's implementation detail.\n */\nfunction maskToolPayload(msg: ChatMessage): ChatMessage {\n if (msg.toolCalls?.length) {\n return { ...msg, toolCalls: msg.toolCalls.map((tc) => ({ ...tc, args: {} })) };\n }\n if (msg.toolResult) {\n // `attachments` is dropped, not spread through. Masking exists to keep another agent's\n // payload out of this one's context, and an image is the largest payload there is \u2014 spreading\n // it would stub the prose while still shipping the render, defeating the mask for exactly the\n // case it matters most. `applyHistoryCap` masks everything past the cap for sub-agent context,\n // so without this every older image rides every sub-agent turn under an \"omitted\" label.\n const { attachments: _masked, ...restOfResult } = msg.toolResult;\n return {\n ...msg,\n toolResult: { ...restOfResult, content: \"[other agent's tool result omitted]\" },\n };\n }\n return msg;\n}\n\n/**\n * Prepares history for the LLM only: masks tool call args and results from other\n * agents so the active specialist is not confused by tools it does not have.\n * Canonical history in `ChatDriver` stays unmasked for UI and logging.\n */\nexport function transformHistoryForAgent(history: ChatMessage[], agentName: string): ChatMessage[] {\n return history.map((msg) => {\n if (!msg.agentName || msg.agentName === agentName) return msg;\n return maskToolPayload(msg);\n });\n}\n\n/**\n * Applies a history cap for sub-agent context: the last `cap` messages are passed\n * verbatim; older messages have their tool payloads masked.\n */\nexport function applyHistoryCap(history: readonly ChatMessage[], cap: number): ChatMessage[] {\n const cutoff = history.length - cap;\n return history.map((msg, i) => (i < cutoff ? maskToolPayload(msg) : msg));\n}\n\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Compaction (GENC-1351 \u00A75.7) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Recent messages kept verbatim when compacting; everything earlier is summarized. */\nexport const COMPACT_KEEP_RECENT_MESSAGES = 4;\n\n/** Don't bother compacting unless at least this many messages would be summarized. */\nexport const COMPACT_MIN_MESSAGES_TO_COMPACT = 4;\n\n/**\n * Index at which the verbatim tail begins \u2014 everything before it gets summarized.\n * The tail starts on a clean turn boundary (a `user` message): a user message\n * never appears between a `tool_use` and its `tool_result`, so cutting there\n * guarantees the summarized region is tool-pair-balanced (compaction only runs\n * when idle, so history is turn-complete). Returns `null` when there is nothing\n * worth compacting (too short, or no earlier user boundary) \u2014 e.g. a freshly\n * restored session whose only user turn is the current one.\n */\nexport function findCompactionCut(history: readonly ChatMessage[]): number | null {\n if (history.length < COMPACT_KEEP_RECENT_MESSAGES + COMPACT_MIN_MESSAGES_TO_COMPACT) {\n return null;\n }\n const target = history.length - COMPACT_KEEP_RECENT_MESSAGES;\n for (let i = target; i > 0; i -= 1) {\n if (history[i].role === 'user') {\n return i >= COMPACT_MIN_MESSAGES_TO_COMPACT ? i : null;\n }\n }\n return null;\n}\n\n/** One-line rendering of a message for the summarizer transcript. */\nfunction renderMessageForSummary(m: ChatMessage): string {\n switch (m.role) {\n case 'compacted-summary':\n return `[Earlier summary] ${m.content}`;\n case 'user':\n return m.content ? `User: ${m.content}` : '';\n case 'assistant': {\n // Reasoning (\"Thinking\") and narration (\"Working\") are display-only assistant splits\n // (GENC-1410) with no tool calls of their own \u2014 fold them into the summary too, labelled\n // the same as the UI so the summarizer knows they were internal, not a final answer.\n if (m.category === 'reasoning') {\n return m.content ? `Thinking: ${m.content}` : '';\n }\n if (m.category === 'narration') {\n return m.content ? `Working: ${m.content}` : '';\n }\n if (m.toolCalls?.length) {\n const calls = m.toolCalls.map((t) => t.name).join(', ');\n return m.content\n ? `Assistant: ${m.content} (called: ${calls})`\n : `Assistant called: ${calls}`;\n }\n return m.content ? `Assistant: ${m.content}` : '';\n }\n case 'tool':\n return m.toolResult ? `Tool result: ${m.toolResult.content}` : '';\n default:\n return ''; // system-event / synthetic-user \u2014 not part of the model transcript\n }\n}\n\n/**\n * Build the one-shot summarizer prompt for a run of older messages (used with\n * `AIProvider.prompt`). Mirrors the `<conversation_history>` block convention\n * that suggestions use. Any existing `compacted-summary` at the head is folded\n * in (rendered as prior-summary context), so rolling re-compaction produces one\n * combined summary.\n */\nexport function buildCompactionSummaryPrompt(toCompact: readonly ChatMessage[]): {\n systemPrompt: string;\n userMessage: string;\n} {\n const transcript = toCompact.map(renderMessageForSummary).filter(Boolean).join('\\n');\n const systemPrompt =\n 'You compress a conversation transcript into a concise summary that lets an AI ' +\n 'assistant continue the conversation seamlessly. Preserve key facts, decisions, ' +\n 'what the user wants, entity names and IDs, and any unresolved threads. Write ' +\n 'plain prose. Never roleplay or continue the conversation.';\n const userMessage =\n `<conversation_history>\\n${transcript}\\n</conversation_history>\\n\\n` +\n 'Summarize the conversation above so it can be dropped from context while ' +\n 'preserving everything needed to continue. Output only the summary prose.';\n return { systemPrompt, userMessage };\n}\n\n/**\n * Normalize history for a provider request (GENC-1351 \u00A75.7): translate each\n * `compacted-summary` message into a `user` message that wraps its summary in a\n * `<conversation_summary>` block, so the raw display-only role never reaches a\n * transport. Other roles pass through untouched. Pure \u2014 returns a new array.\n *\n * Applied at the request-build chokepoint *before* per-agent masking, so the\n * guarantee holds for every provider/transport regardless of any optional\n * per-agent history transform.\n */\nexport function normalizeForProvider(history: readonly ChatMessage[]): ChatMessage[] {\n return history.map((m) => {\n if (m.role !== 'compacted-summary') return m;\n return {\n ...m,\n role: 'user',\n content:\n `<conversation_summary>\\n${m.content}\\n</conversation_summary>\\n\\n` +\n 'The above summarizes earlier parts of this conversation that were compacted. ' +\n 'Continue naturally from it.',\n compaction: undefined,\n };\n });\n}\n\n/** Human-facing divider label for a `compacted-summary` message. */\nexport function compactionDividerLabel(m: ChatMessage): string {\n const n = m.compaction?.compactedCount ?? 0;\n return `Compacted ${n} earlier message${n === 1 ? '' : 's'}`;\n}\n", "import type { AggregateUsage, ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * Zeroed {@link AggregateUsage}. A factory, not a shared const, because callers\n * accumulate into the returned object.\n *\n * @beta\n */\nexport function emptyUsage(): AggregateUsage {\n return {\n costUsd: 0,\n uncachedInputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n outputTokens: 0,\n };\n}\n\n/**\n * Total tokens processed \u2014 the four buckets added up. Safe to sum because the\n * buckets are disjoint (see {@link AggregateUsage}); the equivalent sum over\n * per-message fields would double-count the prompt.\n *\n * Bear in mind what this number is: because every turn resends the conversation,\n * a turn's prompt is counted again in the next turn's. It is billed throughput,\n * NOT the count of distinct tokens in the conversation, so it grows\n * super-linearly with turn count and is expected to dwarf the context size.\n *\n * @beta\n */\nexport function totalTokens(usage: AggregateUsage): number {\n return (\n usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens + usage.outputTokens\n );\n}\n\n/**\n * `a + b`, per bucket, as a new object.\n *\n * Used to lay a row's banked (pre-transcript) spend over what the live transcript\n * proves. Pure rather than in-place because both operands are live state a caller\n * must not mutate.\n *\n * @beta\n */\nexport function addUsage(a: AggregateUsage, b: AggregateUsage): AggregateUsage {\n return {\n costUsd: a.costUsd + b.costUsd,\n uncachedInputTokens: a.uncachedInputTokens + b.uncachedInputTokens,\n cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,\n cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,\n outputTokens: a.outputTokens + b.outputTokens,\n };\n}\n\n/**\n * The four buckets plus USD for ONE message \u2014 the per-message fields projected into\n * the disjoint, addable shape, or `undefined` when the message reports no usage at\n * all (a user turn, a display-only reasoning/narration split, a provider that\n * reports none).\n *\n * Shallow by design: it does NOT recurse into `toolCalls[].subAgentTrace` and does\n * NOT count `compaction.rolledUpUsage`, so it answers \"what did this one request\n * cost\" rather than \"what did this message and everything under it cost\". Use\n * {@link sumUsage} for the latter \u2014 passing a whole transcript through this one\n * message at a time would silently drop both.\n *\n * `costUsd` folds in `externalCostUsd` (non-LLM spend a widget reported), matching\n * `sumUsage`. It is `0` when the provider priced nothing, which is NOT a claim that\n * the call was free \u2014 see {@link AggregateUsage}; `UsageRow.costUsd` is the\n * shape that keeps unpriced distinguishable, and is the right tool for a ledger.\n *\n * @beta\n */\nexport function messageUsage(m: ChatMessage): AggregateUsage | undefined {\n if (\n m.cost == null &&\n m.externalCostUsd == null &&\n m.inputTokens == null &&\n m.outputTokens == null &&\n m.cacheReadTokens == null &&\n m.cacheWriteTokens == null\n ) {\n return undefined;\n }\n const cacheReadTokens = m.cacheReadTokens ?? 0;\n const cacheWriteTokens = m.cacheWriteTokens ?? 0;\n return {\n costUsd: (m.cost ?? 0) + (m.externalCostUsd ?? 0),\n // The uncached REMAINDER, clamped \u2014 the same arithmetic `accumulate` below applies,\n // for the same reasons. The two are deliberately separate implementations (that walk\n // mutates one accumulator rather than allocating per message) and must agree;\n // `sum-usage.test.ts` pins them together.\n uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),\n cacheReadTokens,\n cacheWriteTokens,\n outputTokens: m.outputTokens ?? 0,\n };\n}\n\n/**\n * Sum cost and per-bucket token usage across a message list.\n *\n * One walk produces everything a usage display needs, replacing separate cost and\n * token passes over the same (potentially deep) transcript. Recurses into each\n * tool call's `subAgentTrace`, so LLM work a sub-agent did \u2014 possibly on another\n * provider at other rates \u2014 lands in the total; the driver embeds a whole\n * sub-agent conversation in the parent's tool result, so this is the only place\n * that spend is visible.\n *\n * Splitting the prompt into buckets is the point: `cost` already has the cache\n * discount applied, but a single token total cannot show that a session was cheap\n * because most of its prompt was a cache hit. The three input buckets are derived\n * from the per-message fields, where `inputTokens` is the whole prompt and the\n * cache fields break it down \u2014 so uncached input is the remainder, never an\n * addition.\n *\n * Also counts `compaction.rolledUpUsage`: compaction destroys the messages it\n * summarises, and without their banked usage every total re-derived from the\n * transcript would drop by whatever those turns had already spent.\n *\n * Returns a zeroed total when no message carries usage \u2014 providers that report\n * none (e.g. Chrome built-in) are skipped silently rather than guessed at.\n *\n * @remarks\n * This sums the WHOLE array, which is the right answer only when the array is the\n * whole of the work being billed. A driver whose conversation **continues across\n * rounds** opens its history with turns an earlier round already paid for, so\n * summing it again bills them twice \u2014 and the session total then grows\n * quadratically in the number of rounds while every individual figure in it stays\n * correct. Nothing about the result looks wrong, which is why it is called out\n * here rather than left to the caller to notice.\n *\n * Do NOT solve this with a \"sum from this message onwards\" marker. Compaction\n * *replaces* the messages it summarises \u2014 and compaction is one of this function's\n * own call sites \u2014 so the marker message can be absent from history by the time\n * the sum runs, leaving the caller to either fail or silently sum everything,\n * which is the double-count the marker was meant to prevent.\n *\n * Instead hold a **banked baseline**: spend that predates the current transcript,\n * carried as a value, with `usage = banked + live` composed via {@link addUsage}.\n * `resolveBankedUsage` in `utils/cost-session-history.ts` is the worked form, and\n * the shape of its signature is the load-bearing part. It separates three cases:\n *\n * 1. no prior record \u2014 a genuine first round, so nothing is banked;\n * 2. prior record, and the live transcript already accounts for it (a restored\n * session) \u2014 carry the prior record's own banked figure forward;\n * 3. prior record, and the transcript starts empty \u2014 bank the prior record's\n * whole total, because nothing in the transcript can re-derive it.\n *\n * Case 1 and case 3 take the same arithmetic and mean opposite things, so the\n * prior record must be a **required** input with no zero-defaulting path: a\n * caller who carries a transcript and forgets its baseline reports the entire\n * prior conversation as this round's spend. Distinguishing 2 from 3 is a separate\n * decision, and getting it wrong is destructive in the other direction \u2014 it\n * rewrites a total down to the current page-load and drops earlier spend.\n *\n * @beta\n */\nexport function sumUsage(messages: readonly ChatMessage[]): AggregateUsage {\n const total = emptyUsage();\n accumulate(messages, total);\n return total;\n}\n\n/** Add `from` into `into`, in place. */\nfunction addInto(into: AggregateUsage, from: AggregateUsage): void {\n into.costUsd += from.costUsd;\n into.uncachedInputTokens += from.uncachedInputTokens;\n into.cacheReadTokens += from.cacheReadTokens;\n into.cacheWriteTokens += from.cacheWriteTokens;\n into.outputTokens += from.outputTokens;\n}\n\n/**\n * Walk `messages`, accumulating into `into`. Mutates a single accumulator rather\n * than merging returned objects \u2014 this runs on every transcript change, so the\n * per-message allocation is worth avoiding.\n */\nfunction accumulate(messages: readonly ChatMessage[], into: AggregateUsage): void {\n for (const m of messages) {\n // Provider/LLM cost plus any non-LLM cost a widget reported for its own\n // external service calls. Both are real spend on this session.\n if (m.cost != null) into.costUsd += m.cost;\n if (m.externalCostUsd != null) into.costUsd += m.externalCostUsd;\n\n const cacheRead = m.cacheReadTokens ?? 0;\n const cacheWrite = m.cacheWriteTokens ?? 0;\n into.cacheReadTokens += cacheRead;\n into.cacheWriteTokens += cacheWrite;\n // The uncached remainder of the prompt. Clamped at zero so malformed or\n // hand-edited history whose buckets exceed the prompt total can't drive the\n // session total negative \u2014 a wrong-but-plausible number is worse than a\n // conservative one here, since this feeds a cost display.\n into.uncachedInputTokens += Math.max(0, (m.inputTokens ?? 0) - cacheRead - cacheWrite);\n into.outputTokens += m.outputTokens ?? 0;\n\n // Spend banked by a compaction on this summary's behalf. NOTE: deliberately\n // not `compaction.tokensBefore` \u2014 that is a one-turn context-window reading,\n // not cumulative spend, and counting it here would inflate the total.\n const rolled = m.compaction?.rolledUpUsage;\n if (rolled) addInto(into, rolled);\n\n for (const tc of m.toolCalls ?? []) {\n if (tc.subAgentTrace) accumulate(tc.subAgentTrace, into);\n }\n }\n}\n", "import type { ChatToolDefinition, ChatToolHandlers } from '@genesislcap/foundation-ai';\n\n/**\n * Symbol used to attach ToolFold metadata to a facade handler function.\n * The ChatDriver inspects this to detect fold facades at runtime.\n *\n * @internal\n */\nexport const TOOL_FOLD_SYMBOL = Symbol('toolFold');\n\n/**\n * Internal metadata for a tool fold. Attached to the facade handler via TOOL_FOLD_SYMBOL.\n *\n * @internal\n */\nexport interface ToolFold {\n /** Facade tool name. */\n name: string;\n /** Description shown to the model. */\n description: string;\n /** Optional guidance injected in the fold-open response. */\n usageNotes?: string;\n /** Tool definitions inside this fold. */\n tools: ChatToolDefinition[];\n /** Handlers for the inner tools (keyed by tool name). */\n handlers: ChatToolHandlers;\n /**\n * When true (default), all other tools are removed when this fold opens \u2014\n * the model can only see this fold's tools until it closes.\n * When false, sibling tools remain alongside the inner tools.\n */\n exclusive: boolean;\n}\n\n/**\n * The value returned by `createToolFold`.\n *\n * @beta\n */\nexport interface ToolFoldResult {\n /**\n * The facade tool definition. Add this to your agent's `toolDefinitions`.\n * It is a regular `ChatToolDefinition` with an empty parameter schema.\n */\n definition: ChatToolDefinition;\n /**\n * The facade handler \u2014 a single-entry map keyed by the fold name.\n * Spread this into your agent's `toolHandlers`.\n * Inner tool handlers are NOT included here \u2014 they are encapsulated inside\n * the fold metadata and installed by the driver only when the fold opens.\n */\n handler: ChatToolHandlers;\n}\n\n/**\n * Creates a tool fold \u2014 a facade that hides a group of related tools behind a single\n * named entry, revealing them progressively when the model invokes the facade.\n *\n * The `tools` and `handlers` parameters accept the exact same types as `AgentConfig.toolDefinitions`\n * and `AgentConfig.toolHandlers`, so existing tool creation functions can be passed in unchanged.\n *\n * @example\n * ```typescript\n * const tradingTools = createToolFold({\n * name: 'trading_tools',\n * tools: createTradesToolDefinitions(),\n * handlers: createTradesToolHandlers(connect),\n * });\n *\n * const agent: AgentConfig = {\n * name: 'Trades',\n * systemPrompt: '...',\n * toolDefinitions: [getCurrentDateDef, tradingTools.definition],\n * toolHandlers: { get_current_date: handler, ...tradingTools.handler },\n * };\n * ```\n *\n * @example Nesting folds\n * ```typescript\n * const insertFold = createToolFold({\n * name: 'trade_insertion',\n * tools: [validateDef, insertDef],\n * handlers: { validate_trade: vHandler, insert_trade: iHandler },\n * });\n *\n * const tradingFold = createToolFold({\n * name: 'trading_tools',\n * tools: [searchDef, insertFold.definition],\n * handlers: { search_trades: sHandler, ...insertFold.handler },\n * });\n * ```\n *\n * @beta\n */\nexport function createToolFold(config: {\n /** Facade tool name \u2014 used as the tool name the model calls to open this fold. */\n name: string;\n /**\n * Description shown to the model for the facade tool.\n * If omitted, auto-generated from the inner tool names:\n * \"Contains: tool_a, tool_b. Invoke to access these tools.\"\n */\n description?: string;\n /**\n * Optional usage guidance injected into the fold-open response message.\n * Not included in the facade description \u2014 only visible once the fold is open.\n */\n usageNotes?: string;\n /** Inner tool definitions. Same type as `AgentConfig.toolDefinitions`. */\n tools: ChatToolDefinition[];\n /** Inner tool handlers. Same type as `AgentConfig.toolHandlers`. */\n handlers: ChatToolHandlers;\n /**\n * When true (default), all other tools are removed when this fold opens.\n * When false, sibling tools remain available alongside the inner tools.\n */\n exclusive?: boolean;\n}): ToolFoldResult {\n const description =\n config.description ??\n `Contains: ${config.tools.map((t) => t.name).join(', ')}. Invoke to access these tools.`;\n\n const fold: ToolFold = {\n name: config.name,\n description,\n usageNotes: config.usageNotes,\n tools: config.tools,\n handlers: config.handlers,\n exclusive: config.exclusive ?? true,\n };\n\n const definition: ChatToolDefinition = {\n name: config.name,\n description,\n parameters: { type: 'object', properties: {} },\n };\n\n // The facade handler body is never actually called \u2014 the driver intercepts it\n // via TOOL_FOLD_SYMBOL before dispatch. The body is a no-op fallback.\n const facadeHandler = async (): Promise<string> => `Fold: ${config.name}`;\n (facadeHandler as any)[TOOL_FOLD_SYMBOL] = fold;\n\n return {\n definition,\n handler: {\n [config.name]: facadeHandler,\n },\n };\n}\n\n/**\n * A tool entry in the expanded debug tree.\n * Folds are represented as nodes with a `tools` array; regular tools have none.\n *\n * @beta\n */\nexport interface ToolTreeNode extends ChatToolDefinition {\n /** Present when this tool is a fold \u2014 contains its inner tools recursively expanded. */\n tools?: ToolTreeNode[];\n}\n\n/**\n * Expands a flat list of tool definitions into a nested tree by resolving fold\n * metadata from the corresponding handlers. Use this for debug output so the\n * full tool hierarchy is visible rather than just the top-level facade names.\n *\n * @beta\n */\nexport function expandToolTree(\n definitions: ChatToolDefinition[],\n handlers: ChatToolHandlers,\n): ToolTreeNode[] {\n return definitions.map((def) => {\n const handler = handlers[def.name];\n const fold: ToolFold | undefined = handler ? (handler as any)[TOOL_FOLD_SYMBOL] : undefined;\n if (fold) {\n return { ...def, tools: expandToolTree(fold.tools, fold.handlers) };\n }\n return { ...def };\n });\n}\n", "import type {\n AggregateUsage,\n AIProvider,\n AIProviderRegistry,\n AIProviderType,\n CachePolicy,\n ChatAttachment,\n ChatDriverResult,\n ChatFallback,\n ChatImageAttachment,\n ChatMessage,\n ChatRequestOptions,\n ChatThinkingPolicy,\n ChatToolCall,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n CondensePolicy,\n CondenseTrigger,\n InteractionRequestOptions,\n InteractionResult,\n SubAgentFailureReason,\n SubAgentRequestOptions,\n TurnFailureReason,\n} from '@genesislcap/foundation-ai';\nimport {\n BudgetExhaustedError,\n DEFAULT_BUDGET_EXHAUSTED_MESSAGE,\n DEFAULT_PROVIDER_REFUSED_MESSAGE,\n ProviderRefusedError,\n isObservableAIProviderRegistry,\n MalformedFunctionCallError,\n ResponseTruncatedError,\n vendorTypeOfLabel,\n} from '@genesislcap/foundation-ai';\nimport { type ActivityBus, NOOP_ACTIVITY_BUS } from '../../channel/ai-activity-bus';\nimport type {\n AgentConfig,\n CachePolicyInput,\n ProviderInput,\n ResponseSchemaInput,\n SystemPromptContext,\n SystemPromptInput,\n TailContextInput,\n TemperatureInput,\n ThinkingPolicyInput,\n ToolChoiceInput,\n ToolDefinitionsInput,\n ToolHandlersInput,\n UnresolvedToolInput,\n} from '../../config/config';\nimport { resolveChatProvider } from '../../config/validate-providers';\nimport {\n clearSession,\n getMetaEvents,\n type MetaEvent,\n mergeMetaEvents,\n type MetaEventType,\n recordMetaEvent,\n recordTurnError,\n recordTurnRetry,\n} from '../../state/debug-event-log';\nimport {\n createInteractionContext,\n type InteractionContextHandle,\n} from '../../state/interaction-context';\nimport type { DiagnosticEntry } from '../../state/persistence/diagnostics';\nimport type { InteractionContext } from '../../types/interaction-context';\nimport { applyCondensation, type RegisteredCondensePolicy } from '../../utils/condense-history';\nimport {\n applyHistoryCap,\n buildCompactionSummaryPrompt,\n findCompactionCut,\n normalizeForProvider,\n} from '../../utils/history-transform';\nimport { logger } from '../../utils/logger';\nimport { messageUsage, sumUsage } from '../../utils/sum-usage';\nimport { TOOL_FOLD_SYMBOL, type ToolFold } from '../../utils/tool-fold';\nimport type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';\n\n/**\n * The `budget` payload carried on a `'budget-exhausted'` {@link ChatDriverResult}.\n * Derived from the type rather than restated so the two cannot drift.\n */\ntype BudgetDetail = NonNullable<Extract<ChatDriverResult, { reason: 'done' }>['budget']>;\n/** The `providerRefused` payload on a `'provider-refused'` {@link ChatDriverResult} (GENC-1506). */\ntype ProviderRefusedDetail = NonNullable<\n Extract<ChatDriverResult, { reason: 'done' }>['providerRefused']\n>;\n\n/**\n * Lift the reportable facts off a {@link BudgetExhaustedError}, or `undefined`\n * when it carries none.\n *\n * \"None\" means **no figures AND no attributable vendor** \u2014 not merely no\n * figures. Dropping the whole object on a figure-less 402 also dropped\n * `vendorLabel`, which is the authoritative attribution source, and left the\n * element's latch falling back to the driver's last-resolved provider, i.e. the\n * PREVIOUS turn's vendor. A turn-1 Gemini call followed by a turn-2 classifier\n * refused by Anthropic with a figure-less 402 then walled *Gemini* and advised\n * switching to the vendor that had actually run out. Three live shapes reach\n * here with no figures \u2014 a bare gateway 402, a code-only body, and the framed\n * err frame whose figures are `null` (which the proxy now prefers over a\n * misleading `0`, so this path is getting more common, not less).\n *\n * The figures alone still decide whether banner copy is composed \u2014 see\n * `formatBlockedReason`, which returns `undefined` for a figure-less budget so a\n * host-set explanation survives the latch.\n */\n/**\n * The images on a tool handler's return, or `undefined` if it did not return any.\n *\n * Deliberately strict: `attachments` must be a non-empty array in which EVERY entry carries\n * `kind: 'image'`. A handler returning an ordinary object that happens to have an\n * `attachments` key therefore still JSON-stringifies exactly as it did before, and a\n * half-populated array fails the check rather than silently sending some of the images.\n */\nconst toolResultImages = (result: unknown): ChatImageAttachment[] | undefined => {\n if (!result || typeof result !== 'object') return undefined;\n const candidate = (result as { attachments?: unknown }).attachments;\n if (!Array.isArray(candidate) || candidate.length === 0) return undefined;\n const allImages = candidate.every(\n (att) => !!att && typeof att === 'object' && (att as { kind?: unknown }).kind === 'image',\n );\n return allImages ? (candidate as ChatImageAttachment[]) : undefined;\n};\n\n/**\n * Lift the reportable facts off a {@link ProviderRefusedError} (GENC-1506).\n *\n * Unlike `budgetDetailOf` this is total \u2014 it always returns a detail. The budget version can answer\n * `undefined` because its payload is figures the proxy may not have sent; here every field either\n * comes from the transport that was refused (`vendorLabel`, `kind`) or is plainly optional, so there\n * is no \"nothing worth reporting\" case to model.\n */\nconst providerRefusedDetailOf = (e: ProviderRefusedError): ProviderRefusedDetail => ({\n vendorLabel: e.vendorLabel,\n kind: e.kind,\n ...(e.upstreamStatus != null ? { upstreamStatus: e.upstreamStatus } : {}),\n ...(e.upstreamType ? { upstreamType: e.upstreamType } : {}),\n});\n\nconst budgetDetailOf = (e: BudgetExhaustedError): BudgetDetail | undefined => {\n // The typed vendor is derived from the LABEL, not from `lastResolvedProvider`:\n // the label comes from the transport that was actually refused, whereas the\n // last-resolved provider is stale on the classification seam (an orchestrated\n // turn classifies against the registry default, which this driver may never\n // have resolved). The proxy's own `vendor` is the fallback for a transport\n // whose static label no vendor claims (a multiplexing or white-labelled\n // gateway). Omitted rather than set to `undefined` when neither resolves, so\n // \"we know the vendor\" stays testable by presence alone.\n const vendor = vendorTypeOfLabel(e.vendorLabel) ?? vendorTypeOfLabel(e.serverVendor);\n if (e.budgetUsd == null && e.spentUsd == null && !vendor) return undefined;\n return {\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n vendorLabel: e.vendorLabel,\n ...(vendor ? { vendor } : {}),\n // Server-known truth the client cannot re-derive, so it rides all the way to\n // the banner rather than being re-guessed there from registry membership.\n ...(e.otherVendorAvailable != null ? { otherVendorAvailable: e.otherVendorAvailable } : {}),\n };\n};\n\nconst DEFAULT_MAX_TOOL_ITERATIONS = 50;\nconst DEFAULT_MAX_FOLD_OPERATIONS = 5;\n// TODO: dedup system prompts in-memory to allow raising this cap much higher.\n// Each TurnSnapshot stores the full resolved `systemPrompt`, so the buffer's\n// memory cost scales with cap \u00D7 prompt size \u2014 a stable agent repeats a multi-KB\n// prompt every turn. `getDebugLog` already dedups identical consecutive prompts\n// at export time (`<repeated \u2014 identical to turn N>`); applying the same dedup\n// at capture time (store the prompt only when it changes, back-reference\n// otherwise) would make snapshots nearly as cheap as meta events and let this\n// cap reach thousands for full-session capture without the memory blowup.\nconst DEFAULT_MAX_TURN_SNAPSHOTS = 400;\nconst DEFAULT_MAX_UNKNOWN_TOOL_CALLS = 5;\n// Stale tools (advertised in an earlier state, retired now) and fold-hidden tools are\n// self-correcting \u2014 the model drops them once guided \u2014 so they get a higher loop-protection\n// ceiling than hallucinated names: a few legitimate stale calls across state transitions must\n// not prematurely end the turn. Still bounded so a genuinely stuck loop terminates.\nconst MAX_STALE_TOOL_CALLS = DEFAULT_MAX_UNKNOWN_TOOL_CALLS * 2;\n// Gemini in particular emits short bursts of MALFORMED_FUNCTION_CALL; allow more CONSECUTIVE\n// retries. These counters reset on any productive response, so this is a consecutive-failure\n// ceiling, not a per-turn total.\nconst MAX_MALFORMED_RETRIES = 5;\nconst MAX_EMPTY_RESPONSE_RETRIES = 3;\n// Transient throws while building the per-turn tool surface or calling the provider retry the\n// SAME iteration up to this many times before propagating, rather than tearing down the turn.\nconst MAX_SETUP_TRANSPORT_RETRIES = 3;\nconst SUGGESTIONS_HISTORY_WINDOW = 8;\n\n/**\n * Sub-agent meta events worth folding into the parent's debug timeline: the\n * per-attempt and per-failure signals that do NOT otherwise surface in the\n * sub-agent's (now hoisted) messages \u2014 a retried-away malformed/empty attempt\n * produces no message, and the stale-vs-hallucinated/streak diagnostics live only\n * on the event. High-volume, message-derivable events (turn.start/turn.end,\n * provider.selected, context.updated) are intentionally excluded: read the\n * sub-agent's hoisted messages for model/tokens/cost and turn-by-turn activity.\n * See `ChatDriver.invokeSubAgent`.\n */\nconst HARVESTED_SUBAGENT_EVENTS: ReadonlySet<MetaEventType> = new Set([\n 'turn.retry',\n 'turn.error',\n 'tool.failed',\n 'tool.unresolved',\n]);\n\n/** Name reserved for the cross-agent handoff tool \u2014 injected by OrchestratingDriver. */\nexport const REQUEST_CONTINUATION_TOOL = 'request_continuation';\n\n/** Paired in history for each `request_continuation` so tool_calls stay balanced for the provider. */\nconst HANDOFF_TOOL_RESULT_PLACEHOLDER =\n 'Handoff to another specialist \u2014 routing continues on the next turn.';\n\n/**\n * Event emitted when the chat history is updated (new message appended).\n *\n * @beta\n */\nexport type ChatHistoryUpdatedEvent = CustomEvent<ReadonlyArray<ChatMessage>>;\n\n/**\n * One captured frame of what the LLM saw on a single tool-loop iteration.\n * The driver records these as a ring buffer (cap: configurable via\n * `chatConfig.agent.maxTurnSnapshots`, default 400) so the export log can show,\n * per turn: which agent was active, the resolved system prompt, the tool names\n * visible to the LLM, and any agent-supplied debug snapshot (e.g. machine\n * state for stateful agents).\n *\n * @beta\n */\nexport interface TurnSnapshot {\n /**\n * Turn identifier, always a string. A driver's own turns are the bare counter\n * (`\"0\"`, `\"1\"`, \u2026 \u2014 monotonic, does not reset on agent swap). Turns forwarded\n * up from a sub-agent are re-labelled under the parent turn that activated them\n * \u2014 a sub-agent invoked on parent turn 5 contributes `\"5-1\"`, `\"5-2\"`, \u2026, and a\n * nested sub-agent on `\"5-2\"` contributes `\"5-2-1\"`, \u2026. See\n * `forwardSubAgentSnapshots`.\n */\n turnIndex: string;\n /** ISO timestamp captured just before the LLM call. */\n timestamp: string;\n /** Name of the agent active when this LLM call ran. */\n agentName?: string;\n /**\n * The agent's resolved system prompt sent to the LLM, verbatim. NOTE: this is\n * now the *bare* prompt \u2014 the fold-surface suffix and the malformed/empty retry\n * nudge no longer mutate it (they kept it byte-unstable and busted prompt\n * caching), so they moved to {@link TurnSnapshot.tailContext}. To reconstruct\n * exactly what the model saw, read both fields.\n */\n systemPrompt?: string;\n /**\n * The framed `<system-reminder>` tail appended to the final user turn for this\n * call, verbatim \u2014 never part of stored history, so this snapshot is the only\n * record of it. Carries the framework's volatile additions (fold suffix, retry\n * nudge) and the agent's per-turn `tailContext` (e.g. current file spec, live\n * diagnostics). Undefined when the tail was empty (the normal case).\n */\n tailContext?: string;\n /** Tool names sent to the LLM, in order \u2014 definitions are static per name so names alone suffice. */\n toolNames: string[];\n /**\n * Normalized `0`\u2013`1` sampling temperature in effect for this call, if the\n * agent (or its current state) configured one. Undefined \u2192 provider/model\n * default. Mirrors the value resolved from `BaseAgentConfig.temperature`.\n */\n temperature?: number;\n /**\n * Tool-call mode actually sent to the provider this call \u2014 the effective\n * value, including the sub-agent `'required'` default. Undefined \u2192 `'auto'`.\n * Mirrors the value resolved from `BaseAgentConfig.toolChoice`.\n */\n toolChoice?: ChatToolChoice;\n /**\n * Per-turn display label resolved from the agent's `displayName`, e.g.\n * \"Guided Booking (Counterparties)\". `agentName` stays as the canonical\n * identity used for routing/filtering.\n */\n agentLabel?: string;\n /** Agent-supplied snapshot \u2014 machine state/context for stateful agents, undefined otherwise. */\n agentSnapshot?: unknown;\n /**\n * Concrete model that ran this call (e.g. `'claude-sonnet-4-6'`) \u2014 the serving model\n * where the provider reports one, else the model the resolved tier was configured\n * with. Undefined when the provider exposes no `getStatus` and the transport stamped\n * nothing.\n *\n * Recorded per call, so an agent whose `provider` selector varies by state (a tier\n * switch between steps of a flow) has each step attributed to the model that actually\n * ran it \u2014 without the reader having to join the turn to the message after it, which\n * is impossible for a call that produced no message.\n */\n model?: string;\n /**\n * Registry slot the provider resolved under for this call \u2014 a tier name like\n * `'high'`/`'low'`, or the registry default's name. Kept alongside {@link\n * TurnSnapshot.model} because they answer different questions: the slot is what the\n * agent asked for, the model is what served it, and repointing a slot at a new model\n * mid-session is only visible when both are recorded.\n */\n providerName?: string;\n /** Vendor behind the resolved slot (`'anthropic'`, `'gemini'`, \u2026), when the provider reports it. */\n provider?: AIProviderType;\n /**\n * What this one LLM call cost \u2014 the four disjoint token buckets plus USD, derived\n * from the response's usage by `messageUsage`. Back-filled when the response lands\n * (the rest of the snapshot is captured *before* the call), so it is `undefined`\n * while the call is in flight, on providers that report no usage, and on a call that\n * threw rather than returning \u2014 a malformed-call/truncation/402 error carries no usage\n * block, so any tokens the provider billed for it are not recoverable here.\n *\n * A snapshot is one **model call**, not one user turn: every tool-loop iteration and\n * every retried attempt records its own. That makes this the only record of spend on\n * an attempt that produced no message \u2014 a blank or refused response is billed and\n * then discarded (see the empty-response retries), so summing the transcript alone\n * under-reports the turn.\n *\n * For a call that DID produce a message, this is the same money as that message's\n * `cost`/token fields, not additional money \u2014 never add turn usage to message usage.\n */\n usage?: AggregateUsage;\n}\n\ninterface FoldStackFrame {\n foldName: string;\n previousDefinitions: ChatToolDefinition[];\n previousHandlers: ChatToolHandlers;\n}\n\n/**\n * Construction-time configuration for {@link ChatDriver}. Everything except the provider\n * registry is optional \u2014 most fields are also settable per-agent via `applyAgent`, so a\n * bare `new ChatDriver(registry)` is valid. Mirrors the `(registry, options)` shape of\n * `OrchestratingDriver`.\n *\n * @beta\n */\nexport interface ChatDriverConfig {\n /** Initial tool handlers (static map or per-turn factory). Default `{}`. */\n toolHandlers?: ToolHandlersInput;\n /** Initial tool definitions (static array or per-turn factory). Default `[]`. */\n toolDefinitions?: ToolDefinitionsInput;\n /** Initial system prompt (string or per-turn resolver). */\n systemPrompt?: SystemPromptInput;\n /** Primer history prepended to the conversation. */\n primerHistory?: ChatMessage[];\n /** Hard cap on tool-loop iterations. Default `50`. */\n maxToolIterations?: number;\n /** Hard cap on fold operations. Default `5`. */\n maxFoldOperations?: number;\n /**\n * Collapse `condenseWhen` payloads in batches of this many model-calls rather than as\n * soon as each trigger fires. A positive integer; decimals are floored and anything\n * below `1` becomes `1`. Default `1` \u2014 collapse immediately, the historical behaviour.\n *\n * Condensation rewrites history in place, so collapsing continuously breaks the\n * provider's prompt cache on nearly every call of a re-read loop. Raising this trades\n * up to that many calls' worth of extra context for one cache break per batch.\n */\n condenseBatchCalls?: number;\n /** Ring-buffer size for per-turn snapshots. Default `400`. */\n maxTurnSnapshots?: number;\n /** Session identity used to file meta events onto the shared debug-log timeline. */\n sessionKey?: string;\n /**\n * Activity bus for lifecycle/halo/tool-loop events. Injected by the browser host\n * (the shared cross-tab singleton); omitted off-browser (Node, tests, headless), where\n * it defaults to {@link NOOP_ACTIVITY_BUS} so no `BroadcastChannel` is ever opened.\n */\n activityBus?: ActivityBus;\n /**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464),\n * used VERBATIM \u2014 set it only to own the copy entirely (white-labelling).\n * When unset, the driver composes the bubble per wall: the neutral\n * `DEFAULT_BUDGET_EXHAUSTED_MESSAGE`, upgraded with \"switch to another AI\n * provider\" advice only when the 402's `otherVendorAvailable` positively says\n * another metered vendor still has headroom \u2014 the same rule the blocked\n * banner applies, so the two surfaces can no longer contradict each other.\n *\n * The assistant element already lets a host override the blocked **banner**\n * via `setBlocked(true, reason)`; without this the transcript **bubble** stayed\n * on the default, so a white-labelled host got its own copy in the banner and\n * the shipped default directly below it. Passing the same effective copy here\n * keeps the two surfaces saying one thing.\n *\n * Deliberately a driver-config field rather than something read off a chat\n * config: `ChatDriver` has no `chatConfig` and is used standalone (see\n * `chat-driver-node`), so threading one in would be a much larger and less\n * reversible change.\n */\n budgetExhaustedMessage?: string;\n\n /**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account\n * (GENC-1506) \u2014 see `DEFAULT_PROVIDER_REFUSED_MESSAGE`.\n *\n * Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend\n * cap a host administrator can raise, this is the vendor declining to serve us at all. A host that\n * white-labels one will usually want to white-label both, but conflating them into one field would\n * force identical copy on two situations with different remedies.\n *\n * Rarely needed: unlike the budget default, the shipped sentence names no vendor and no Genesis, so\n * it is already safe for a white-labelled deployment.\n */\n providerRefusedMessage?: string;\n}\n\n/**\n * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop.\n * Owned by `FoundationAiAssistant` \u2014 created in `connectedCallback`, torn down in `disconnectedCallback`.\n *\n * Dispatches `'history-updated'` events on itself so the owning element can observe changes.\n *\n * @fires history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution, post-resolve external cost) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`\n *\n * @beta\n */\nexport class ChatDriver extends EventTarget implements AiDriver {\n private history: ChatMessage[] = [];\n private busy = false;\n /** Epoch ms when the current turn loop began \u2014 drives the `turn.end` duration. */\n private turnStartedAt = 0;\n private pendingInteractions = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (reason?: any) => void;\n /** Present when the call requested a chat-input override. */\n overrideId?: string;\n /** Present when the call set `timeoutMs`; cleared on resolution. */\n timeoutHandle?: ReturnType<typeof setTimeout>;\n }\n >();\n /**\n * Live per-interaction contexts (GENC-1390), keyed by interactionId. Created in\n * `requestInteraction` alongside the pending entry, disposed + removed in\n * `resolveInteraction`. Non-serialisable (sockets, timers, subscriber sets), so\n * they live here on the driver \u2014 not on the DOM, not in the persisted store \u2014 and\n * therefore survive the element remounts (layout reflow/drag, transcript\n * re-render) that this feature exists to make harmless. At most one is live at a\n * time (see the one-interaction-at-a-time guard in `requestInteraction`).\n */\n private interactionContexts = new Map<string, InteractionContextHandle>();\n\n private systemPrompt?: SystemPromptInput;\n /**\n * Resolved tool definitions visible to the LLM. Folds mutate this in place\n * (push/pop on open/close). When `toolDefinitionsFactory` is set, this is\n * overwritten each tool-loop iteration with the factory's output.\n */\n private toolDefinitions: ChatToolDefinition[];\n /**\n * Optional dynamic-tools source. When set, called each tool-loop iteration\n * to recompute `toolDefinitions` before the LLM call. `defineStatefulAgent`\n * forbids folds when this is set, so the fold-mutation path is unreachable\n * in that case.\n */\n private toolDefinitionsFactory?: (\n ctx: SystemPromptContext,\n ) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>;\n /**\n * Resolved tool handler map used for dispatch. When `toolHandlersFactory` is\n * set, this is overwritten each tool-loop iteration with the factory's output\n * \u2014 keeping it in lockstep with `toolDefinitions` so handlers don't have to\n * defend themselves against being dispatched in states where their tool\n * isn't advertised. Folds mutate this in place; `defineStatefulAgent`\n * forbids folds when a factory is set, so the fold-mutation path is\n * unreachable in that case.\n */\n private toolHandlers: ChatToolHandlers;\n /**\n * Optional per-turn handler-map source. Mirrors `toolDefinitionsFactory` so\n * the LLM-visible tools and the dispatchable handlers can be narrowed in\n * lockstep. Resolved each tool-loop iteration before the LLM call.\n */\n private toolHandlersFactory?: (\n ctx: SystemPromptContext,\n ) => ChatToolHandlers | Promise<ChatToolHandlers>;\n private primerHistory?: ChatMessage[];\n private activeAgentName?: string;\n /**\n * Per-turn display label resolved from the agent's `displayName`. Stamped\n * onto outgoing messages and turn snapshots for UX; `activeAgentName` stays\n * stable for routing/history-transform identity matching.\n */\n private activeAgentLabel?: string;\n private displayName?: SystemPromptInput;\n /**\n * When set, `requestInteraction` delegates to this callback instead of using\n * this driver's own pending map. Wired by `invokeSubAgent` so a sub-agent's\n * widget renders in \u2014 and resolves through \u2014 the parent (ultimately the\n * root) driver, where the main UI is listening.\n */\n private hostInteractionRequester?: <T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ) => Promise<T>;\n /**\n * When set (e.g. by OrchestratingDriver), applied only to the conversation slice\n * sent to the model \u2014 stored `history` stays unchanged for UI and logging.\n */\n private providerHistoryTransform?: (history: ChatMessage[]) => ChatMessage[];\n /**\n * Tool-declared condensation policies, keyed by tool-call id. Populated by\n * `condenseWhen` (first-wins per call); read by `applyCondensation` before each\n * provider call to collapse stale payloads from the model-bound history only.\n * Accumulates across agents on a shared driver (a superseded read collapses no\n * matter which agent made it) and is never cleared \u2014 it dies with the driver.\n */\n private readonly condensePolicies = new Map<string, RegisteredCondensePolicy>();\n /**\n * Monotonic model-call counter for the driver's whole lifetime \u2014 the age clock\n * for `condenseWhen({ on: { kind: 'age' } })`. The per-`sendMessage` `iterations`\n * loop counter resets to 0 every turn, so it can only measure age WITHIN a\n * single turn; this never resets, so `age` counts model-calls since the result\n * appeared across turn boundaries (each short turn still advances it \u2265 1).\n * Bumped once per tool-loop iteration (provider call).\n */\n private modelCallSeq = 0;\n /**\n * Monotonic turn counter \u2014 the `turnEnd` clock. Bumped once per `sendMessage`\n * (a user turn; NOT per handoff continuation, which is the same request), never\n * reset. `turnEnd` collapses a payload once `turnSeq` exceeds the turn it was\n * created in.\n */\n private turnSeq = 0;\n /**\n * Monotonic agent-activation counter \u2014 the `agentEnd` clock. Advances when the\n * active flow ends: a swap to a different-named agent (`applyAgent`) OR an\n * explicit `releaseAgent` / `completeSubAgent`. A stateful agent re-resolving\n * the same name across turns keeps one activation. `agentEnd` fires for a\n * payload once a LATER activation is current (`callActivation < currentActivation`)\n * \u2014 so a re-run of a released agent gets a fresh activation and is NOT\n * collapsed until IT ends.\n */\n private currentActivation = 0;\n /**\n * Monotonic phase-epoch counter \u2014 the `phaseEnd` clock. Advanced by the\n * handler-context `endPhase()` (an app-declared phase boundary within one\n * activation), never reset. Unlike `currentActivation` it is NOT tied to agent\n * swaps or releases \u2014 it ticks only when the agent itself declares a phase\n * done. `phaseEnd` fires for a payload once a LATER epoch is current\n * (`callPhaseEpoch < currentPhaseEpoch`), with an `agentEnd` backstop.\n */\n private currentPhaseEpoch = 0;\n\n /** Stack of fold frames \u2014 grows when a fold opens, shrinks when it closes. */\n private foldStack: FoldStackFrame[] = [];\n /** Consecutive fold open/close ops without a real tool call. Reset on real tool execution. */\n private consecutiveFoldOps = 0;\n /** Consecutive unknown-tool calls without a real tool call. Reset on real tool execution. */\n private consecutiveUnknownToolCalls = 0;\n /**\n * Distinct unknown-tool names seen in the current consecutive streak \u2014 stamped\n * onto the `unknown-tool-limit` turn.error so a triager knows which tools were\n * hallucinated. Reset alongside `consecutiveUnknownToolCalls`.\n */\n private readonly recentUnknownToolNames = new Set<string>();\n /**\n * Union of every tool name advertised at any point during the current agent\n * activation. Lets the unknown-tool path tell a *stale* call (a real tool from\n * an earlier state, now retired \u2014 or one an open exclusive fold is hiding)\n * apart from a *hallucinated* one. Reset on agent swap in `applyAgent`.\n */\n private readonly everSeenToolNames = new Set<string>();\n /**\n * Subset of the current unknown-tool streak that was stale (previously\n * available) rather than hallucinated \u2014 surfaced separately on the\n * `unknown-tool-limit` turn.error so triage can tell a state/prompt-design\n * problem from a model that's inventing tools. Reset alongside\n * `recentUnknownToolNames`.\n */\n private readonly recentStaleToolNames = new Set<string>();\n private readonly maxFoldOperations: number;\n\n /** Sub-agents declared on the active agent config, keyed by name. */\n private subAgentsMap: Map<string, AgentConfig> = new Map();\n /**\n * Set by `completeSubAgent` inside a sub-agent tool handler. Checked at the\n * same point in the loop as `REQUEST_CONTINUATION_TOOL` \u2014 after tool results\n * are appended \u2014 so the exit path mirrors the system-call pattern.\n * `undefined` means the loop has not been stopped early.\n */\n private subAgentCompletion: { result: unknown } | undefined;\n /**\n * True when this driver runs as a child sub-agent (created by a parent\n * driver's `invokeSubAgent`). Sub-agents force tool use every turn so a turn\n * can only end via their completion tool, and on any non-completion exit they\n * record a typed `SubAgentFailureReason` instead of appending a\n * user-facing message \u2014 the parent decides how to surface the failure.\n */\n private isSubAgent = false;\n /**\n * Set when a sub-agent's tool loop ends without `completeSubAgent` being\n * called. Read by the parent's `invokeSubAgent` to build the `{ ok: false }`\n * branch of `requestSubAgent`. Only ever set when `isSubAgent` is true.\n *\n * `budget` rides along on a `'budget_exhausted'` failure so the parent inherits\n * the child's ATTRIBUTION, not just the fact of a wall \u2014 see\n * `budgetWallDetail`.\n */\n private subAgentFailure:\n | {\n reason: SubAgentFailureReason;\n budget?: BudgetDetail;\n /**\n * The refusing vendor and kind, when a child hit the PROVIDER wall (GENC-1506).\n *\n * Carried for the same reason `budget` is: the child is a **separate driver instance**, so\n * nothing it sets on itself is visible to the parent. Without this the parent could report\n * `provider-refused` but not say which vendor or which kind \u2014 losing the only signal that\n * distinguishes \"top up the account\" from \"rotate the key\", since the user copy is cause-free.\n */\n providerRefused?: ProviderRefusedDetail;\n }\n | undefined;\n /**\n * Set by `releaseAgent` inside a top-level tool handler \u2014 typically a stateful\n * agent's terminal-state handler signalling that its flow is complete and the\n * auto-pin lock can release. Checked by the orchestrator after `sendMessage`\n * returns; the orchestrator fires `onDeactivate` and clears the pin.\n *\n * Reset at the start of each `sendMessage` so a release from a previous turn\n * doesn't leak forward.\n */\n private agentReleaseRequested = false;\n /**\n * Ring buffer of per-LLM-call snapshots. Cap is configurable via\n * `chatConfig.agent.maxTurnSnapshots`; older entries drop off as new ones\n * arrive. See {@link TurnSnapshot} for the captured shape.\n */\n private turnSnapshots: TurnSnapshot[] = [];\n /**\n * `turn` + `message` diagnostic-log entries harvested from an out-of-band source (a resolved\n * interaction whose widget returned `InteractionResult.diagnostics` \u2014 e.g. a server-side\n * ChatDriver's debug log). `event` entries are NOT kept here \u2014 they're folded into the session's\n * meta-event registry via `mergeMetaEvents` (see `resolveInteraction`) so they inherit fresh host\n * indices, and reach the log through `getMetaEvents`. Append-only; the host folds these into its\n * debug log alongside this driver's own timeline. Not cleared here \u2014 it lives with the driver\n * instance, like `turnSnapshots`, so a new chat (fresh driver) starts empty while a compaction\n * (same instance) keeps it. (GENC-1461.)\n */\n private readonly externalDiagnostics: DiagnosticEntry[] = [];\n /**\n * Monotonic count of external-diagnostics batches harvested this driver-lifetime. Namespaces each\n * batch's re-keyed `turn` entries so distinct server generations in one chat session can't collide\n * on `turnIndex` in the forward-capture persister (which dedups turns by that key). (GENC-1461.)\n */\n private externalDiagnosticsBatches = 0;\n /** Monotonic counter that survives agent swaps \u2014 useful for cross-referencing with history. */\n private globalTurnIndex = 0;\n /** Captured from `applyAgent` so we don't store the whole `AgentConfig`. */\n private debugSnapshotter?: () => unknown;\n private readonly maxTurnSnapshots: number;\n\n /**\n * Aborted by `dispose()` on driver teardown (e.g. an agent-config swap).\n * Threaded into every provider call as `ChatRequestOptions.signal`, so a\n * disposed driver's in-flight LLM request is cancelled instead of running on\n * to completion or the transport timeout. Also passed to prompt/tool\n * factories via `SystemPromptContext.signal`.\n */\n private readonly lifecycleController = new AbortController();\n\n /**\n * Per-turn abort controller, reset at the start of every turn by `beginTurn`.\n * Aborted by `cancel()` (user stop) and chained to `lifecycleController` so a\n * driver dispose also ends the current turn. Its signal \u2014 not the lifecycle\n * one \u2014 is what reaches the provider call, so a turn can be cancelled without\n * bricking the driver for the next message.\n */\n private turnController = new AbortController();\n /** True when the current turn was stopped via `cancel()` (vs a dispose). Drives the \"Stopped.\" marker. */\n private turnCancelled = false;\n /** Detaches the lifecycle\u2192turn abort link at turn end; set by `beginTurn`. */\n private unlinkLifecycleFromTurn?: () => void;\n\n /**\n * Active agent's provider selector (static name or per-turn resolver).\n * `undefined` means \"use the registry default\".\n */\n private activeProviderInput?: ProviderInput;\n /**\n * Active agent's temperature selector (static number or per-turn resolver),\n * normalized to `0`\u2013`1`. `undefined` means \"use the provider/model default\".\n */\n private activeTemperatureInput?: TemperatureInput;\n /**\n * Active agent's tool-call mode selector (static value or per-turn resolver).\n * `undefined` falls back to the per-turn default (sub-agents force a tool\n * call; top-level turns are `'auto'`).\n */\n private activeToolChoiceInput?: ToolChoiceInput;\n /**\n * Active agent's prompt-cache policy selector (static value or per-turn resolver).\n * `undefined` requests no caching (equivalent to `{ scope: 'default' }`).\n */\n private activeCachePolicyInput?: CachePolicyInput;\n /**\n * Active agent's extended-thinking selector (static value or per-turn resolver). `undefined` \u2014\n * unset, or returned by the resolver \u2014 leaves the model on its own default posture, which is\n * neither uniformly on nor off, so an agent that never sets this is unaffected by the option.\n */\n private activeThinkingPolicyInput?: ThinkingPolicyInput;\n /**\n * Active agent's tail-context selector (static value or per-turn resolver). The driver frames\n * the resolved string in a `<system-reminder>` marker and injects it at the message tail.\n */\n private activeTailContextInput?: TailContextInput;\n /**\n * Active agent's structured-output schema selector (static value or per-turn resolver).\n * When it resolves to a schema, the model's final answer is constrained to it this turn.\n */\n private activeResponseSchemaInput?: ResponseSchemaInput;\n /**\n * Active agent's refusal-fallback chain (static). Passed through to the provider so a refused\n * turn (e.g. Fable 5) is re-run on the next model server-side.\n */\n private activeFallbacks?: ChatFallback[];\n /**\n * Active agent's unresolved-tool hook, captured from `applyAgent`. Consulted\n * only when a tool call cannot be dispatched (a stale or hallucinated name);\n * `undefined` keeps the framework's default messages. See\n * `resolveUnresolvedToolContent`.\n */\n private activeOnUnresolvedTool?: UnresolvedToolInput;\n /**\n * Caches validated provider lookups per name within the current agent. Cleared\n * by `applyAgent` so each new agent's static/function-resolved names are\n * validated fresh.\n */\n private resolvedProviderCache = new Map<string, AIProvider>();\n /** Last successfully resolved provider name \u2014 drives `getActiveProviderName`. */\n private lastResolvedProviderName?: string;\n /** Last dispatched `provider-changed` name; avoids duplicate events on stable turns. */\n private lastDispatchedProviderName?: string;\n /**\n * Concrete model id of the provider resolved for the current turn, read from\n * its `getStatus()` and stamped onto the resulting assistant message so the\n * debug log carries per-message model lineage. Re-resolved each turn in\n * `resolveProviderForTurn`.\n */\n private lastResolvedModel?: string;\n /**\n * Vendor id from the provider's `getStatus()` for the current turn (e.g.\n * `'anthropic'`, `'gemini'`). Stamped onto assistant messages alongside\n * `lastResolvedModel`.\n */\n private lastResolvedProvider?: AIProviderType;\n /**\n * Memoised `name \u2192 getStatus()` lookups, so per-turn resolution doesn't\n * re-await `getStatus()` every turn. Cleared (with `resolvedProviderCache`) on\n * an observable-registry change, so a model swapped behind a stable name is\n * picked up on the next turn.\n */\n private resolvedStatusCache = new Map<string, { model?: string; provider?: AIProviderType }>();\n /**\n * Unsubscribe handle for the provider-registry change listener (only set when\n * the injected registry is observable). Called in `dispose` so the long-lived\n * registry doesn't retain this driver \u2014 see the constructor and the sub-agent\n * teardown in `runSubAgent`.\n */\n private unsubscribeRegistry?: () => void;\n\n /** Hard cap on tool-loop iterations. */\n private readonly maxToolIterations: number;\n /** Model-calls per condensation batch; `1` collapses as soon as a trigger fires. */\n private readonly condenseBatchCalls: number;\n /** Session identity used to file meta events onto the shared debug-log timeline. */\n private readonly sessionKey: string;\n /** Injected activity bus; defaults to a no-op off-browser (Node/tests/headless). */\n private readonly activityBus: ActivityBus;\n /**\n * Host override for the budget-wall transcript copy, used verbatim \u2014 see\n * `ChatDriverConfig.budgetExhaustedMessage`. `undefined` means no override,\n * and the bubble is composed per wall by {@link ChatDriver.budgetExhaustedBubble}.\n */\n private readonly budgetExhaustedMessageOverride?: string;\n\n /**\n * Host override for the provider-refusal sentence, from\n * `ChatDriverConfig.providerRefusedMessage`. `undefined` means no override, so the shipped default\n * is used verbatim.\n */\n private readonly providerRefusedMessageOverride?: string;\n\n /**\n * A provider refusal was observed this turn, so the tool loop must not call the model again\n * (GENC-1506).\n *\n * Exists for the SUB-AGENT path only, exactly like `budgetExhaustedThisTurn`: this driver's own\n * refusal returns straight out of the catch, whereas a child's refusal reaches the parent as a tool\n * result, and without this flag the loop would issue another call into the same wall \u2014 N batched\n * children costing N doomed calls plus a doomed parent one.\n */\n private providerRefusedThisTurn = false;\n\n /** The refusal detail latched off a sub-agent's failure, for the parent's own result. */\n private providerRefusedDetail?: ProviderRefusedDetail;\n /**\n * Set the moment a budget wall is observed anywhere in this turn \u2014 this\n * driver's own 402, or a sub-agent's (which surfaces here only as a\n * `'budget_exhausted'` tool result). Read at the top of the tool loop to end\n * the turn before issuing another model call that would hit the same wall.\n * Reset per turn alongside the other per-turn counters.\n */\n private budgetExhaustedThisTurn = false;\n /**\n * The refusing vendor's own attribution for the wall `budgetExhaustedThisTurn`\n * records, when it was knowable. Kept SEPARATE from the flag rather than\n * replacing it: a figure-less 402 from a transport no vendor claims yields no\n * detail at all (`budgetDetailOf` returns `undefined`), and folding the two\n * would make that case stop ending the turn.\n *\n * It matters most for a sub-agent's wall. The child can sit on a different\n * vendor from its parent \u2014 `applyAgent` reads `config.provider` \u2014 so without\n * this the parent's short-circuit reports `lastResolvedProvider`, i.e. the one\n * vendor that did NOT refuse. Under a mixed registry that walls Gemini because\n * an Anthropic child 402'd, and if those are the only two reachable vendors the\n * host then derives `blocked` and locks a composer that still had headroom.\n */\n private budgetWallDetail?: BudgetDetail;\n /**\n * Whether this turn's budget wall came from a SUB-AGENT rather than this\n * driver's own request. Decides whether `lastResolvedProvider` is a valid\n * attribution fallback: for an own wall it is the refusing vendor, for a\n * child's wall it is the parent's vendor \u2014 the one known NOT to have refused.\n * Reset per turn alongside `budgetWallDetail`.\n */\n private budgetWallViaSubAgent = false;\n\n constructor(\n private readonly providerRegistry: AIProviderRegistry,\n config: ChatDriverConfig = {},\n ) {\n super();\n const {\n toolHandlers = {},\n toolDefinitions = [],\n systemPrompt,\n primerHistory,\n maxToolIterations = DEFAULT_MAX_TOOL_ITERATIONS,\n maxFoldOperations = DEFAULT_MAX_FOLD_OPERATIONS,\n condenseBatchCalls = 1,\n maxTurnSnapshots = DEFAULT_MAX_TURN_SNAPSHOTS,\n sessionKey = '',\n activityBus = NOOP_ACTIVITY_BUS,\n budgetExhaustedMessage,\n providerRefusedMessage,\n } = config;\n this.maxToolIterations = maxToolIterations;\n this.condenseBatchCalls = condenseBatchCalls;\n this.sessionKey = sessionKey;\n this.activityBus = activityBus;\n this.budgetExhaustedMessageOverride = budgetExhaustedMessage;\n this.providerRefusedMessageOverride = providerRefusedMessage;\n if (typeof toolHandlers === 'function') {\n this.toolHandlersFactory = toolHandlers;\n this.toolHandlers = {};\n } else {\n this.toolHandlersFactory = undefined;\n this.toolHandlers = toolHandlers;\n }\n if (typeof toolDefinitions === 'function') {\n this.toolDefinitionsFactory = toolDefinitions;\n this.toolDefinitions = [];\n } else {\n this.toolDefinitionsFactory = undefined;\n this.toolDefinitions = toolDefinitions;\n }\n this.systemPrompt = systemPrompt;\n this.primerHistory = primerHistory;\n this.maxFoldOperations = maxFoldOperations;\n this.maxTurnSnapshots = maxTurnSnapshots;\n // Runtime provider switching: when the host registered an observable\n // registry, drop our memoised provider lookups whenever its mapping/default\n // changes so the next turn re-resolves against the new providers. Resetting\n // `lastDispatchedProviderName` forces the next `resolveProviderForTurn` to\n // re-emit `provider-changed` even when the resolved *name* is unchanged\n // (e.g. a tier name like 'high' kept, but the vendor underneath swapped) \u2014\n // that's what lets status UI refresh on a same-name switch. Feature-detect\n // means immutable/empty registries are a no-op. Child sub-agent drivers get\n // the same registry and so subscribe here too; each cleans up in `dispose`.\n if (isObservableAIProviderRegistry(this.providerRegistry)) {\n this.unsubscribeRegistry = this.providerRegistry.subscribe(() => {\n this.resolvedProviderCache.clear();\n this.resolvedStatusCache.clear();\n this.lastResolvedProviderName = undefined;\n this.lastResolvedModel = undefined;\n this.lastResolvedProvider = undefined;\n this.lastDispatchedProviderName = undefined;\n });\n }\n }\n\n /**\n * Tear down the driver: aborts the lifecycle signal so any in-flight provider\n * request (and prompt/tool factories awaiting it) cancels instead of running\n * on to completion or the transport timeout. Called by the host on driver\n * swap and by `OrchestratingDriver.dispose()`. Idempotent.\n *\n * Deliberately does NOT settle `pendingInteractions` here: dispose is never\n * reached while one is pending. The only host-level dispose is the agent-swap\n * rebuild, which is guarded by `isBusy()` \u2014 a pending interaction keeps the\n * tool loop suspended (`busy === true`), so the swap is deferred until the\n * widget resolves. Sub-agent child disposes always have an empty pending map\n * (widgets park on the parent via `setHostInteractionRequester`). A pending\n * interaction is instead settled by `resolveInteraction` (user response or\n * timeout), which also stamps history and reverts the chat-input override.\n */\n dispose(): void {\n this.lifecycleController.abort(new DOMException('AI assistant driver disposed', 'AbortError'));\n // Drop any live interaction contexts (GENC-1390). Normally empty at teardown\n // (a context is created and destroyed with its pending interaction, and dispose\n // is not reached mid-interaction); disposed defensively so a stray context can\n // never leak an open socket/timer.\n for (const handle of this.interactionContexts.values()) handle.dispose();\n this.interactionContexts.clear();\n // Detach from the provider registry so the long-lived registry doesn't pin\n // this driver (and its closure) after teardown. Guard-cleared so a second\n // dispose is a no-op, matching this method's idempotent contract.\n this.unsubscribeRegistry?.();\n this.unsubscribeRegistry = undefined;\n }\n\n /**\n * Stop the current turn (user \"stop\" button). Aborts the in-flight provider\n * request immediately; if a tool is mid-execution it runs to completion and\n * the loop bails at the next boundary (tools are atomic). No-op when idle.\n * The driver stays usable for the next message.\n */\n cancel(): void {\n if (!this.busy) return;\n this.turnCancelled = true;\n this.turnController.abort(new DOMException('Cancelled by user', 'AbortError'));\n }\n\n /**\n * Start a fresh per-turn abort scope. Chains `lifecycleController` into the\n * new `turnController` so a dispose mid-turn also aborts the request.\n */\n private beginTurn(): void {\n this.turnCancelled = false;\n this.turnController = new AbortController();\n const lifecycle = this.lifecycleController.signal;\n if (lifecycle.aborted) {\n this.turnController.abort(lifecycle.reason);\n this.unlinkLifecycleFromTurn = undefined;\n return;\n }\n const onDispose = () => this.turnController.abort(lifecycle.reason);\n lifecycle.addEventListener('abort', onDispose, { once: true });\n this.unlinkLifecycleFromTurn = () => lifecycle.removeEventListener('abort', onDispose);\n }\n\n /** Detach the lifecycle\u2192turn link so a long-lived lifecycle signal doesn't accumulate listeners. */\n private endTurn(): void {\n this.unlinkLifecycleFromTurn?.();\n this.unlinkLifecycleFromTurn = undefined;\n }\n\n /**\n * Finish a turn whose signal aborted. A user cancel adds a subtle \"Stopped.\"\n * marker; a dispose-driven abort stops quietly (the widget is gone and the\n * cached history would otherwise gain a stray marker on remount).\n */\n private completeAbortedTurn(): ChatDriverResult {\n if (this.turnCancelled) {\n logger.warn('ChatDriver: turn cancelled by user');\n this.appendToHistory({ role: 'system-event', content: 'Stopped.' });\n } else {\n logger.warn('ChatDriver: turn aborted (driver disposed)');\n }\n return { reason: 'done' };\n }\n\n /**\n * Build the `done` loop result, carrying the typed failure reason when the turn\n * bailed (PTC-0). The discriminant stays `'done'` either way \u2014 the same value a\n * clean turn returns \u2014 so consumers matching on `reason === 'done'` are unchanged;\n * `failureReason` is simply present on a failure and absent on success. Omitted\n * (rather than set to `undefined`) so a happy-path result stays byte-identical to\n * the historical `{ reason: 'done' }`.\n */\n private turnDone(\n failureReason?: TurnFailureReason,\n budget?: BudgetDetail,\n providerRefused?: ProviderRefusedDetail,\n ): ChatDriverResult {\n if (!failureReason) return { reason: 'done' };\n // Both payloads are omitted rather than set to `undefined`, so a failure that carries neither has\n // a shape unchanged for a consumer that structurally compares it.\n return {\n reason: 'done',\n failureReason,\n ...(budget ? { budget } : {}),\n ...(providerRefused ? { providerRefused } : {}),\n };\n }\n\n /**\n * Terminal budget outcome for a wall hit **outside** the tool loop \u2014 today,\n * `OrchestratingDriver`'s classification phase, which calls the provider\n * directly and so never enters `runToolLoop`.\n *\n * Does **not** publish `tool-loop-end`: no `tool-loop-start` was published for\n * the classify phase, and an unbalanced end would break start/end pairing for\n * subscribers that rely on it. The driver **return value** is what reports this\n * case \u2014 see `FoundationAiAssistant`'s latch, which reads both seams for\n * exactly this reason.\n *\n * The non-sub-agent tail of the in-loop `BudgetExhaustedError` branch lives\n * here so there is one copy of the log line, the debug-log entry, the\n * transcript bubble and the result shape rather than two that can drift.\n *\n * @param pendingUserMessage - a user message that has NOT yet been appended,\n * appended first so the answer does not end up replying to nothing. Only the\n * classification seam passes it: `OrchestratingDriver` dispatches the user's\n * text as an optimistic `history-updated` detail and leaves the real append\n * to `chatDriver.sendMessage`, which never runs when `classify()` throws \u2014 so\n * the bubble below would re-dispatch a history the user's own message was\n * never in, and it would vanish from the transcript on the next render. The\n * in-loop caller has already appended it and passes nothing.\n *\n * @internal\n */\n private budgetExhaustedBubble(wall?: {\n vendorLabel?: string;\n otherVendorAvailable?: boolean;\n }): string {\n // A host override wins verbatim \u2014 the white-label contract on\n // `ChatDriverConfig.budgetExhaustedMessage` (its copy may not even be\n // English; composing onto it would mangle it).\n if (this.budgetExhaustedMessageOverride != null) return this.budgetExhaustedMessageOverride;\n // Only a POSITIVE `otherVendorAvailable` earns the switch advice. `false`\n // means every other metered vendor is exhausted too, and `undefined` means\n // an older proxy did not say \u2014 in both cases advertising a switch to a\n // vendor that may itself be walled is worse than the neutral default. This\n // mirrors the blocked banner's rule, and closes the gap where the banner\n // said \"switch\" while the transcript bubble directly under it said only\n // \"contact your administrator\" (GENC-1464 tester finding).\n if (wall?.otherVendorAvailable !== true) return DEFAULT_BUDGET_EXHAUSTED_MESSAGE;\n // The label is display copy, nothing more \u2014 attribution (which vendor gets\n // WALLED) stays `budgetDetailOf`'s job. The parameter is the shared shape of\n // both call sites: the thrown `BudgetExhaustedError` on the direct path, and\n // the latched `budgetWallDetail` on the sub-agent path.\n const subject = wall?.vendorLabel\n ? `${wall.vendorLabel}'s AI usage limit`\n : 'your AI usage limit';\n return `You've reached ${subject}. Switch to another AI provider in Settings to keep going, or contact your administrator to raise it.`;\n }\n\n reportBudgetExhausted(\n e: BudgetExhaustedError,\n pendingUserMessage?: ChatMessage,\n ): ChatDriverResult {\n if (pendingUserMessage) this.appendToHistory(pendingUserMessage);\n this.budgetExhaustedThisTurn = true;\n logger.error('ChatDriver: AI budget exhausted', e);\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n // The registry ALIAS (e.g. 'high') is what `provider` records; the vendor\n // is the thing a per-vendor budget is actually scoped to, and it was known\n // at both ends and discarded in the middle until now. Taken from the\n // refusing transport's label first \u2014 this method also serves the\n // classification seam, where `lastResolvedProvider` is the PREVIOUS turn's\n // vendor (or nothing), because classify runs against the registry default.\n vendor:\n vendorTypeOfLabel(e.vendorLabel) ??\n vendorTypeOfLabel(e.serverVendor) ??\n this.lastResolvedProvider,\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n isSubAgent: this.isSubAgent,\n });\n this.appendToHistory({ role: 'assistant', content: this.budgetExhaustedBubble(e) });\n return this.turnDone('budget-exhausted', budgetDetailOf(e));\n }\n\n /**\n * The sentence shown when the upstream provider refuses (GENC-1506).\n *\n * Deliberately far simpler than `budgetExhaustedBubble`: no vendor name, no figures, no\n * switch-provider advice, and no branching on `kind`. The copy is cause-free by design \u2014 a user who\n * can see their own remaining spend must not be told about a limit, and we must not imply the bill\n * has gone unpaid \u2014 so there is nothing here to compose. A host override wins verbatim.\n */\n private providerRefusedBubble(): string {\n return this.providerRefusedMessageOverride ?? DEFAULT_PROVIDER_REFUSED_MESSAGE;\n }\n\n /**\n * Terminal provider-refusal outcome. Mirrors `reportBudgetExhausted` so the two walls behave\n * identically from the caller's side, while keeping their diagnostics distinct.\n *\n * `kind` reaches the debug log and the result but never the transcript: it is what lets an operator\n * tell \"top up the account\" from \"rotate the key\", and with cause-free user copy this is the only\n * place that distinction survives.\n */\n private reportProviderRefused(e: ProviderRefusedError): ChatDriverResult {\n const detail = providerRefusedDetailOf(e);\n this.providerRefusedThisTurn = true;\n this.providerRefusedDetail = detail;\n logger.error('ChatDriver: provider refused the request', e);\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,\n kind: e.kind,\n upstreamStatus: e.upstreamStatus,\n upstreamType: e.upstreamType,\n isSubAgent: this.isSubAgent,\n });\n this.appendToHistory({ role: 'assistant', content: this.providerRefusedBubble() });\n return this.turnDone('provider-refused', undefined, detail);\n }\n\n /** The typed failure reason on a loop result, or `undefined` for a clean turn / handoff. */\n private static failureReasonOf(result: ChatDriverResult): TurnFailureReason | undefined {\n return result.reason === 'done' ? result.failureReason : undefined;\n }\n\n /**\n * Build the `tool-loop-end` event detail for a turn's result. A failure carries a\n * `{ failureReason }` detail; a clean turn emits `undefined` \u2014 the historical shape,\n * kept byte-identical so subscribers see exactly what they always have.\n *\n * A budget failure additionally carries `vendor` \u2014 the concrete vendor\n * (`'anthropic'`/`'gemini'`) the walled turn resolved to, which the driver knows\n * and used to discard. Optional and additive: a subscriber reading only\n * `failureReason` is unaffected, a non-budget failure still emits the historical\n * `{ failureReason }` with no `vendor` key, and the value is a plain string so\n * the detail stays structured-cloneable for the cross-tab hop. It is the field a\n * per-vendor budget model needs and the one that would be awkward to retrofit.\n */\n private loopEndDetail(result: ChatDriverResult):\n | {\n failureReason: TurnFailureReason;\n vendor?: AIProviderType;\n budget?: BudgetDetail;\n }\n | undefined {\n const failureReason = ChatDriver.failureReasonOf(result);\n if (!failureReason) return undefined;\n if (failureReason !== 'budget-exhausted') {\n return { failureReason };\n }\n // The figures ride the event, not just the return value: this publish happens in\n // sendMessage's `finally`, so for an in-loop wall it reaches the host's latch FIRST\n // and the return-value seam is then a no-op (the latch is idempotent). Omitted\n // entirely \u2014 never set to undefined \u2014 when the proxy sent no figures.\n const budget = result.reason === 'done' ? result.budget : undefined;\n // Prefer the refusing transport's own attribution over the driver's\n // last-resolved provider, for the same staleness reason as `budgetDetailOf`.\n //\n // The fallback is legitimate ONLY for this driver's own wall \u2014 its resolved\n // provider IS the refuser then. When the wall came from a SUB-AGENT\n // (`budgetWallViaSubAgent`), the refuser is the child's vendor, and on a\n // mixed registry `lastResolvedProvider` is the one vendor known NOT to have\n // refused; an unattributable child wall degrades to the vendor-agnostic\n // event instead, which the host's latch handles fail-safe.\n const vendor =\n budget?.vendor ?? (this.budgetWallViaSubAgent ? undefined : this.lastResolvedProvider);\n return {\n failureReason,\n ...(vendor ? { vendor } : {}),\n ...(budget ? { budget } : {}),\n };\n }\n\n /**\n * Swap in a new agent's configuration. Called by OrchestratingDriver before\n * each specialist turn so the shared driver runs with the right tools and prompt.\n */\n applyAgent(config: AgentConfig): void {\n // A real swap to a different agent begins a NEW activation \u2014 the prior agent's\n // flow is over, so its `agentEnd`-tagged payloads become collapsible. Guarded\n // on a name change so re-applying the same agent (e.g. a per-turn re-resolve)\n // does not spuriously advance the clock and prematurely drop its payloads.\n if (config.name !== this.activeAgentName) this.currentActivation += 1;\n this.systemPrompt = config.systemPrompt;\n if (typeof config.toolDefinitions === 'function') {\n this.toolDefinitionsFactory = config.toolDefinitions;\n // Cleared each turn by the factory in runToolLoop; empty is safe in the\n // meantime (no LLM call happens before resolution).\n this.toolDefinitions = [];\n } else {\n this.toolDefinitionsFactory = undefined;\n this.toolDefinitions = config.toolDefinitions ?? [];\n }\n if (typeof config.toolHandlers === 'function') {\n this.toolHandlersFactory = config.toolHandlers;\n // Cleared each turn by the factory in runToolLoop; empty is safe in the\n // meantime (no LLM call happens before resolution).\n this.toolHandlers = {};\n } else {\n this.toolHandlersFactory = undefined;\n this.toolHandlers = config.toolHandlers ?? {};\n }\n this.primerHistory = config.primerHistory;\n this.activeAgentName = config.name;\n this.displayName = config.displayName;\n // Static string form resolves to a stable label up-front; the function\n // form gets re-resolved each tool-loop iteration. Falls back to the\n // canonical name when displayName is unset.\n this.activeAgentLabel =\n typeof config.displayName === 'string' ? config.displayName : config.name;\n this.debugSnapshotter = config.getDebugSnapshot;\n this.subAgentsMap = new Map((config.subAgents ?? []).map((s) => [s.name, s]));\n this.activeProviderInput = config.provider;\n this.activeTemperatureInput = config.temperature;\n this.activeToolChoiceInput = config.toolChoice;\n this.activeCachePolicyInput = config.cachePolicy;\n this.activeThinkingPolicyInput = config.thinkingPolicy;\n this.activeTailContextInput = config.tailContext;\n this.activeResponseSchemaInput = config.responseSchema;\n this.activeFallbacks = config.fallbacks;\n this.activeOnUnresolvedTool = config.onUnresolvedTool;\n this.resolvedProviderCache.clear();\n this.lastResolvedProviderName = undefined;\n // Static validation: resolve the name now so unknown-provider and missing-\n // capability errors fire at agent swap rather than on the first LLM call.\n // Function-form `provider` is validated lazily inside `resolveProviderForTurn`.\n if (typeof config.provider === 'string') {\n this.resolveProviderByName(config.provider, config.name);\n }\n // Reset fold state when agent changes \u2014 each specialist starts fresh\n this.foldStack = [];\n this.consecutiveFoldOps = 0;\n // Forget the previous agent's tools \u2014 \"previously available\" is scoped to\n // the current activation, so a stateful agent accumulates its tools across\n // states while a swap to a different specialist starts clean.\n this.everSeenToolNames.clear();\n }\n\n /**\n * Resolve the tool-result content for an unresolved tool call. Consults the\n * active agent's `onUnresolvedTool` hook (if any) with the attempted tool\n * name, the failure `kind`, and the currently dispatchable tools, and returns\n * the hook's non-empty string. Falls back to `fallback` when no hook is set,\n * the hook returns nothing/empty, or the hook throws \u2014 so a misbehaving hook\n * can never break tool dispatch.\n */\n private async resolveUnresolvedToolContent(\n toolName: string,\n kind: 'stale' | 'unknown',\n fallback: string,\n ): Promise<string> {\n if (typeof this.activeOnUnresolvedTool !== 'function') {\n return fallback;\n }\n try {\n const custom = await this.activeOnUnresolvedTool({\n toolName,\n kind,\n availableTools: Object.keys(this.toolHandlers),\n });\n return typeof custom === 'string' && custom.trim().length > 0 ? custom : fallback;\n } catch (e) {\n logger.warn(\n `ChatDriver: onUnresolvedTool threw for \"${toolName}\" \u2014 using default message`,\n e,\n );\n return fallback;\n }\n }\n\n /**\n * Returns the most recently resolved provider name. Falls back to the\n * registry's default when no per-turn resolution has happened yet.\n */\n getActiveProviderName(): string {\n return this.lastResolvedProviderName ?? this.providerRegistry.defaultName();\n }\n\n /**\n * Resolve a named provider against the registry. Cached per-agent so\n * repeated lookups during one agent's lifetime don't re-validate.\n * Validation lives in `resolveChatProvider`; this wrapper just adds the\n * cache.\n */\n private resolveProviderByName(name: string, agentName: string): AIProvider {\n const cached = this.resolvedProviderCache.get(name);\n if (cached) return cached;\n const provider = resolveChatProvider(this.providerRegistry, name, agentName);\n this.resolvedProviderCache.set(name, provider);\n return provider;\n }\n\n /**\n * Resolve the provider to use for the current turn. Walks the agent's\n * `provider` selector (static or function form) or falls back to the\n * registry default. Dispatches `provider-changed` when the resolved name\n * differs from the last dispatched value.\n */\n private async resolveProviderForTurn(ctx: SystemPromptContext): Promise<AIProvider> {\n let provider: AIProvider;\n let resolvedName: string;\n if (this.activeProviderInput === undefined) {\n provider = this.providerRegistry.default();\n resolvedName = this.providerRegistry.defaultName();\n } else {\n const name =\n typeof this.activeProviderInput === 'function'\n ? await this.activeProviderInput(ctx)\n : this.activeProviderInput;\n provider = this.resolveProviderByName(name, this.activeAgentName ?? '<unknown>');\n resolvedName = name;\n }\n this.lastResolvedProviderName = resolvedName;\n const status = await this.resolveStatusForProvider(resolvedName, provider);\n this.lastResolvedModel = status.model;\n this.lastResolvedProvider = status.provider;\n if (resolvedName !== this.lastDispatchedProviderName) {\n this.lastDispatchedProviderName = resolvedName;\n recordMetaEvent(this.sessionKey, 'provider.selected', {\n // `provider` is the registry SLOT (a tier name like 'high'), kept under that key\n // for compatibility; `model` and `vendor` are what it resolved to. Recording all\n // three is the difference between \"the agent switched to its high tier\" and\n // knowing which model that actually was \u2014 a tier can be repointed mid-session,\n // and a slot name alone cannot distinguish anthropic from gemini.\n provider: resolvedName,\n model: status.model,\n vendor: status.provider,\n agent: this.activeAgentName,\n });\n this.dispatchEvent(\n new CustomEvent<{ name: string }>('provider-changed', { detail: { name: resolvedName } }),\n );\n }\n return provider;\n }\n\n /**\n * Resolve model id and vendor from a provider via its optional `getStatus()`,\n * memoised by registry name. Used to stamp `model` and `provider` onto outgoing\n * messages. Best-effort: a provider without `getStatus`, a null status, or a\n * throw all yield empty fields \u2014 attribution is diagnostic, never load-bearing.\n */\n private async resolveStatusForProvider(\n name: string,\n provider: AIProvider,\n ): Promise<{ model?: string; provider?: AIProviderType }> {\n if (this.resolvedStatusCache.has(name)) return this.resolvedStatusCache.get(name)!;\n let status: { model?: string; provider?: AIProviderType } = {};\n try {\n const resolved = await provider.getStatus?.();\n if (resolved) {\n status = { model: resolved.model, provider: resolved.provider };\n }\n } catch {\n status = {};\n }\n this.resolvedStatusCache.set(name, status);\n return status;\n }\n\n /**\n * Resolve a per-turn config input that is either a static value or a function\n * of the turn context \u2014 the value-or-resolver shape shared by `provider`,\n * `temperature`, and `toolChoice`. Returns undefined when the input is unset.\n */\n private async resolveTurnInput<T>(\n input: T | ((ctx: SystemPromptContext) => T | Promise<T>) | undefined,\n ctx: SystemPromptContext,\n ): Promise<T | undefined> {\n if (input === undefined) return undefined;\n return typeof input === 'function'\n ? (input as (ctx: SystemPromptContext) => T | Promise<T>)(ctx)\n : input;\n }\n\n /**\n * Returns the early-stop result set by `completeSubAgent`, if any.\n * Called by a parent `ChatDriver` after running this instance as a sub-agent.\n */\n getSubAgentCompletion(): { result: unknown } | undefined {\n return this.subAgentCompletion;\n }\n\n /**\n * Mark this driver as running as a sub-agent. Called by a parent driver's\n * `invokeSubAgent` immediately after construction, before the first turn.\n * Enables forced tool use and typed failure reporting (see `isSubAgent`).\n */\n markAsSubAgent(): void {\n this.isSubAgent = true;\n }\n\n /**\n * Returns the typed failure recorded when a sub-agent run ended without\n * `completeSubAgent`, if any. Called by a parent `ChatDriver` after running\n * this instance as a sub-agent.\n */\n getSubAgentFailure():\n | {\n reason: SubAgentFailureReason;\n budget?: BudgetDetail;\n providerRefused?: ProviderRefusedDetail;\n }\n | undefined {\n return this.subAgentFailure;\n }\n\n /**\n * Record a sub-agent failure reason (first one wins). No-op for top-level\n * agents, so loop-exit sites can call it unconditionally. The parent reads\n * this via `getSubAgentFailure()` and emits the `subagent.failed` meta event\n * under its *own* session \u2014 see `invokeSubAgent`. (A child sub-agent runs\n * under a separate session key, so recording here would orphan the event off\n * the user-visible debug-log timeline.)\n */\n private failSubAgent(\n reason: SubAgentFailureReason,\n budget?: BudgetDetail,\n providerRefused?: ProviderRefusedDetail,\n ): void {\n if (!this.isSubAgent || this.subAgentFailure) return;\n // Each payload is omitted rather than set to `undefined` so a failure carrying neither has a shape\n // unchanged for a structural comparison, matching `turnDone`.\n this.subAgentFailure = {\n reason,\n ...(budget ? { budget } : {}),\n ...(providerRefused ? { providerRefused } : {}),\n };\n }\n\n /**\n * Returns true if `releaseAgent` was called during the most recent turn.\n * Consumed by the orchestrator to trigger the auto-pin release path.\n */\n getAgentReleaseRequested(): boolean {\n return this.agentReleaseRequested;\n }\n\n /**\n * Return the per-turn snapshots captured so far. Used by the host's debug\n * log exporter to show what the LLM saw on each turn \u2014 system prompt, tool\n * surface, and agent-supplied state (e.g. a machine snapshot).\n *\n * Ring-buffered at `MAX_TURN_SNAPSHOTS`; older entries are dropped.\n */\n getTurnSnapshots(): ReadonlyArray<TurnSnapshot> {\n return this.turnSnapshots;\n }\n\n /**\n * The `turn` + `message` diagnostic-log entries harvested from resolved interactions'\n * `InteractionResult.diagnostics` (e.g. a server-side ChatDriver's collated debug log). The host\n * concatenates these into its own debug log so `downloadDebugLog`/the persisted diagnostics stream\n * include external-engine logs; `event` entries are excluded here because they're merged into the\n * session's meta-event registry instead (see `resolveInteraction`) and reach the log via\n * `getMetaEvents`. Opaque, chronologically sorted by the host at assemble time. (GENC-1461.)\n */\n getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry> {\n return this.externalDiagnostics;\n }\n\n /**\n * Merge a sub-agent's turn snapshots into this driver's buffer so they surface\n * as `kind:'turn'` entries in the exported debug log. The child runs as a\n * separate, discarded driver, so its snapshots would otherwise be lost. Each is\n * re-labelled under the parent turn that activated the sub-agent: the child's\n * own (numeric) turns become `\"<parentTurn>-1\"`, `\"-2\"`, \u2026 (1-based, in order);\n * any already-forwarded grand-child labels (strings) have their leading segment\n * remapped the same way, so nesting composes (`\"5-2\"` \u2192 `\"5-2-1\"`).\n *\n * Note: two sub-agents invoked in the *same* parent turn share the prefix, so\n * their labels can repeat \u2014 `agentName` on each snapshot disambiguates them.\n */\n private forwardSubAgentSnapshots(childSnapshots: ReadonlyArray<TurnSnapshot>): void {\n if (childSnapshots.length === 0) return;\n // The activating parent turn = the most recent snapshot this driver recorded\n // before entering the tool handler that invoked the sub-agent.\n const parentTurn = Math.max(0, this.globalTurnIndex - 1);\n const ownTurnLabel = new Map<string, string>();\n let ownPos = 0;\n for (const snap of childSnapshots) {\n let turnIndex: string;\n if (!snap.turnIndex.includes('-')) {\n // The child's own turn (a bare counter) \u2192 number it under the parent turn.\n ownPos += 1;\n turnIndex = `${parentTurn}-${ownPos}`;\n ownTurnLabel.set(snap.turnIndex, turnIndex);\n } else {\n // An already-forwarded grand-child label \u2014 remap its leading segment.\n const [lead, ...rest] = snap.turnIndex.split('-');\n const leadLabel = ownTurnLabel.get(lead) ?? `${parentTurn}-${lead}`;\n turnIndex = [leadLabel, ...rest].join('-');\n }\n this.turnSnapshots.push({ ...snap, turnIndex });\n }\n while (this.turnSnapshots.length > this.maxTurnSnapshots) {\n this.turnSnapshots.shift();\n }\n }\n\n /**\n * Push one snapshot to the ring buffer. Called inside `runToolLoop` just\n * before each LLM call \u2014 that's the latest point where the prompt, tool\n * surface, and agent state line up with what the model is about to see.\n *\n * Returns the pushed object so the caller can back-fill what only the response\n * knows (`usage`). Mutating it after the fact is safe whether or not the ring\n * buffer has since evicted it \u2014 an evicted snapshot is simply no longer exported.\n */\n private recordTurnSnapshot(\n resolvedSystemPrompt: string | undefined,\n temperature: number | undefined,\n toolChoice: ChatToolChoice | undefined,\n tailContext: string | undefined,\n ): TurnSnapshot {\n let agentSnapshot: unknown;\n if (this.debugSnapshotter) {\n try {\n agentSnapshot = this.debugSnapshotter();\n } catch (e) {\n // A snapshotter throwing must not derail the LLM call \u2014 capture the\n // error string in place of the snapshot so the export still shows\n // *something* happened.\n agentSnapshot = `<getDebugSnapshot threw: ${e instanceof Error ? e.message : String(e)}>`;\n }\n }\n const turnIndex = String(this.globalTurnIndex);\n this.globalTurnIndex += 1;\n const snapshot: TurnSnapshot = {\n turnIndex,\n timestamp: new Date().toISOString(),\n agentName: this.activeAgentName,\n agentLabel: this.activeAgentLabel,\n systemPrompt: resolvedSystemPrompt,\n tailContext,\n toolNames: this.toolDefinitions.map((t) => t.name),\n temperature,\n toolChoice,\n agentSnapshot,\n };\n this.turnSnapshots.push(snapshot);\n if (this.turnSnapshots.length > this.maxTurnSnapshots) {\n this.turnSnapshots.shift();\n }\n return snapshot;\n }\n\n /**\n * Optional transform applied to conversation history immediately before each LLM request.\n * Cleared when `undefined`. Does not alter stored history.\n */\n setProviderHistoryTransform(transform?: (history: ChatMessage[]) => ChatMessage[]): void {\n this.providerHistoryTransform = transform;\n }\n\n getHistory(): ReadonlyArray<ChatMessage> {\n return this.history;\n }\n\n getRawHistory(): readonly ChatMessage[] {\n return this.history;\n }\n\n /** Returns the current fold stack names for debugging. */\n getActiveFoldNames(): string[] {\n return this.foldStack.map((f) => f.foldName);\n }\n\n async getSuggestions(\n history: ChatMessage[],\n prompt: string,\n count: number,\n allAgentInfo?: AllAgentSummary[],\n ): Promise<string[]> {\n // Suggestions are an out-of-turn UI helper, not bound to any single agent \u2014\n // always run against the registry default. Best-effort: a default with no\n // `prompt()` just means no suggestions, not a hard error.\n const defaultProvider = this.providerRegistry.default();\n if (!defaultProvider.prompt) {\n logger.warn('ChatDriver: default AI provider does not implement prompt()');\n return [];\n }\n\n let agentContext = '';\n let toolContext = '';\n\n if (allAgentInfo?.length) {\n const agentDescriptions = allAgentInfo\n .map((agent) => {\n const tools = agent.tools.map((t) => t.name).join(', ');\n return `- ${agent.name} (${agent.description}): ${tools ? `(Tools: ${tools})` : 'No tools'}`;\n })\n .join('\\n');\n agentContext = `The assistant has the following capabilities:\\n${agentDescriptions}`;\n\n const allToolNames = allAgentInfo\n .flatMap((agent) => agent.tools.map((t) => t.name))\n .filter((value, index, self) => self.indexOf(value) === index)\n .join(', ');\n toolContext = allToolNames\n ? `You have access to the following tools across all agents: ${allToolNames}.`\n : '';\n } else if (this.activeAgentName) {\n const toolNames = this.toolDefinitions.map((tool) => tool.name).join(', ');\n agentContext = `You are currently acting as the \"${this.activeAgentName}\" agent.`;\n toolContext = toolNames ? `You have access to the following tools: ${toolNames}.` : '';\n }\n\n // System prompt is intentionally short: it sets the role only. Concrete\n // instructions live in the user message *after* the transcript so the\n // immediately-preceding context for the model is \"here is data, now do X\"\n // rather than \"here is a dialogue, continue it\". This matters for Anthropic\n // \u2014 without it, Claude reads the transcript as an in-progress conversation\n // and produces a normal assistant turn instead of a list of suggestions.\n const systemPrompt =\n 'You generate suggested prompts that a user could send to an AI assistant. ' +\n 'You never continue the conversation or roleplay as the assistant.';\n\n const capabilitiesBlock =\n agentContext || toolContext\n ? `\\n\\n<capabilities>\\n${[agentContext, toolContext].filter(Boolean).join('\\n')}\\n</capabilities>\\nSuggestions must only cover what the agent is capable of. Do not suggest anything outside these capabilities.`\n : '';\n\n const guidanceBlock = prompt ? `\\n\\nAdditional guidance: \"${prompt}\"` : '';\n\n let userMessage: string;\n if (history.length === 0) {\n userMessage =\n `Generate exactly ${count} brief starter prompts to show a user what an AI assistant can do. ` +\n `Phrase each one as the user would write it. Keep them short and generic \u2014 do not invent specific names, IDs, or data (e.g. prefer \"Search for a trade\" over \"Find all trades with Client A\").` +\n capabilitiesBlock +\n guidanceBlock +\n `\\n\\nOutput format (strict):\\n` +\n `- Exactly ${count} lines.\\n` +\n `- One suggestion per line.\\n` +\n `- No numbering, bullets, markdown, emojis, code blocks, or quotes around the suggestion.\\n` +\n `- No preamble, headings, summary, or commentary before or after the list.`;\n } else {\n const conversationContext = history\n .filter(\n (m) =>\n (m.role === 'user' || m.role === 'assistant') &&\n !m.toolCalls?.length &&\n !m.thinking &&\n !!m.content?.trim(),\n )\n .slice(-SUGGESTIONS_HISTORY_WINDOW)\n .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)\n .join('\\n');\n\n userMessage =\n `<conversation_history>\\n${conversationContext}\\n</conversation_history>\\n\\n` +\n `The conversation above has ended. Do not continue it or respond as the assistant. ` +\n `Generate exactly ${count} follow-up prompts the *user* might send next, phrased in first person as the user would write them. ` +\n `The first ${Math.max(0, count - 1)} should be natural follow-ups to the last turn. ` +\n `Do not invent specific names, IDs, or data values that do not appear in <conversation_history>.` +\n capabilitiesBlock +\n guidanceBlock +\n `\\n\\nOutput format (strict):\\n` +\n `- Exactly ${count} lines.\\n` +\n `- One suggestion per line.\\n` +\n `- No numbering, bullets, markdown, emojis, code blocks, or quotes around the suggestion.\\n` +\n `- No preamble, headings, summary, or commentary before or after the list.`;\n }\n\n const text = await defaultProvider.prompt!(userMessage, { systemPrompt });\n\n // Lenient parsing as a defensive backstop: even with the strict prompt,\n // models occasionally slip in numbering, bullets, or surrounding markdown.\n return (\n text\n .split('\\n')\n .map((s) => s.trim())\n // strip leading bullets/numbers (\"- \", \"* \", \"\u2022 \", \"1. \", \"1) \")\n .map((s) => s.replace(/^([-*\u2022]|\\d+[.)])\\s+/, ''))\n // strip surrounding bold/italic markers\n .map((s) => s.replace(/^[*_]{1,3}|[*_]{1,3}$/g, '').trim())\n // drop empty lines, separators, and obvious preamble lines\n .filter((s) => s.length > 0)\n .filter((s) => !/^[-=]{2,}$/.test(s))\n .filter((s) => !/^here (are|is) /i.test(s))\n .filter((s) => !s.endsWith(':'))\n .slice(0, count)\n );\n }\n\n /**\n * Whether `compact()` would do anything right now \u2014 a summarizable run of older\n * turns exists behind a clean boundary. Uses the same `history` `compact()`\n * acts on, so the UI's gate can't disagree with the action (GENC-1351 follow-up).\n */\n canCompact(): boolean {\n return findCompactionCut(this.history) != null;\n }\n\n /**\n * Destructively compact older turns into a single `compacted-summary` message\n * (GENC-1351 \u00A75.7). Summarizes everything before a clean recent-tail boundary\n * via the registry-default provider's one-shot `prompt()`, then **atomically**\n * replaces the covered turns with one summary message at the head \u2014 history is\n * mutated only on success. Rolling: any existing head summary is folded into\n * the new one. Returns the created summary message, or `null` when there is\n * nothing worth compacting or the default provider cannot summarize.\n */\n async compact(): Promise<ChatMessage | null> {\n if (this.busy) return null;\n const defaultProvider = this.providerRegistry.default();\n if (!defaultProvider.prompt) {\n logger.warn('ChatDriver: default AI provider has no prompt(); cannot compact');\n return null;\n }\n\n const history = this.history;\n const cut = findCompactionCut(history);\n if (cut == null) return null;\n\n const toCompact = history.slice(0, cut);\n const tail = history.slice(cut);\n\n // Summarize BEFORE mutating history \u2014 a failed/empty call leaves the\n // transcript untouched (atomic generate-then-replace).\n const { systemPrompt, userMessage } = buildCompactionSummaryPrompt(toCompact);\n // Surface a failure the way turn errors are surfaced \u2014 a brief \"sorry\" agent\n // message \u2014 while leaving the transcript itself untouched (atomic). Retrying\n // is safe (nothing was spliced).\n const failMessage =\n \"Sorry, I couldn't compact the conversation just now. Nothing was changed \u2014 please try again.\";\n let summaryText: string;\n try {\n summaryText = (await defaultProvider.prompt!(userMessage, { systemPrompt }))?.trim() ?? '';\n } catch (e) {\n logger.warn(`ChatDriver: compaction summary failed: ${e instanceof Error ? e.message : e}`);\n this.appendToHistory({ role: 'assistant', content: failMessage });\n return null;\n }\n if (!summaryText) {\n logger.warn('ChatDriver: compaction summary was empty; leaving history untouched');\n this.appendToHistory({ role: 'assistant', content: failMessage });\n return null;\n }\n\n let tokensBefore: number | undefined;\n for (let i = history.length - 1; i >= 0; i -= 1) {\n if (history[i].inputTokens != null) {\n tokensBefore = history[i].inputTokens;\n break;\n }\n }\n const status = await defaultProvider.getStatus?.();\n const createdAt = new Date().toISOString();\n const summaryMessage: ChatMessage = {\n role: 'compacted-summary',\n content: summaryText,\n // Stamp with the covered region's start, not \"now\": the summary stands in\n // for the oldest messages and sits at the head of history, so this keeps it\n // sorted to the head in any timestamp-ordered view (the debug timeline) and\n // history time-monotonic. Its true creation time is in compaction.createdAt.\n timestamp: toCompact[0]?.timestamp ?? createdAt,\n compaction: {\n compactedCount: toCompact.length,\n coveredThroughTimestamp: toCompact[toCompact.length - 1]?.timestamp,\n tokensBefore,\n model: status?.model,\n createdAt,\n // Bank what the replaced turns spent. `toCompact` is dropped from history\n // below, taking its per-message cost/token fields with it \u2014 so a host total\n // re-derived from the transcript would otherwise fall by exactly this much\n // on every compaction. Summarising a turn does not refund what it cost.\n rolledUpUsage: sumUsage(toCompact),\n },\n };\n\n this.loadHistory([summaryMessage, ...tail]);\n return summaryMessage;\n }\n\n isBusy(): boolean {\n return this.busy;\n }\n\n /**\n * Wire a parent driver as the host for this driver's interactions. When set,\n * `requestInteraction` delegates upward so the widget renders in (and\n * resolves through) the parent's history and pending map. Calls chain\n * naturally: a grandchild \u2192 child \u2192 root.\n */\n public setHostInteractionRequester(\n fn: <T>(componentName: string, data: any, options?: InteractionRequestOptions) => Promise<T>,\n ): void {\n this.hostInteractionRequester = fn;\n }\n\n /**\n * Request a custom UI interaction. Emits a new message with the interaction.\n * Tool handlers can call this to pause execution until the user completes the UI interaction.\n *\n * If a host requester is wired (sub-agent case), the call delegates upward\n * so the interaction lives on the parent \u2014 the main UI is only listening to\n * the root driver. Only one interaction may be in flight at any time on a\n * given root: concurrent calls (e.g. two parallel sub-agents both spawning a\n * widget) throw. Parallel sub-agents are for parallel work, not for user\n * interaction, which is inherently sequential.\n *\n * @param componentName - The custom element name to render.\n * @param data - Data to pass to the component.\n * @param options - Optional per-call overrides, including\n * `chatInputDuringExecution` to hide or disable the main chat input while\n * the widget is awaiting user input (reverts when the interaction resolves),\n * and `presentation` to control whether the host wraps the widget in a chat\n * bubble and/or shows the \"Assistant\" label.\n */\n public async requestInteraction<T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ): Promise<T> {\n if (this.hostInteractionRequester) {\n return this.hostInteractionRequester<T>(componentName, data, options);\n }\n if (this.pendingInteractions.size > 0) {\n throw new Error(\n 'requestInteraction: another user interaction is already in flight. ' +\n 'Only one interaction may be active at a time \u2014 sequence them in a single tool handler ' +\n 'rather than spawning widgets from parallel sub-agents or parallel tool calls.',\n );\n }\n const interactionId = crypto.randomUUID();\n const chatInputDuringExecution = options?.chatInputDuringExecution;\n const timeoutMs = options?.timeoutMs;\n const presentation = options?.presentation;\n return new Promise((resolve, reject) => {\n this.pendingInteractions.set(interactionId, {\n resolve,\n reject,\n overrideId: chatInputDuringExecution ? interactionId : undefined,\n // Resolve the interaction with a timeout result if the user does not\n // respond in time. `resolveInteraction` runs the same teardown a normal\n // resolution does (marks the widget read-only, reverts any input\n // override) and clears any still-pending handle.\n timeoutHandle:\n timeoutMs != null\n ? setTimeout(() => {\n this.resolveInteraction(interactionId, {\n status: 'timeout',\n message: `Interaction timed out after ${timeoutMs}ms.`,\n } satisfies InteractionResult);\n }, timeoutMs)\n : undefined,\n });\n recordMetaEvent(this.sessionKey, 'interaction.requested', {\n interactionId,\n component: componentName,\n agent: this.activeAgentName,\n });\n // Signal the park boundary on the activity bus so turn-aware UI can tell\n // \"actively computing\" from \"parked awaiting the user\" \u2014 the latter is a\n // safe window for actions disallowed mid-request (e.g. switching provider\n // during a long journey step). Paired with `interaction-resolved`.\n this.activityBus.publish('interaction-requested', undefined);\n if (chatInputDuringExecution) {\n this.dispatchEvent(\n new CustomEvent('interaction-start', {\n detail: { interactionId, chatInputDuringExecution },\n }),\n );\n }\n // Create the live context (GENC-1390) BEFORE the widget can mount, so the\n // wrapper finds it when it builds the pending `interaction` descriptor.\n this.interactionContexts.set(interactionId, createInteractionContext(interactionId));\n this.appendToHistory({\n role: 'assistant',\n content: '',\n interaction: {\n interactionId,\n componentName,\n data,\n ...(presentation ? { presentation } : {}),\n },\n });\n });\n }\n\n /**\n * Add external (non-LLM) spend to an interaction's message AFTER it has resolved.\n *\n * **Why this exists separately from `resolveInteraction`.** A widget's spend reaches the session\n * total only through `InteractionResult.costUsd`, which is read exactly once \u2014 `resolveInteraction`\n * does its whole job inside `if (interaction)` and then deletes the entry from\n * `pendingInteractions`. That is correct for the resolution itself, but it assumes a widget stops\n * costing money when it resolves, and several deliberately do not: a widget that resolves EARLY so\n * the assistant stops waiting (options shown, a preview rendered) may stay interactive for minutes\n * afterwards and do more paid work on the user's behalf. Re-emitting `interaction-completed` does\n * not help \u2014 with the interaction gone from the map the call is a silent no-op \u2014 so that spend had\n * nowhere to go and was simply missing from the figure shown to the user.\n *\n * Additive by design: the caller reports a DELTA, not a running total, so repeated calls sum. It\n * touches only `externalCostUsd`; the recorded `interaction.resolved` payload is left exactly as\n * the resolution wrote it, because this is not a second resolution and must not read like one.\n *\n * Deliberately does NOT require the interaction to be pending, does not resurrect it, and has no\n * loading/turn side effects \u2014 this is bookkeeping about a turn that already happened.\n *\n * @param interactionId the interaction whose message owns the spend.\n * @param costUsd a positive delta in USD. Non-finite, zero and negative values are ignored.\n * @returns `true` when the spend was recorded; `false` when it was not \u2014 either the value was\n * not a positive finite amount, or the message is no longer in history (trimmed or condensed\n * away). A real outcome a caller may want to log rather than a failure to throw on; every\n * `false` also records an `interaction.external-cost-dropped` meta event here, so money can\n * never disappear without a trace.\n * @beta\n */\n public recordExternalCost(interactionId: string, costUsd: number): boolean {\n const drop = (reason: string): false => {\n recordMetaEvent(this.sessionKey, 'interaction.external-cost-dropped', {\n interactionId,\n costUsd,\n reason,\n });\n return false;\n };\n if (!interactionId) return drop('no interactionId');\n if (typeof costUsd !== 'number' || !Number.isFinite(costUsd) || costUsd <= 0) {\n return drop('not a positive finite amount');\n }\n const idx = this.history.findIndex((m) => m.interaction?.interactionId === interactionId);\n // The message is gone (trimmed or condensed): the spend is real and already billed, so it is\n // recorded as dropped rather than silently discarded \u2014 an invisible gap in the session total\n // is exactly what this whole channel exists to close.\n if (idx === -1) return drop('interaction message no longer in history');\n this.history[idx] = {\n ...this.history[idx],\n externalCostUsd: (this.history[idx].externalCostUsd ?? 0) + costUsd,\n };\n recordMetaEvent(this.sessionKey, 'interaction.external-cost', { interactionId, costUsd });\n // A NARROW event, deliberately not `history-updated`.\n //\n // The host answers `history-updated` by reassigning `messages`, which re-evaluates\n // `activeInteractionRow` \u2014 and the trailing interaction slot renders through a\n // `repeat(..., { recycle: false })`, so every view in it is disposed and rebuilt regardless of\n // item identity. That is correct for a PENDING interaction (GENC-1429: a recycled wrapper\n // carries the previous interaction's truthy `resolved` and swallows the next completion), and\n // survivable because `buildInteraction` hands a remounted pending widget the same driver-owned\n // `interactionContext`.\n //\n // A RESOLVED one has no such context \u2014 `resolveInteraction` disposed and deleted it \u2014 so\n // announcing this on `history-updated` would tear down and blank the very widget that just\n // reported, in exactly the flow this channel exists for (a user tweaking an option after the\n // interaction resolved). Bookkeeping about a finished turn must stay invisible, so the host\n // recomputes its totals from this driver's history and saves, without touching what is\n // rendered. Reviewer catch on #2474 \u2014 confirmed against the layout widget, whose tweak result\n // went off screen because the rebuild raced the session write that would have restored it.\n this.dispatchEvent(\n new CustomEvent<{ interactionId: string; costUsd: number }>('external-cost-recorded', {\n detail: { interactionId, costUsd },\n }),\n );\n return true;\n }\n\n /**\n * Resolve a pending interaction. The wrapper component calls this on completion.\n * Marks the interaction message as resolved so it renders read-only on re-render.\n */\n public resolveInteraction(interactionId: string, result: any): void {\n const interaction = this.pendingInteractions.get(interactionId);\n if (interaction) {\n // Clear the timeout so a user resolution doesn't later fire a stale\n // timeout (and a timeout firing here clears its own already-fired handle).\n if (interaction.timeoutHandle) clearTimeout(interaction.timeoutHandle);\n // Harvest any out-of-band diagnostic entries the widget collated (e.g. from a server-side\n // ChatDriver) so the host's debug log + persisted diagnostics include them. Independent of the\n // message `idx` below \u2014 they describe the widget's own work, not this message.\n //\n // The harvested entries carry the SOURCE engine's own index space (0-based turns/events), which\n // would collide with this host's cursors in the forward-capture persister \u2014 turns dedup by\n // `turnIndex`, events by an `index` high-water mark \u2014 so foreign entries get silently dropped\n // from the persisted stream. Route each kind through the host's own collision-safe machinery,\n // mirroring how a sub-agent's log is folded in (see `invokeSubAgent`):\n // \u2022 `event` \u2192 `mergeMetaEvents`, which re-indexes them onto this session's monotonic event\n // counter (clearing the high-water) while preserving their timestamps; they then\n // reach the log via `getMetaEvents` in `buildTimelineEntries`, not this buffer.\n // \u2022 `turn` \u2192 re-key `turnIndex` to the turn's local position within a per-batch namespace,\n // so turns stay unique even when one interaction folds in several independent\n // server runs that each number their own turns from 0 (a consolidator carries a\n // consolidator-code run AND a table-code run), and never collide with the host's\n // own bare-integer turn keys.\n // \u2022 `message` \u2192 kept as-is; the persister already keys messages by content, so they survive.\n // TODO(GENC-1461, option 2 / streaming): expose an imperative `appendDiagnostics(entries)` on\n // the handler context (see buildHandlerContext) that runs this same decomposition as SSE ticks\n // arrive, so a streaming widget can surface its external engine's log live rather than only at\n // resolve time. Batch-at-resolve (here) is the current, non-streaming path.\n const harvestedDiagnostics = (result as { diagnostics?: readonly unknown[] } | undefined)\n ?.diagnostics;\n if (Array.isArray(harvestedDiagnostics) && harvestedDiagnostics.length) {\n const batch = (this.externalDiagnosticsBatches += 1);\n const externalEvents: MetaEvent[] = [];\n let turnCount = 0;\n let messageCount = 0;\n for (const raw of harvestedDiagnostics) {\n // The harvest is external and typed `unknown[]`, so an element could be a primitive, null,\n // or an object without a string `kind`. Guard before reading `.kind` so a malformed entry\n // can't throw here (and gets skipped rather than derailing the whole fold).\n if (\n !raw ||\n typeof raw !== 'object' ||\n typeof (raw as { kind?: unknown }).kind !== 'string'\n ) {\n continue;\n }\n const entry = raw as DiagnosticEntry;\n if (entry.kind === 'event') {\n const { kind: _kind, ...event } = entry;\n externalEvents.push(event as unknown as MetaEvent);\n } else if (entry.kind === 'turn') {\n // Local position within THIS harvest, not the source engine's own `turnIndex`: one\n // interaction can carry several independent server runs (a consolidator folds in its\n // consolidator-code run and its table-code run), each numbering its turns from 0, so\n // keying by the source index would collide them. The local position keeps every turn key\n // distinct within the batch, so the persister's per-`turnIndex` dedup keeps them all.\n this.externalDiagnostics.push({\n ...entry,\n turnIndex: `server-generation.${batch}:${turnCount}`,\n });\n turnCount += 1;\n } else if (entry.kind === 'message') {\n messageCount += 1;\n this.externalDiagnostics.push(entry);\n }\n // Any other kind is intentionally dropped, not folded. A sibling's `buildTimelineEntries`\n // only ever emits message/turn/event; `meta-snapshot` is host/DOM-owned (latest-wins on\n // reassembly, plus its own persister dedup), so folding a foreign one would pollute this\n // host's timeline and meta cursor. Restricting to the three real kinds also keeps the\n // manifest counts accurate (nothing miscounted as a `message`).\n }\n if (externalEvents.length) mergeMetaEvents(this.sessionKey, externalEvents);\n // Manifest: one provenance marker for the fold itself \u2014 records that an out-of-band engine's\n // log crossed into this session and how much of each kind, so a regression that silently\n // drops a generation's diagnostics (e.g. a new path that forgets to thread them across the\n // boundary) surfaces as a zero/absent manifest rather than only by diffing a download. Also\n // the natural seed for the streaming PR's open/close bracket. Stamped at resolve, so it\n // closes the block on the sorted timeline. (GENC-1461.)\n recordMetaEvent(this.sessionKey, 'external-diagnostics.folded', {\n interactionId,\n batch,\n counts: { turn: turnCount, event: externalEvents.length, message: messageCount },\n });\n }\n const idx = this.history.findIndex((m) => m.interaction?.interactionId === interactionId);\n if (idx !== -1) {\n // Fold any widget-reported external (non-LLM) cost onto the message, so\n // the host's `sumCosts` recompute includes it in the session total.\n // Accumulates defensively in case a widget reports more than once.\n const costUsd =\n typeof result?.costUsd === 'number' &&\n Number.isFinite(result.costUsd) &&\n result.costUsd > 0\n ? result.costUsd\n : undefined;\n this.history[idx] = {\n ...this.history[idx],\n interaction: { ...this.history[idx].interaction!, resolved: result },\n ...(costUsd != null\n ? { externalCostUsd: (this.history[idx].externalCostUsd ?? 0) + costUsd }\n : {}),\n };\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n // A widget may opt into echoing its outcome on the user's side of the\n // chat by returning `userMessage`. Appended as a display-only\n // `'synthetic-user'` message: it is tracked in history (and the debug log)\n // and rendered like a user message, but transports never serialize it \u2014\n // the model already learns the outcome from this handler's return value.\n // Appended before `interaction.resolve` so it precedes the tool result and\n // any follow-up turn the resumed handler produces.\n if (typeof result?.userMessage === 'string' && result.userMessage.trim()) {\n this.appendToHistory({ role: 'synthetic-user', content: result.userMessage });\n }\n if (interaction.overrideId) {\n this.dispatchEvent(new CustomEvent('interaction-stop', { detail: { interactionId } }));\n }\n recordMetaEvent(this.sessionKey, 'interaction.resolved', { interactionId });\n // The park is ending and the loop is about to resume computing \u2014 paired\n // with `interaction-requested`. Fires for every resolution path (user\n // completion, timeout, cancellation), since all route through here.\n this.activityBus.publish('interaction-resolved', undefined);\n interaction.resolve(result);\n this.pendingInteractions.delete(interactionId);\n // Tear down the live context on RESOLVE (not on element unmount) \u2014 this closes\n // any sockets/timers the widget parked on it via `onDispose`. (GENC-1390)\n this.interactionContexts.get(interactionId)?.dispose();\n this.interactionContexts.delete(interactionId);\n } else {\n logger.warn(`Interaction with ID ${interactionId} not found.`);\n }\n }\n\n /**\n * The live {@link InteractionContext} for a pending interaction (GENC-1390), or\n * `undefined` once resolved/evicted. Read by `AiChatInteractionWrapper` (via the\n * host) to build the widget's pending `interaction` descriptor.\n */\n public getInteractionContext(interactionId: string): InteractionContext | undefined {\n return this.interactionContexts.get(interactionId)?.context;\n }\n\n /**\n * Resolve every in-flight interaction with a `'timeout'` result, closing its\n * widget read-only. Used when a sub-agent that owns the open widget times out:\n * the widget is parked in *this* driver's map (interactions resolve on the\n * host, not the child), so cancelling it here unblocks the sub-agent handler\n * awaiting it. The \"one interaction at a time\" invariant means there is at\n * most one.\n */\n private cancelPendingInteractions(message: string): void {\n for (const interactionId of [...this.pendingInteractions.keys()]) {\n this.resolveInteraction(interactionId, {\n status: 'timeout',\n message,\n } satisfies InteractionResult);\n }\n }\n\n /**\n * Seeds the driver with a prior conversation history so a new component instance\n * can continue an existing conversation. Call this before the first user message.\n */\n public loadHistory(messages: ChatMessage[]): void {\n this.history = [...messages];\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n\n async sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult> {\n if (this.busy || (!userInput.trim() && !attachments?.length)) return { reason: 'done' };\n\n this.busy = true;\n this.beginTurn();\n // A new user turn \u2014 advances the `turnEnd` clock (continuations after a\n // handoff stay on the same turn; they go through `continueFromHistory`).\n this.turnSeq += 1;\n this.subAgentCompletion = undefined;\n this.subAgentFailure = undefined;\n this.agentReleaseRequested = false;\n this.budgetExhaustedThisTurn = false;\n this.budgetWallDetail = undefined;\n this.budgetWallViaSubAgent = false;\n this.providerRefusedThisTurn = false;\n this.providerRefusedDetail = undefined;\n this.appendToHistory({ role: 'user', content: userInput, attachments });\n this.turnStartedAt = Date.now();\n recordMetaEvent(this.sessionKey, 'turn.start', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n });\n this.activityBus.publish('tool-loop-start', undefined);\n\n // Captured so the `finally` can carry the turn's outcome onto `tool-loop-end`.\n let result: ChatDriverResult = { reason: 'done' };\n try {\n result = await this.runToolLoop(userInput, attachments);\n return result;\n } catch (e) {\n logger.error('ChatDriver error:', e);\n recordTurnError(this.sessionKey, 'exception', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e instanceof Error ? e.name : undefined,\n message: e instanceof Error ? e.message : String(e),\n });\n this.appendToHistory({\n role: 'assistant',\n content: 'Sorry, something went wrong on my end. Please try again in a moment.',\n });\n result = this.turnDone('exception');\n return result;\n } finally {\n recordMetaEvent(this.sessionKey, 'turn.end', {\n phase: 'sendMessage',\n agent: this.activeAgentName,\n durationMs: Date.now() - this.turnStartedAt,\n });\n this.busy = false;\n this.endTurn();\n this.activityBus.publish('tool-loop-end', this.loopEndDetail(result));\n }\n }\n\n /**\n * Builds the context object passed to every tool handler call.\n * Centralised here so fold shortcut dispatch and the main tool loop use the\n * same context without duplication.\n *\n * @param activeToolCallId - The id of the tool call this context belongs to, so\n * `condenseWhen` can register against the right call (it stamps the clocks\n * straight off the driver). Absent for dispatch paths with no addressable tool\n * call (e.g. the fold-close handler), where `condenseWhen` is a no-op.\n * @param traceCapture - Optional per-tool-call accumulator. When provided, every\n * sub-agent call's trace is **appended** here rather than written to shared\n * instance state, so parallel tool calls each capture their own traces\n * independently.\n *\n * Deliberately a list of traces, not one slot. A single handler may call\n * `requestSubAgent` more than once \u2014 a code-driven scheduler dispatching a\n * dependency graph, a retry of a timed-out child, any fan-out helper \u2014 and a\n * single slot kept only the last, so every other child ran, was billed by the\n * provider, and then vanished from history. The loss was silent in the worst\n * way: `sumUsage` and `usageRows` both recurse into the trace, so they summed a\n * truncated input and still agreed with each other. Measured at 1 of 7 traces\n * kept on a seven-way fan-out, reporting ~2.3x under the real cost, with the\n * error growing as the fan-out widens.\n */\n private buildHandlerContext(\n activeToolCallId?: string,\n traceCapture?: { traces: ChatMessage[][] },\n ) {\n return {\n requestInteraction: <T>(\n componentName: string,\n data: any,\n options?: InteractionRequestOptions,\n ): Promise<T> => this.requestInteraction(componentName, data, options),\n ...(this.subAgentsMap.size > 0 && {\n requestSubAgent: <T = never>(\n name: string,\n options?: SubAgentRequestOptions,\n ): Promise<\n | { ok: true; result: T; reason?: never }\n | { ok: false; result?: never; reason: SubAgentFailureReason }\n > =>\n this.invokeSubAgent<T>(name, options).then(({ outcome, trace }) => {\n // Append, never assign: see `traceCapture` on `buildHandlerContext`. Order\n // is completion order, which is fine \u2014 every message carries its own\n // timestamp and the timeline sorts on that.\n if (traceCapture && trace) traceCapture.traces.push(trace);\n return outcome;\n }),\n }),\n completeSubAgent: (result: unknown): void => {\n if (this.subAgentCompletion) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): completeSubAgent called more than once \u2014 ignoring`,\n );\n return;\n }\n this.subAgentCompletion = { result };\n // This activation's flow has ended \u2014 advance the clock so its\n // `agentEnd` payloads collapse and a re-run starts a fresh activation.\n this.currentActivation += 1;\n },\n releaseAgent: (): void => {\n if (this.agentReleaseRequested) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): releaseAgent called more than once \u2014 ignoring`,\n );\n return;\n }\n this.agentReleaseRequested = true;\n // The stateful flow has wrapped up \u2014 advance the clock so its `agentEnd`\n // payloads collapse and a re-run starts a fresh activation.\n this.currentActivation += 1;\n },\n endPhase: (): void => {\n // Advance the phase epoch so payloads registered with `{ on: phaseEnd }`\n // during the phase that just ended collapse on the next provider call.\n // Repeatable (no once-only guard, unlike releaseAgent/completeSubAgent):\n // each call opens a fresh phase for subsequent reads to accumulate in.\n this.currentPhaseEpoch += 1;\n },\n condenseWhen: (policy: CondensePolicy): void => {\n // No addressable tool call (e.g. fold-close handler) \u2014 nothing to attach to.\n if (!activeToolCallId) return;\n if (!policy?.args && !policy?.response) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called with neither args nor response \u2014 ignoring`,\n );\n return;\n }\n const triggers = Array.isArray(policy.on) ? policy.on : [policy.on];\n const validTrigger = (t: CondenseTrigger | undefined): boolean =>\n t?.kind === 'superseded'\n ? typeof t.by === 'string' && t.by.length > 0\n : t?.kind === 'age'\n ? typeof t.turns === 'number' && t.turns >= 1\n : t?.kind === 'turnEnd' || t?.kind === 'agentEnd' || t?.kind === 'phaseEnd';\n if (triggers.length === 0 || !triggers.every(validTrigger)) {\n logger.warn(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called with an invalid trigger \u2014 ignoring`,\n );\n return;\n }\n // First-wins: a handler declares its policy once per call. A second\n // declaration for the same tool call is a handler bug, not a refinement.\n if (this.condensePolicies.has(activeToolCallId)) {\n logger.error(\n `ChatDriver(${this.activeAgentName ?? 'unknown'}): condenseWhen called more than once for the same tool call \u2014 keeping the first policy, ignoring this one`,\n );\n return;\n }\n // Stamp the three clocks NOW (read straight off the driver \u2014 the handler\n // runs during the current model-call's tool batch).\n this.condensePolicies.set(activeToolCallId, {\n policy,\n iteration: this.modelCallSeq,\n turn: this.turnSeq,\n activation: this.currentActivation,\n phaseEpoch: this.currentPhaseEpoch,\n });\n },\n };\n }\n\n /**\n * Creates a child `ChatDriver` for the named sub-agent, runs it to completion,\n * and returns its structured result (or final text fallback) together with the\n * full child conversation trace. Callers receive both values so each parallel\n * invocation can capture its own trace without touching shared instance state.\n */\n private async invokeSubAgent<T = never>(\n name: string,\n options?: SubAgentRequestOptions,\n ): Promise<{\n // Closed union (see ChatToolHandlers.requestSubAgent) \u2014 keeps `result`/`reason`\n // accessible for consumers compiled without strictNullChecks.\n outcome:\n | { ok: true; result: T; reason?: never }\n | { ok: false; result?: never; reason: SubAgentFailureReason };\n trace: ChatMessage[];\n }> {\n const subConfig = this.subAgentsMap.get(name);\n if (!subConfig) {\n const available = [...this.subAgentsMap.keys()].join(', ') || '(none)';\n throw new Error(\n `Sub-agent \"${name}\" not found on agent \"${this.activeAgentName}\". Available: ${available}`,\n );\n }\n\n const { task, historyCap, context, timeoutMs } = options ?? {};\n\n // Exclude the current in-flight assistant message (the one with tool calls that\n // triggered this invocation) \u2014 it has unresolved tool calls that would confuse\n // the sub-agent into thinking it needs to handle tools it doesn't own.\n const lastMsg = this.history[this.history.length - 1];\n const baseHistory =\n lastMsg?.role === 'assistant' && lastMsg.toolCalls?.length\n ? this.history.slice(0, -1)\n : this.history;\n\n const snapshotHistory =\n historyCap != null ? applyHistoryCap(baseHistory, historyCap) : [...baseHistory];\n\n const contextMessages: ChatMessage[] = context\n ? [{ role: 'user', content: `[Sub-agent context]: ${JSON.stringify(context)}` }]\n : [];\n\n const effectivePrimer: ChatMessage[] = [\n ...snapshotHistory,\n ...contextMessages,\n ...(subConfig.primerHistory ?? []),\n ];\n\n // Unique per-invocation id \u2014 reused for the lifecycle event bracket below \u2014\n // and a child session key derived from it. The child files its meta events\n // under this own bucket (rather than the shared empty-key sink), so they can\n // be harvested into THIS session on completion and then discarded.\n const invocationId = crypto.randomUUID();\n const childSessionKey = `${this.sessionKey}::sub:${invocationId}`;\n const child = new ChatDriver(this.providerRegistry, {\n sessionKey: childSessionKey,\n // Inherit the parent's bus so the sub-agent's tool-loop events still surface\n // (off-browser this is the shared no-op).\n activityBus: this.activityBus,\n });\n // Mark before the first turn so the child forces tool use and reports a\n // typed failure (rather than user-facing text) if it never completes.\n child.markAsSubAgent();\n // Propagate disposal: if this (parent) driver is torn down while the\n // sub-agent is mid-flight, dispose the child too so its in-flight request\n // aborts. Detached in the `finally` below once the sub-agent completes.\n const disposeChild = () => child.dispose();\n if (this.lifecycleController.signal.aborted) {\n disposeChild();\n } else {\n this.lifecycleController.signal.addEventListener('abort', disposeChild, { once: true });\n }\n child.applyAgent({ ...subConfig, primerHistory: effectivePrimer });\n // Route interactions back through this driver so widgets render in the\n // parent's (ultimately the root's) history and resolve via the same\n // pending map the main UI is wired to. Recurses naturally for nested\n // sub-agents.\n child.setHostInteractionRequester(\n <R>(componentName: string, data: any, opts?: InteractionRequestOptions): Promise<R> =>\n this.requestInteraction<R>(componentName, data, opts),\n );\n\n const forwardTrace = (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('sub-agent-history-updated', {\n detail: { agentName: subConfig.name, history: (e as CustomEvent<ChatMessage[]>).detail },\n }),\n );\n };\n // Re-dispatch the child's `provider-changed` so the UI reflects whichever\n // provider is *actually* running right now (the sub-agent may use a\n // different provider than the parent). Restoration of the parent's\n // provider on `sub-agent-stop` is handled by the listener in main.ts.\n const forwardProviderChanged = (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('provider-changed', { detail: (e as CustomEvent).detail }),\n );\n };\n child.addEventListener('history-updated', forwardTrace);\n child.addEventListener('provider-changed', forwardProviderChanged);\n\n const chatInputDuringExecution = options?.chatInputDuringExecution;\n const lifecycleDetail = { name, invocationId, chatInputDuringExecution };\n\n this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: lifecycleDetail }));\n // Bracket the run on the timeline (mirrors turn.start/turn.end). Recorded\n // under THIS (parent) session \u2014 like subagent.completed/failed below \u2014 so the\n // sub-agent's span is visible on the user-facing timeline, not the child's.\n recordMetaEvent(this.sessionKey, 'subagent.started', { agent: name });\n let timedOut = false;\n const runPromise = child.sendMessage(task ?? '');\n try {\n if (timeoutMs == null) {\n await runPromise;\n } else {\n // Race the run against the deadline. On timeout, abort the child (which\n // cancels its in-flight provider request) and let the aborted run settle\n // before we tear down and return the timeout outcome.\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n const timeoutSignal = new Promise<'timeout'>((resolveTimeout) => {\n timeoutHandle = setTimeout(() => resolveTimeout('timeout'), timeoutMs);\n });\n const winner = await Promise.race([\n runPromise.then(() => 'done' as const),\n timeoutSignal,\n ]);\n if (winner === 'timeout') {\n timedOut = true;\n child.dispose();\n // The sub-agent may be parked awaiting a user interaction, which is\n // routed up to this driver and parked in *this* pending map (widgets\n // resolve on the host, not the child). Disposing the child does not\n // settle that promise, so the child stays suspended \u2014 cancel the\n // interaction to close the widget and unblock the child. Without this,\n // `await runPromise` below would hang forever and the timeout would\n // never complete (or record `subagent.failed`).\n this.cancelPendingInteractions(`Sub-agent \"${name}\" timed out after ${timeoutMs}ms.`);\n await runPromise.catch(() => undefined);\n }\n } finally {\n // Always clear the timer \u2014 even if the race rejects \u2014 so it never leaks.\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n } finally {\n this.lifecycleController.signal.removeEventListener('abort', disposeChild);\n child.removeEventListener('history-updated', forwardTrace);\n child.removeEventListener('provider-changed', forwardProviderChanged);\n // Tear the child down on every exit path, not just timeout/parent-abort.\n // A child that completes normally is otherwise never disposed, so its\n // provider-registry subscription (wired in the ChatDriver constructor)\n // would leak \u2014 the long-lived registry would retain every completed\n // sub-agent driver. dispose() is idempotent and only aborts the (already\n // settled) lifecycle, so the snapshot/completion reads below still work.\n child.dispose();\n this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: lifecycleDetail }));\n // Capture the child's diagnostics into THIS session, then ALWAYS discard its\n // transient bucket \u2014 done in the `finally` so an unexpected `sendMessage`\n // rejection (which propagates out of this method) can't orphan the bucket in\n // the registry, and a crashed sub-agent still leaves its turns/events behind.\n // Forward the child's per-LLM-call snapshots so they show as `kind:'turn'`\n // entries in the exported debug log, re-numbered under the activating parent turn.\n this.forwardSubAgentSnapshots(child.getTurnSnapshots());\n // Fold the sub-agent's high-value meta events (retries/errors/tool failures \u2014\n // see HARVESTED_SUBAGENT_EVENTS) into THIS session, preserving their original\n // timestamps so they interleave within the subagent.started\u2192completed/failed\n // bracket. Each is breadcrumbed `\"<parent> \u203A <sub-agent>\"`, composing for a\n // nested sub-agent whose own breadcrumb the child already merged.\n const parentName = this.activeAgentName ?? '?';\n const harvested = getMetaEvents(childSessionKey)\n .filter((e) => HARVESTED_SUBAGENT_EVENTS.has(e.type))\n .map((e) => {\n const existing = e.detail?.subAgent as string | undefined;\n return { ...e, detail: { ...e.detail, subAgent: `${parentName} \u203A ${existing ?? name}` } };\n });\n mergeMetaEvents(this.sessionKey, harvested);\n clearSession(childSessionKey);\n }\n\n const trace = child.getHistory() as ChatMessage[];\n\n if (timedOut) {\n // Same failure shape as any other non-completion \u2014 the parent handler\n // recovers on its existing `{ ok: false }` branch. Recorded under THIS\n // (parent) session so it lands on the user-visible debug-log timeline.\n recordMetaEvent(this.sessionKey, 'subagent.failed', { agent: name, reason: 'timeout' });\n return { outcome: { ok: false, reason: 'timeout' }, trace };\n }\n\n const completion = child.getSubAgentCompletion();\n\n if (completion) {\n recordMetaEvent(this.sessionKey, 'subagent.completed', { agent: name });\n return { outcome: { ok: true, result: completion.result as T }, trace };\n }\n\n // No completion \u2192 the sub-agent's loop ended without calling its completion\n // tool. Surface the typed reason it recorded; default to 'max_iterations'\n // for the defensive case where the loop ended with no reason set (e.g. a\n // provider ignored forced tool use and returned text). The previous\n // final-text fallback is intentionally gone \u2014 sub-agents return a\n // structured outcome only, and the parent handler decides how to recover.\n const failure = child.getSubAgentFailure();\n const reason = failure?.reason ?? 'max_iterations';\n // Record under THIS (parent) driver's session so the failure lands on the\n // user-visible debug-log timeline \u2014 the child ran under its own session key.\n // This is also the only telemetry for the defensive default above, where the\n // child's loop ended without recording an explicit failure reason.\n recordMetaEvent(this.sessionKey, 'subagent.failed', { agent: name, reason });\n // A child that hit the budget wall walls this driver too \u2014 the cap is shared,\n // and the parent's very next model call would 402 as well. Flagged (not\n // thrown) because the handler's return value is still appended as a tool\n // result: the loop reads the flag before the next provider call and ends the\n // turn there, which is what makes the `'budget_exhausted'` doc's \"terminal\n // for the parent too\" actually true.\n //\n // The child's attribution is inherited with it: the vendor that refused is\n // the child's, which under a mixed registry is not this driver's. See\n // `budgetWallDetail` for what mis-attributing it costs.\n //\n // FIRST attribution wins (`??=`). With batched delegations, child A walling\n // WITH attribution can be followed by child B walling WITHOUT one (a\n // figure-less 402 behind a transport label no vendor claims); a plain\n // assignment reset the field to `undefined` and the short-circuit's\n // fallback then named the parent's own vendor \u2014 the one known NOT to have\n // refused.\n if (reason === 'budget_exhausted') {\n this.budgetExhaustedThisTurn = true;\n this.budgetWallViaSubAgent = true;\n this.budgetWallDetail ??= failure?.budget;\n }\n // The PROVIDER wall via a child (GENC-1506) \u2014 the same shape as the budget wall above, and needed\n // for the same non-obvious reason: **the child is a separate driver instance**, so the flag it set\n // on itself is invisible here. Without this branch the child's failure was appended as an ordinary\n // tool result, the parent's short-circuit never fired, and the parent issued another model call\n // straight into the same wall. Worse, if that call happened to succeed the turn could finish\n // WITHOUT `failureReason: 'provider-refused'` at all \u2014 reporting a clean turn over a dead account.\n //\n // FIRST attribution wins (`??=`), for the reason spelled out on `budgetWallDetail`: batched\n // delegations can pair an attributable child refusal with an unattributable one, and a plain\n // assignment would let the later `undefined` erase what the earlier child knew.\n if (reason === 'provider_refused') {\n this.providerRefusedThisTurn = true;\n this.providerRefusedDetail ??= failure?.providerRefused;\n }\n return { outcome: { ok: false, reason }, trace };\n }\n\n /**\n * Continue the tool loop from current history without appending a new user message.\n * Used by OrchestratingDriver after an agent handoff.\n */\n async continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult> {\n if (this.busy) return { reason: 'done' };\n\n this.busy = true;\n this.beginTurn();\n this.subAgentCompletion = undefined;\n this.subAgentFailure = undefined;\n this.budgetExhaustedThisTurn = false;\n this.budgetWallDetail = undefined;\n this.budgetWallViaSubAgent = false;\n this.providerRefusedThisTurn = false;\n this.providerRefusedDetail = undefined;\n this.turnStartedAt = Date.now();\n recordMetaEvent(this.sessionKey, 'turn.start', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n });\n this.activityBus.publish('tool-loop-start', undefined);\n // Captured so the `finally` can carry the turn's outcome onto `tool-loop-end`.\n let result: ChatDriverResult = { reason: 'done' };\n try {\n result = await this.runToolLoop('', undefined, transientPrimer);\n return result;\n } catch (e) {\n logger.error('ChatDriver error:', e);\n recordTurnError(this.sessionKey, 'exception', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e instanceof Error ? e.name : undefined,\n message: e instanceof Error ? e.message : String(e),\n });\n this.appendToHistory({\n role: 'assistant',\n content: 'Sorry, something went wrong on my end. Please try again in a moment.',\n });\n result = this.turnDone('exception');\n return result;\n } finally {\n recordMetaEvent(this.sessionKey, 'turn.end', {\n phase: 'continueFromHistory',\n agent: this.activeAgentName,\n durationMs: Date.now() - this.turnStartedAt,\n });\n this.busy = false;\n this.endTurn();\n this.activityBus.publish('tool-loop-end', this.loopEndDetail(result));\n }\n }\n\n // ---------------------------------------------------------------------------\n // Fold mechanics\n // ---------------------------------------------------------------------------\n\n /** Extract ToolFold metadata from a handler, or undefined if it isn't a fold facade. */\n private getFold(toolName: string): ToolFold | undefined {\n const handler = this.toolHandlers[toolName];\n return handler ? ((handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined) : undefined;\n }\n\n /**\n * Search all currently registered fold facades (and their nested folds recursively)\n * to find which fold contains a given tool name. Returns the immediate parent fold name.\n */\n private findFoldContaining(toolName: string, handlers?: ChatToolHandlers): string | null {\n const source = handlers ?? this.toolHandlers;\n for (const [, handler] of Object.entries(source)) {\n const fold = (handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined;\n if (!fold) continue;\n // Direct inner tool match\n if (fold.handlers[toolName]) return fold.name;\n // Recurse into nested folds\n const nested = this.findFoldContaining(toolName, fold.handlers);\n if (nested) return fold.name;\n }\n return null;\n }\n\n /**\n * If an open fold is hiding a previously-available tool, return the name of\n * the fold to close to start getting it back. Only exclusive folds hide tools\n * (they replace the tool set on open rather than extending it), so a base tool\n * that was visible before the fold opened now sits in a fold-stack frame's\n * `previousHandlers` but not in the live handler map. Only the top fold's\n * `close_` tool is active, so that's always the actionable next step \u2014 even\n * when the tool lives further down the stack, closing repeatedly walks back to\n * it. Returns null when no open fold accounts for the tool.\n */\n private foldHidingTool(toolName: string): string | null {\n if (this.foldStack.length === 0) return null;\n const hidden = this.foldStack.some((f) => f.previousHandlers[toolName]);\n return hidden ? this.foldStack[this.foldStack.length - 1].foldName : null;\n }\n\n /**\n * Install the fold's inner tool set, replacing (exclusive) or extending (non-exclusive)\n * the current tool set. Also injects the close tool. Does NOT touch the fold stack.\n */\n private applyFoldToolSet(fold: ToolFold, foldName: string): void {\n const closeToolName = `close_${foldName}`;\n const newDefs: ChatToolDefinition[] = [];\n const newHandlers: ChatToolHandlers = {};\n\n if (!fold.exclusive) {\n // Non-exclusive: keep existing tools minus the facade we just opened\n for (const def of this.toolDefinitions) {\n if (def.name !== foldName) newDefs.push(def);\n }\n for (const [name, handler] of Object.entries(this.toolHandlers)) {\n if (name !== foldName) newHandlers[name] = handler;\n }\n }\n\n // Install inner tools from fold metadata\n newDefs.push(...fold.tools);\n Object.assign(newHandlers, fold.handlers);\n\n // Inject the close tool\n newDefs.push({\n name: closeToolName,\n description: `Close the ${foldName} fold and return to the previous set of tools.`,\n parameters: { type: 'object', properties: {} },\n });\n newHandlers[closeToolName] = async (): Promise<string> => this.closeFold();\n\n this.toolDefinitions = newDefs;\n this.toolHandlers = newHandlers;\n }\n\n /** Open a fold: push a stack frame, swap the tool set, return the response message. */\n private openFold(\n foldName: string,\n fold: ToolFold,\n args: Record<string, unknown>,\n activeToolCallId?: string,\n ): Promise<string> {\n // Shortcut dispatch: model passed inner tool args directly, e.g.\n // trading_tools({ search_trades: { side: \"BUY\" } })\n for (const key of Object.keys(args)) {\n const innerHandler = fold.handlers[key];\n if (innerHandler) {\n logger.debug(`ChatDriver: fold shortcut dispatch \"${foldName}\" \u2192 \"${key}\"`);\n // Open the fold first so the tool set is correct for subsequent calls\n this.pushFoldFrame(foldName);\n this.applyFoldToolSet(fold, foldName);\n this.consecutiveFoldOps = 0; // shortcut dispatch counts as real work\n const innerArgs =\n typeof args[key] === 'object' && args[key] !== null\n ? (args[key] as Record<string, unknown>)\n : {};\n return innerHandler(innerArgs, this.buildHandlerContext(activeToolCallId)).then((r) =>\n typeof r === 'string' ? r : JSON.stringify(r),\n );\n }\n }\n\n // Normal two-step open\n this.pushFoldFrame(foldName);\n this.applyFoldToolSet(fold, foldName);\n\n const innerToolNames = fold.tools.map((t) => t.name);\n const closeToolName = `close_${foldName}`;\n let message = `Fold opened: ${foldName}. Tools now available: ${[...innerToolNames, closeToolName].join(', ')}.`;\n if (fold.usageNotes) message += ` Notes: ${fold.usageNotes}`;\n message += ` Call ${closeToolName} when done to return to the previous tools.`;\n return Promise.resolve(message);\n }\n\n private pushFoldFrame(foldName: string): void {\n this.foldStack.push({\n foldName,\n previousDefinitions: [...this.toolDefinitions],\n previousHandlers: { ...this.toolHandlers },\n });\n }\n\n /** Close the top fold: pop the stack frame, restore the previous tool set. */\n private closeFold(): string {\n const frame = this.foldStack.pop();\n if (!frame) return 'No fold is currently open.';\n\n this.toolDefinitions = frame.previousDefinitions;\n this.toolHandlers = frame.previousHandlers;\n\n const toolNames = this.toolDefinitions.map((t) => t.name);\n return `Fold closed: ${frame.foldName}. Tools now available: ${toolNames.join(', ')}.`;\n }\n\n /** Build the fold-awareness suffix appended to the system prompt each LLM call. */\n private buildFoldSystemPromptSuffix(): string {\n // Collect fold facades from the current handler map\n const activeFolds: ToolFold[] = [];\n for (const handler of Object.values(this.toolHandlers)) {\n const fold = (handler as any)[TOOL_FOLD_SYMBOL] as ToolFold | undefined;\n if (fold) activeFolds.push(fold);\n }\n\n if (activeFolds.length === 0 && this.foldStack.length === 0) return '';\n\n const parts: string[] = ['\\n\\n--- Tool Folds ---'];\n parts.push(\n 'Some tools are grouped into folds. You may see tool calls in the conversation history for tools that are not currently available \u2014 they are inside a fold. To access them, invoke the fold tool first.',\n );\n\n if (this.foldStack.length > 0) {\n const current = this.foldStack[this.foldStack.length - 1];\n parts.push(\n `You are currently inside the \"${current.foldName}\" fold. Call close_${current.foldName} when you are done with these tools.`,\n );\n }\n\n for (const fold of activeFolds) {\n parts.push(`\u2022 ${fold.name}: ${fold.description}`);\n }\n\n return parts.join('\\n');\n }\n\n // ---------------------------------------------------------------------------\n // Tool loop\n // ---------------------------------------------------------------------------\n\n // oxlint-disable-next-line complexity\n private async runToolLoop(\n userInput: string,\n attachments?: ChatAttachment[],\n transientPrimer?: ChatMessage[],\n ): Promise<ChatDriverResult> {\n if (!this.systemPrompt) {\n logger.warn(\n 'ChatDriver: no systemPrompt set. The assistant will have no instructions \u2014 provide a systemPrompt via agents config or the foundation-ai-assistant property.',\n );\n }\n\n let currentInput = userInput;\n let currentAttachments: ChatAttachment[] | undefined = attachments;\n let iterations = 0;\n let malformedAttempts = 0;\n let emptyResponseAttempts = 0;\n // Bounded retries for transient throws while resolving the per-turn tool surface or\n // calling the provider. Without this, a single transient throw tears down the whole turn\n // and strands the agent's unflushed work behind an opaque error.\n let setupTransportAttempts = 0;\n // True only for the very first LLM call. Used to exclude the pending user message\n // from history (it is passed separately as currentInput). Must not be derived from\n // `iterations` because fold operations decrement iterations, which would incorrectly\n // re-trigger the slice on subsequent calls after a fold open/close.\n let firstLlmCall = !!currentInput;\n // Thinking posture for this WHOLE turn, resolved on the first model call and then held.\n //\n // Unlike temperature or toolChoice, this one cannot vary per iteration: a tool-use loop is\n // a single assistant turn, and Anthropic requires one thinking mode for its duration.\n // Toggling mid-loop does not error \u2014 the API silently disables thinking for that request\n // and strips blocks that would leave the turn structure invalid, so an `'auto' -> 'off'`\n // switch loses the reasoning continuity the opening call established while an\n // `'off' -> 'auto'` switch simply does not deliver the reasoning asked for. It also\n // invalidates the prompt cache, which costs more than the reasoning it was meant to save.\n // Resolved per USER turn instead, which is where the docs say to choose it.\n let pinnedThinkingPolicy: ChatThinkingPolicy | undefined;\n let thinkingPolicyPinned = false;\n\n while (iterations < this.maxToolIterations) {\n iterations += 1;\n // Monotonic across the driver's life \u2014 the age clock. Unlike `iterations`,\n // it is NOT reset per turn and NOT decremented for folds, so `age` keeps\n // counting model-calls once a turn ends. (See the `modelCallSeq` field.)\n this.modelCallSeq += 1;\n\n // A cancel (or dispose) that landed while the previous iteration's tool\n // batch was running takes effect here \u2014 before issuing another LLM call.\n // An abort during the call itself is handled by the catch below.\n if (this.turnController.signal.aborted) {\n return this.completeAbortedTurn();\n }\n\n // A budget wall observed earlier this turn ends it HERE, before another\n // model call. Reachable only via a sub-agent (this driver's own 402\n // returns straight out of the catch below) \u2014 `invokeSubAgent` sets the\n // flag, its `{ ok: false, reason: 'budget_exhausted' }` outcome is\n // appended as a tool result, and without this the loop would call the\n // provider again into the same wall: N batched sub-agent calls otherwise\n // cost N doomed children AND a doomed parent call.\n //\n // Scoped strictly to the budget reason: every other SubAgentFailureReason\n // is something the parent can legitimately recover from, so those still\n // let the loop continue.\n // A provider refusal seen earlier this turn ends it HERE, before another model call. Reachable\n // only via a sub-agent \u2014 this driver's own refusal returns straight out of the catch \u2014 and\n // without it the loop would call the provider again into the same wall (GENC-1506).\n if (this.providerRefusedThisTurn) {\n logger.error('ChatDriver: ending the turn \u2014 a sub-agent hit the provider wall');\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n kind: this.providerRefusedDetail?.kind,\n via: 'sub-agent',\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // The detail is forwarded, not just the reason \u2014 this driver may itself be an INTERMEDIATE\n // sub-agent, and a refusal that started in a grandchild reaches its own parent only through\n // this call. Dropping it here still stopped the top-level turn (the reason travels), but\n // arrived with no vendor and no kind, which is the whole diagnostic this payload exists to\n // carry across hops. The adjacent budget path forwards `budgetWallDetail` for the same reason.\n this.failSubAgent('provider_refused', undefined, this.providerRefusedDetail);\n } else {\n this.appendToHistory({ role: 'assistant', content: this.providerRefusedBubble() });\n }\n return this.turnDone('provider-refused', undefined, this.providerRefusedDetail);\n }\n if (this.budgetExhaustedThisTurn) {\n logger.error('ChatDriver: ending the turn \u2014 a sub-agent hit the AI budget wall');\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n // The CHILD's vendor when it knew one, and NOTHING otherwise. On this\n // path the wall is definitionally the child's, and on a mixed registry\n // `lastResolvedProvider` is this driver's own vendor \u2014 the one known\n // NOT to have refused. An unattributable child wall must degrade to\n // the vendor-agnostic block (which `latchBlockedFrom` handles\n // fail-safe), never to a vendor that is known to be wrong: naming the\n // parent's vendor here walled BOTH \u2014 the child's via its own\n // tool-loop-end, the parent's via this event \u2014 and derived `blocked`\n // over headroom that still existed.\n vendor: this.budgetWallDetail?.vendor,\n via: 'sub-agent',\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('budget_exhausted', this.budgetWallDetail);\n } else {\n // Composed from the DETAIL, not an error object: on this path the wall\n // arrived as a sub-agent's failure payload \u2014 `budgetWallDetail`, first\n // attribution wins \u2014 and an unattributable child wall (detail\n // undefined) composes the neutral default.\n this.appendToHistory({\n role: 'assistant',\n content: this.budgetExhaustedBubble(this.budgetWallDetail),\n });\n }\n // Carried onto the result so `loopEndDetail` publishes the refusing\n // vendor rather than falling through to `lastResolvedProvider`, and the\n // host's latch walls the vendor that actually ran out.\n return this.turnDone('budget-exhausted', this.budgetWallDetail);\n }\n\n const promptCtx: SystemPromptContext = {\n agentName: this.activeAgentName ?? '',\n history: this.history,\n turnIndex: iterations - 1,\n signal: this.turnController.signal,\n };\n\n // Re-resolve dynamic tool definitions before each LLM call. The static\n // case is a no-op (factory is undefined and `this.toolDefinitions` was\n // set by applyAgent). Folds operate on `this.toolDefinitions` and are\n // forbidden when a factory is set, so the array form is always valid.\n // Sequential await is required \u2014 each iteration must see fresh values\n // before constructing the LLM request.\n // A transient throw while building the tool surface should retry the iteration, not\n // tear down the whole turn and strand the agent's unflushed buffer behind an opaque\n // error. The handler-map factory re-resolves in lockstep so dispatch sees only the\n // handlers valid for the current state, in step with the tool definitions exposed\n // above. Folds are forbidden when either factory is set, so the fold-mutation paths\n // on `this.toolDefinitions` / `this.toolHandlers` are unreachable.\n try {\n if (this.toolDefinitionsFactory) {\n // oxlint-disable-next-line no-await-in-loop\n this.toolDefinitions = await this.toolDefinitionsFactory(promptCtx);\n }\n if (this.toolHandlersFactory) {\n // oxlint-disable-next-line no-await-in-loop\n this.toolHandlers = await this.toolHandlersFactory(promptCtx);\n }\n } catch (e) {\n setupTransportAttempts += 1;\n if (setupTransportAttempts < MAX_SETUP_TRANSPORT_RETRIES) {\n logger.warn(\n `ChatDriver: tool-surface resolution failed, retrying (${setupTransportAttempts}/${MAX_SETUP_TRANSPORT_RETRIES})`,\n );\n iterations -= 1;\n continue;\n }\n throw e;\n }\n\n // Record everything advertised this turn so the unknown-tool path can tell\n // a stale tool (real earlier, retired now) from a hallucinated one. Runs\n // for both the static and factory cases; folds also flow through here as\n // their inner tools become visible on the iteration after they open.\n for (const def of this.toolDefinitions) this.everSeenToolNames.add(def.name);\n\n const resolvedSystemPrompt =\n typeof this.systemPrompt === 'function'\n ? // oxlint-disable-next-line no-await-in-loop\n await this.systemPrompt(promptCtx)\n : this.systemPrompt;\n\n // Re-resolve the per-turn display label. Falls back to the canonical\n // agent name when displayName is unset. Stamped onto outgoing messages\n // and turn snapshots for UX only; routing/history-transform continues\n // to read `activeAgentName`.\n if (typeof this.displayName === 'function') {\n // oxlint-disable-next-line no-await-in-loop\n this.activeAgentLabel = await this.displayName(promptCtx);\n }\n\n // Volatile framework additions \u2014 the fold-surface suffix and the per-attempt malformed/empty\n // retry nudge \u2014 that would otherwise destabilize a cached system prompt. They are routed to\n // the framed tail (below), never appended to the system string, so the system prompt stays\n // byte-stable for every agent.\n const foldSuffix = this.buildFoldSystemPromptSuffix();\n const retryNudge =\n malformedAttempts > 0\n ? '\\n\\nIMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.'\n : emptyResponseAttempts > 0\n ? \"\\n\\nIMPORTANT: You must respond to the user's message. Call the appropriate tool or provide a text response \u2014 do not return an empty response.\"\n : '';\n const frameworkSystemSuffix = `${foldSuffix}${retryNudge}`;\n\n // Normalize the primer at the same chokepoint as the driver's own history\n // (GENC-1351 \u00A75.7): a parent's `compacted-summary` message rides into a\n // sub-agent's primer (`requestSubAgent` snapshots the parent's raw history),\n // and it must be translated to a `<conversation_summary>` user message here \u2014\n // otherwise the transports' role filter silently drops it and the sub-agent\n // loses all summarized context. `normalizeForProvider` only touches\n // `compacted-summary`, so it's a safe pass-through for everything else.\n const primer = normalizeForProvider([\n ...(this.primerHistory ?? []),\n ...(transientPrimer ?? []),\n ]);\n const baseHistory = firstLlmCall ? this.history.slice(0, -1) : this.history;\n firstLlmCall = false;\n // Collapse stale tool payloads this agent declared via `condenseWhen`\n // (GENC-1369), then translate any compacted-summary \u2192 a\n // <conversation_summary> user message (GENC-1351 \u00A75.7) before any per-agent\n // masking, so the raw display-only role can never reach a transport. Each\n // step runs on a copy \u2014 stored history is untouched.\n const condensedHistory = applyCondensation(\n [...baseHistory],\n this.condensePolicies,\n {\n modelCall: this.modelCallSeq,\n turn: this.turnSeq,\n // A call's activation has ended once a later activation is current \u2014 a\n // swap or release/complete both advance the counter.\n activationEnded: (activation) => activation < this.currentActivation,\n // A call's phase has ended once the app declared a later phase epoch\n // current via `endPhase()`.\n phaseEnded: (phaseEpoch) => phaseEpoch < this.currentPhaseEpoch,\n batchCalls: this.condenseBatchCalls,\n },\n (detail) => recordMetaEvent(this.sessionKey, 'context.condensed', detail),\n );\n const normalizedHistory = normalizeForProvider(condensedHistory);\n const historyForProvider = this.providerHistoryTransform\n ? this.providerHistoryTransform(normalizedHistory)\n : normalizedHistory;\n const historyForCall = [...primer, ...historyForProvider];\n\n // Resolve the per-turn temperature and tool-call mode the same way the\n // provider is resolved \u2014 static value or a function of the turn context\n // (which carries the live state for stateful agents). Resolved before the\n // snapshot so the debug log records the exact request config the model saw.\n const [\n resolvedTemperature,\n resolvedToolChoice,\n resolvedCachePolicy,\n resolvedTailContext,\n resolvedResponseSchema,\n firstResolvedThinkingPolicy,\n ] =\n // oxlint-disable-next-line no-await-in-loop\n await Promise.all([\n this.resolveTurnInput<number>(this.activeTemperatureInput, promptCtx),\n this.resolveTurnInput<ChatToolChoice>(this.activeToolChoiceInput, promptCtx),\n this.resolveTurnInput<CachePolicy>(this.activeCachePolicyInput, promptCtx),\n this.resolveTurnInput<string>(this.activeTailContextInput, promptCtx),\n this.resolveTurnInput<object | undefined>(this.activeResponseSchemaInput, promptCtx),\n // Only consulted on the first iteration (see `pinnedThinkingPolicy`); resolved\n // alongside the others so a resolver still sees the same turn context.\n thinkingPolicyPinned\n ? Promise.resolve(undefined)\n : this.resolveTurnInput<ChatThinkingPolicy | undefined>(\n this.activeThinkingPolicyInput,\n promptCtx,\n ),\n ]);\n if (!thinkingPolicyPinned) {\n pinnedThinkingPolicy = firstResolvedThinkingPolicy;\n thinkingPolicyPinned = true;\n }\n // The system prompt is always just the agent's resolved prompt \u2014 byte-stable, so it can be\n // cached. The framework's volatile additions (fold suffix, retry nudge) and the agent's tail\n // context all go to the framed tail: one uniform channel, no cache-scope branch. On a normal\n // turn `frameworkSystemSuffix` is empty, so the tail is empty too \u2014 a no-op. The framework\n // owns the framing; the corrective retry nudge lands last (recency).\n const systemPrompt = resolvedSystemPrompt || undefined;\n const tailBody = [resolvedTailContext, frameworkSystemSuffix]\n .map((part) => (part ?? '').trim())\n .filter((part) => part.length > 0)\n .join('\\n\\n');\n const tailContext = tailBody\n ? `<system-reminder>\\n${tailBody}\\n</system-reminder>`\n : undefined;\n // An agent/state-configured tool-call mode wins. Otherwise sub-agents must\n // finish by calling a tool (their completion tool) so the turn can't end\n // on a free-text answer; top-level agents stay 'auto'. (Transports no-op a\n // force when no tools are advertised.)\n const effectiveToolChoice = resolvedToolChoice ?? (this.isSubAgent ? 'required' : undefined);\n\n const turnSnapshot = this.recordTurnSnapshot(\n systemPrompt,\n resolvedTemperature,\n effectiveToolChoice,\n tailContext,\n );\n\n // Capture the pending user input, then clear the slots BEFORE the chat\n // call. `sendMessage` already appended the user message to `this.history`,\n // so on retries (empty / malformed) we must rely on history alone \u2014\n // otherwise the message gets sent twice (once via history, once via\n // `currentInput`), which Gemini answers with an empty response and then\n // we retry forever.\n const userInputForCall = currentInput;\n const attachmentsForCall = currentAttachments;\n currentInput = '';\n currentAttachments = undefined;\n\n const options: ChatRequestOptions = {\n systemPrompt,\n // Strip fold-only properties (foldEvent, foldPath) before sending to provider\n tools: this.toolDefinitions.length ? this.toolDefinitions : undefined,\n attachments: attachmentsForCall,\n // Per-turn signal: aborts on user cancel, and (via beginTurn's chain)\n // on driver dispose. Cancels the in-flight request either way.\n signal: this.turnController.signal,\n toolChoice: effectiveToolChoice,\n // Agent/state-configured sampling temperature (normalized 0\u20131); each\n // transport translates it to its native range. Undefined \u2192 provider default.\n temperature: resolvedTemperature,\n // Prompt-cache policy for this turn (Anthropic places breakpoints per scope; Gemini\n // caches implicitly regardless). Undefined \u2192 no caching requested.\n cachePolicy: resolvedCachePolicy,\n // Extended-thinking posture, pinned for the whole tool loop (one assistant turn) rather\n // than re-resolved per iteration \u2014 see `pinnedThinkingPolicy`. Undefined \u2014 unset, or the\n // resolver's answer for this turn \u2014 is NOT \"off\": it leaves the model on its own default,\n // so agents that never set this are priced exactly as before. Transports clamp models\n // that can't honour it.\n thinkingPolicy: pinnedThinkingPolicy,\n // Framed volatile context injected at the message tail (never stored). Undefined \u2192 none.\n tailContext,\n // Structured-output schema for this turn (agent/state-resolved). When set, the transport\n // constrains the final answer to it natively where the model supports it. Undefined \u2192 free text.\n responseSchema: resolvedResponseSchema,\n // Refusal-fallback chain (e.g. Fable 5 \u2192 Opus 4.8). Passed to the provider; applied\n // server-side where supported. Undefined \u2192 no fallback.\n fallbacks: this.activeFallbacks,\n };\n\n // Resolve the active provider for this turn. Static names were validated\n // in `applyAgent`; function-form names are validated on first resolution\n // here and cached for the agent's lifetime.\n // oxlint-disable-next-line no-await-in-loop\n const activeProvider = await this.resolveProviderForTurn(promptCtx);\n\n // Attribute the turn to the tier/model it resolved. Stamped HERE, not inside\n // `recordTurnSnapshot`: the snapshot is taken before this line runs, so reading\n // `lastResolved*` there yields the PREVIOUS call's model \u2014 wrong on precisely the\n // turn where an agent's per-state `provider` selector switches tier, which is the\n // turn a reader is looking for. `model` is refined to the serving model once the\n // response lands (see below); until then \u2014 and on a call that throws \u2014 it is the\n // model we ASKED for, which is the only thing knowable at that point.\n if (this.lastResolvedProviderName !== undefined) {\n turnSnapshot.providerName = this.lastResolvedProviderName;\n }\n if (this.lastResolvedProvider !== undefined)\n turnSnapshot.provider = this.lastResolvedProvider;\n if (this.lastResolvedModel !== undefined) turnSnapshot.model = this.lastResolvedModel;\n\n let response: ChatMessage;\n try {\n // oxlint-disable-next-line no-await-in-loop\n response = await activeProvider.chat!(historyForCall, userInputForCall, options);\n } catch (e) {\n if (e instanceof MalformedFunctionCallError) {\n malformedAttempts += 1;\n if (malformedAttempts < MAX_MALFORMED_RETRIES) {\n logger.warn(\n `ChatDriver: MALFORMED_FUNCTION_CALL, retrying (${malformedAttempts}/${MAX_MALFORMED_RETRIES})`,\n );\n recordTurnRetry(this.sessionKey, 'malformed-function-call', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempt: malformedAttempts,\n maxAttempts: MAX_MALFORMED_RETRIES,\n finishMessage: e.finishMessage,\n });\n iterations -= 1;\n continue;\n }\n logger.error('ChatDriver: MALFORMED_FUNCTION_CALL, max retries reached');\n recordTurnError(this.sessionKey, 'malformed-function-call', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempts: malformedAttempts,\n finishMessage: e.finishMessage,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('malformed_tool_call');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'While working on your request, I repeatedly called my tools incorrectly. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps.',\n });\n }\n return this.turnDone('malformed-function-call');\n }\n // The response was truncated at the provider's output-token cap while it\n // still carried a tool call \u2014 its arguments are incomplete and unusable.\n // Unlike a malformed call this is DETERMINISTIC: re-issuing the same\n // request hits the same cap, so a silent retry just loops. Bail with a\n // clear, actionable signal instead. The remedy is config (raise the\n // provider maxTokens) or a smaller step \u2014 neither is fixed by retrying.\n if (e instanceof ResponseTruncatedError) {\n logger.error('ChatDriver: response truncated at the output-token cap', e);\n recordTurnError(this.sessionKey, 'response-truncated', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n model: e.model,\n maxTokens: e.maxTokens,\n outputTokens: e.outputTokens,\n tools: e.toolNames,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('response_truncated');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'My response was cut off because a single step reached the model output limit. This usually means one step tried to produce too much at once \u2014 try breaking your request into smaller steps.',\n });\n }\n return this.turnDone('response-truncated');\n }\n // The AI-spend budget is gone and the proxy refused the request (HTTP\n // 402). Terminal in the strongest sense available to us: unlike a\n // truncation \u2014 which a smaller request would get past \u2014 *no* request\n // succeeds until someone raises the budget out of band. So there is no\n // retry here and no \"try again\" in the copy; the turn ends and the host\n // locks the composer off the `'budget-exhausted'` failure reason (see\n // `FoundationAiAssistant.blocked`).\n // The upstream vendor refused this ACCOUNT (GENC-1506) \u2014 its credit is gone, a usage cap is\n // reached, or the credential is dead. Terminal in the strongest sense available: unlike a\n // truncation, no smaller request gets past it, and unlike our own budget wall nobody in this\n // system can raise anything to clear it. So no retry and no \"try again\" in the copy.\n //\n // Placed before the transient-retry step below, which is the whole point: without this the\n // error is an untyped transport failure, gets re-issued MAX_SETUP_TRANSPORT_RETRIES times\n // against a wall that cannot move, and then surfaces as \"something went wrong on my end\" \u2014\n // wrong twice over, since nothing went wrong on our end and trying again will not help.\n if (e instanceof ProviderRefusedError) {\n if (this.isSubAgent) {\n logger.error('ChatDriver: provider refused the request', e);\n recordTurnError(this.sessionKey, 'provider-refused', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor: vendorTypeOfLabel(e.vendorLabel) ?? this.lastResolvedProvider,\n kind: e.kind,\n upstreamStatus: e.upstreamStatus,\n upstreamType: e.upstreamType,\n isSubAgent: true,\n });\n // The detail is BUBBLED, not merely flagged. Setting `providerRefusedThisTurn` on `this`\n // would be pointless here \u2014 `this` is the CHILD, and the parent that must stop is a\n // different driver instance. `invokeSubAgent` reads this payload off the child and sets its\n // own flag; see the branch there.\n const detail = providerRefusedDetailOf(e);\n this.failSubAgent('provider_refused', undefined, detail);\n return this.turnDone('provider-refused', undefined, detail);\n }\n return this.reportProviderRefused(e);\n }\n if (e instanceof BudgetExhaustedError) {\n // Flagged as well as returned: a sub-agent's wall reaches the PARENT\n // only as a tool result, and the parent must not issue another model\n // call after it (see the short-circuit at the top of this loop).\n this.budgetExhaustedThisTurn = true;\n this.budgetWallDetail = budgetDetailOf(e);\n // Paired with the detail everywhere it is written: this is the\n // driver's OWN wall, so the sub-agent marker must not survive from an\n // earlier child and suppress the `lastResolvedProvider` fallback that\n // is legitimate here. Unreachable today (the short-circuit fires\n // before a second wall can land in one turn) \u2014 kept structural so the\n // pairing does not depend on that ordering staying true.\n this.budgetWallViaSubAgent = false;\n if (this.isSubAgent) {\n logger.error('ChatDriver: AI budget exhausted', e);\n recordTurnError(this.sessionKey, 'budget-exhausted', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n vendor:\n vendorTypeOfLabel(e.vendorLabel) ??\n vendorTypeOfLabel(e.serverVendor) ??\n this.lastResolvedProvider,\n budgetUsd: e.budgetUsd,\n spentUsd: e.spentUsd,\n isSubAgent: true,\n });\n // Bubble a typed failure to the parent instead of speaking to the\n // user, carrying the attribution so the parent walls the vendor that\n // actually refused rather than its own.\n this.failSubAgent('budget_exhausted', this.budgetWallDetail);\n return this.turnDone('budget-exhausted', this.budgetWallDetail);\n }\n return this.reportBudgetExhausted(e);\n }\n // A request timeout from the transport (tagged `TimeoutError`) is not a\n // bug on our end \u2014 surface it distinctly instead of letting it fall\n // through to the generic \"something went wrong\" catch. No auto-retry:\n // the timeout ceiling is already minutes long, so a silent retry would\n // just make the user wait again.\n if (e instanceof DOMException && e.name === 'TimeoutError') {\n logger.error('ChatDriver: request timed out', e);\n recordTurnError(this.sessionKey, 'exception', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n name: e.name,\n message: e.message,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n // Bubble a typed failure to the parent instead of speaking to the user.\n this.failSubAgent('timeout');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n 'The request timed out. You can ask me to try again, or break this into a smaller step.',\n });\n }\n // Recorded as `exception` above (there is no separate `timeout` member of\n // TurnFailureReason for the main turn); surface the same reason here.\n return this.turnDone('exception');\n }\n // The request was aborted: either a user cancel (turnController) or a\n // driver dispose (lifecycleController, chained into the turn). A user\n // cancel adds a \"Stopped.\" marker; a dispose stops quietly. Handled\n // before the transient-retry below so an intentional abort/timeout is\n // never retried.\n if (e instanceof DOMException && e.name === 'AbortError') {\n return this.completeAbortedTurn();\n }\n // A transient provider/transport error should retry the SAME iteration a bounded\n // number of times rather than tearing down the whole turn (which strands the\n // agent's unflushed buffer behind an opaque error message).\n setupTransportAttempts += 1;\n if (setupTransportAttempts < MAX_SETUP_TRANSPORT_RETRIES) {\n logger.warn(\n `ChatDriver: provider/transport error, retrying (${setupTransportAttempts}/${MAX_SETUP_TRANSPORT_RETRIES})`,\n );\n iterations -= 1;\n continue;\n }\n throw e;\n }\n\n // Attribute the response to the concrete model + registry slot that\n // produced it (resolved for this turn in `resolveProviderForTurn`). Carried\n // on the assistant message so the debug-log timeline shows per-message\n // model lineage \u2014 and thus per-tool-call, since tool calls ride on the\n // assistant message that requests them. Harmless on a response later\n // discarded as empty/retried; only kept copies reach history.\n //\n // Attach each key only when resolved: a provider with no `getStatus` (etc.)\n // leaves the key off entirely rather than carrying it as `undefined`.\n // JSON.stringify already drops undefined from the exported log, so this is\n // chiefly about keeping the in-memory message shape honest.\n // Fill, never overwrite \u2014 but still only when there is something to fill with.\n // A transport that already stamped a model knows something the driver does not:\n // `lastResolvedModel` is the model we ASKED for, so overwriting would relabel a\n // fallback-served turn as the requested model and misattribute its spend.\n // Written as a guard rather than `??=` because `??=` ASSIGNS undefined, which\n // would create the key and break the omit-when-unresolved contract above.\n if (response.model === undefined && this.lastResolvedModel !== undefined) {\n response.model = this.lastResolvedModel;\n }\n if (this.lastResolvedProvider !== undefined) response.provider = this.lastResolvedProvider;\n if (this.lastResolvedProviderName !== undefined) {\n response.providerName = this.lastResolvedProviderName;\n }\n\n // Back-fill what this call cost onto the snapshot taken just before it, so the\n // exported debug log prices each model call next to the prompt/tools/state that\n // produced it (GENC-1480 follow-up). Stamped BEFORE the empty-response branch\n // below deliberately: a blank or refused response is billed and then thrown away,\n // so the snapshot is the only place that spend is ever recorded.\n turnSnapshot.usage = messageUsage(response);\n // Take the SERVING model over the requested one, now that it is known. `response.model`\n // was just filled from `lastResolvedModel` if the transport left it unset, so this is\n // the same rule the message gets \u2014 which is the point: a turn and the message it\n // produced must never disagree about which model ran, including when a server-side\n // fallback chain answered on a different model than the one we asked for.\n if (response.model !== undefined) turnSnapshot.model = response.model;\n\n const isThinkingStep = response.content && response.toolCalls?.length;\n const isEmptyResponse = !response.content?.trim() && !response.toolCalls?.length;\n // A pre-output refusal (safety-classifier decline, e.g. Fable 5 `stop_reason: 'refusal'`)\n // comes back with empty content, so it looks like a blank response \u2014 but it is deterministic:\n // retrying re-sends the identical request and refuses again, burning up to\n // MAX_EMPTY_RESPONSE_RETRIES turns on the most expensive models for the same outcome, ending\n // in the misleading \"blank response\" message. Treat it as a terminal, non-retried failure with\n // its own reason and message. (GENC-1461)\n const isRefusal = response.responseMeta?.finishReason === 'refusal';\n\n if (isEmptyResponse) {\n emptyResponseAttempts += 1;\n if (!isRefusal && emptyResponseAttempts < MAX_EMPTY_RESPONSE_RETRIES) {\n logger.warn(\n `ChatDriver: empty model response, retrying (${emptyResponseAttempts}/${MAX_EMPTY_RESPONSE_RETRIES})`,\n );\n recordTurnRetry(this.sessionKey, 'empty-response', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempt: emptyResponseAttempts,\n maxAttempts: MAX_EMPTY_RESPONSE_RETRIES,\n // Provider diagnostic (Gemini: finishReason, thoughtsTokens, parts,\n // blockReason) so the timeline shows *why* the turn came back blank \u2014\n // e.g. a high thoughtsTokens with a 'STOP' finish is \"thought, then\n // stopped without answering\".\n ...response.responseMeta,\n });\n iterations -= 1;\n continue;\n }\n const failureReason = isRefusal ? 'refusal' : 'empty-response';\n logger.error(\n isRefusal\n ? 'ChatDriver: model refused the request (safety decline) \u2014 not retrying'\n : 'ChatDriver: empty model response after all retries',\n );\n recordTurnError(this.sessionKey, failureReason, {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n attempts: emptyResponseAttempts,\n isSubAgent: this.isSubAgent,\n ...response.responseMeta,\n });\n if (this.isSubAgent) {\n this.failSubAgent(isRefusal ? 'refusal' : 'empty_response');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content: isRefusal\n ? 'This request was declined. Try rephrasing it, or breaking it into smaller steps.'\n : 'While working on your request, I repeatedly generated a blank response. This often works on a second try \u2014 would you like me to try again? If it happens again, try breaking your request into smaller steps.',\n });\n }\n return this.turnDone(failureReason);\n } else {\n // Split one model response into separate, individually-toggleable messages so each has its\n // own visibility toggle and debug-log category:\n // - reasoning (chain-of-thought summary) \u2192 category 'reasoning', hidden unless showThinkingSteps\n // - narration (interstitial prose emitted alongside a tool call) \u2192 category 'narration',\n // hidden unless showNarration\n // - the answer / tool-call message \u2192 always shown; carries this turn's usage.\n // Cost invariant (GENC-1410): exactly ONE message carries cost/tokens and is appended LAST, so\n // `sumCosts`/`sumTokens` don't double-count and `contextTokens` reads it. Reasoning/narration are\n // display-only (usage undefined) and are skipped when building the provider request. `model` /\n // `provider` / `providerName` stay on every split message so each is still attributed.\n //\n // EVERY usage field has to be cleared here, not just the three the invariant was\n // originally written against \u2014 keep this list in step with the usage fields on\n // `ChatMessage`. The cache buckets arrived later (GENC-1475) and were left riding\n // along on the copies, so a response carrying reasoning AND narration counted its\n // cache read/write volume three times in `sumUsage`/`usageRows` \u2014 invisible in the\n // cost total (which comes from `cost`) but wrong in every bucket display and in the\n // exported log.\n const { reasoning, ...rest } = response;\n const displayOnly = {\n cost: undefined,\n externalCostUsd: undefined,\n inputTokens: undefined,\n outputTokens: undefined,\n cacheReadTokens: undefined,\n cacheWriteTokens: undefined,\n };\n if (reasoning) {\n this.appendToHistory({\n ...rest,\n ...displayOnly,\n content: reasoning,\n toolCalls: undefined,\n category: 'reasoning',\n });\n }\n if (isThinkingStep) {\n // content + tool call \u2192 the content is interstitial narration, not the final answer.\n this.appendToHistory({\n ...rest,\n ...displayOnly,\n toolCalls: undefined,\n category: 'narration',\n });\n this.appendToHistory({ ...rest, content: '' });\n } else {\n // No tool call \u2192 `content` is the final answer (always shown), or this is a bare tool-call\n // turn with no narration. Either way it carries this turn's usage; append it last.\n this.appendToHistory(rest);\n }\n }\n\n // Reset retry budgets on any productive (non-empty) response, so the caps mean\n // \"N CONSECUTIVE failures\" not \"N total per turn\".\n emptyResponseAttempts = 0;\n malformedAttempts = 0;\n setupTransportAttempts = 0;\n\n if (!response.toolCalls?.length) {\n break;\n }\n\n const [toolCalls, systemCalls] = response.toolCalls.reduce<[ChatToolCall[], ChatToolCall[]]>(\n (acc, tc) => {\n if (tc.name === REQUEST_CONTINUATION_TOOL) acc[1].push(tc);\n else acc[0].push(tc);\n return acc;\n },\n [[], []],\n );\n\n const executedById = new Map<\n string,\n {\n toolCallId: string;\n content: string;\n attachments?: ChatImageAttachment[];\n subAgentTrace?: ChatMessage[];\n }\n >();\n const unknownToolIds = new Set<string>();\n // Subset of unknownToolIds that were stale (previously available) rather\n // than hallucinated \u2014 drives the `stale` UI flag back-patched below.\n const staleToolIds = new Set<string>();\n let anyRealToolExecuted = false;\n let hitUnknownToolLimit = false;\n\n if (toolCalls.length > 0) {\n // oxlint-disable-next-line no-await-in-loop -- Promise.all is correct parallelism, not sequential loop awaiting\n await Promise.all(\n toolCalls.map(async (tc) => {\n // Check for fold facade\n const fold = this.getFold(tc.name);\n if (fold) {\n this.consecutiveFoldOps += 1;\n if (this.consecutiveFoldOps > this.maxFoldOperations) {\n logger.warn(\n `ChatDriver: fold operation limit (${this.maxFoldOperations}) reached \u2014 injecting guidance`,\n );\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `You have opened and closed folds ${this.consecutiveFoldOps} times without calling any tools. Please call a specific tool to make progress, or respond to the user.`,\n });\n return;\n }\n const content = await this.openFold(tc.name, fold, tc.args, tc.id);\n executedById.set(tc.id, { toolCallId: tc.id, content });\n // Fold open/close does NOT count as a real iteration \u2014 decrement to compensate\n iterations -= 1;\n return;\n }\n\n // Check for close-fold tool\n if (tc.name.startsWith('close_') && this.foldStack.length > 0) {\n const topFoldName = this.foldStack[this.foldStack.length - 1].foldName;\n if (tc.name === `close_${topFoldName}`) {\n this.consecutiveFoldOps += 1;\n if (this.consecutiveFoldOps > this.maxFoldOperations) {\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `You have opened and closed folds ${this.consecutiveFoldOps} times without calling any tools. Please call a specific tool to make progress, or respond to the user.`,\n });\n return;\n }\n const content = this.closeFold();\n executedById.set(tc.id, { toolCallId: tc.id, content });\n iterations -= 1;\n return;\n }\n }\n\n // Regular tool \u2014 check if it's inside a fold and guide the model\n const handler = this.toolHandlers[tc.name];\n if (!handler) {\n const containingFold = this.findFoldContaining(tc.name);\n if (containingFold) {\n logger.debug(\n `ChatDriver: model called folded tool \"${tc.name}\" \u2014 guiding to open \"${containingFold}\"`,\n );\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: 'folded',\n fold: containingFold,\n });\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content: `\"${tc.name}\" is not directly available. It is inside the \"${containingFold}\" fold. Call ${containingFold} first to access it.`,\n });\n // Guidance does not count as a real iteration or fold op\n iterations -= 1;\n return;\n }\n\n // Not in any registered fold. If the tool was advertised earlier\n // in this agent's lifetime it's *stale* (a stateful agent moved on,\n // or an exclusive fold is hiding it) rather than hallucinated \u2014 a\n // distinction worth making, because the model should stop retrying\n // a retired tool rather than treat the failure as a typo. Stale\n // calls still trip loop protection, but at a higher ceiling than\n // hallucinated tools (see below) \u2014 they are self-correcting, so the\n // guidance, telemetry, and limit differ.\n if (this.everSeenToolNames.has(tc.name)) {\n this.consecutiveUnknownToolCalls += 1;\n const hidingFold = this.foldHidingTool(tc.name);\n let content: string;\n if (hidingFold) {\n content = `\"${tc.name}\" is not available while the \"${hidingFold}\" fold is open. Call close_${hidingFold} to return to the previous set of tools, then call ${tc.name}.`;\n logger.warn(\n `ChatDriver: tool \"${tc.name}\" is hidden behind open fold \"${hidingFold}\" (${this.consecutiveUnknownToolCalls}/${MAX_STALE_TOOL_CALLS})`,\n );\n } else {\n content = `\"${tc.name}\" was available earlier but is not part of the current step \u2014 that step is complete, so do not call it again. Continue with the tools available now: ${Object.keys(this.toolHandlers).join(', ') || '(none)'}.`;\n logger.warn(\n `ChatDriver: stale tool \"${tc.name}\" \u2014 advertised earlier this activation but retired in the current state (${this.consecutiveUnknownToolCalls}/${MAX_STALE_TOOL_CALLS})`,\n );\n }\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: hidingFold ? 'fold-hidden' : 'stale',\n fold: hidingFold ?? undefined,\n consecutive: this.consecutiveUnknownToolCalls,\n max: MAX_STALE_TOOL_CALLS,\n });\n // Fold-hidden tools keep their fold-specific guidance; a plain\n // stale tool is a step-ordering miss, so offer the agent's\n // redirect when it supplies one.\n const staleContent = hidingFold\n ? content\n : await this.resolveUnresolvedToolContent(tc.name, 'stale', content);\n executedById.set(tc.id, { toolCallId: tc.id, content: staleContent });\n unknownToolIds.add(tc.id);\n staleToolIds.add(tc.id);\n this.recentUnknownToolNames.add(tc.name);\n this.recentStaleToolNames.add(tc.name);\n if (this.consecutiveUnknownToolCalls >= MAX_STALE_TOOL_CALLS) {\n hitUnknownToolLimit = true;\n }\n return;\n }\n\n // Never advertised \u2014 a hallucinated tool name.\n this.consecutiveUnknownToolCalls += 1;\n logger.warn(\n `ChatDriver: no handler registered for tool \"${tc.name}\" (${this.consecutiveUnknownToolCalls}/${DEFAULT_MAX_UNKNOWN_TOOL_CALLS}). Available tools: ${Object.keys(this.toolHandlers).join(', ') || '(none)'}`,\n );\n recordMetaEvent(this.sessionKey, 'tool.unresolved', {\n tool: tc.name,\n agent: this.activeAgentName,\n kind: 'unknown',\n consecutive: this.consecutiveUnknownToolCalls,\n max: DEFAULT_MAX_UNKNOWN_TOOL_CALLS,\n availableTools: Object.keys(this.toolHandlers),\n });\n const unknownContent = await this.resolveUnresolvedToolContent(\n tc.name,\n 'unknown',\n `Unknown tool: ${tc.name}`,\n );\n executedById.set(tc.id, { toolCallId: tc.id, content: unknownContent });\n unknownToolIds.add(tc.id);\n this.recentUnknownToolNames.add(tc.name);\n if (this.consecutiveUnknownToolCalls >= DEFAULT_MAX_UNKNOWN_TOOL_CALLS) {\n hitUnknownToolLimit = true;\n }\n return;\n }\n\n // Real tool execution.\n //\n // The accumulator is declared OUTSIDE the try so the catch can attach it\n // too: a handler that ran sub-agents and then threw (post-processing their\n // results failed, say) has already spent real money on children that\n // completed. Losing their traces on the error path would under-report the\n // run exactly as the single-slot bug did \u2014 and just as silently, since\n // `sumUsage` and `usageRows` would still agree with each other.\n const traceCapture: { traces: ChatMessage[][] } = { traces: [] };\n const capturedTrace = (): ChatMessage[] | undefined =>\n traceCapture.traces.length ? traceCapture.traces.flat() : undefined;\n try {\n const result = await handler(tc.args, this.buildHandlerContext(tc.id, traceCapture));\n // A handler that returns images gets them carried as real attachments instead of\n // JSON-stringified into the text \u2014 the difference between a model reading\n // `{\"kind\":\"image\",\"data\":\"iVBOR\u2026\"}` as prose and actually SEEING the render.\n // The guard is deliberately narrow (every entry must carry `kind: 'image'`) so an\n // ordinary object return that happens to have an `attachments` key still\n // stringifies exactly as before.\n const resultImages = toolResultImages(result);\n const content = resultImages\n ? typeof (result as { content?: unknown }).content === 'string'\n ? (result as { content: string }).content\n : JSON.stringify({ ...(result as object), attachments: undefined })\n : typeof result === 'string'\n ? result\n : JSON.stringify(result);\n executedById.set(tc.id, {\n toolCallId: tc.id,\n content,\n ...(resultImages ? { attachments: resultImages } : {}),\n // Concatenated when a handler invoked several children, so none is lost.\n // Stays `undefined` when nothing was captured \u2014 readers key off presence,\n // and an empty array is a different claim from \"no sub-agent ran\".\n subAgentTrace: capturedTrace(),\n });\n anyRealToolExecuted = true;\n } catch (e) {\n logger.error(`ChatDriver tool \"${tc.name}\" failed:`, e);\n recordMetaEvent(this.sessionKey, 'tool.failed', {\n tool: tc.name,\n agent: this.activeAgentName,\n message: e instanceof Error ? e.message : String(e),\n });\n executedById.set(tc.id, {\n toolCallId: tc.id,\n // Structured recovery hint so the model retries or routes around a tool\n // failure instead of apologising and giving up.\n content: `Tool error: ${(e as Error).message}\\nRECOVERY: this tool failed once \u2014 you may retry it, or take a different valid action to make progress. Do NOT abandon the task, ask the user to rephrase, or claim you cannot make changes. If a planning tool failed, retry it or proceed with the information you already have.`,\n // Children that completed before the throw were still billed \u2014 keep\n // their traces so the run's cost stays whole.\n subAgentTrace: capturedTrace(),\n });\n anyRealToolExecuted = true; // treat errors as real work for fold op counting\n }\n }),\n );\n }\n\n // Reset counters whenever a real tool executes\n if (anyRealToolExecuted) {\n this.consecutiveFoldOps = 0;\n this.consecutiveUnknownToolCalls = 0;\n this.recentUnknownToolNames.clear();\n this.recentStaleToolNames.clear();\n }\n\n // Tag tool calls with fold UI metadata before appending results\n const foldPath = this.foldStack.map((f) => f.foldName);\n\n for (const tc of response.toolCalls) {\n if (tc.name === REQUEST_CONTINUATION_TOOL) {\n this.appendToHistory({\n role: 'tool',\n content: '',\n toolResult: { toolCallId: tc.id, content: HANDOFF_TOOL_RESULT_PLACEHOLDER },\n });\n } else {\n const r = executedById.get(tc.id);\n if (r) {\n // Persist only `toolCallId`/`content` on the tool result \u2014 the sub-agent\n // trace lives on the tool *call* (back-patched below from `executedById`),\n // which is what the UI's trace panel and `sumCosts` read. Appending the\n // trace here too would duplicate the entire child conversation in history\n // (and the exported debug log) for no reader.\n this.appendToHistory({\n role: 'tool',\n content: '',\n toolResult: {\n toolCallId: r.toolCallId,\n content: r.content,\n // Images DO persist, unlike the sub-agent trace above: they are the payload\n // the model must see on every replay of this turn, not a one-off UI artefact.\n // `condenseWhen` is what sheds them once they are spent \u2014 see condense-history.\n ...(r.attachments ? { attachments: r.attachments } : {}),\n },\n });\n }\n }\n }\n\n // Back-patch foldEvent and foldPath onto the tool call message we just appended.\n // The response was appended before execution \u2014 find it and annotate.\n let tcMsgIdx = -1;\n for (let i = this.history.length - 1; i >= 0; i -= 1) {\n if (this.history[i].role === 'assistant' && this.history[i].toolCalls?.length) {\n tcMsgIdx = i;\n break;\n }\n }\n if (tcMsgIdx !== -1) {\n const tcMsg = this.history[tcMsgIdx];\n const availableToolNames = Object.keys(this.toolHandlers);\n const annotatedCalls = tcMsg.toolCalls!.map((tc) => {\n const isFoldOpen =\n !!this.getFold(tc.name) ||\n // Was a fold facade at time of the call (now the tool set has changed)\n // \u2014 detect by checking if the result message indicated a fold open\n executedById.get(tc.id)?.content?.startsWith('Fold opened:');\n const isFoldClose = executedById.get(tc.id)?.content?.startsWith('Fold closed:');\n const isUnknown = unknownToolIds.has(tc.id);\n return {\n ...tc,\n foldEvent: isFoldOpen\n ? ('open' as const)\n : isFoldClose\n ? ('close' as const)\n : undefined,\n // Use the fold path that was active at the START of this iteration (before any opens/closes)\n foldPath: !isFoldOpen && !isFoldClose && foldPath.length > 0 ? foldPath : undefined,\n unknown: isUnknown || undefined,\n availableTools: isUnknown ? availableToolNames : undefined,\n // Distinguish a retired tool from a hallucinated one so the UI can\n // say \"no longer available here\" rather than \"does not exist\".\n stale: staleToolIds.has(tc.id) || undefined,\n subAgentTrace: executedById.get(tc.id)?.subAgentTrace,\n };\n });\n this.history[tcMsgIdx] = { ...tcMsg, toolCalls: annotatedCalls };\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n\n if (hitUnknownToolLimit) {\n logger.error(\n `ChatDriver: unknown-tool limit (${DEFAULT_MAX_UNKNOWN_TOOL_CALLS}) reached \u2014 stopping`,\n );\n const unknownTools = [\n ...new Set([\n ...this.recentUnknownToolNames,\n ...(response.toolCalls ?? [])\n .filter((tc) => unknownToolIds.has(tc.id))\n .map((tc) => tc.name),\n ]),\n ];\n // Stale tools were real earlier this activation; hallucinated tools\n // never existed. The hard stop counts both the same way, but the split\n // tells a triager whether the cause is a state/prompt-design problem\n // (stale) or a model inventing tool names (hallucinated).\n const staleTools = [\n ...new Set([\n ...this.recentStaleToolNames,\n ...(response.toolCalls ?? [])\n .filter((tc) => staleToolIds.has(tc.id))\n .map((tc) => tc.name),\n ]),\n ];\n const hallucinatedTools = unknownTools.filter((t) => !staleTools.includes(t));\n recordTurnError(this.sessionKey, 'unknown-tool-limit', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n unknownTools,\n staleTools,\n hallucinatedTools,\n availableTools: Object.keys(this.toolHandlers),\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('unknown_tool_limit');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n \"I'm sorry, I repeatedly tried to use tools that aren't available to me, so I couldn't complete that. If a 'Download agent log' option appears in the Settings (cog) menu, you can download the log and share it with whoever set up this assistant to help fix the issue.\",\n });\n }\n return this.turnDone('unknown-tool-limit');\n }\n\n const firstContinuation = systemCalls[0];\n if (firstContinuation) {\n const { summary, remaining_task: remainingTask } = firstContinuation.args as {\n summary: string;\n remaining_task: string;\n };\n return { reason: 'agent-handoff', summary, remainingTask };\n }\n\n // Sub-agent early exit \u2014 checked here so the exit point mirrors the\n // system-call pattern above. Set by completeSubAgent() in a tool handler.\n if (this.subAgentCompletion) {\n return this.turnDone();\n }\n }\n\n // The loop fell through: either it hit the iteration cap (a failure) or it\n // broke on a clean final answer (success). Only the former carries a reason.\n let failureReason: TurnFailureReason | undefined;\n if (iterations >= this.maxToolIterations) {\n logger.warn('ChatDriver: reached max tool iterations, stopping');\n recordTurnError(this.sessionKey, 'max-iterations', {\n agent: this.activeAgentName,\n provider: this.lastResolvedProviderName,\n iterations,\n limit: this.maxToolIterations,\n isSubAgent: this.isSubAgent,\n });\n if (this.isSubAgent) {\n this.failSubAgent('max_iterations');\n } else {\n this.appendToHistory({\n role: 'assistant',\n content:\n \"I've reached my limit for this response. You can ask me to continue and I'll pick up where I left off.\",\n });\n }\n failureReason = 'max-iterations';\n }\n\n return this.turnDone(failureReason);\n }\n\n private appendToHistory(message: ChatMessage): void {\n const tagged: ChatMessage = {\n ...message,\n // Stamp on first append; preserve any caller-supplied timestamp.\n timestamp: message.timestamp ?? new Date().toISOString(),\n ...(this.activeAgentName\n ? {\n agentName: this.activeAgentName,\n // Display-only \u2014 falls back to agentName in renderers when unset.\n agentLabel: this.activeAgentLabel,\n }\n : {}),\n };\n this.history = [...this.history, tagged];\n this.dispatchEvent(\n new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {\n detail: this.history,\n }),\n );\n }\n}\n", "import type {\n AIProviderRegistry,\n ChatAttachment,\n ChatDriverResult,\n ChatMessage,\n ChatRequestOptions,\n} from '@genesislcap/foundation-ai';\nimport { BudgetExhaustedError } from '@genesislcap/foundation-ai';\nimport type { ActivityBus } from '../../channel/ai-activity-bus';\nimport type {\n AgentConfig,\n FallbackAgentConfig,\n SpecialistAgentConfig,\n SystemPromptContext,\n SystemPromptInput,\n} from '../../config/config';\nimport { validateStaticAgentProviders } from '../../config/validate-providers';\nimport { recordMetaEvent } from '../../state/debug-event-log';\nimport type { DiagnosticEntry } from '../../state/persistence/diagnostics';\nimport type { InteractionContext } from '../../types/interaction-context';\nimport { transformHistoryForAgent } from '../../utils/history-transform';\nimport { logger } from '../../utils/logger';\nimport type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';\nimport {\n ChatDriver,\n REQUEST_CONTINUATION_TOOL,\n type TurnSnapshot,\n} from '../chat-driver/chat-driver';\n\nconst DEFAULT_MAX_HANDOFFS = 3;\nconst DEFAULT_CLASSIFIER_HISTORY_LENGTH = 4;\nconst DEFAULT_CLASSIFIER_RETRIES = 2;\n\nconst REQUEST_CONTINUATION_DEFINITION = {\n name: REQUEST_CONTINUATION_TOOL,\n description:\n \"Call this when you have completed your part of the task but fulfilling the user's full request requires capabilities outside your domain. Do not call this if you can complete the request yourself. Pass a plain-language description of what still needs to be done \u2014 another specialist will be selected automatically.\",\n parameters: {\n type: 'object',\n required: ['summary', 'remaining_task'],\n properties: {\n summary: {\n type: 'string',\n description: 'What you found or did \u2014 passed as context to the next specialist.',\n },\n remaining_task: {\n type: 'string',\n description:\n 'What still needs to be done, in plain language. Used to route to the right specialist.',\n },\n },\n },\n};\n\nfunction isSpecialist(agent: AgentConfig): agent is SpecialistAgentConfig {\n return !agent.fallback;\n}\n\nfunction isFallback(agent: AgentConfig): agent is FallbackAgentConfig {\n return agent.fallback === true;\n}\n\nfunction buildFallbackSystemPrompt(\n fallback: FallbackAgentConfig,\n specialists: SpecialistAgentConfig[],\n): SystemPromptInput | undefined {\n const agentList = specialists.map((s) => `- ${s.name}: ${s.description}`).join('\\n');\n if (typeof fallback.systemPrompt === 'string') {\n return fallback.systemPrompt.replace('{{agents}}', agentList);\n }\n if (typeof fallback.systemPrompt === 'function') {\n // Function-form fallback prompt \u2014 pass through unchanged. The `{{agents}}`\n // substitution is a string-template convenience; consumers using the\n // function form can compose the agent list themselves if they want it.\n return fallback.systemPrompt;\n }\n return `You are a helpful assistant. You cannot directly help with the user's request, but the following specialists are available:\\n\\n${agentList}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request.`;\n}\n\n/**\n * Orchestrates multiple specialist agents. Sits between `FoundationAiAssistant`\n * and `ChatDriver`, classifying each user message and routing it to the right\n * specialist \u2014 each with its own focused system prompt, tools, and primer.\n *\n * @beta\n */\nexport class OrchestratingDriver extends EventTarget implements AiDriver {\n private readonly chatDriver: ChatDriver;\n private readonly specialists: SpecialistAgentConfig[];\n private readonly fallback?: FallbackAgentConfig;\n private readonly maxHandoffs: number;\n private readonly classifierHistoryLength: number;\n private readonly classifierRetries: number;\n private readonly sessionKey: string;\n /**\n * Aborted on driver disposal. Threaded into `AgentLifecycleContext.signal`\n * so long-running `onActivate` work can bail if the session disconnects.\n */\n private readonly lifecycleAbortController = new AbortController();\n /**\n * Set by `cancel()` for the duration of a `sendMessage` run. Breaks the\n * handoff loop so we don't classify or start another agent turn after the\n * user stops. Reset at the start of each `sendMessage`.\n */\n private cancelled = false;\n /**\n * Whether the CURRENT turn's user message has reached the inner driver's\n * history. False through the pre-first-turn classify (where the only echo of\n * the message is an optimistic `history-updated` dispatch), true from the\n * moment `chatDriver.sendMessage` is entered \u2014 including through every later\n * handoff classify. Read by the budget-wall catch in `sendMessage` to decide\n * whether `reportBudgetExhausted` must append the message itself: appending\n * it when already appended duplicated it; not appending it when unappended\n * made it vanish. Reset at the top of each `runOrchestratedTurn`.\n */\n private userMessageAppended = false;\n /**\n * Sticky user pick from the picker (or the host's `setAgent` API). Only\n * changes on explicit user action. Survives flow completion: when a stateful\n * agent releases, the user-pin stays put and routing falls back to it on\n * the next turn.\n */\n private pinnedAgentName: string | null = null;\n /**\n * Transient flow lock \u2014 set when a stateful agent's `onActivate` fires,\n * cleared by `releaseActiveAgent`. While non-null, routing precedence goes\n * to this agent and the picker is locked. Independent of\n * `pinnedAgentName` so completing a flow doesn't wipe the user's sticky\n * choice.\n */\n private flowOwnerAgentName: string | null = null;\n\n /**\n * Per-agent restored state for a rehydrated session, keyed by agent name.\n * Primed by the host on restore; each entry is passed to that agent's\n * `onActivate` as `ctx.restored` on its next activation, then deleted so a\n * later re-activation starts fresh.\n */\n private restoredAgentStates: Record<string, unknown> = {};\n\n activeAgent?: AgentConfig;\n\n constructor(\n private readonly providerRegistry: AIProviderRegistry,\n private readonly agents: AgentConfig[],\n options: {\n sessionKey?: string;\n maxHandoffs?: number;\n classifierHistoryLength?: number;\n classifierRetries?: number;\n maxToolIterations?: number;\n maxFoldOperations?: number;\n maxTurnSnapshots?: number;\n /** Activity bus passed through to the inner ChatDriver (browser host injects the singleton). */\n activityBus?: ActivityBus;\n /** Budget-wall transcript copy, passed through to the inner ChatDriver (GENC-1464). */\n budgetExhaustedMessage?: string;\n } = {},\n ) {\n super();\n this.sessionKey = options.sessionKey ?? '';\n this.maxHandoffs = options.maxHandoffs ?? DEFAULT_MAX_HANDOFFS;\n this.classifierHistoryLength =\n options.classifierHistoryLength ?? DEFAULT_CLASSIFIER_HISTORY_LENGTH;\n this.classifierRetries = options.classifierRetries ?? DEFAULT_CLASSIFIER_RETRIES;\n\n // Static-name validation: walk every agent (and nested sub-agents). Any\n // `provider: '<name>'` that isn't registered, or resolves to a provider\n // without `chat()`, throws now rather than at first turn.\n validateStaticAgentProviders(agents, providerRegistry);\n\n // Specialists drive the classifier. `excludeFromClassifier` agents are still\n // resolvable by name (so manual pinning works) but never auto-routed.\n this.specialists = agents.filter(isSpecialist).filter((a) => !a.excludeFromClassifier);\n const fallbacks = agents.filter(isFallback);\n if (fallbacks.length > 1) {\n logger.warn(\n 'OrchestratingDriver: multiple fallback agents found \u2014 only the first will be used.',\n );\n }\n\n const rawFallback = fallbacks[0];\n this.fallback = rawFallback\n ? { ...rawFallback, systemPrompt: buildFallbackSystemPrompt(rawFallback, this.specialists) }\n : undefined;\n\n this.chatDriver = new ChatDriver(providerRegistry, {\n maxToolIterations: options.maxToolIterations,\n maxFoldOperations: options.maxFoldOperations,\n maxTurnSnapshots: options.maxTurnSnapshots,\n sessionKey: this.sessionKey,\n activityBus: options.activityBus,\n budgetExhaustedMessage: options.budgetExhaustedMessage,\n });\n\n // Proxy events from the shared driver\n this.chatDriver.addEventListener('history-updated', (e: Event) => {\n this.dispatchEvent(new CustomEvent('history-updated', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('sub-agent-history-updated', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('sub-agent-history-updated', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('sub-agent-start', (e: Event) => {\n this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('sub-agent-stop', (e: Event) => {\n this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: (e as CustomEvent).detail }));\n });\n this.chatDriver.addEventListener('interaction-start', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('interaction-start', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('interaction-stop', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('interaction-stop', { detail: (e as CustomEvent).detail }),\n );\n });\n this.chatDriver.addEventListener('provider-changed', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('provider-changed', { detail: (e as CustomEvent).detail }),\n );\n });\n // Post-resolve external cost. The host only ever holds THIS wrapper (`createDriver` returns\n // one for any non-empty `agents`), so an event the inner driver raises and this list omits is\n // an event the host never sees: `recordExternalCost` still delegates and the money still lands\n // on the message, but the totals never refresh and the save is never scheduled \u2014 and in the\n // flow this exists for the interaction is the last thing in the session, so \"stale until the\n // next history change\" means permanently. Reviewer catch on #2474.\n this.chatDriver.addEventListener('external-cost-recorded', (e: Event) => {\n this.dispatchEvent(\n new CustomEvent('external-cost-recorded', { detail: (e as CustomEvent).detail }),\n );\n });\n }\n\n resolveInteraction(interactionId: string, result: unknown): void {\n this.chatDriver.resolveInteraction(interactionId, result);\n }\n\n /** Delegated for the same reason as `resolveInteraction`: the history that owns the\n * interaction \u2014 and therefore the cost \u2014 lives on the wrapped driver, not here. */\n recordExternalCost(interactionId: string, costUsd: number): boolean {\n return this.chatDriver.recordExternalCost(interactionId, costUsd);\n }\n\n getInteractionContext(interactionId: string): InteractionContext | undefined {\n return this.chatDriver.getInteractionContext(interactionId);\n }\n\n isBusy(): boolean {\n return this.chatDriver.isBusy();\n }\n\n /** Currently active provider name from the underlying ChatDriver. */\n getActiveProviderName(): string {\n return this.chatDriver.getActiveProviderName();\n }\n\n /**\n * Pins routing to a specific agent by name. While pinned, the classifier is\n * skipped and the continuation tool is hidden from the agent's tool list, so\n * the agent cannot quietly hand back to the orchestrator. Pass `null` to\n * return to automatic routing.\n */\n setPinnedAgent(name: string | null): void {\n this.pinnedAgentName = name;\n }\n\n /**\n * Set the flow-owner lock \u2014 used to restore state from Redux on driver\n * reconstruction (agents-array changes, pop-in/pop-out). Not intended for\n * external callers to manipulate routing; that's what `setPinnedAgent` is\n * for.\n */\n setFlowOwner(name: string | null): void {\n this.flowOwnerAgentName = name;\n }\n\n loadHistory(messages: ChatMessage[]): void {\n this.chatDriver.loadHistory(messages);\n }\n\n getRawHistory(): readonly ChatMessage[] {\n return this.chatDriver.getHistory();\n }\n\n /** {@inheritDoc AiDriver.compact} */\n compact(): Promise<ChatMessage | null> {\n return this.chatDriver.compact();\n }\n\n /** {@inheritDoc AiDriver.canCompact} */\n canCompact(): boolean {\n return this.chatDriver.canCompact();\n }\n\n /** Delegates to the inner {@link ChatDriver} \u2014 turns are captured there. */\n getTurnSnapshots(): ReadonlyArray<TurnSnapshot> {\n return this.chatDriver.getTurnSnapshots();\n }\n\n /** Delegates to the inner {@link ChatDriver} \u2014 interactions resolve there, so it holds the buffer. */\n getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry> {\n return this.chatDriver.getExternalDiagnostics();\n }\n\n async getSuggestions(\n history: ChatMessage[],\n prompt: string,\n count: number,\n allAgentInfo?: AllAgentSummary[],\n ): Promise<string[]> {\n // When pinned to a specialist, scope suggestions to that agent so the\n // proposed prompts reflect the active routing instead of the full panel.\n const pinned = this.resolvePinnedAgent();\n const candidates = pinned && isSpecialist(pinned) ? [pinned] : this.specialists;\n const agentInfo = candidates.map((s) => ({\n name: s.name,\n description: s.description,\n // Suggestions use tool names for prompt hints. Dynamic agents resolve\n // their tools per-turn against a SystemPromptContext we don't have here\n // \u2014 pass an empty list rather than invoke the factory with a fake one.\n tools: Array.isArray(s.toolDefinitions) ? s.toolDefinitions : [],\n }));\n return this.chatDriver.getSuggestions(history, prompt, count, agentInfo);\n }\n\n async sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult> {\n try {\n return await this.runOrchestratedTurn(input, attachments);\n } catch (e) {\n // The classifier calls the provider directly, outside any ChatDriver turn,\n // so a budget wall raised there would escape as an unhandled rejection \u2014\n // `FoundationAiAssistant.send()` has a `finally` but no `catch`. Land it on\n // the driver that owns the transcript, which appends the user-facing copy\n // and returns the same terminal result an in-loop wall would.\n //\n // The user's message rides along ONLY while it is genuinely unappended.\n // `classify()` runs at two seams: before the first agent turn \u2014 where the\n // `history-updated` dispatch in `runOrchestratedTurn` is optimistic only\n // and the real append lives inside `chatDriver.sendMessage`, which the\n // wall prevents from ever running \u2014 and again at the END of every handoff\n // iteration, by which point `chatDriver.sendMessage` HAS appended it.\n // Passing the message unconditionally duplicated it on the handoff seam:\n // `['user','assistant','tool','user','assistant']` in the transcript, the\n // snapshot, and the history sent to the model once the budget is raised.\n if (e instanceof BudgetExhaustedError) {\n return this.chatDriver.reportBudgetExhausted(\n e,\n this.userMessageAppended\n ? undefined\n : {\n role: 'user',\n content: input,\n ...(attachments ? { attachments } : {}),\n },\n );\n }\n throw e;\n }\n }\n\n private async runOrchestratedTurn(\n input: string,\n attachments?: ChatAttachment[],\n ): Promise<ChatDriverResult> {\n this.cancelled = false;\n this.userMessageAppended = false;\n const history = this.chatDriver.getHistory() as ChatMessage[];\n\n // Emit the user message immediately so the UI reflects it during the classify\n // round-trip \u2014 without this the chat appears frozen until classify returns.\n this.dispatchEvent(\n new CustomEvent('history-updated', {\n detail: [...history, { role: 'user', content: input, attachments }],\n }),\n );\n\n const pinned = this.resolvePinnedAgent();\n if (!pinned) this.dispatchEvent(new CustomEvent('orchestrating-start'));\n let currentAgent = pinned ?? (await this.classify(input, history, this.activeAgent));\n let isHandoff = false;\n let handoffs = 0;\n let handoffSummary = '';\n let remainingTask = '';\n // The outcome of the agent turn that ENDS the loop \u2014 see the return below.\n let lastResult: ChatDriverResult | undefined;\n\n while (true) {\n // Cancelled before a (next) agent turn started \u2014 e.g. during classify.\n // The chat driver appends its own \"Stopped.\" marker when a turn it was\n // running is cancelled, so we just stop here without a duplicate.\n if (this.cancelled) break;\n\n // oxlint-disable-next-line no-await-in-loop\n await this.applyAgent(currentAgent);\n\n let result: ChatDriverResult;\n if (isHandoff) {\n const contextPrimer: ChatMessage[] = handoffSummary\n ? [{ role: 'user', content: `[Context from previous agent]: ${handoffSummary}` }]\n : [];\n // oxlint-disable-next-line no-await-in-loop\n result = await this.chatDriver.continueFromHistory(contextPrimer);\n } else {\n // From here the inner driver owns the user message \u2014 it appends it as\n // its first act, before any provider call can throw. Set BEFORE the\n // await so a wall raised anywhere inside the turn (or on a later\n // handoff classify) sees the append as done.\n this.userMessageAppended = true;\n // oxlint-disable-next-line no-await-in-loop\n result = await this.chatDriver.sendMessage(input, attachments);\n }\n lastResult = result;\n\n // Release check: a stateful agent called `releaseAgent` from a terminal\n // tool handler. Fire onDeactivate, clear the pin, drop the user back to\n // classifier-mode. The LLM has already emitted its final wrap-up message\n // by the time we get here \u2014 release is purely a teardown.\n if (this.chatDriver.getAgentReleaseRequested()) {\n // oxlint-disable-next-line no-await-in-loop\n await this.releaseActiveAgent();\n break;\n }\n\n // Pinned agents never hand off \u2014 the continuation tool is filtered out in\n // applyAgent, but this guards against a model hallucinating a handoff result.\n if (result.reason !== 'agent-handoff' || isFallback(currentAgent) || pinned) {\n break;\n }\n\n handoffs += 1;\n if (handoffs > this.maxHandoffs) {\n this.appendInlineMessage(\n `I wasn't able to fully complete your request \u2014 the task required more hand-offs between specialists than allowed. Please try breaking your request into smaller steps.`,\n );\n break;\n }\n\n handoffSummary = result.summary;\n remainingTask = result.remainingTask;\n isHandoff = true;\n\n const updatedHistory = this.chatDriver.getHistory() as ChatMessage[];\n this.dispatchEvent(new CustomEvent('orchestrating-start'));\n // oxlint-disable-next-line no-await-in-loop\n currentAgent = await this.classify(remainingTask, updatedHistory);\n }\n\n // The orchestrated turn reports the outcome of the agent turn that ENDED it.\n // The hardcoded `{ reason: 'done' }` that used to live here made every\n // typed failure unreachable for an agents-configured host \u2014 including\n // `'budget-exhausted'`, which the element latches its blocked state off.\n //\n // \"Last wins\" cannot hide an earlier failure behind a later success: a\n // failing inner turn always ends the loop, because the loop only continues\n // on `reason === 'agent-handoff'`. The two breaks that hold a non-'done'\n // result (the handoff cap, and the pinned/fallback break) both carry\n // `'agent-handoff'`, which is an internal routing protocol that must never\n // escape to the host \u2014 the collapse below strips it. A cancel before the\n // first turn leaves `lastResult` undefined; the release break returns the\n // inner turn's real result, which is correct, because that turn ran.\n return lastResult?.reason === 'done' ? lastResult : { reason: 'done' };\n }\n\n async continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult> {\n return this.chatDriver.continueFromHistory(transientPrimer);\n }\n\n /** {@inheritDoc AiDriver.primeRestoredAgentState} */\n primeRestoredAgentState(snapshots: Record<string, unknown>): void {\n this.restoredAgentStates = { ...snapshots };\n }\n\n /** {@inheritDoc AiDriver.getActiveAgent} */\n getActiveAgent(): AgentConfig | undefined {\n return this.activeAgent;\n }\n\n private async applyAgent(agent: AgentConfig): Promise<void> {\n const previousAgent = this.activeAgent;\n const isSwitch = !previousAgent || previousAgent.name !== agent.name;\n\n // Record the agent transition on the debug-log timeline. A `null` `from`\n // marks the initial activation; a named `from` is a handoff between agents.\n if (isSwitch) {\n recordMetaEvent(this.sessionKey, 'agent.handoff', {\n from: previousAgent?.name ?? null,\n to: agent.name,\n // GENC-1351: was a restored snapshot waiting for this agent at activation?\n restored: this.restoredAgentStates[agent.name] !== undefined,\n });\n }\n\n // Fire lifecycle hooks around the swap \u2014 outgoing first, then incoming.\n // Both are awaited so a heavy `onActivate` (e.g. machine restore) completes\n // before the agent's first turn runs.\n if (isSwitch && previousAgent?.onDeactivate) {\n try {\n await previousAgent.onDeactivate({\n agentName: previousAgent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: onDeactivate(\"${previousAgent.name}\") threw:`, e);\n }\n }\n if (isSwitch && agent.onActivate) {\n // On a session restore, hand this agent its persisted state exactly once\n // (consumed here) so a stateful machine resumes at the right step; a later\n // re-activation of the same agent then starts fresh.\n const restored = this.restoredAgentStates[agent.name];\n if (restored !== undefined) delete this.restoredAgentStates[agent.name];\n try {\n await agent.onActivate({\n agentName: agent.name,\n sessionKey: this.sessionKey,\n previousAgentName: previousAgent?.name,\n signal: this.lifecycleAbortController.signal,\n restored,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: onActivate(\"${agent.name}\") threw:`, e);\n }\n }\n\n const hasLifecycleHooks = !!(agent.onActivate || agent.onDeactivate);\n\n // Stateful agents auto-lock the flow on activation. The lock guarantees\n // the machine survives subsequent turns (the classifier would otherwise be\n // free to route away mid-flow, tearing the machine down). Release happens\n // when the agent calls `releaseAgent` from a terminal-state tool handler\n // \u2014 see the post-sendMessage check below. We write `flowOwnerAgentName`\n // rather than `pinnedAgentName` so completing a flow doesn't wipe the\n // user's sticky picker choice.\n if (isSwitch && hasLifecycleHooks && this.flowOwnerAgentName !== agent.name) {\n this.flowOwnerAgentName = agent.name;\n this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: agent.name }));\n }\n\n // Terminal agents do not get the cross-agent handoff tool. Four cases:\n // \u2022 fallback \u2014 already a leaf; handoff would loop\n // \u2022 user-pinned \u2014 user explicitly selected this agent; do not auto-route away\n // \u2022 flow-owner \u2014 a stateful flow is mid-stream; do not auto-route away\n // \u2022 stateful \u2014 agents with lifecycle hooks own state for the duration of\n // their flow. Initiating a handoff mid-flow would abandon\n // that state with no clean exit and dump the user into the\n // classifier mid-machine. Capture the tool loop until the\n // user (or the agent itself, via `releaseAgent`) releases.\n const isTerminal =\n isFallback(agent) ||\n this.pinnedAgentName !== null ||\n this.flowOwnerAgentName !== null ||\n hasLifecycleHooks;\n\n let agentToApply: AgentConfig = agent;\n if (!isTerminal) {\n const declaredTools = agent.toolDefinitions;\n agentToApply = {\n ...agent,\n toolDefinitions:\n typeof declaredTools === 'function'\n ? async (ctx: SystemPromptContext) => [\n ...(await declaredTools(ctx)),\n REQUEST_CONTINUATION_DEFINITION,\n ]\n : [...(declaredTools ?? []), REQUEST_CONTINUATION_DEFINITION],\n };\n }\n\n if (previousAgent && previousAgent.name !== agent.name) {\n const rawHistory = this.chatDriver.getHistory() as ChatMessage[];\n this.chatDriver.loadHistory([\n ...rawHistory,\n { role: 'system-event', content: agent.name, timestamp: new Date().toISOString() },\n ]);\n }\n\n this.chatDriver.setProviderHistoryTransform((h) => transformHistoryForAgent(h, agent.name));\n this.chatDriver.applyAgent(agentToApply);\n this.activeAgent = agent;\n this.dispatchEvent(new CustomEvent('orchestrating-stop'));\n this.dispatchEvent(new CustomEvent('agent-changed', { detail: agent }));\n }\n\n /**\n * Release the current stateful agent: fire `onDeactivate`, clear the\n * flow-owner lock, dispatch events so the host (and Redux) reflect the\n * unlocked state. Called automatically when a tool handler invokes\n * `context.releaseAgent`.\n *\n * The user-pin (`pinnedAgentName`) is intentionally *not* cleared \u2014 a user\n * who explicitly picked this agent should stay on it after the flow ends,\n * so the next message starts a fresh flow on the same agent rather than\n * routing through the classifier.\n */\n private async releaseActiveAgent(): Promise<void> {\n const agent = this.activeAgent;\n if (!agent) return;\n if (agent.onDeactivate) {\n try {\n await agent.onDeactivate({\n agentName: agent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: release onDeactivate(\"${agent.name}\") threw:`, e);\n }\n }\n this.activeAgent = undefined;\n if (this.flowOwnerAgentName !== null) {\n this.flowOwnerAgentName = null;\n this.dispatchEvent(new CustomEvent('flow-owner-changed', { detail: null }));\n }\n this.dispatchEvent(new CustomEvent('agent-released', { detail: agent }));\n this.dispatchEvent(new CustomEvent('agent-changed', { detail: undefined }));\n }\n\n /**\n * Stop the current turn (user \"stop\" button). Cancels the inner chat driver's\n * in-flight request and breaks the handoff loop so no further agent turn or\n * classify runs. The driver stays usable for the next message.\n */\n cancel(): void {\n this.cancelled = true;\n this.chatDriver.cancel();\n }\n\n /**\n * Fire `onDeactivate` on the current active agent and abort any pending\n * lifecycle work. Called by the host on session teardown so machines can\n * release resources cleanly.\n */\n async dispose(): Promise<void> {\n const previousAgent = this.activeAgent;\n if (previousAgent?.onDeactivate) {\n try {\n await previousAgent.onDeactivate({\n agentName: previousAgent.name,\n sessionKey: this.sessionKey,\n signal: this.lifecycleAbortController.signal,\n });\n } catch (e) {\n logger.warn(`OrchestratingDriver: dispose onDeactivate(\"${previousAgent.name}\") threw:`, e);\n }\n }\n this.lifecycleAbortController.abort();\n // Tear down the inner driver too, so any in-flight provider request aborts.\n this.chatDriver.dispose();\n this.activeAgent = undefined;\n }\n\n private async classify(\n input: string,\n history: ChatMessage[],\n contextAgent?: AgentConfig,\n ): Promise<AgentConfig> {\n // Single-candidate short-circuits. No point asking the LLM to route\n // when there's only one viable choice. Skipped if a fallback is\n // configured \u2014 that's an explicit \"escape hatch\" signal from the\n // consumer, and we preserve the LLM's ability to send unrelated\n // messages there by returning -1 from select_agent.\n if (this.specialists.length === 1 && !this.fallback) {\n return this.specialists[0];\n }\n if (this.specialists.length === 0) {\n // No classifier-eligible specialists. If exactly one non-fallback\n // agent exists (typically a stateful agent flagged\n // `excludeFromClassifier`) and there's no fallback to preserve as an\n // escape hatch, route to it \u2014 this is what fixes the previously-\n // silent single-stateful-agent case. Otherwise drop to the fallback;\n // excluded specialists remain reachable via manual pin.\n if (!this.fallback) {\n const routable = this.agents.filter((a) => !isFallback(a));\n if (routable.length === 1) {\n return routable[0];\n }\n }\n return this.fallback ?? { name: 'Assistant', fallback: true };\n }\n\n const agentList = this.specialists\n .map((a, i) => `${i}: ${a.name} \u2014 ${a.description}`)\n .join('\\n');\n\n const recentMessages = history\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .slice(-this.classifierHistoryLength)\n .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content}`)\n .join('\\n');\n\n const continuationHint =\n contextAgent && isSpecialist(contextAgent)\n ? `\\n\\nThe previous turn was handled by \"${contextAgent.name}\". If the new message is a refinement, correction, or continuation of that work, prefer \"${contextAgent.name}\" \u2014 unless the topic has clearly shifted to another specialist's domain.`\n : '';\n\n const classifierPrompt = `You are a routing classifier. Call select_agent with the index of the best matching agent for the user message. Use -1 only if the request is entirely unrelated to every agent listed \u2014 prefer the closest match when in doubt. If the request spans multiple agents, pick the one that should act first; I will re-classify and route again once that agent is done.\\n\\nAgents:\\n${agentList}${continuationHint}${recentMessages ? `\\n\\nRecent conversation:\\n${recentMessages}` : ''}`;\n\n const routingTool = {\n name: 'select_agent',\n description: 'Select the most appropriate agent for the user message.',\n parameters: {\n type: 'object',\n required: ['agent_index'],\n properties: {\n agent_index: {\n type: 'integer',\n description: 'Zero-based index of the matching agent, or -1 if no agent matches.',\n },\n },\n },\n };\n\n // True only when the classifier RAN and answered \"no match\" (index -1). The\n // no-fallback apology below is gated on it: an exhausted-retries exit never\n // earned that apology, and emitting it there put a routing excuse ahead of\n // the real error the routed turn is about to produce.\n let routedNoMatch = false;\n\n for (let attempt = 0; attempt <= this.classifierRetries; attempt += 1) {\n try {\n const options: ChatRequestOptions = {\n systemPrompt: classifierPrompt,\n tools: [routingTool],\n };\n // Classification is orchestrator-level, not bound to any single agent \u2014\n // always run against the registry default.\n const classifierProvider = this.providerRegistry.default();\n if (!classifierProvider.chat) {\n logger.warn(\n 'OrchestratingDriver: default AI provider does not implement chat() \u2014 cannot classify.',\n );\n break;\n }\n // oxlint-disable-next-line no-await-in-loop\n const response = await classifierProvider.chat([], input, options);\n const tc = response.toolCalls?.[0];\n const index = tc?.name === 'select_agent' ? (tc.args.agent_index as number) : -1;\n\n if (index >= 0 && index < this.specialists.length) {\n return this.specialists[index];\n }\n // index === -1 \u2014 fall through to fallback\n routedNoMatch = true;\n break;\n } catch (e) {\n // Terminal: no ladder clears a budget wall. Short-circuit the\n // classifier's own retries the same way 402 short-circuits the\n // transport's \u2014 this loop is a SECOND retry ladder stacked on that one,\n // so without this a single wall costs `classifierRetries + 1` doomed\n // classifier calls and then a doomed fallback turn on top. Deliberately\n // narrow: a generic classifier failure must still retry and fall back.\n if (e instanceof BudgetExhaustedError) throw e;\n logger.warn(`OrchestratingDriver: classifier attempt ${attempt + 1} failed:`, e);\n if (attempt === this.classifierRetries) {\n logger.error('OrchestratingDriver: classifier failed after all retries, using fallback');\n }\n }\n }\n\n if (this.fallback) return this.fallback;\n\n // No fallback configured. Route to the first specialist as a no-op \u2014 but\n // only APOLOGISE when the classifier actually said \"none of these\". On an\n // exhausted-retries exit the classifier never expressed an opinion, so the\n // apology would be a routing excuse the user reads immediately above the\n // real error that turn is about to produce.\n if (routedNoMatch) {\n const specialistNames = this.specialists.map((s) => s.name).join(', ');\n this.appendInlineMessage(\n `I'm not sure how to help with that. I can assist with: ${specialistNames}.`,\n );\n }\n return this.specialists[0];\n }\n\n /**\n * Returns the agent that the current turn is locked to, if any. Flow-owner\n * (transient, set by stateful-agent activation) wins over user-pin (sticky,\n * set by picker click). `undefined` falls back to the classifier.\n *\n * Logs and returns `undefined` if a name no longer matches the agents array\n * \u2014 protects against stale state after an agents-array reassignment.\n */\n private resolvePinnedAgent(): AgentConfig | undefined {\n const name = this.flowOwnerAgentName ?? this.pinnedAgentName;\n if (name === null) return undefined;\n const match = this.agents.find((a) => a.name === name);\n if (!match) {\n logger.warn(\n `OrchestratingDriver: pinned agent \"${name}\" not found in agents array \u2014 falling back to classifier.`,\n );\n return undefined;\n }\n return match;\n }\n\n private appendInlineMessage(content: string): void {\n const history = this.chatDriver.getHistory() as ChatMessage[];\n this.chatDriver.loadHistory([\n ...history,\n { role: 'assistant', content, timestamp: new Date().toISOString() },\n ]);\n this.dispatchEvent(\n new CustomEvent('history-updated', { detail: this.chatDriver.getHistory() }),\n );\n }\n}\n", "import type {\n CachePolicy,\n ChatFallback,\n ChatInputDuringExecutionMode,\n ChatMessage,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n} from '@genesislcap/foundation-ai';\n\nexport type {\n CachePolicy,\n ChatFallback,\n ChatInputDuringExecutionMode,\n ChatThinkingPolicy,\n ChatToolChoice,\n};\n\n/**\n * Context passed to `onActivate` / `onDeactivate` lifecycle hooks on an agent.\n *\n * @beta\n */\nexport interface AgentLifecycleContext {\n /** The agent the hook is firing for. */\n agentName: string;\n /** The assistant session key \u2014 stable across reloads, unique per assistant instance. */\n sessionKey: string;\n /** The agent that was active immediately before this one, if any. Only set on `onActivate`. */\n previousAgentName?: string;\n /** Aborted if the session disconnects mid-activation. */\n signal: AbortSignal;\n /**\n * A previously-serialized state image for this agent (from the agent's\n * `serialize`), passed only on `onActivate` when resuming a persisted\n * session. A stateful\n * agent's `init` rebuilds from it \u2014 e.g. via `restoreMachine` \u2014 or starts\n * fresh when it is `undefined`.\n */\n restored?: unknown;\n}\n\n/**\n * Context passed to an agent's `resumable` predicate (GENC-1351 \u00A75.9), evaluated\n * at session-save time on the active agent (which, for a locked guided flow, is\n * the flow-owner).\n *\n * @beta\n */\nexport interface AgentPersistenceContext {\n /** The agent being consulted. */\n agentName: string;\n /** The assistant session key \u2014 stable across reloads. */\n sessionKey: string;\n /**\n * This agent's just-serialized state image \u2014 the value its `serialize()`\n * returned for this save (or the carried-forward image). Inspect the machine\n * step here. Derive the decision from this (not live closure state): the\n * predicate must be a pure function of the state so a resumable snapshot stays\n * resumable when re-evaluated on restore.\n */\n state: unknown;\n /** Full conversation transcript at save time. */\n messages: ReadonlyArray<ChatMessage>;\n /** True when this agent currently owns the guided flow (`name === flowOwnerAgentName`). */\n isFlowOwner: boolean;\n}\n\n/**\n * Context passed to the function form of `systemPrompt` / `toolDefinitions`.\n * Resolved each tool-loop iteration so the agent can vary what the LLM sees per turn.\n *\n * @beta\n */\nexport interface SystemPromptContext {\n /** The active agent's name. */\n agentName: string;\n /** Full conversation history up to (but not including) the message being processed. */\n history: ReadonlyArray<ChatMessage>;\n /** 0 = first LLM call this turn; > 0 = retry or subsequent tool-loop iteration. */\n turnIndex: number;\n /** Aborted if the turn is cancelled. */\n signal: AbortSignal;\n}\n\n/**\n * System prompt for an agent. Either a static string (resolved once) or a function\n * resolved each tool-loop iteration. The function form lets the agent compute the\n * prompt from external state \u2014 e.g. a state machine's current step.\n *\n * @beta\n */\nexport type SystemPromptInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Tool definitions for an agent. Either a static array (the conventional shape) or\n * a function resolved each tool-loop iteration. The function form lets the agent\n * narrow the tool surface per turn \u2014 e.g. expose only the tools valid in the\n * current state of a state machine.\n *\n * @beta\n */\nexport type ToolDefinitionsInput =\n | ChatToolDefinition[]\n | ((ctx: SystemPromptContext) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>);\n\n/**\n * Tool handlers for an agent. Either a static map (the conventional shape) or a\n * function resolved each tool-loop iteration. The function form lets the agent\n * narrow the dispatchable handler set per turn \u2014 pair it with the function form\n * of `toolDefinitions` so the LLM-visible tools and the dispatchable handlers\n * stay in lockstep, and handlers don't have to defend themselves against being\n * dispatched in states where their tool isn't advertised.\n *\n * @beta\n */\nexport type ToolHandlersInput =\n | ChatToolHandlers\n | ((ctx: SystemPromptContext) => ChatToolHandlers | Promise<ChatToolHandlers>);\n\n/**\n * Names which registered `AIProviderRegistry` entry an agent uses. Either\n * a static string (resolved once at agent registration) or a function resolved\n * each tool-loop iteration \u2014 pick the function form to vary the provider by\n * current state (e.g. a stateful agent that switches providers between\n * machine states).\n *\n * Unknown provider names hard-error: static names at agent registration time,\n * function-resolved names on first resolution.\n *\n * @beta\n */\nexport type ProviderInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Sampling temperature for an agent, normalized to `0`\u2013`1` (`0` = deterministic,\n * `1` = the most random the active provider allows). Either a static number\n * (resolved once) or a function resolved each tool-loop iteration \u2014 pick the\n * function form to vary it by current state (e.g. a lower temperature for a\n * precise extraction step, higher for brainstorming). Each transport translates\n * the normalized value into its own native range. Omit to use the\n * provider/model default. See `ChatRequestOptions.temperature`.\n *\n * @beta\n */\nexport type TemperatureInput = number | ((ctx: SystemPromptContext) => number | Promise<number>);\n\n/**\n * Tool-call mode for an agent. Either a static `ChatToolChoice` (resolved\n * once) or a function resolved each tool-loop iteration \u2014 pick the function form\n * to vary it by current state (e.g. force a classifier tool in an intake step,\n * then `'auto'` everywhere multi-step work happens). Omit to use the default\n * (`'auto'`, except sub-agent turns which force `'required'`).\n *\n * @beta\n */\nexport type ToolChoiceInput =\n | ChatToolChoice\n | ((ctx: SystemPromptContext) => ChatToolChoice | Promise<ChatToolChoice>);\n\n/**\n * Prompt-cache policy for an agent. Either a static `CachePolicy` (resolved once) or a\n * function resolved each tool-loop iteration \u2014 pick the function form to vary it by current state\n * (e.g. cache `'history'` in a long generating phase, `'default'` in short low-touch ones). Omit\n * to request no caching. Resolved and applied the same way as {@link TemperatureInput}.\n *\n * @beta\n */\nexport type CachePolicyInput =\n | CachePolicy\n | ((ctx: SystemPromptContext) => CachePolicy | Promise<CachePolicy>);\n\n/**\n * Extended-thinking posture for an agent \u2014 whether the model reasons before answering. Either a\n * static `ChatThinkingPolicy` or a function resolved **once per user turn**, at the start of the\n * tool loop. Pick the function form to vary it by current state: reason in the state that makes a\n * real decision, and drop it in states that only step a known sequence, where reasoning bills at\n * the full output rate to re-derive what the state machine already knows.\n *\n * Note the resolution point, which differs from every other per-turn input here: a tool-use loop\n * is a single assistant turn and its thinking mode must hold for the whole of it, so this resolver\n * is consulted on the first model call of a turn and its answer reused for the rest. A resolver\n * that returns a different value part-way through a loop will not see it applied until the next\n * user turn.\n *\n * **Omit \u2014 or return `undefined` from the function \u2014 to keep the model's own default**, which is\n * a distinct third state rather than a synonym for either value: Sonnet 5 and Fable 5 think by\n * default, the rest do not. So an agent that leaves this unset, or a resolver that answers\n * `undefined` on some turns, behaves and prices exactly as it did before this option existed.\n *\n * A request, not a guarantee \u2014 transports clamp what a model cannot honour (Fable 5 and Gemini\n * 2.5 Pro always think) and warn once instead of failing the turn. Resolved and applied the same\n * way as {@link TemperatureInput}. See `ChatThinkingPolicy`.\n *\n * @beta\n */\nexport type ThinkingPolicyInput =\n | ChatThinkingPolicy\n | ((\n ctx: SystemPromptContext,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);\n\n/**\n * Per-turn tail context for an agent \u2014 volatile content (current file/spec, diagnostics, live\n * state) injected at the tail of every model-call so the model sees it without invalidating the\n * cached prefix. Either a static string or a function resolved each tool-loop iteration. **Provide\n * raw content** \u2014 the framework frames it (wraps it in a `<system-reminder>` marker) so the model\n * reads it as ambient context, not user input. Omit, or return an empty string, for none.\n *\n * @beta\n */\nexport type TailContextInput = string | ((ctx: SystemPromptContext) => string | Promise<string>);\n\n/**\n * Structured-output schema for an agent. When set, the model's final (non-tool) answer is\n * constrained to this JSON Schema instead of free text. Either a static schema or a function\n * resolved each tool-loop iteration \u2014 return the schema on the turn(s) it should apply and\n * `undefined` otherwise, so \"whole-loop\" vs \"finalize-turn\" enforcement is just what the\n * resolver returns (e.g. `({ state }) => state.machine.matches('finalizing') ? schema : undefined`).\n *\n * Orthogonal to {@link ToolChoiceInput}: an agent can carry both `tools` and a `responseSchema`.\n * Each provider applies it natively where possible (Anthropic `output_config.format`, Gemini\n * JSON mode) and degrades gracefully otherwise. The schema is a plain JSON Schema object; keep to\n * the portable subset providers share (`additionalProperties: false`, explicit `required`, enums,\n * `anyOf` for nullables \u2014 no numeric/string constraints or recursion).\n *\n * @beta\n */\nexport type ResponseSchemaInput =\n | object\n | ((ctx: SystemPromptContext) => object | undefined | Promise<object | undefined>);\n\n/**\n * Context passed to an agent's `onUnresolvedTool` hook when the model calls a\n * tool the driver cannot dispatch.\n *\n * @beta\n */\nexport interface UnresolvedToolContext {\n /** The tool name the model attempted to call. */\n toolName: string;\n /**\n * Why the call could not be dispatched:\n * - `'stale'` \u2014 the tool was advertised earlier this activation but is not\n * part of the current step (e.g. a stateful agent has moved on).\n * - `'unknown'` \u2014 the tool was never advertised this activation (a\n * hallucinated name).\n */\n kind: 'stale' | 'unknown';\n /**\n * The tool names dispatchable right now, so the hook can steer the model\n * back to a valid call.\n */\n availableTools: string[];\n}\n\n/**\n * Optional per-agent hook consulted only on the already-failing unresolved-tool\n * path \u2014 when the model calls a tool the driver cannot dispatch. Lets the agent\n * replace the framework's default message with a context-aware redirect.\n *\n * Return a non-empty string to override the default tool-result message; return\n * `undefined` (or an empty/whitespace string, or throw) to fall back to the\n * framework default. The happy path is never affected. See\n * {@link UnresolvedToolContext}.\n *\n * @beta\n */\nexport type UnresolvedToolInput = (\n ctx: UnresolvedToolContext,\n) => string | undefined | Promise<string | undefined>;\n\n/**\n * Opts an agent in to manual selection from the assistant's agent picker.\n *\n * Only applies to top-level agents \u2014 sub-agents are never user-selectable.\n * Has no effect unless the assistant's `agentPicker` is also enabled.\n *\n * @beta\n */\nexport interface ManualSelectionConfig {\n /**\n * Whether this agent appears in the picker.\n */\n enabled: boolean;\n /**\n * Optional short description shown as a tooltip on the picker entry, and as\n * a secondary line in the dropdown variant.\n */\n hint?: string;\n}\n\ninterface BaseAgentConfig {\n /**\n * Stable identity for this agent. Used for classifier routing, manual\n * pinning, and history filtering \u2014 must not vary per turn. For a per-turn\n * display label (e.g. \"Guided Booking (Counterparties)\"), supply\n * {@link BaseAgentConfig.displayName}.\n */\n name: string;\n /**\n * Optional per-turn display label. Resolved each tool-loop iteration and\n * stamped onto outgoing messages (`agentLabel`) and the debug-log timeline.\n * Renderers fall back to `name` when this is unset. Use the function form\n * to vary the label by current state (e.g. a state machine's step).\n *\n * Identity stays on `name` \u2014 this is for UX only.\n */\n displayName?: SystemPromptInput;\n /**\n * System prompt injected into every conversation turn for this agent.\n *\n * Either a string (resolved once) or a function resolved each tool-loop\n * iteration \u2014 pick the function form when the prompt depends on per-turn state\n * (e.g. a state machine's current step). See {@link SystemPromptInput}.\n */\n systemPrompt?: SystemPromptInput;\n /**\n * Tool definitions (JSON Schema) passed to the AI provider for this agent.\n *\n * Either a static array or a function resolved each tool-loop iteration \u2014\n * pick the function form to narrow the tool surface per turn (e.g. expose\n * only the tools valid in the current state of a state machine).\n * See {@link ToolDefinitionsInput}.\n */\n toolDefinitions?: ToolDefinitionsInput;\n /**\n * Tool handler implementations for this agent.\n *\n * Either a static map or a function resolved each tool-loop iteration \u2014\n * pick the function form to narrow the dispatchable handler set per turn,\n * matching the function form of `toolDefinitions`.\n * See {@link ToolHandlersInput}.\n */\n toolHandlers?: ToolHandlersInput;\n /**\n * Which registered AI provider this agent uses, by name. Either a static\n * string (resolved once at agent registration) or a function resolved each\n * tool-loop iteration \u2014 pick the function form to vary the provider by\n * current state (e.g. a stateful agent that switches providers between\n * machine states).\n *\n * Omit to use the registry's default provider. Unknown names hard-error:\n * static names at registration time, function-resolved names on first\n * resolution.\n *\n * Known limitation: switching provider mid-conversation can blow the\n * smaller provider's context window if history accumulated under a\n * larger one. No automatic trimming is performed.\n *\n * @beta\n */\n provider?: ProviderInput;\n /**\n * Sampling temperature for this agent, normalized to `0`\u2013`1`. Either a static\n * number or a function resolved each tool-loop iteration \u2014 pick the function\n * form to vary it by current state. Omit to use the provider/model default.\n * Resolved and applied the same way as {@link BaseAgentConfig.provider}.\n * See {@link TemperatureInput}.\n *\n * @beta\n */\n temperature?: TemperatureInput;\n /**\n * Tool-call mode for this agent \u2014 whether the model may, must, or must not\n * call a tool this turn (and optionally which one). Either a static value or\n * a function resolved each tool-loop iteration \u2014 pick the function form to\n * vary it by current state (e.g. force a single tool at a known juncture).\n * Omit to use the default (`'auto'`, except sub-agent turns which force\n * `'required'`). See {@link ToolChoiceInput}.\n *\n * @beta\n */\n toolChoice?: ToolChoiceInput;\n /**\n * Prompt-cache policy for this agent \u2014 whether to emit cache breakpoints and how far up the\n * prefix. Either a static value or a function resolved each tool-loop iteration (vary by state).\n * Resolved and applied the same way as {@link BaseAgentConfig.temperature}. Omit to request no\n * caching. Provider-neutral \u2014 see {@link CachePolicyInput} / `CachePolicy` for the\n * Anthropic-vs-Gemini behaviour. See {@link CachePolicyInput}.\n *\n * @beta\n */\n cachePolicy?: CachePolicyInput;\n /**\n * Extended-thinking posture for this agent \u2014 whether the model reasons before answering. Either\n * a static value or a function resolved **once per user turn** and held for that turn's whole\n * tool loop (vary by state: `'auto'` where the turn is a genuine decision, `'off'` where it only\n * steps a known sequence and reasoning is billed at the full output rate for no benefit). Omit \u2014\n * or return `undefined` \u2014 to keep the model's own default, which is neither `'auto'` nor `'off'`\n * uniformly. Provider-neutral; transports clamp models that cannot honour it.\n * See {@link ThinkingPolicyInput}.\n *\n * @beta\n */\n thinkingPolicy?: ThinkingPolicyInput;\n /**\n * Volatile per-turn context injected at the tail of every model-call (after the history and any\n * cache breakpoint), so it is seen each turn without busting the cached prefix \u2014 the place to put\n * the changing parts (current file/spec, diagnostics, live state) that would otherwise\n * destabilize a cached system prompt. Provide *raw* content; the framework frames it (wraps it in\n * a `<system-reminder>` marker). Resolved per turn like {@link BaseAgentConfig.temperature}. See\n * {@link TailContextInput}.\n *\n * @beta\n */\n tailContext?: TailContextInput;\n /**\n * Structured-output schema for this agent. When resolved to a schema on a turn, the model's\n * final (non-tool) answer is constrained to it instead of free text. Composes with `tools`;\n * resolved per turn like {@link BaseAgentConfig.cachePolicy}, so returning `undefined` on\n * working turns and the schema on the finalize turn gives finalize-turn enforcement for free.\n * See {@link ResponseSchemaInput}.\n *\n * @beta\n */\n responseSchema?: ResponseSchemaInput;\n /**\n * Refusal-fallback chain for this agent (provider-neutral). If the model declines a turn\n * (`stop_reason: 'refusal'` \u2014 e.g. Fable 5 safety classifiers), the provider re-runs it on the\n * next listed model. Typical use: a Fable 5 agent with `[{ model: 'claude-opus-4-8' }]`. Static\n * (not per-turn); providers that support it apply it server-side, others ignore it.\n *\n * @beta\n */\n fallbacks?: ChatFallback[];\n /**\n * Optional hook consulted when the model calls a tool the driver cannot\n * dispatch \u2014 either a *stale* tool (advertised earlier this activation but\n * not part of the current step) or an *unknown* one (never advertised this\n * activation). Return a context-aware redirect string to replace the\n * framework's default message, or `undefined` to keep it. Consulted only on\n * the already-failing unresolved-tool path; the happy path is unaffected.\n * See {@link UnresolvedToolInput}.\n *\n * @beta\n */\n onUnresolvedTool?: UnresolvedToolInput;\n /**\n * Optional primer history prepended to every call (not visible to the user).\n * Used to establish agent identity and behavioural rules.\n */\n primerHistory?: ChatMessage[];\n /**\n * Sub-agents available to this agent's tool handlers via `requestSubAgent`.\n */\n subAgents?: AgentConfig[];\n /**\n * How the main chat input area behaves while this agent is executing.\n * Defaults to `'disabled'`. See {@link ChatInputDuringExecutionMode}.\n */\n chatInputDuringExecution?: ChatInputDuringExecutionMode;\n /**\n * Opts this agent in to manual selection from the assistant's agent picker.\n * Has no effect on sub-agents or when the assistant's `agentPicker` is\n * disabled. See {@link ManualSelectionConfig}.\n */\n manualSelection?: ManualSelectionConfig;\n /**\n * Fires when this agent becomes the active specialist (including being pinned).\n * Use to instantiate per-agent state that should outlive a single turn \u2014 e.g.\n * a state machine the agent owns across the conversation. Awaited before the\n * agent's first turn runs.\n *\n * Capture dependencies (services, redux store refs, etc.) via closure on the\n * host element rather than expecting them on the context.\n *\n * @beta\n */\n onActivate?: (ctx: AgentLifecycleContext) => void | Promise<void>;\n /**\n * Fires when this agent is being deactivated (the user switches to another\n * agent, the session is torn down, or the agent is unpinned and replaced).\n * Use to dispose per-agent state created in `onActivate`. Awaited before the\n * incoming agent's `onActivate` runs.\n *\n * @beta\n */\n onDeactivate?: (ctx: AgentLifecycleContext) => void | Promise<void>;\n /**\n * Returns an agent-supplied debug payload for the export log. Called once per\n * LLM call by the driver (alongside the resolved prompt and tool list) and\n * once at log-export time for the latest snapshot. Stateful agents should\n * return their machine state and captured context so the exported timeline\n * captures what drove each turn.\n *\n * Return value must be JSON-serializable. {@link defineStatefulAgent} wires a\n * sensible default that snapshots any machine-shaped state automatically.\n *\n * @beta\n */\n getDebugSnapshot?: () => unknown;\n /**\n * Returns a lossless, JSON-serializable image of the agent's state for session\n * persistence \u2014 distinct from `getDebugSnapshot`, which may abbreviate for\n * readability. Pass the value back to the agent on restore (as\n * `ctx.restored` in its `init`) to resume. {@link defineStatefulAgent} wires a\n * default that snapshots any machine-shaped state via `getPersistedSnapshot()`\n * and returns plain state as-is.\n *\n * @beta\n */\n serialize?: () => unknown;\n /**\n * Whether the agent's current state is resumable \u2014 i.e. worth persisting so the\n * session can be restored mid-flow (GENC-1351 \u00A75.9). Consulted at save time on\n * the active agent (the flow-owner during a locked flow). Return `true`\n * (or leave the field absent) to persist and resume normally; return `false`\n * for a point that shouldn't be resumed \u2014 the session is not persisted, and on\n * return the assistant shows {@link AgentConfig.notResumableMessage} (or a\n * default) and pre-fills the composer with the prompt that started the flow so\n * the user can re-run it.\n *\n * Only consulted when the user has persistence enabled. Must be a **pure\n * function of `ctx.state`** \u2014 it may be re-evaluated on a restored snapshot, so\n * a resumable state must stay resumable. A thrown error is treated as `true`\n * (fail-safe: never drop a resumable chat on a predicate bug).\n *\n * @beta\n */\n resumable?: (ctx: AgentPersistenceContext) => boolean | Promise<boolean>;\n /**\n * Message shown on return when {@link AgentConfig.resumable} returned `false`\n * and the user comes back to a non-resumable session (GENC-1351 \u00A75.9). Falls\n * back to a built-in default when omitted.\n *\n * @beta\n */\n notResumableMessage?: string;\n}\n\n/**\n * Configuration for a specialist agent.\n *\n * Specialist agents are offered to the classifier for intent routing. The\n * `description` is used to auto-generate the classifier prompt \u2014 no manual\n * routing prompt authoring required.\n *\n * @beta\n */\nexport interface SpecialistAgentConfig extends BaseAgentConfig {\n /**\n * Plain-language description of what this agent handles.\n * Used by the classifier to auto-generate its routing prompt.\n */\n description: string;\n fallback?: never;\n /**\n * When `true`, the classifier never auto-routes to this agent. The user can\n * still select it manually via the picker, provided both prerequisites are\n * met: this agent has `manualSelection.enabled` set to `true`, *and* the\n * assistant has the picker enabled via `chatConfig.picker.mode`.\n *\n * Use this for agents that overlap heavily with a sibling (e.g. a guided\n * wizard sitting next to a free-form agent in the same domain) and should\n * only be reached intentionally rather than via classifier routing.\n *\n * @beta\n */\n excludeFromClassifier?: boolean;\n}\n\n/**\n * Configuration for a fallback agent.\n *\n * Invoked when the classifier returns no match. Excluded from the classifier\n * prompt. Only one fallback is permitted per agents array.\n *\n * @beta\n */\nexport interface FallbackAgentConfig extends BaseAgentConfig {\n /**\n * Marks this agent as the fallback for unrecognised requests.\n */\n fallback: true;\n description?: never;\n}\n\n/**\n * Configuration for an agent passed to `FoundationAiAssistant`.\n *\n * Either a specialist (requires `description`) or a fallback (requires\n * `fallback: true`). Passing both or neither is a compile error.\n *\n * @beta\n */\nexport type AgentConfig = SpecialistAgentConfig | FallbackAgentConfig;\n\n/**\n * Identity helper that infers the narrowest possible type for an agent config,\n * preserving string literal types (including `name`) without requiring `as const`.\n *\n * Use this when you need `typeof myAgent` to carry the literal `name` type \u2014\n * for example, when wiring `ChatToolHandlers<typeof myAgent>`.\n *\n * ```ts\n * const myAgent = defineAgent({ name: 'my_agent', ... });\n * type Handlers = ChatToolHandlers<typeof myAgent>;\n * // requestSubAgent name param is now typed as 'my_agent'\n * ```\n *\n * @beta\n */\n\nexport function defineAgent<const T extends AgentConfig>(config: T): T {\n return config;\n}\n", "import type {\n CachePolicy,\n ChatMessage,\n ChatThinkingPolicy,\n ChatToolChoice,\n ChatToolDefinition,\n ChatToolHandlers,\n} from '@genesislcap/foundation-ai';\nimport { TOOL_FOLD_SYMBOL } from '../utils/tool-fold';\nimport type {\n AgentConfig,\n AgentLifecycleContext,\n AgentPersistenceContext,\n CachePolicyInput,\n ChatInputDuringExecutionMode,\n ManualSelectionConfig,\n ProviderInput,\n SystemPromptContext,\n SystemPromptInput,\n TailContextInput,\n TemperatureInput,\n ThinkingPolicyInput,\n ToolChoiceInput,\n ToolDefinitionsInput,\n ToolHandlersInput,\n UnresolvedToolContext,\n UnresolvedToolInput,\n} from './config';\n\n/**\n * Context passed to per-turn resolvers on a stateful agent \u2014 the standard\n * {@link SystemPromptContext} plus the live `state` value. Used by\n * `systemPrompt`, `displayName`, and the function form of `toolDefinitions`.\n *\n * Exported so consumers can lift resolvers into separate files without\n * re-deriving the shape.\n *\n * @beta\n */\nexport type StatefulAgentContext<S> = SystemPromptContext & { state: S };\n\n/**\n * Context passed to a stateful agent's `resumable` predicate (GENC-1351 \u00A75.9) \u2014\n * the standard {@link AgentPersistenceContext} but with `state` as the **live**\n * state bag `S` (not the serialized image), so a machine agent can gate on its\n * current step directly.\n *\n * @beta\n */\nexport type StatefulAgentPersistenceContext<S> = Omit<AgentPersistenceContext, 'state'> & {\n state: S;\n};\n\n/**\n * Init options for {@link defineStatefulAgent}. Generic over the state shape `S`\n * the agent owns (a state machine, an observable controller, anything).\n *\n * The helper threads `state` through `systemPrompt`, `toolDefinitions`, and the\n * `toolHandlers` factory so consumer code never has to reach for a closure or\n * a module-level mutable.\n *\n * @beta\n */\nexport interface StatefulAgentInit<S> {\n /** Display name \u2014 must be unique within the agents array. */\n name: string;\n /** Plain-language description used by the classifier. Required: stateful agents are always specialists. */\n description: string;\n /**\n * Hide this agent from the classifier \u2014 only reachable via manual pinning.\n * Stateful agents are always specialists; they cannot be the fallback (a\n * fallback is a leaf invoked when no specialist matches, with no flow to\n * own state for).\n */\n excludeFromClassifier?: boolean;\n /** Static primer history prepended to every call (not visible to the user). */\n primerHistory?: ChatMessage[];\n /** Sub-agents available to this agent's tool handlers via `requestSubAgent`. */\n subAgents?: AgentConfig[];\n /** Opt this agent in to manual picker selection. */\n manualSelection?: ManualSelectionConfig;\n /** How the main chat input behaves while this agent is executing. */\n chatInputDuringExecution?: ChatInputDuringExecutionMode;\n\n /**\n * Construct the agent-scoped state. Called by the framework when this agent\n * becomes active (`onActivate`). Awaited before the agent's first turn runs.\n *\n * On a persisted-session restore, `ctx.restored` carries this agent's previous\n * `serialize` output \u2014 rebuild from it (e.g. via `restoreMachine`), or start\n * fresh when it is `undefined`.\n */\n init: (ctx: AgentLifecycleContext) => S | Promise<S>;\n\n /**\n * Tear down the agent-scoped state. Called when the agent is being replaced.\n * Awaited before the incoming agent's `init` runs.\n */\n dispose?: (ctx: AgentLifecycleContext & { state: S }) => void | Promise<void>;\n\n /**\n * System prompt composed from current state. Resolved each tool-loop\n * iteration. Use this to feed the LLM whatever the current state implies\n * (e.g. a state machine's `meta.systemPrompt` plus captured context).\n */\n systemPrompt?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;\n\n /**\n * Per-turn display label, e.g. \"Guided Booking (Counterparties)\". Resolved\n * each tool-loop iteration and stamped onto outgoing messages and the\n * debug-log timeline \u2014 display only. The agent's `name` stays as the\n * canonical identity used for routing/history filtering.\n */\n displayName?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;\n\n /**\n * Tool definitions the LLM sees. Either a static array (resolved once) or a\n * function resolved each tool-loop iteration. The function form is how a\n * machine-driven agent narrows the surface per state.\n *\n * **Constraint:** the resolved handlers (returned from {@link StatefulAgentInit.toolHandlers})\n * must not include fold facades. Folds are an LLM-driven UX optimisation\n * that competes with the machine for control of the tool view; one of them\n * has to be in charge. Helper throws at init time if a fold-tagged handler\n * is detected.\n */\n toolDefinitions?:\n | ChatToolDefinition[]\n | ((ctx: StatefulAgentContext<S>) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>);\n\n /**\n * Factory returning the handler map for the **current state**. Called each\n * tool-loop iteration with the live `state` value, so the handler set the\n * driver dispatches against matches what `toolDefinitions` exposes to the\n * LLM that turn. Return only the handlers valid right now \u2014 no need to\n * advertise every handler the agent might ever expose, and no defensive\n * `if (!machine.matches(...))` guards inside each handler.\n *\n * Pair with the function form of `toolDefinitions` so the visible tools and\n * the dispatchable handlers stay in lockstep.\n *\n * **Constraint:** resolved handlers must not include fold facades. Folds and\n * state-machine-driven tool filtering both try to control the LLM's tool\n * view \u2014 pick one. Helper samples once on activation (init state) and\n * throws if a fold-tagged handler is detected; subsequent resolves also\n * validate, so misuse on a non-init state surfaces when that state is\n * reached.\n */\n toolHandlers?: (state: S) => ChatToolHandlers | Promise<ChatToolHandlers>;\n\n /**\n * Which registered AI provider this agent uses, by name. Either a static\n * string or a function resolved each tool-loop iteration with the current\n * `state` \u2014 pick the function form to vary provider per machine state\n * (e.g. swap to a heavier model only for the planning step).\n *\n * Omit to use the registry's default provider. Unknown names hard-error.\n */\n provider?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);\n\n /**\n * Sampling temperature, normalized to `0`\u2013`1`. Either a static number or a\n * function resolved each tool-loop iteration with the current `state` \u2014 pick\n * the function form to vary it per machine state (e.g. low for a precise\n * extraction step, higher for free-form drafting). Omit for the default.\n */\n temperature?: number | ((ctx: StatefulAgentContext<S>) => number | Promise<number>);\n\n /**\n * Tool-call mode. Either a static `ChatToolChoice` or a function\n * resolved each tool-loop iteration with the current `state` \u2014 pick the\n * function form to force a specific tool in one state (e.g. a classifier in\n * intake) and leave `'auto'` in states where multi-step work happens. Omit\n * for the default.\n */\n toolChoice?:\n | ChatToolChoice\n | ((ctx: StatefulAgentContext<S>) => ChatToolChoice | Promise<ChatToolChoice>);\n\n /**\n * Prompt-cache policy. Either a static `CachePolicy` or a function resolved each tool-loop\n * iteration with the current `state` \u2014 pick the function form to vary it per machine state\n * (e.g. `'history'` in a long generating phase, `'default'` in short low-touch ones). Omit to\n * request no caching.\n */\n cachePolicy?:\n | CachePolicy\n | ((ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>);\n\n /**\n * Extended-thinking posture. Either a static `ChatThinkingPolicy` or a function resolved with\n * the current `state` **once per user turn** \u2014 the function form is the point of this option on\n * a machine agent: `'auto'` in the state that makes a real decision, `'off'` in the states that\n * only step a known sequence, where reasoning is billed at the full output rate to re-derive\n * what the machine already knows. Omit, or return `undefined` from the function, to keep the\n * model's own default for that turn.\n *\n * Resolved once per turn rather than per tool-loop iteration (unlike `temperature` and\n * `toolChoice`): a tool-use loop is one assistant turn and its thinking mode must hold for the\n * whole of it. A state transition part-way through a loop therefore takes effect on the next\n * user turn, not immediately.\n */\n thinkingPolicy?:\n | ChatThinkingPolicy\n | ((\n ctx: StatefulAgentContext<S>,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);\n\n /**\n * Volatile per-turn tail context (current file/spec, diagnostics, live state). Either a static\n * string or a function resolved each tool-loop iteration with the current `state`. Provide raw\n * content; the framework frames it. Omit, or return an empty string, for none.\n */\n tailContext?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);\n\n /**\n * Hook consulted when the model calls a tool that isn't dispatchable in the\n * current state \u2014 a *stale* tool (valid in an earlier state of this agent) or\n * an *unknown* one. Receives the current `state` alongside the attempted tool\n * name and the currently dispatchable tools, so a machine-driven agent can\n * return a step-aware redirect (e.g. \"that belongs to a later step \u2014 finish\n * this one first\"). Return `undefined` to keep the framework default; a\n * pre-init call also degrades to the default rather than throwing.\n * See {@link UnresolvedToolContext}.\n */\n onUnresolvedTool?: (\n ctx: UnresolvedToolContext & { state: S },\n ) => string | undefined | Promise<string | undefined>;\n\n /**\n * Optional getter for the debug-log snapshot. Defaults to auto-snapshotting\n * any property on `state` that looks like a foundation-state-machine\n * instance (has `state`, `context`, and `complete` fields). Override when\n * the default doesn't capture what you need \u2014 e.g. multiple machines, or\n * non-machine state worth recording.\n *\n * Return value must be JSON-serializable.\n */\n getDebugSnapshot?: (state: S) => unknown;\n\n /**\n * Lossless serializer for session persistence \u2014 infra-agnostic. Return any\n * JSON/structured-clone-safe image of `state`.\n * \u2022 Machine agents (`{ machine }`): omit \u2014 the default snapshots every\n * machine-shaped property via `getPersistedSnapshot()`.\n * \u2022 Plain-data agents (e.g. `{ plan, cursor }`): omit too \u2014 the default\n * returns plain state as-is. Provide one only when the state holds\n * something the default can't capture.\n * Distinct from `getDebugSnapshot` (which may be lossy by design). Pair with\n * `init` reading `ctx.restored` to rebuild.\n */\n serialize?: (state: S) => unknown;\n\n /**\n * Whether the agent's current state is resumable \u2014 worth persisting so the\n * session restores mid-flow (GENC-1351 \u00A75.9). Receives the **live** state bag\n * `S` (like the other per-turn resolvers), so a machine agent gates on its step\n * directly: `resumable: ({ state }) => state.machine.state !== 'confirm'`.\n * Return `false` for a point that shouldn't resume \u2014 the session isn't persisted,\n * and on return the assistant shows {@link StatefulAgentInit.notResumableMessage}\n * (or a default) and pre-fills the composer with the prompt that started the flow.\n * Only consulted with persistence enabled; a thrown error is treated as `true`\n * (fail-safe \u2014 never drop a resumable chat on a predicate bug).\n */\n resumable?: (ctx: StatefulAgentPersistenceContext<S>) => boolean | Promise<boolean>;\n /**\n * Message shown on return when {@link StatefulAgentInit.resumable} returned\n * `false`. Falls back to a built-in default when omitted.\n */\n notResumableMessage?: string;\n}\n\n/**\n * Walk a state object and snapshot any machine-shaped values found on it.\n * Recognises foundation-state-machine instances by structural shape rather\n * than `instanceof`, so the helper stays free of a runtime dep on\n * foundation-state-machine.\n *\n * Strips the `errors`/`error` framework noise from each machine's context \u2014\n * these are foundation-state-machine internals (an ErrorMap instance and its\n * last-error pointer) that bloat the debug payload without aiding debugging.\n */\nfunction defaultStatefulDebugSnapshot(state: unknown): unknown {\n if (!state || typeof state !== 'object') return state;\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(state as Record<string, unknown>)) {\n if (val && typeof val === 'object' && 'state' in val && 'context' in val && 'complete' in val) {\n const m = val as {\n state: unknown;\n context: Record<string, unknown>;\n complete: unknown;\n output?: unknown;\n };\n const ctx = m.context ?? {};\n const { errors: _e, error: _err, ...userContext } = ctx;\n result[key] = {\n state: m.state,\n context: userContext,\n complete: m.complete,\n output: m.output,\n };\n }\n }\n return Object.keys(result).length\n ? result\n : '<no auto-snapshot \u2014 state has no machine-shaped properties; provide getDebugSnapshot>';\n}\n\n/**\n * Build a restore-ready snapshot of agent state. Each property exposing a\n * `getPersistedSnapshot()` method (a foundation-state-machine `AbstractMachine`)\n * is replaced by its persisted snapshot \u2014 the lossless, JSON-safe image\n * {@link restoreMachine} feeds back via `start({ state })`. Every other property\n * is kept as-is, so plain serializable state (e.g. a planner's `{ plan, cursor }`)\n * round-trips directly with no per-agent `serialize`.\n *\n * Distinct from `defaultStatefulDebugSnapshot`, which abbreviates for the debug\n * log and is not guaranteed lossless.\n */\nfunction defaultStatefulSerialize(state: unknown): unknown {\n if (!state || typeof state !== 'object') return state;\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(state as Record<string, unknown>)) {\n result[key] =\n val &&\n typeof val === 'object' &&\n typeof (val as { getPersistedSnapshot?: unknown }).getPersistedSnapshot === 'function'\n ? (val as { getPersistedSnapshot: () => unknown }).getPersistedSnapshot()\n : val;\n }\n return result;\n}\n\n/**\n * Restore a foundation-state-machine instance from a snapshot produced by the\n * default serializer (or `machine.getPersistedSnapshot()`). Call inside a\n * stateful agent's `init` to resume the machine in its exact prior place:\n *\n * ```ts\n * init: ({ restored }) => {\n * const machine = new MyMachine();\n * restoreMachine(machine, restored); // resume, or no-op on a fresh start\n * return { machine };\n * }\n * ```\n *\n * No-ops when there is nothing to restore (a fresh session), leaving the\n * freshly-constructed machine in its initial state.\n *\n * @param machine - the machine to restore (already constructed/started).\n * @param restored - the agent's serialized image (`ctx.restored` in `init`).\n * @param key - the property the machine occupies in the snapshot; defaults to\n * `'machine'` to match the conventional `{ machine }` state bag.\n * @beta\n */\nexport function restoreMachine(\n machine: { stop: () => void; start: (options?: { state?: unknown }) => void },\n restored: unknown,\n key = 'machine',\n): void {\n const snapshot = (restored as Record<string, unknown> | undefined)?.[key];\n if (snapshot === undefined || snapshot === null) {\n return;\n }\n machine.stop();\n machine.start({ state: snapshot });\n}\n\n/**\n * Build an `AgentConfig` whose `systemPrompt`, `toolDefinitions`, and tool\n * handlers all close over a long-lived state object created on activation.\n *\n * The framework wires the lifecycle: `init` on `onActivate`, `dispose` on\n * `onDeactivate`. State is held inside the helper's closure \u2014 never exposed on\n * the resulting `AgentConfig` \u2014 so the redux serializer doesn't see it.\n *\n * @example\n * ```ts\n * const guidedBooking = defineStatefulAgent<{ machine: GuidedBookingMachine }>({\n * name: 'Guided Booking',\n * description: 'Books a trade via a guided wizard.',\n * excludeFromClassifier: true,\n * manualSelection: { enabled: true, hint: 'Step-by-step trade booking' },\n * init: () => ({ machine: new GuidedBookingMachine() }),\n * dispose: ({ state }) => state.machine.stop(),\n * systemPrompt: ({ state }) => composeFromMachine(state.machine),\n * toolDefinitions: ({ state }) => toolsForState(state.machine.state),\n * toolHandlers: ({ machine }) => ({ ... }),\n * });\n * ```\n *\n * @beta\n */\nexport function defineStatefulAgent<S>(opts: StatefulAgentInit<S>): AgentConfig {\n let state: S | undefined;\n\n const assertNoFolds = (handlers: ChatToolHandlers): void => {\n for (const [name, handler] of Object.entries(handlers)) {\n if ((handler as any)[TOOL_FOLD_SYMBOL]) {\n throw new Error(\n `Stateful agent \"${opts.name}\" tool \"${name}\" carries fold metadata. ` +\n `Folds and state-machine-driven tool filtering both try to control the ` +\n `LLM's tool view \u2014 pick one. Remove the fold or migrate this agent to ` +\n `a non-stateful AgentConfig.`,\n );\n }\n }\n };\n\n // Wrap the optional dynamic-tools factory so it threads `state` in and asserts\n // we never accidentally resolved a fold-tagged tool. Static arrays are passed\n // through unchanged.\n const wrappedTools: ToolDefinitionsInput | undefined = (() => {\n const td = opts.toolDefinitions;\n if (typeof td === 'function') {\n return async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" tools called before init`);\n }\n return td({ ...ctx, state });\n };\n }\n return td;\n })();\n\n // Wrap the handler factory into the ctx-shaped form the driver expects, and\n // validate folds on each resolve. The driver re-resolves this per tool-loop\n // iteration, so the handler set the driver dispatches against always\n // matches the LLM-visible tools for the current state \u2014 handlers don't need\n // defensive `if (!machine.matches(...))` guards.\n const wrappedHandlers: ToolHandlersInput | undefined = opts.toolHandlers\n ? async () => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" handlers called before init`);\n }\n const handlers = await opts.toolHandlers!(state);\n assertNoFolds(handlers);\n return handlers;\n }\n : undefined;\n\n const wrappedDisplayName: SystemPromptInput | undefined = opts.displayName\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" displayName called before init`);\n }\n return opts.displayName!({ ...ctx, state });\n }\n : undefined;\n\n // Function-form `provider` needs `state` injected the same way the other\n // per-turn resolvers do; the static-string form is passed through unchanged\n // and validated up-front by OrchestratingDriver.\n const wrappedProvider: ProviderInput | undefined =\n typeof opts.provider === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" provider called before init`);\n }\n return (opts.provider as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({\n ...ctx,\n state,\n });\n }\n : opts.provider;\n\n // `temperature` and `toolChoice` thread `state` in exactly like `provider`;\n // static values pass through unchanged.\n const wrappedTemperature: TemperatureInput | undefined =\n typeof opts.temperature === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" temperature called before init`);\n }\n return (opts.temperature as (ctx: StatefulAgentContext<S>) => number | Promise<number>)({\n ...ctx,\n state,\n });\n }\n : opts.temperature;\n\n const wrappedToolChoice: ToolChoiceInput | undefined =\n typeof opts.toolChoice === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" toolChoice called before init`);\n }\n return (\n opts.toolChoice as (\n ctx: StatefulAgentContext<S>,\n ) => ChatToolChoice | Promise<ChatToolChoice>\n )({ ...ctx, state });\n }\n : opts.toolChoice;\n\n const wrappedCachePolicy: CachePolicyInput | undefined =\n typeof opts.cachePolicy === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" cachePolicy called before init`);\n }\n return (\n opts.cachePolicy as (ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>\n )({ ...ctx, state });\n }\n : opts.cachePolicy;\n\n // Unlike the resolvers above, a pre-init call returns `undefined` rather than throwing: that is\n // this option's \"model default\" state, so degrading to it costs a turn its thinking preference\n // instead of breaking the turn outright.\n const wrappedThinkingPolicy: ThinkingPolicyInput | undefined =\n typeof opts.thinkingPolicy === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) return undefined;\n return (\n opts.thinkingPolicy as (\n ctx: StatefulAgentContext<S>,\n ) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>\n )({ ...ctx, state });\n }\n : opts.thinkingPolicy;\n\n const wrappedTailContext: TailContextInput | undefined =\n typeof opts.tailContext === 'function'\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" tailContext called before init`);\n }\n return (opts.tailContext as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({\n ...ctx,\n state,\n });\n }\n : opts.tailContext;\n\n // `onUnresolvedTool` threads `state` in like the resolvers above, but unlike\n // them returns `undefined` before init rather than throwing: it fires on the\n // tool-dispatch path, so a pre-init call must degrade to the framework\n // default instead of breaking dispatch.\n const wrappedOnUnresolvedTool: UnresolvedToolInput | undefined =\n typeof opts.onUnresolvedTool === 'function'\n ? async (ctx) => {\n if (!state) {\n return undefined;\n }\n return opts.onUnresolvedTool!({ ...ctx, state });\n }\n : opts.onUnresolvedTool;\n\n // `resumable` threads the LIVE state bag in (like the resolvers above) rather\n // than the serialized image the raw `AgentConfig` form receives \u2014 so a machine\n // agent gates on `state.machine.state` directly. Consulted only while active\n // (state is set); a pre-init call degrades to `true` (resumable, fail-safe).\n const wrappedResumable: AgentConfig['resumable'] | undefined = opts.resumable\n ? async (ctx: AgentPersistenceContext): Promise<boolean> => {\n if (state === undefined) return true;\n return opts.resumable!({\n agentName: ctx.agentName,\n sessionKey: ctx.sessionKey,\n messages: ctx.messages,\n isFlowOwner: ctx.isFlowOwner,\n state,\n });\n }\n : undefined;\n\n const base = {\n name: opts.name,\n displayName: wrappedDisplayName,\n primerHistory: opts.primerHistory,\n subAgents: opts.subAgents,\n manualSelection: opts.manualSelection,\n chatInputDuringExecution: opts.chatInputDuringExecution,\n toolDefinitions: wrappedTools,\n toolHandlers: wrappedHandlers,\n provider: wrappedProvider,\n temperature: wrappedTemperature,\n toolChoice: wrappedToolChoice,\n cachePolicy: wrappedCachePolicy,\n thinkingPolicy: wrappedThinkingPolicy,\n tailContext: wrappedTailContext,\n onUnresolvedTool: wrappedOnUnresolvedTool,\n resumable: wrappedResumable,\n notResumableMessage: opts.notResumableMessage,\n\n onActivate: async (ctx: AgentLifecycleContext) => {\n state = await opts.init(ctx);\n // Sample once with the init state to fail loud on fold misuse at the\n // agent-switch boundary instead of waiting for the first tool call.\n // The driver re-resolves the factory each iteration, so misuse on\n // handlers gated behind a non-init state surfaces when that state is\n // reached \u2014 same loud failure mode, narrower coverage.\n if (opts.toolHandlers) {\n const sampled = await opts.toolHandlers(state);\n assertNoFolds(sampled);\n }\n },\n\n onDeactivate: async (ctx: AgentLifecycleContext) => {\n if (state !== undefined && opts.dispose) {\n await opts.dispose({ ...ctx, state });\n }\n // Orchestrator serializes onActivate/onDeactivate; concurrent calls\n // cannot interleave the read-then-write of `state`.\n // eslint-disable-next-line require-atomic-updates\n state = undefined;\n },\n\n systemPrompt: opts.systemPrompt\n ? async (ctx: SystemPromptContext) => {\n if (!state) {\n throw new Error(`Stateful agent \"${opts.name}\" systemPrompt called before init`);\n }\n return opts.systemPrompt!({ ...ctx, state });\n }\n : undefined,\n\n // Called per LLM call by ChatDriver, and once at debug-log export time.\n // Returns `undefined` before activation (state hasn't been built yet) and\n // after deactivation (state was disposed) \u2014 the snapshotter is best-effort\n // and the driver tolerates undefined.\n getDebugSnapshot: () => {\n if (!state) return undefined;\n return opts.getDebugSnapshot\n ? opts.getDebugSnapshot(state)\n : defaultStatefulDebugSnapshot(state);\n },\n\n // Lossless restore image for session persistence (see `serialize` on the\n // config). Returns undefined before activation / after disposal.\n serialize: () => {\n if (state === undefined) return undefined;\n return opts.serialize ? opts.serialize(state) : defaultStatefulSerialize(state);\n },\n };\n\n return {\n ...base,\n description: opts.description,\n excludeFromClassifier: opts.excludeFromClassifier,\n } as AgentConfig;\n}\n", "import type { FallbackAgentConfig } from './config';\n\n/**\n * A warm, conversational fallback agent. Acknowledges it can't help directly,\n * explains what the available specialists can do, and invites the user to retry.\n *\n * The system prompt is generated at runtime by `OrchestratingDriver` from the\n * specialist list \u2014 no manual authoring required.\n *\n * @beta\n */\nexport const friendlyFallbackAgent: FallbackAgentConfig = {\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a warm, friendly assistant. For general conversation like \"Hi\" or \"How are you\", you can have a friendly chat. For anything more complex, you cannot directly help, but you can explain what specialists are available. The available specialists are:\\n\\n{{agents}}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request if it is outside your scope.`,\n};\n\n/**\n * A brief, professional fallback agent. States what is available without\n * elaboration. The `{{agents}}` placeholder is replaced at runtime by\n * `OrchestratingDriver` with the generated specialist list.\n *\n * @beta\n */\nexport const strictFallbackAgent: FallbackAgentConfig = {\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a concise assistant. The user's request is outside your scope. Respond with a single short sentence stating what you can assist with. Do not elaborate. The available specialists are: {{agents}}.`,\n};\n", "import type { AggregateUsage, AIProviderType, ChatMessage } from '@genesislcap/foundation-ai';\nimport { vendorOfModel } from '@genesislcap/foundation-ai';\n\n/**\n * One billable unit of spend, projected out of a transcript.\n *\n * @remarks\n * Deliberately **not** a `ChatMessage`, and not an extension of one. A row is a\n * derived record for a ledger, and keeping the types distinct makes the one\n * dangerous mistake \u2014 feeding rows back into `sumUsage`, which does its own\n * recursion and would count everything twice \u2014 a compile error rather than a\n * plausible wrong number.\n *\n * @beta\n */\nexport interface UsageRow {\n /**\n * Where the spend came from.\n *\n * - `'request'` \u2014 one model call, with a message behind it.\n * - `'compaction'` \u2014 spend **banked** by a compaction. The turns that incurred it\n * were summarised and deleted, so there is no single call to attribute it to;\n * the amount survives on the summary's `compaction.rolledUpUsage`. Emitted as\n * its own row because otherwise this money is simply missing from a per-call\n * view while remaining present in the total, and the two disagree silently.\n */\n source: 'request' | 'compaction';\n /**\n * Model that produced the call. `undefined` on a `'compaction'` row: the banked\n * spend covers however many turns were summarised, which may have run on\n * different models, so attributing it to one would invent a fact. (The summary's\n * `compaction.model` is the model that did the *summarising* \u2014 a different thing,\n * and not what this spend was.)\n */\n model?: string;\n /**\n * Vendor that served the call. Taken from the provider the driver stamped on the message,\n * which is authoritative and covers vendors the model allowlists do not \u2014 a server-proxied\n * `gpt-5` turn is `'openai'` here and unknown to `vendorOfModel`. Falls back to resolving\n * {@link UsageRow.model} through `vendorOfModel` only for messages persisted before that\n * field existed, and is left unset when neither knows rather than guessed at.\n */\n provider?: AIProviderType;\n /**\n * USD for this row, as reported by the provider and stamped by the transport.\n *\n * `undefined` means no cost was reported \u2014 **not** zero. Nothing here estimates\n * one from the token counts: an estimate is plausible, unremarkable and quietly\n * wrong, whereas a total that is visibly too low gets investigated. A row with\n * tokens but no `costUsd` is worth alarming on; that is the shape that check needs.\n */\n costUsd?: number;\n /** Non-LLM spend a host reported for this turn (an external service it called). */\n externalCostUsd?: number;\n /** Prompt tokens billed at the full uncached rate \u2014 the remainder after the cache buckets. */\n uncachedInputTokens: number;\n /** Prompt tokens served from the provider's cache. */\n cacheReadTokens: number;\n /** Prompt tokens written to the provider's cache. */\n cacheWriteTokens: number;\n /** Generated tokens, including reasoning tokens the provider bills as output. */\n outputTokens: number;\n /** Agent that produced the call, when known. */\n agentName?: string;\n /** Delegation depth: 0 for the top-level conversation, 1 for a sub-agent, 2 for its sub-agent, \u2026 */\n subAgentDepth: number;\n /** Id of the tool call that spawned this row's conversation \u2014 correlates a row back to its delegation. */\n subAgentOf?: string;\n}\n\n/** Whether a message carries anything a ledger would record. */\nfunction hasUsage(m: ChatMessage): boolean {\n return (\n m.cost != null ||\n m.externalCostUsd != null ||\n m.inputTokens != null ||\n m.outputTokens != null ||\n m.cacheReadTokens != null ||\n m.cacheWriteTokens != null\n );\n}\n\n/**\n * Project a transcript into one row per billable unit of spend.\n *\n * @remarks\n * Reads the messages and returns a table; it stores nothing, mutates nothing, and\n * adds nothing to history. Use it where an **aggregate is not enough** \u2014 writing\n * usage rows for per-project attribution, a cost dashboard, or auditing which turns\n * came back unpriced. For a single total, `sumUsage` is the answer and this is the\n * wrong tool.\n *\n * Walks the same shape `sumUsage` does, and is guaranteed to agree with it: summing\n * `costUsd` and `externalCostUsd` across these rows equals `sumUsage(...).costUsd`\n * over the same input, and the four token buckets reconcile likewise. That property\n * is the point of the function \u2014 a per-call view that quietly disagrees with the\n * total is worse than no per-call view, because both look right in isolation.\n *\n * Covers the two places spend hides:\n *\n * - **Sub-agent conversations.** A delegating tool call carries the child's entire\n * conversation on `toolCall.subAgentTrace`, so a walk of top-level messages alone\n * misses everything a delegating agent spent. A consumer that reimplemented this\n * and omitted the branch reported $0.106 on a run that cost $0.234.\n * - **Compactions.** A compaction deletes the messages it summarises, banking their\n * spend on the summary. Those turns produce a single `source: 'compaction'` row.\n *\n * Messages carrying no usage at all (a user turn, a narration) produce no row.\n *\n * **Do not pass the result to `sumUsage`** \u2014 the types prevent it, and the reason is\n * that both recurse, so a pre-flattened list would be counted twice. Both functions\n * take raw history.\n *\n * @beta\n */\nexport function usageRows(messages: readonly ChatMessage[]): UsageRow[] {\n return collectRows(messages, 0, undefined);\n}\n\n/** Map an already-bucketed {@link AggregateUsage} onto a row's token fields. */\nfunction bucketsOf(\n usage: AggregateUsage,\n): Pick<UsageRow, 'uncachedInputTokens' | 'cacheReadTokens' | 'cacheWriteTokens' | 'outputTokens'> {\n return {\n uncachedInputTokens: usage.uncachedInputTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n outputTokens: usage.outputTokens,\n };\n}\n\nfunction collectRows(\n messages: readonly ChatMessage[],\n depth: number,\n subAgentOf: string | undefined,\n): UsageRow[] {\n const rows: UsageRow[] = [];\n for (const m of messages) {\n if (hasUsage(m)) {\n const cacheReadTokens = m.cacheReadTokens ?? 0;\n const cacheWriteTokens = m.cacheWriteTokens ?? 0;\n rows.push({\n source: 'request',\n model: m.model,\n // The driver stamps `ChatMessage.provider` from the resolved provider's own\n // status, so it is AUTHORITATIVE and covers vendors the model allowlists do\n // not \u2014 a server-proxied `gpt-5` turn is `provider: 'openai'` on the message\n // and unknown to `vendorOfModel`. Prefer it; fall back to resolving the model\n // id only for messages persisted before the field existed. Still left\n // undefined when neither knows, rather than guessed at.\n provider: m.provider ?? (m.model ? vendorOfModel(m.model) : undefined),\n ...(m.cost != null && { costUsd: m.cost }),\n ...(m.externalCostUsd != null && { externalCostUsd: m.externalCostUsd }),\n // Uncached input is the REMAINDER, matching `sumUsage`: `inputTokens` is the\n // whole prompt and the cache fields break it down. Clamped for the same\n // reason \u2014 hand-edited history must not drive a total negative.\n uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),\n cacheReadTokens,\n cacheWriteTokens,\n outputTokens: m.outputTokens ?? 0,\n ...(m.agentName != null && { agentName: m.agentName }),\n subAgentDepth: depth,\n ...(subAgentOf != null && { subAgentOf }),\n });\n }\n\n // Spend the compaction banked on this summary's behalf. Its buckets are already\n // disjoint (it is an `AggregateUsage`), so they map across without the\n // subtraction a per-message record needs.\n const rolled = m.compaction?.rolledUpUsage;\n if (rolled) {\n rows.push({\n source: 'compaction',\n ...(rolled.costUsd != null && { costUsd: rolled.costUsd }),\n ...bucketsOf(rolled),\n ...(m.agentName != null && { agentName: m.agentName }),\n subAgentDepth: depth,\n ...(subAgentOf != null && { subAgentOf }),\n });\n }\n\n for (const tc of m.toolCalls ?? []) {\n if (tc.subAgentTrace) rows.push(...collectRows(tc.subAgentTrace, depth + 1, tc.id));\n }\n }\n return rows;\n}\n", "import type { ChatMessage } from '@genesislcap/foundation-ai';\n\n/**\n * A chat message lifted into the debug-log timeline as a `kind: 'message'` entry.\n *\n * @beta\n */\nexport type TimelineMessage = ChatMessage & {\n kind: 'message';\n /**\n * Set only on entries hoisted out of a `subAgentTrace`: the sub-agent's own\n * (un-breadcrumbed) `agentName`, kept for filtering since the displayed\n * `agentName` is rewritten to a `\"<parent> \u203A <sub-agent>\"` breadcrumb.\n */\n subAgentName?: string;\n /** Delegation depth \u2014 absent/0 for top-level, 1 for a sub-agent, 2 for a sub-agent's sub-agent, \u2026 */\n subAgentDepth?: number;\n /** Id of the parent tool call that spawned this run \u2014 correlates a hoisted message back to its delegation. */\n subAgentOf?: string;\n};\n\n/**\n * Flatten sub-agent conversations into a single top-level message stream for the\n * debug-log timeline.\n *\n * A tool call that delegates to a sub-agent carries the sub-agent's entire\n * conversation on `toolCall.subAgentTrace`. The live UI reads that nested shape,\n * but a top-to-bottom timeline reads far better with those messages inline next to\n * the turn that produced them. This walks the list and, for every tool call with a\n * `subAgentTrace`, hoists the sub-agent's messages up as their own timeline\n * entries while **removing** the nested copy from the emitted parent tool call \u2014 a\n * move, not a copy. The data is relocated, never duplicated: the export stays the\n * same size and a naive `sum(timeline[].cost)` does not double-count (the\n * canonical `sumCosts` total still reads the un-flattened history).\n *\n * Hoisted entries are:\n * - **breadcrumbed**: `agentName` becomes `\"<parent> \u203A <sub-agent>\"`, composing for\n * nested sub-agents (`\"<parent> \u203A <sub> \u203A <subsub>\"`); the raw sub-agent name is\n * preserved on `subAgentName`.\n * - **depth-tagged** (`subAgentDepth`) and **correlated** to the spawning tool call\n * (`subAgentOf`), so the delegation tree is reconstructable even when two\n * sub-agents run within the same parent turn.\n *\n * Top-level messages (depth 0) are emitted unchanged apart from the trace strip.\n * Order is preserved within each list; the caller sorts the whole timeline by\n * timestamp afterwards, and every sub-agent message carries its own timestamp, so\n * hoisted entries interleave chronologically between the parent's tool-call and\n * tool-result messages.\n *\n * @internal\n */\nexport function flattenSubAgentMessages(\n messages: readonly ChatMessage[],\n prefix = '',\n depth = 0,\n subAgentOf?: string,\n): TimelineMessage[] {\n return messages.flatMap((m) => {\n const breadcrumb = prefix ? `${prefix} \u203A ${m.agentName ?? '?'}` : m.agentName;\n const traceCalls = m.toolCalls?.filter((tc) => tc.subAgentTrace?.length) ?? [];\n\n const entry: TimelineMessage = {\n kind: 'message',\n ...m,\n // Move the (about-to-be-hoisted) child conversations out of the emitted tool\n // calls. Setting it to `undefined` drops the key from the serialized export.\n ...(traceCalls.length > 0 && {\n toolCalls: m.toolCalls!.map((tc) =>\n tc.subAgentTrace ? { ...tc, subAgentTrace: undefined } : tc,\n ),\n }),\n // Mark + breadcrumb hoisted sub-agent messages; top-level (depth 0) stays as-is.\n ...(depth > 0 && {\n agentName: breadcrumb,\n subAgentName: m.agentName,\n subAgentDepth: depth,\n subAgentOf,\n }),\n };\n\n if (traceCalls.length === 0) return [entry];\n\n const hoisted = traceCalls.flatMap((tc) =>\n flattenSubAgentMessages(tc.subAgentTrace!, breadcrumb ?? '', depth + 1, tc.id),\n );\n return [entry, ...hoisted];\n });\n}\n", "/**\n * Shared, pure builder for the debug-log timeline entries (`message` / `turn` / `event`) \u2014 the\n * common core of the host element's `buildDiagnosticEntries` and any HEADLESS consumer that drives\n * a `ChatDriver` of its own (e.g. `ai-service` running the engine server-side) and needs to harvest\n * that engine's debug log for the client to fold into its own download / persisted stream\n * (GENC-1461 unified diagnostics). DOM-clean and dependency-light so it works in bare Node.\n *\n * It deliberately excludes the `meta-snapshot` entry: that block is host/DOM-specific (it reads\n * `window.location.host`, the element's agent list, live context/cost), and a merged log keeps only\n * the newest snapshot anyway \u2014 a headless source's agent/prompt/tools are already captured in its\n * `turn` entries.\n *\n * @packageDocumentation\n */\n\nimport type { ChatMessage } from '@genesislcap/foundation-ai';\nimport { flattenSubAgentMessages } from '../../utils/flatten-sub-agent-messages';\nimport type { MetaEvent } from '../debug-event-log';\nimport type { DiagnosticEntry } from './diagnostics';\n\n/**\n * The minimal shape this builder reads off a turn snapshot. The driver's full `TurnSnapshot` is a\n * structural superset, so it assigns to this without the builder depending on the component layer.\n */\nexport interface TurnSnapshotLike {\n turnIndex: string;\n systemPrompt?: string;\n}\n\n/**\n * Build the `message` / `turn` / `event` timeline entries from a driver's pull surfaces\n * (`getRawHistory()` / `getTurnSnapshots()` / `getMetaEvents(sessionKey)`). Order within the array\n * is message \u2192 turn \u2192 event; the caller (`assembleDebugLog`) sorts the whole timeline by timestamp,\n * so this ordering only sets the co-timestamp tie-break. Pure.\n */\nexport function buildTimelineEntries(input: {\n turnSnapshots: readonly TurnSnapshotLike[];\n messages: readonly ChatMessage[];\n metaEvents: readonly MetaEvent[];\n}): DiagnosticEntry[] {\n const { turnSnapshots, messages, metaEvents } = input;\n\n // Collapse a turn's systemPrompt when byte-identical to the previous turn's \u2014 a stable agent\n // repeats the same (often multi-KB) prompt every turn, while a stateful agent's changes. The\n // prompt is shown in full whenever it changes, so prompt evolution stays visible.\n let lastFullPrompt: string | undefined;\n let lastFullIndex = '';\n const turns = turnSnapshots.map((t) => {\n let { systemPrompt } = t;\n if (systemPrompt != null && systemPrompt === lastFullPrompt) {\n systemPrompt = `<repeated \u2014 identical to turn ${lastFullIndex}>`;\n } else if (systemPrompt != null) {\n lastFullPrompt = systemPrompt;\n lastFullIndex = t.turnIndex;\n }\n return { kind: 'turn' as const, ...t, systemPrompt };\n });\n\n // Sub-agent conversations are stored nested on the parent tool call's `subAgentTrace`;\n // `flattenSubAgentMessages` hoists them to top-level `kind: 'message'` entries (breadcrumbed +\n // correlated, the nested copy moved out \u2014 not duplicated) so the timeline reads chronologically.\n const messageEntries = flattenSubAgentMessages(messages);\n const eventEntries = metaEvents.map((e) => ({ kind: 'event' as const, ...e }));\n\n return [...messageEntries, ...turns, ...eventEntries] as DiagnosticEntry[];\n}\n", "/**\n * Server-saved diagnostics (GENC-1351 \u00A75.8) \u2014 the forward-only stream that lets\n * the debug log persist across a whole session lifetime, not just the current\n * page load. This module owns the *pure* pieces: the entry type and the\n * reassembly back into the `{ readme, sessionUsage, timeline, meta }` debug-log\n * shape. The element owns capture/cadence; the provider owns storage layout.\n *\n * @packageDocumentation\n */\n\nimport type { AggregateUsage } from '@genesislcap/foundation-ai';\n\n/**\n * One entry in the diagnostics stream \u2014 the debug-log timeline-entry union\n * (`message` / `turn` / `event`, as `getDebugLog()` builds) plus a point-in-time\n * **`meta-snapshot`** carrying the export-time `meta` block (agent summary,\n * context, active debug snapshot, \u2026). Kept permissive: a provider stores and\n * returns these opaquely, and reassembly reads only `kind`, `timestamp` (for\n * ordering), `usage` (on a turn) and `meta` (on a snapshot).\n *\n * @public\n */\nexport interface DiagnosticEntry {\n kind: 'message' | 'turn' | 'event' | 'meta-snapshot';\n /** ISO timestamp \u2014 string-comparable, so it orders the stream chronologically. */\n timestamp?: string;\n /** Present on `meta-snapshot` entries: the export-time `meta` block. */\n meta?: unknown;\n /**\n * Present on a `turn` entry once its model call has returned and reported usage \u2014\n * the four token buckets plus USD for that one call (`TurnSnapshot.usage`).\n *\n * Read by the forward-capture delta as well as by readers: the turn entry is\n * created *before* the call, so a flush that lands mid-call persists it without\n * usage, and the delta re-emits it once (see `collectDiagnosticsDelta`) so the\n * priced copy reaches the stream. {@link assembleDebugLog} then collapses the pair.\n */\n usage?: AggregateUsage;\n /**\n * Present on `meta-snapshot` entries: a stable signature of the near-static config\n * (excludes volatile timestamp/context/debug-snapshot), used by the forward-capture\n * delta to skip re-appending an unchanged block (GENC-1351 \u00A75.8). Absent on other\n * kinds and on pre-signature entries (the delta falls back to the full `meta` then).\n */\n dedupSignature?: string;\n [key: string]: unknown;\n}\n\n/** The reassembled debug log \u2014 the exact shape `getDebugLog()` returns. @public */\nexport interface DebugLog {\n readme: readonly string[];\n /**\n * Session usage \u2014 the four token buckets plus USD cost \u2014 lifted out of the newest\n * `meta-snapshot`'s `meta.context.sessionUsage` so the headline spend figures sit at\n * the top of an exported log rather than buried under the (large) `meta` block. The\n * same object, not a second derivation.\n *\n * `undefined` when the stream carries no `meta-snapshot`, or one written before the\n * field existed. Never re-derived from the timeline: the per-request costs the\n * transports stamped are authoritative, and a ring-buffered timeline can have lost\n * entries the total still legitimately counts.\n *\n * **As current as the snapshot it came from, which is not automatically \"now\".** The\n * forward-capture delta only re-appends a `meta-snapshot` when the near-static config\n * signature changes, so the newest STORED snapshot of a session whose config never\n * changed is its first \u2014 with the totals frozen there. A caller reassembling a stored\n * stream on its own therefore gets stale figures unless it appends an export-time\n * snapshot first: see {@link withFreshMetaSnapshot}, which is what the assistant's own\n * download path does. `meta.timestamp` against the newest timeline entry tells you\n * which case you are holding.\n */\n sessionUsage?: AggregateUsage;\n timeline: DiagnosticEntry[];\n meta: unknown;\n}\n\n/**\n * Stable identity for a message diagnostic entry \u2014 `timestamp::role::subAgentOf::category`.\n * Used by the forward-capture delta (skip already-emitted messages) and by the\n * restore watermark (skip messages already present in a prior load's stream).\n * `null` when the entry has no timestamp \u2192 treat as always-new. Shared so the\n * element's diagnostics capture and the `SessionPersister`'s restore watermark\n * compute identity identically (GENC-1351 \u00A75.8/\u00A75.10).\n *\n * `category` is part of the key because the reasoning/narration/answer split (GENC-1411) emits\n * SEVERAL messages from one model response \u2014 the thought summary, any interstitial narration, and\n * the answer/tool-call message \u2014 which share `timestamp` + `role` + `subAgentOf`. Keying on those\n * alone collapsed them to one, so the forward-capture dropped all but the first: a server\n * generation's answer message vanished from the persisted debug log while its reasoning survived\n * (GENC-1461). `category` is stable across a message's in-place annotation (only `toolCalls` change,\n * which is deliberately excluded), so a genuine re-append of the same message still dedups.\n *\n * @internal\n */\nexport function diagnosticsMessageKey(entry: DiagnosticEntry): string | null {\n return typeof entry.timestamp === 'string'\n ? `${entry.timestamp}::${(entry.role as string) ?? ''}::${(entry.subAgentOf as string) ?? ''}::${(entry.category as string) ?? ''}`\n : null;\n}\n\n/**\n * Identity of a `turn` entry \u2014 `turnIndex::timestamp::agentName`.\n *\n * Deliberately NOT the serialized entry, which two copies of the same call do not always\n * share. `buildTimelineEntries` renders `systemPrompt` *relative to the preceding\n * snapshots* (collapsing it to `<repeated \u2014 identical to turn N>` when it matches the\n * previous full prompt), so if the snapshot holding that full prompt is evicted from the\n * ring buffer between the unpriced flush and the priced one, the surviving turn renders\n * its prompt differently and the two serializations diverge. Both copies are in the\n * stream by then, so nothing would collapse them \u2014 and the log whose purpose is per-call\n * cost would show one model call as two turns, one of them unpriced.\n *\n * All three components are fixed when the snapshot is created and never re-derived.\n * `turnIndex` alone is not enough: it restarts at `'0'` on each page load, and a lifetime\n * log legitimately holds one turn `'0'` per load. `agentName` separates two sub-agents\n * invoked in the same parent turn, which share a `turnIndex` prefix by construction (see\n * `forwardSubAgentSnapshots`).\n */\nfunction turnIdentity(entry: DiagnosticEntry): string {\n return `turn::${String(entry.turnIndex ?? '')}::${entry.timestamp ?? ''}::${String(entry.agentName ?? '')}`;\n}\n\n// Tie-break co-timestamped entries by cause \u2192 call \u2192 output (event, turn, message),\n// matching the original in-place `getDebugLog` sort.\nconst KIND_RANK: Record<string, number> = { event: 0, turn: 1, message: 2 };\n// Any non-{event,turn,message} kind (shouldn't reach the timeline \u2014 meta-snapshots\n// are filtered out first) sorts last.\nconst UNKNOWN_KIND_RANK = 99;\n\n/**\n * Reassemble diagnostic entries into the `{ readme, sessionUsage, timeline, meta }`\n * debug-log shape (GENC-1351 \u00A75.8). `timeline` = the `message`/`turn`/`event` entries sorted\n * by ISO `timestamp` (kind-rank tie-break). `meta` = the **newest** `meta-snapshot`'s\n * block only \u2014 a \"state at export\" photo, matching the single-page log. The older\n * snapshots are intentionally dropped: the per-turn evolution they would show is\n * already in the timeline (`turn.agentSnapshot` + `context.updated` events), so\n * keeping them would just repeat the bulky, near-static `agentSummary`. `readme` =\n * the passed (current) constant. `sessionUsage` = that same newest snapshot's\n * `meta.context.sessionUsage`, lifted to the top level. Pure \u2014 reused for both the\n * live current-page log and the reassembled lifetime log stitched from the persisted\n * stream, so both come out shape-identical.\n *\n * NOTE for a caller stitching a STORED stream (a headless consumer harvesting its own\n * lifetime log, say): the newest stored `meta-snapshot` is frozen at the last\n * config-signature change, so `meta` and `sessionUsage` are as old as that unless you\n * pass a fresh snapshot of your own \u2014 {@link withFreshMetaSnapshot} does exactly that,\n * and the element's download path goes through it.\n */\nexport function assembleDebugLog(entries: DiagnosticEntry[], readme: readonly string[]): DebugLog {\n // Safety net for exact-duplicate entries: two element instances sharing one\n // session (bubble + popped-out panel) can each append the same entry, and a\n // reload's second instance can re-append restored history. Such copies are\n // byte-identical, so collapse by serialized identity \u2014 genuinely-distinct entries\n // (e.g. two real `assistant.connected` from two instances) differ in index /\n // placement and are kept. (The shared cursor store prevents most of this at\n // write time; this guards the read path regardless of what's in the stream.)\n //\n // A `turn` is identified by `turnIndex` + `timestamp` + `agentName` instead (see\n // `turnIdentity`), so the unpriced copy a mid-call flush persisted and the priced copy\n // that follows it collapse into ONE turn \u2014 the priced one \u2014 rather than reading as two\n // model calls.\n const seenAt = new Map<string, number>();\n let latestMeta: DiagnosticEntry | undefined;\n const timeline: DiagnosticEntry[] = [];\n for (const entry of entries) {\n if (entry.kind === 'meta-snapshot') {\n if (!latestMeta || (entry.timestamp ?? '') >= (latestMeta.timestamp ?? '')) {\n latestMeta = entry;\n }\n continue;\n }\n const id = entry.kind === 'turn' ? turnIdentity(entry) : JSON.stringify(entry);\n const at = seenAt.get(id);\n if (at !== undefined) {\n // Same entry seen twice \u2014 keep the richer copy. `usage` on a turn is the only\n // field that can arrive late, so it is the only upgrade there is to make.\n if (entry.usage && !timeline[at].usage) timeline[at] = entry;\n continue;\n }\n seenAt.set(id, timeline.length);\n timeline.push(entry);\n }\n timeline.sort((a, b) => {\n const ta = a.timestamp ?? '';\n const tb = b.timestamp ?? '';\n if (ta < tb) return -1;\n if (ta > tb) return 1;\n return (KIND_RANK[a.kind] ?? UNKNOWN_KIND_RANK) - (KIND_RANK[b.kind] ?? UNKNOWN_KIND_RANK);\n });\n // The session totals live inside the newest snapshot's `meta`, which is `unknown` by\n // design (a provider stores these opaquely) \u2014 so this narrows just the one path it\n // reads rather than typing the whole block.\n const context = (latestMeta?.meta as { context?: { sessionUsage?: AggregateUsage } } | undefined)\n ?.context;\n return { readme, sessionUsage: context?.sessionUsage, timeline, meta: latestMeta?.meta };\n}\n\n/**\n * A stored diagnostics stream with its `meta-snapshot`s replaced by `fresh` \u2014 what to\n * pass {@link assembleDebugLog} when reassembling a persisted stream for export.\n *\n * The stored snapshots are dropped rather than out-timestamped. `assembleDebugLog` keeps\n * whichever claims the later time, and a stream written on another machine can carry a\n * skewed clock; `fresh` is built from live state and so is the more current by\n * construction. Only one snapshot ever survives reassembly, so the count is unchanged \u2014\n * though a snapshot taken while the driver is unwired (mid-popout) can leave\n * `activeFoldStack`/`activeDebugSnapshot` unset where a stored one had them. The figures\n * this exists for \u2014 the context block and `sessionUsage` \u2014 read the session store and\n * element props, which survive an unwire.\n *\n * Pure, and separate from the element for that reason: the swap it performs is the fix\n * for a silent bug (a lifetime log reporting near-zero spend against a transcript full of\n * priced messages), so it needs to be testable without mounting anything.\n */\nexport function withFreshMetaSnapshot(\n stored: readonly DiagnosticEntry[],\n fresh: DiagnosticEntry,\n): DiagnosticEntry[] {\n return [...stored.filter((e) => e.kind !== 'meta-snapshot'), fresh];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["v", "createConsola", "createConsola", "logger", "isPlainObject", "frame", "_a", "DEFAULT_MODEL", "DEFAULT_TIMEOUT", "DEFAULT_STALL_TIMEOUT", "_a", "_b", "imageParts", "textParts", "registry", "logger", "logger", "logger", "prompt", "failureReason", "logger", "prompt"]
|
|
7
7
|
}
|