@skaile/workspaces 4.5.2 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-G4WIFRFX.js → asset-feeds-3XUEJHLJ.js} +4 -4
  4. package/dist/{asset-feeds-G4WIFRFX.js.map → asset-feeds-3XUEJHLJ.js.map} +1 -1
  5. package/dist/asset-manager/index.js +1 -1
  6. package/dist/bridge/drivers/claude-sdk.js +4 -4
  7. package/dist/bridge/drivers/codex.js +2 -2
  8. package/dist/bridge/drivers/continue.js +2 -2
  9. package/dist/bridge/drivers/echo.js +3 -3
  10. package/dist/bridge/drivers/gemini.js +4 -4
  11. package/dist/bridge/drivers/goose.js +2 -2
  12. package/dist/bridge/drivers/omp.js +1 -1
  13. package/dist/bridge/drivers/opencode.js +2 -2
  14. package/dist/bridge/drivers/qwen.js +4 -4
  15. package/dist/bridge/index.js +5 -5
  16. package/dist/{chunk-JHPBSZIP.js → chunk-2CFREMKM.js} +3 -3
  17. package/dist/{chunk-JHPBSZIP.js.map → chunk-2CFREMKM.js.map} +1 -1
  18. package/dist/{chunk-CKLCKPC7.js → chunk-2HZJKDLG.js} +2 -2
  19. package/dist/{chunk-CKLCKPC7.js.map → chunk-2HZJKDLG.js.map} +1 -1
  20. package/dist/{chunk-NOH5UDO7.js → chunk-3GKBSHUG.js} +3 -3
  21. package/dist/{chunk-NOH5UDO7.js.map → chunk-3GKBSHUG.js.map} +1 -1
  22. package/dist/{chunk-XXRQHASJ.js → chunk-5CDL6VZQ.js} +6 -6
  23. package/dist/{chunk-XXRQHASJ.js.map → chunk-5CDL6VZQ.js.map} +1 -1
  24. package/dist/{chunk-AMJEPVNB.js → chunk-63PBQN5U.js} +6 -6
  25. package/dist/{chunk-AMJEPVNB.js.map → chunk-63PBQN5U.js.map} +1 -1
  26. package/dist/{chunk-YVQZQGVW.js → chunk-6ZQU5WKJ.js} +3 -3
  27. package/dist/{chunk-YVQZQGVW.js.map → chunk-6ZQU5WKJ.js.map} +1 -1
  28. package/dist/{chunk-3OLCTLTH.js → chunk-7WVPAQPE.js} +3 -2
  29. package/dist/chunk-7WVPAQPE.js.map +1 -0
  30. package/dist/{chunk-JF77XKD7.js → chunk-CU32AWH5.js} +3 -3
  31. package/dist/{chunk-JF77XKD7.js.map → chunk-CU32AWH5.js.map} +1 -1
  32. package/dist/{chunk-DHYIUGZW.js → chunk-D3332IMQ.js} +3 -3
  33. package/dist/{chunk-DHYIUGZW.js.map → chunk-D3332IMQ.js.map} +1 -1
  34. package/dist/{chunk-VJJUKODI.js → chunk-DXXIALYF.js} +3 -3
  35. package/dist/{chunk-VJJUKODI.js.map → chunk-DXXIALYF.js.map} +1 -1
  36. package/dist/{chunk-Q5C77OZW.js → chunk-EVVE4SL4.js} +3 -3
  37. package/dist/{chunk-Q5C77OZW.js.map → chunk-EVVE4SL4.js.map} +1 -1
  38. package/dist/{chunk-C2CYBRYJ.js → chunk-KMFZVPYR.js} +2 -2
  39. package/dist/{chunk-C2CYBRYJ.js.map → chunk-KMFZVPYR.js.map} +1 -1
  40. package/dist/{chunk-U4AA7MOV.js → chunk-QAH24E5U.js} +6 -3
  41. package/dist/chunk-QAH24E5U.js.map +1 -0
  42. package/dist/{chunk-VP2CACF2.js → chunk-QVTROHEZ.js} +3 -3
  43. package/dist/{chunk-VP2CACF2.js.map → chunk-QVTROHEZ.js.map} +1 -1
  44. package/dist/{chunk-CNYIITSZ.js → chunk-R4OMDCGZ.js} +3 -3
  45. package/dist/{chunk-CNYIITSZ.js.map → chunk-R4OMDCGZ.js.map} +1 -1
  46. package/dist/{chunk-6GA27VV4.js → chunk-SAXTWLXZ.js} +10 -10
  47. package/dist/{chunk-6GA27VV4.js.map → chunk-SAXTWLXZ.js.map} +1 -1
  48. package/dist/chunk-SDNGG6FB.js +32 -0
  49. package/dist/chunk-SDNGG6FB.js.map +1 -0
  50. package/dist/{chunk-Y5E6LHSQ.js → chunk-TRGMQUAZ.js} +94 -55
  51. package/dist/chunk-TRGMQUAZ.js.map +1 -0
  52. package/dist/{chunk-GVOPQBGM.js → chunk-V7SHQXDI.js} +4 -4
  53. package/dist/{chunk-GVOPQBGM.js.map → chunk-V7SHQXDI.js.map} +1 -1
  54. package/dist/{chunk-PJP2TOCB.js → chunk-VZOUBMM4.js} +5 -5
  55. package/dist/{chunk-PJP2TOCB.js.map → chunk-VZOUBMM4.js.map} +1 -1
  56. package/dist/{chunk-GNXKNQPU.js → chunk-YNZ5FIFH.js} +2 -2
  57. package/dist/{chunk-GNXKNQPU.js.map → chunk-YNZ5FIFH.js.map} +1 -1
  58. package/dist/{chunk-MKJ2QYID.js → chunk-ZGYPEVZW.js} +4 -4
  59. package/dist/{chunk-MKJ2QYID.js.map → chunk-ZGYPEVZW.js.map} +1 -1
  60. package/dist/cli/index.js +35 -34
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/connectors/index.js +7 -6
  63. package/dist/connectors/src/classify-connect-error.d.ts +20 -0
  64. package/dist/connectors/src/classify-connect-error.d.ts.map +1 -0
  65. package/dist/connectors/src/connect-error-kind.d.ts +47 -0
  66. package/dist/connectors/src/connect-error-kind.d.ts.map +1 -0
  67. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  68. package/dist/connectors/src/index.d.ts +3 -0
  69. package/dist/connectors/src/index.d.ts.map +1 -1
  70. package/dist/connectors-shared/index.js +2 -0
  71. package/dist/connectors-shared/index.js.map +1 -1
  72. package/dist/connectors-shared/src/index.d.ts +7 -2
  73. package/dist/connectors-shared/src/index.d.ts.map +1 -1
  74. package/dist/{ensure-sources-J5J2TBRA.js → ensure-sources-MFQDQPYL.js} +4 -4
  75. package/dist/{ensure-sources-J5J2TBRA.js.map → ensure-sources-MFQDQPYL.js.map} +1 -1
  76. package/dist/factory-assets/connectors/box.js +7 -6
  77. package/dist/factory-assets/connectors/deploy.js +7 -6
  78. package/dist/factory-assets/connectors/devserver.js +7 -6
  79. package/dist/factory-assets/connectors/flow/adapter.js +7 -6
  80. package/dist/factory-assets/connectors/flow/run-flow.js +8 -7
  81. package/dist/factory-assets/connectors/flow.js +7 -6
  82. package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
  83. package/dist/factory-assets/connectors/git.js +7 -6
  84. package/dist/factory-assets/connectors/gmail.js +7 -6
  85. package/dist/factory-assets/connectors/googledrive.js +7 -6
  86. package/dist/factory-assets/connectors/local.js +7 -6
  87. package/dist/factory-assets/connectors/mattermost.js +7 -6
  88. package/dist/factory-assets/connectors/memory.js +7 -6
  89. package/dist/factory-assets/connectors/minio.js +7 -6
  90. package/dist/factory-assets/connectors/postgres.js +7 -6
  91. package/dist/factory-assets/connectors/s3.js +7 -6
  92. package/dist/factory-assets/connectors/sharepoint.js +7 -6
  93. package/dist/factory-assets/connectors/sqlite.js +7 -6
  94. package/dist/factory-assets/connectors/static-server.js +7 -6
  95. package/dist/factory-assets/connectors/tunnel.js +7 -6
  96. package/dist/factory-assets/connectors/webdav.js +7 -6
  97. package/dist/factory-assets/connectors/xstate-store.js +7 -6
  98. package/dist/factory-assets/connectors/xstate.js +7 -6
  99. package/dist/{helpers-OJJNDSPO.js → helpers-VQLLQ6HB.js} +4 -4
  100. package/dist/{helpers-OJJNDSPO.js.map → helpers-VQLLQ6HB.js.map} +1 -1
  101. package/dist/{library-publish-TDT5HCLA.js → library-publish-73SFVNCE.js} +6 -6
  102. package/dist/{library-publish-TDT5HCLA.js.map → library-publish-73SFVNCE.js.map} +1 -1
  103. package/dist/{open-library-OAVUUOAN.js → open-library-QGTUQMUG.js} +5 -5
  104. package/dist/{open-library-OAVUUOAN.js.map → open-library-QGTUQMUG.js.map} +1 -1
  105. package/dist/{project-PNSDEXUH.js → project-LWS5PYIF.js} +5 -5
  106. package/dist/{project-PNSDEXUH.js.map → project-LWS5PYIF.js.map} +1 -1
  107. package/dist/runner/index.js +11 -10
  108. package/dist/sdk/asset-manager.js +1 -1
  109. package/dist/sdk/bridge.js +5 -5
  110. package/dist/sdk/index.js +11 -10
  111. package/dist/sdk/index.js.map +1 -1
  112. package/dist/sdk/runner.js +11 -10
  113. package/dist/sdk/session.js +2 -2
  114. package/dist/sdk/store.js +1 -1
  115. package/dist/sdk/types.js +1 -1
  116. package/dist/session/index.js +2 -2
  117. package/dist/{setup-6FAITLPM.js → setup-EOJWDJK2.js} +10 -10
  118. package/dist/{setup-6FAITLPM.js.map → setup-EOJWDJK2.js.map} +1 -1
  119. package/dist/{source-RTVNF6GB.js → source-Q5IIYTRA.js} +6 -6
  120. package/dist/{source-RTVNF6GB.js.map → source-Q5IIYTRA.js.map} +1 -1
  121. package/dist/{source-manifest-publish-U2PVHXCF.js → source-manifest-publish-Z3WC4HA2.js} +7 -7
  122. package/dist/{source-manifest-publish-U2PVHXCF.js.map → source-manifest-publish-Z3WC4HA2.js.map} +1 -1
  123. package/dist/store/index.js +1 -1
  124. package/dist/store/src/resource-client.d.ts.map +1 -1
  125. package/dist/store/src/types.d.ts +3 -1
  126. package/dist/store/src/types.d.ts.map +1 -1
  127. package/dist/tui/index.js +11 -10
  128. package/dist/tui/index.js.map +1 -1
  129. package/dist/types/index.js +1 -1
  130. package/dist/types/src/events.d.ts +22 -0
  131. package/dist/types/src/events.d.ts.map +1 -1
  132. package/dist/types/src/index.d.ts +2 -1
  133. package/dist/types/src/index.d.ts.map +1 -1
  134. package/dist/workspace-plugin/adapters/mcp.js +2 -2
  135. package/dist/workspace-plugin/index.js +1 -1
  136. package/package.json +1 -1
  137. package/dist/chunk-3OLCTLTH.js.map +0 -1
  138. package/dist/chunk-U4AA7MOV.js.map +0 -1
  139. package/dist/chunk-Y5E6LHSQ.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../types/src/events.ts","../types/src/mentions.ts","../types/src/protocol.ts","../types/src/reactions.ts","../types/src/capabilities.ts","../types/src/tool-activity.ts","../types/src/version.ts"],"names":[],"mappings":"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","file":"chunk-QAH24E5U.js","sourcesContent":["/**\n * Agent Events — the unified event stream.\n *\n * These are the real-time events emitted by agent drivers (bridge, vm-agent)\n * and consumed by runners, gateways, and frontends. Persistent events are\n * wrapped in a {@link Message} envelope by the host's persistence layer.\n */\n\nimport type {\n CapabilityDeregisterEvent,\n CapabilityInvokedEvent,\n CapabilityRegisterEvent,\n RenderInvokedEvent,\n} from \"./capabilities.js\";\nimport type {\n IncompatibleProtocolEvent,\n ProtocolInfoEvent,\n SessionInitAckEvent,\n SessionInitMismatchEvent,\n} from \"./lifecycle.js\";\nimport type { LogEntry } from \"./logging.js\";\n\n// ---------------------------------------------------------------------------\n// Agent event — discriminated union of all event types\n// ---------------------------------------------------------------------------\n\n/**\n * Discriminated union of every event the Skaile agent runtime can emit.\n *\n * Persistent events are wrapped in a `MessageV2` envelope by the host's persistence\n * layer. Transient events are forwarded over the transport but not appended to the\n * message store. Narrow via `event.type` or a `switch` statement.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type AgentEvent =\n | TextEvent\n | TextRetractEvent\n | ToolCallEvent\n | ToolResultEvent\n | QuestionEvent\n | QuestionReplyEvent\n | ErrorEvent\n | StatusEvent\n | DevServerEvent\n | FileChangeEvent\n | SubagentEvent\n | FinishedEvent\n | A2AMessageEvent\n | StateChangedEvent\n | HandoffEvent\n | ConnectorResponseEvent\n | ConnectorQueryResponseEvent\n | ConnectorMutateResponseEvent\n | PromptAckEvent\n | ConnectorsAvailableEvent\n | LifecycleCompleteEvent\n | TypingEvent\n | UserMessageEvent\n | SyncStatusEvent\n | SecretsReadyEvent\n | ConfiguredEvent\n | MountMountedEvent\n | MountUnmountedEvent\n | MountChangedEvent\n | MountSyncStatusEvent\n | DebugResultEvent\n | LogEntryEvent\n | ValidationWarningEvent\n | SkillsChangedEvent\n | CommandsAvailableEvent\n | FlowBreadcrumbEvent\n | FlowPromptEvent\n | SessionInfoEvent\n | ReactionAddedEvent\n | ReactionRemovedEvent\n | ResourceStatusEvent\n | ConnectorStatusEvent\n | CustomMessageEvent\n | SnapshotEvent\n | CompactionAttemptEvent\n | RuntimeSessionEvent\n | ResumeAttemptedEvent\n | ResumeFailedEvent\n // Protocol v2 capability + lifecycle events\n | CapabilityRegisterEvent\n | CapabilityDeregisterEvent\n | CapabilityInvokedEvent\n | RenderInvokedEvent\n | ProtocolInfoEvent\n | IncompatibleProtocolEvent\n // Protocol v3 session_init lifecycle events\n | SessionInitAckEvent\n | SessionInitMismatchEvent\n // Agent prompt composition (system_prompt_composed)\n | SystemPromptComposedEvent\n // Live AI-provider health telemetry (401 / 429 attribution)\n | ProviderResponseSeenEvent\n // Live AI-provider quota-window readings\n | ProviderQuotaObservedEvent;\n\n/**\n * A text message from the agent to the user.\n *\n * The most common event type, containing plain-text content generated by the agent.\n *\n * @docLink packages/types/events#text-event\n */\nexport type TextEvent = {\n type: \"text\";\n content: string;\n};\n\n/**\n * Takes back text the agent already streamed as {@link TextEvent}s.\n *\n * Sent when the driver abandons an attempt mid-message and replays the prompt\n * (a lost-transcript resume, an auth refresh, a seat failover): the replay\n * streams the reply afresh, so the half-message the failed attempt left behind\n * would otherwise sit in front of it. `content` is exactly the text to remove\n * and is always a suffix of what the consumer has accumulated since the last\n * boundary it committed. A consumer that already committed that text (or holds\n * something else) should leave it alone rather than cut unrelated prose.\n *\n * Only unfinished text is ever retracted — a message the model completed is\n * part of the transcript the replay resumes from and stays.\n *\n * @since protocol 4.3.0\n * @docLink packages/types/events#text-retract-event\n */\nexport type TextRetractEvent = {\n type: \"text_retract\";\n content: string;\n};\n\n/**\n * A tool call request from the agent.\n *\n * Indicates the agent wants to invoke a tool with the given name and input arguments.\n * The platform should execute the tool and return the result via {@link ToolResultEvent}.\n *\n * @property tool - The name of the tool to invoke (must match a registered tool)\n * @property input - The input arguments to pass to the tool (structure depends on the tool)\n * @property summary - Short technical summary of the tool call (e.g. `$ git status`)\n * @property label - Plain-language description of the call for non-technical\n * users: the agent's own `activity_label` (Bash: `description`), else a\n * derived phrase for built-in tools. Absent when neither is available.\n *\n * @see {@link TextEvent} for plain text messages\n * @see {@link ToolResultEvent} for tool execution results\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#tool-call-event\n */\nexport type ToolCallEvent = {\n type: \"tool_call\";\n tool: string;\n input: unknown;\n summary: string;\n /** @since 3.24.0 */\n label?: string;\n};\n\n/**\n * The result of a tool execution.\n *\n * Contains the output returned by a tool after it has been executed.\n * This event is typically sent by the platform in response to a {@link ToolCallEvent}.\n *\n * @property tool - The name of the tool that was executed\n * @property output - The result data returned by the tool (structure depends on the tool)\n * @property summary - Short human-readable summary of the result\n *\n * @see {@link ToolCallEvent} for the corresponding tool invocation\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#tool-result-event\n */\nexport type ToolResultEvent = {\n type: \"tool_result\";\n tool: string;\n output: unknown;\n summary: string;\n};\n\n/**\n * A question posed by the agent to the user.\n *\n * Used when the agent needs clarification or input from the user to proceed.\n * The question may include multiple-choice options to guide the user's response.\n *\n * @property question - The question text to display to the user\n * @property options - Optional array of suggested answers (when provided, user should select one)\n *\n * @see {@link QuestionReplyEvent} for the user's response\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#question-event\n */\n/** Durable native approval presentation, never tool identity or permission authority. */\nexport type NativeApprovalDescription = {\n kind: \"command\" | \"file\" | \"permissions\" | \"mcp\";\n details: string[];\n};\n\nexport type QuestionEvent = {\n /** Opaque correlated request identity; managed replies must echo it unchanged. */\n requestId?: string;\n /** Fixed Approve once/Deny card; clients must preserve this request's exact identity. */\n approval?: NativeApprovalDescription;\n type: \"question\";\n question: string;\n options?: string[];\n};\n\n/**\n * The user's reply to a question asked by the agent.\n *\n * Sent in response to a {@link QuestionEvent} when the user provides an answer.\n *\n * @property answer - The user's response text\n *\n * @see {@link QuestionEvent} for the original question\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#question-event\n */\nexport type QuestionReplyEvent = {\n type: \"question_reply\";\n answer: string;\n};\n\n/**\n * An error condition encountered during agent execution.\n *\n * Indicates something went wrong during the agent's operation.\n * The severity determines whether execution can continue.\n *\n * @property message - Human-readable description of the error\n * @property fatal - When true, indicates the error is unrecoverable and execution should stop\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#error-event\n */\n\nexport type ErrorEvent = {\n type: \"error\";\n message: string;\n fatal: boolean;\n category?: ErrorCategory;\n /**\n * Short actionable advice for display to the user. Set by the bridge's\n * error classifier when it recognises the upstream failure mode (e.g.\n * \"Quota exhausted on the configured Anthropic account — try again\n * after the rate-limit window resets\"). Optional.\n */\n hint?: string;\n /**\n * Usage of the turn that ended in this error, present only when the error\n * is a turn result (`error_max_turns`, `error_during_execution`, …) and the\n * driver tracked usage. The provider bills the turn either way; a consumer\n * that ledgers `finished` should ledger these too. Same fields and meaning\n * as on {@link FinishedEvent}. Absent on errors that are not a turn result.\n * Added in 3.12.0.\n */\n costUsd?: number;\n /** Main-thread token usage of the failed turn. See {@link FinishedEvent.tokens}. Added in 3.12.0. */\n tokens?: TokenUsage;\n /** Per-model usage of the failed turn. See {@link FinishedEvent.modelUsage}. Added in 3.12.0. */\n modelUsage?: Record<string, ModelTokenUsage>;\n /** Context fill of the failed turn. See {@link FinishedEvent.contextTokens}. Added in 3.12.0. */\n contextTokens?: number;\n /** Context window of the main model. See {@link FinishedEvent.contextWindow}. Added in 3.12.0. */\n contextWindow?: number;\n};\n\n/**\n * A status change notification for the agent.\n *\n * Emitted when the agent's execution phase changes (e.g., thinking → working → idle).\n *\n * @see {@link AgentPhase} for available phase values\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#supporting-types\n */\nexport type StatusEvent = {\n type: \"status\";\n phase: AgentPhase;\n};\n\n/**\n * Emitted when a dev server (e.g. Vite, Next.js) starts, becomes ready, or crashes.\n *\n * The platform uses this to surface a preview URL in the session UI.\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#agent-event\n */\nexport type DevServerEvent = {\n type: \"dev_server\";\n url: string;\n status: \"starting\" | \"ready\" | \"crashed\";\n};\n\n/**\n * A file system change event.\n *\n * Emitted when files are created, edited, deleted, or conflicted.\n *\n * @property type - Always \"file_changed\"\n * @property path - The file path that changed\n * @property action - What happened: create, edit, delete, or conflict\n * @property mountId - Which mount triggered the change, if any\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#file-change-event\n */\n\nexport type FileChangeEvent = {\n type: \"file_changed\";\n path: string;\n action: \"create\" | \"edit\" | \"delete\" | \"conflict\";\n /** Which mount triggered the change, if any. */\n mountId?: string;\n};\n\n/**\n * Status update for a subagent dispatched by the primary agent.\n *\n * Emitted when a named subagent starts or finishes execution. On \"finished\",\n * carries structured output with a summary, changed files, and concerns.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type SubagentEvent = {\n type: \"subagent\";\n name: string;\n status: \"started\" | \"finished\";\n description: string;\n /** Flow node this subagent is executing (set by orchestrator) */\n nodeId?: string;\n /** Structured output from the subagent (set on \"finished\") */\n output?: {\n summary: string;\n filesChanged: string[];\n status: string;\n concerns: string[];\n };\n};\n\n/**\n * Per-turn token usage reported by a driver.\n *\n * All fields are optional so the type can represent partial data — different\n * providers expose different subsets:\n *\n * | Provider | input | output | cacheRead | cacheCreation | reasoning |\n * |-----------|-------|--------|-----------|---------------|-----------|\n * | Anthropic | y | y | y | y | - |\n * | OpenAI | y* | y | y | - | y |\n *\n * `*` Anthropic's `inputTokens` excludes cached/cache-creation reads (they\n * are reported separately). OpenAI's `inputTokens` is the *total* including\n * cached tokens — consumers that want a strict \"fresh input\" count must\n * subtract `cacheReadTokens` themselves.\n *\n * @category Cost\n * @since 3.1.0\n * @docLink packages/types/events#token-usage\n */\nexport type TokenUsage = {\n /** Input/prompt tokens consumed by the turn (provider-specific semantics — see type docstring). */\n inputTokens?: number;\n /** Output/completion tokens generated by the model. */\n outputTokens?: number;\n /** Tokens served from the provider's prompt cache (Anthropic: cache_read_input_tokens; OpenAI: cached_input_tokens). */\n cacheReadTokens?: number;\n /** Tokens written to the prompt cache for future reads (Anthropic-only — OpenAI does not expose this). */\n cacheCreationTokens?: number;\n /** Reasoning tokens consumed by OpenAI reasoning models (o1, o3, ...). */\n reasoningTokens?: number;\n /** Total tokens for the turn when the provider supplies one. */\n totalTokens?: number;\n};\n\n/**\n * One model's share of a turn, including calls the turn-level `tokens` omit.\n *\n * `TokenUsage` on a `FinishedEvent` describes the main thread only: Claude\n * Code's result `usage` skips every request a Task subagent made, while its\n * reported cost includes them. `FinishedEvent.modelUsage` fills that gap,\n * keyed by model id, so consumers can attribute the whole bill and derive the\n * subagent share as `sum(modelUsage[*]) − tokens`. Field semantics follow\n * `TokenUsage` (Anthropic: disjoint prompt slices). Drivers emit per-turn\n * figures here even when the provider reports run-cumulative counters.\n *\n * @category Cost\n * @since 3.11.0\n */\nexport type ModelTokenUsage = Pick<\n TokenUsage,\n \"inputTokens\" | \"outputTokens\" | \"cacheReadTokens\" | \"cacheCreationTokens\"\n> & {\n /** Provider-reported cost of this model's calls in the turn, in USD. */\n costUsd?: number;\n /** Context window of this model, in tokens. */\n contextWindow?: number;\n};\n\n/**\n * Emitted when the agent completes a turn.\n *\n * Carries cost / usage data and optionally a custom message payload for dynamic\n * rendering via the v2 capability registry (`customType` + `customData` fields).\n *\n * `costUsd` semantics: this is per-turn cost in USD. Some providers report a\n * run-cumulative figure instead of a per-turn one — the driver is responsible\n * for normalizing it into a per-turn delta before emitting it here. Drivers\n * that don't surface provider-reported cost emit `0`; consumers distinguishing\n * \"free\" from \"not reported\" should pair `costUsd === 0` with `tokens` being\n * present/absent.\n *\n * @docLink packages/types/events#finished-event\n */\nexport type FinishedEvent = {\n type: \"finished\";\n summary: string;\n costUsd: number;\n /**\n * Per-turn token usage when the driver tracks it. Absent for drivers\n * that do not surface usage (e.g. omp RPC today). Added in 3.1.0.\n */\n tokens?: TokenUsage;\n /**\n * Per-model usage for the turn, subagent calls included, when the driver\n * reports it. See {@link ModelTokenUsage}. Added in 3.11.0.\n */\n modelUsage?: Record<string, ModelTokenUsage>;\n /**\n * Prompt size of the turn's last main-thread API call — the real context\n * fill — when the driver tracks it. `tokens` cannot answer this: it sums\n * every call in the turn. Added in 3.11.0.\n */\n contextTokens?: number;\n /** Context window of the main model, in tokens, when known. Added in 3.11.0. */\n contextWindow?: number;\n /** True when the response was cancelled by the user (partial content). */\n cancelled?: boolean;\n /** Custom message type (e.g. \"gif\") — clients render via a registered dynamic component. */\n customType?: string;\n /** Structured data for custom message types — used as component props. */\n customData?: Record<string, unknown>;\n};\n\n/**\n * An agent-to-agent (A2A) message exchanged between two linked sessions.\n *\n * Persisted as a `Message` row in BOTH the caller and target session\n * conversations — each side stores its own copy with the matching\n * `direction`. `inbound` is the copy in the receiving session's\n * conversation; `outbound` is the copy in the initiating session's\n * conversation. The two copies share the same `exchangeId`.\n *\n * Hosts (the Skaile platform) write this event into `Message.payload`\n * alongside the dedicated `a2aExchangeId` / `peerSessionId` / `a2aDirection`\n * columns. The chat UI's Network / All views render it as a badged A2A card.\n *\n * @docLink packages/types/events#a2a-message-event\n */\nexport type A2AMessageEvent = {\n type: \"a2a_message\";\n /** `inbound` = this session received it; `outbound` = this session sent it. */\n direction: \"inbound\" | \"outbound\";\n /** The other end of the exchange — the peer session's id. */\n peerSessionId: string;\n /** Human-readable name of the peer session, for UI display. */\n peerName: string;\n /** The A2A exchange this message belongs to (`A2AExchange.id`). */\n exchangeId: string;\n /** The message body — the question, answer, or async message text. */\n text: string;\n};\n\n/**\n * Emitted when a shared state store's snapshot changes.\n *\n * Carries the full serialized state snapshot for the named store (e.g. \"flow\", \"session\").\n * Frontends and the platform gateway subscribe to build reactive state views.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type StateChangedEvent = {\n type: \"state_changed\";\n /** Store identifier, e.g. \"flow\", \"session\" */\n store: string;\n /** Serialized state snapshot */\n state: Record<string, unknown>;\n};\n\n/**\n * Emitted when the orchestrator hands execution off to a specific flow node and skill.\n *\n * Carries the context sources and approximate context size used to curate\n * the handoff prompt so operators can diagnose context-window decisions.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type HandoffEvent = {\n type: \"handoff\";\n /** Flow node being handed off to */\n nodeId: string;\n /** Skill being executed */\n skillId: string;\n /** Node IDs that contributed context to this handoff */\n contextSources: string[];\n /** Approximate size of curated context in characters */\n contextSize: number;\n};\n\n/**\n * Response to a `ConnectorRequestCommand` (wire type: `\"resource_response\"`).\n *\n * Correlates to the originating request via `requestId` and carries the\n * operation result or an error string. The wire `type:` string stays as\n * `\"resource_response\"` for protocol stability.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ConnectorResponseEvent = {\n type: \"resource_response\";\n /** Correlates to the originating resource_request. */\n requestId: string;\n /** Which connector handled the request. */\n resourceId: string;\n /** Which operation was performed. */\n operation: ConnectorOperation;\n /** Result data — shape depends on the operation. */\n data?: unknown;\n /** Error message if the operation failed. */\n error?: string;\n /** Machine-readable failure class, when the runner knows one. Since protocol 4.2.0. */\n code?: ConnectorResponseFailureCode;\n};\n\n/**\n * Response to a `ConnectorQueryCommand`. Carries the JSON-encoded result of\n * a `ConnectorManager.executeOp` call, correlated by `requestId`.\n *\n * Persistence: transient. Hosts that want to record the query side effects\n * should rely on the runner's structured log stream, not on this event.\n *\n * @docLink packages/types/events#connector-query-response-event\n * @since 2.2.0\n */\nexport type ConnectorQueryResponseEvent = {\n type: \"connector_query_response\";\n /** Correlates to the originating ConnectorQueryCommand. */\n requestId: string;\n /** Whether the underlying executeOp resolved without throwing. */\n ok: boolean;\n /** JSON-encoded executeOp result, when `ok === true`. */\n result?: string;\n /** Error message when `ok === false`. */\n error?: string;\n};\n\n/**\n * Machine-readable failure class carried by {@link ConnectorMutateResponseEvent}.\n * Present iff `ok === false`. Hosts branch on this rather than on the free-text\n * `error` string, which is a runner/adapter message and may change.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type ConnectorMutateFailureCode =\n /** The target connector never became available within the readiness wait. */\n | \"connector_unavailable\"\n /** `planFlowMutate` rejected the op (malformed or conflicting payload). */\n | \"rejected\"\n /** The adapter threw — illegal transition, unknown node, read-only violation. */\n | \"op_failed\"\n /** `sessionReady` rejected: the session build failed, the container is unusable. */\n | \"session_unavailable\";\n\n/**\n * Outcome of replaying `payload.pendingDecisions` during a flow `hydrate`.\n *\n * Invariant: every supplied entry that carried a string `nodeId` appears in\n * exactly one of `applied` / `skipped`. A skip is a deliberate structural\n * decision, never a failure — the hydrate itself has already succeeded by the\n * time reconciliation runs. Gotcha: the skip entry deliberately carries only\n * `nodeId` + `reason`; the decision payload is user content and is never echoed.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type FlowHydrateReconciliation = {\n /** nodeIds whose pending decision was applied during this hydrate. */\n applied: string[];\n /** nodeIds whose pending decision was deliberately not applied. */\n skipped: Array<{\n nodeId: string;\n reason: \"not_parked\" | \"already_decided\" | \"unknown_node\" | \"payload_invalid\";\n }>;\n};\n\n/**\n * Response to a `ConnectorMutateCommand` that carried a `requestId`.\n *\n * Emission invariant: **exactly one** per command that set `requestId`, on every\n * terminal path (including the paths that previously only logged), and **never**\n * for a command without one — that opt-in is the whole 3.6 back-compat story.\n *\n * Persistence: transient. Like `connector_query_response` this is system RPC,\n * not chat; hosts must keep it out of the message store.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type ConnectorMutateResponseEvent = {\n type: \"connector_mutate_response\";\n /** Correlates to the originating ConnectorMutateCommand.requestId. */\n requestId: string;\n /** Whether the mutation was applied. */\n ok: boolean;\n /** JSON-encoded executeOp result, when ok === true and the op returned one. */\n result?: string;\n /** Human-readable failure message when ok === false. */\n error?: string;\n /** Machine-readable failure class. Present iff ok === false. */\n code?: ConnectorMutateFailureCode;\n /**\n * Outcome of `payload.pendingDecisions` reconciliation. Present only for\n * `op === \"hydrate\"` on the flow connector, and only when the host supplied\n * pending decisions. Absent is NOT \"nothing applied\" — it is \"not attempted\".\n */\n reconciled?: FlowHydrateReconciliation;\n};\n\n/**\n * Receipt acknowledgement for a `prompt` command that carried a `messageId`.\n *\n * Emission invariant: **exactly one** per prompt that set `messageId`, emitted\n * as the runner's first act — before the session-readiness gate, the secrets\n * check, and the driver start, each of which can otherwise drop the prompt with\n * no trace. It says \"the frame arrived and was decoded\", nothing about the turn\n * ever running; turn-level supervision is a separate concern.\n *\n * Persistence: transient. System RPC, not chat.\n *\n * @category Protocol\n * @since 3.8.0\n */\nexport type PromptAckEvent = {\n type: \"prompt_ack\";\n /** Echoes the originating `prompt` command's `messageId` verbatim. */\n messageId: string;\n};\n\n/**\n * Emitted after session boot listing all connected mounts and connectors.\n *\n * Consumers use this event to populate the resource explorer and build initial\n * connector status maps. The wire type is `\"resources_available\"`.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ConnectorsAvailableEvent = {\n type: \"resources_available\";\n /** All connected mounts with their metadata. */\n mounts: MountInfo[];\n /** All connected connectors with their metadata. */\n connectors: ConnectorInfo[];\n /** All runner-managed MCP servers with their metadata. */\n mcp_servers: McpServerInfo[];\n /**\n * `true` when the runner accepts `resource_request` writes and deletes\n * addressed to `SESSION_ROOT_CONNECTOR_ID` (`\"@session\"`), which resolve against the\n * session's own root instead of a mount. Absent on older runners: a host\n * must then keep delivering through the workspace mount.\n */\n sessionRoot?: boolean;\n};\n\n/**\n * Emitted whenever a connector's connection state changes.\n *\n * Transient — not persisted to the message store. Consumed exclusively by\n * `ResourceClient._handleEvent()` in `@skaile/workspaces/store` to maintain the\n * reactive `connectorStatus` map.\n *\n * @docLink packages/types/events#connector-status-event\n */\nexport interface ConnectorStatusEvent {\n type: \"connector_status\";\n /** Matches ConnectorDeclaration.id. */\n connectorId: string;\n /** Current connection state. */\n status: \"connecting\" | \"connected\" | \"error\" | \"disconnected\";\n /** Present when status === \"error\". */\n error?: string;\n /**\n * What kind of failure `error` is, when the runner could tell — present only\n * with status === \"error\". Absent means unclassified, not \"none of the\n * kinds\": most drivers throw plain errors, and older runners never send it.\n */\n errorKind?: ConnectorErrorKind;\n /** Round-trip latency in milliseconds from the last health check. */\n latencyMs?: number;\n}\n\n/**\n * Where a connector connect failure can be fixed.\n *\n * - `credential` — the credential is missing, refused or unusable; reconnecting\n * the account (or re-provisioning the secret) is the fix.\n * - `repo-state` — the on-disk checkout is in a state the connect cannot work\n * with (e.g. a live `.git/index.lock`); a new credential changes nothing.\n * - `config` — the declaration itself is missing or invalid (no source URL, a\n * bad branch name, a required field that resolves to nothing).\n *\n * Senders set a kind only when the thrown error identifies it structurally;\n * receivers must treat an absent or unknown value as unclassified.\n */\nexport type ConnectorErrorKind = (typeof CONNECTOR_ERROR_KINDS)[number];\n\n/** Every {@link ConnectorErrorKind}, for receivers that validate the wire field. */\nexport const CONNECTOR_ERROR_KINDS = [\"credential\", \"repo-state\", \"config\"] as const;\n\n/**\n * Emitted when a lifecycle phase (hibernate, close, compact) completes across all resources.\n *\n * Carries per-resource results so the platform can surface which resources failed\n * during the phase. The `phase` field identifies which lifecycle stage completed.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type LifecycleCompleteEvent = {\n type: \"lifecycle_complete\";\n /** Which lifecycle phase completed. */\n phase: LifecyclePhase;\n /** Per-resource results. */\n results: LifecycleResult[];\n};\n\n/**\n * Transient — broadcast when a user or agent adds an emoji reaction to a message.\n *\n * Not persisted as a message. Consumed by frontends to update the reaction display in real time.\n *\n * @docLink packages/types/events#reaction-events\n */\nexport type ReactionAddedEvent = {\n type: \"reaction_added\";\n /** ID of the message being reacted to. */\n messageId: string;\n /** Sequence number of the target message (for efficient frontend lookup). */\n messageSeq: number;\n emoji: string;\n userId: string;\n userName: string;\n};\n\n/**\n * Transient — broadcast when a user removes a reaction from a message.\n *\n * Not persisted as a message. Consumed by frontends to update the reaction display in real time.\n *\n * @docLink packages/types/events#reaction-events\n */\nexport type ReactionRemovedEvent = {\n type: \"reaction_removed\";\n messageId: string;\n messageSeq: number;\n emoji: string;\n userId: string;\n};\n\n/**\n * Transient typing indicator — not persisted.\n *\n * Broadcast to all session subscribers when a participant starts or stops typing.\n * Frontends use this to render the \"X is typing...\" indicator.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type TypingEvent = {\n type: \"typing\";\n userId: string;\n userName: string;\n isTyping: boolean;\n};\n\n/**\n * Transient echo of a user message broadcast to all session subscribers — not persisted.\n *\n * Carries reply-threading fields so clients can detect parent-message relationships\n * and route mention-style notifications.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type UserMessageEvent = {\n type: \"user_message\";\n senderId: string;\n senderName: string;\n content: string;\n /** Set when this user message is a reply to a previous message. */\n parentMessageId?: string;\n /** Sender id of the parent message — lets clients detect \"reply to me\". */\n parentSenderId?: string;\n /** When true, clients should treat this reply as a mention-style notification target. */\n notifyParent?: boolean;\n\n // ---------------------------------------------------------------------------\n // Platform extension fields (multi-user privacy / recipient routing).\n // Added with @skaile/workspaces/types 3.2.0 for platform F-23 (mention recipient\n // suffixes). Framework consumers that don't run multi-user sessions can\n // ignore these — single-user forge apps leave them undefined and the\n // event behaves identically to pre-3.2 envelopes.\n // ---------------------------------------------------------------------------\n\n /**\n * Routing mode of the message envelope.\n * - `\"Public\"` (default when omitted) — broadcast to every session\n * subscriber (humans + agent).\n * - `\"Private\"` — visible only to the sender plus everyone listed in\n * `privateRecipientIds`.\n * - `\"HumansOnly\"` — visible to all human subscribers; the agent is\n * excluded from broadcast and notifications.\n *\n * **Invariant (NOT enforced by the type system):** producers MUST populate\n * a non-empty `privateRecipientIds` whenever this is `\"Private\"`. The\n * shape is intentionally flat (rather than a discriminated union) to\n * keep wire compat with older consumers, but this means TypeScript will\n * not catch violations at the call site. **Persistence-layer\n * implementations MUST validate this invariant on intake** and reject /\n * downgrade / log a violation rather than persist a Private message\n * with no recipients (which would be visible to nobody and effectively\n * lost).\n *\n * Reference platform implementation: `PlatformMessageStore.append`\n * throws on `Private + empty recipientIds` to fail fast.\n */\n visibilityMode?: \"Public\" | \"Private\" | \"HumansOnly\";\n\n /**\n * Recipient list for `visibilityMode: \"Private\"`. Each entry is either a\n * user id (matching the platform's user-id shape) or the sentinel\n * `\"__agent__\"` when the agent itself is an explicit recipient (i.e. the\n * sender wrote `@agent_`).\n *\n * MUST be non-empty when `visibilityMode === \"Private\"` — see the\n * invariant note on `visibilityMode` above.\n *\n * Empty / absent for `Public` and `HumansOnly` — recipient sets in those\n * modes are implicit (everyone / everyone-except-agent).\n */\n privateRecipientIds?: string[];\n};\n\n/**\n * Transient signal that provisioned secrets have been stored and resources initialized.\n *\n * The platform waits for this event after sending a `SecretProvisionCommand` before\n * allowing further session interaction.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type SecretsReadyEvent = {\n type: \"secrets_ready\";\n};\n\n/**\n * Transient ACK emitted once the agent has finished processing a `configure`\n * command (shared state stores registered, MCP tools rebuilt, active flows\n * rehydrated). Backends await this before releasing the session so prompts\n * can't race the configure handler and start the driver with stale tools.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type ConfiguredEvent = {\n type: \"configured\";\n};\n\n/**\n * Emitted when a mount is successfully attached to the workspace.\n *\n * Carries the mount id, filesystem path, driver name, and access level.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountMountedEvent = {\n type: \"mount_mounted\";\n id: string;\n mountPath: string;\n driver: string;\n access: string;\n};\n\n/**\n * Emitted when a mount is detached from the workspace.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountUnmountedEvent = {\n type: \"mount_unmounted\";\n id: string;\n};\n\n/**\n * Emitted when a file changes within a mounted source.\n *\n * Similar to `FileChangeEvent` but scoped to a specific mount by `id`.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountChangedEvent = {\n type: \"mount_changed\";\n id: string;\n path: string;\n action: \"create\" | \"edit\" | \"delete\" | \"conflict\";\n};\n\n/**\n * Progress update for a mount's initial synchronization phase.\n *\n * Emitted repeatedly during the sync lifecycle (enumerating, stubs_ready,\n * downloading, initial_sync_complete). Carries file counts for progress display.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountSyncStatusEvent = {\n type: \"mount_sync_status\";\n id: string;\n phase: SyncStatusPhase;\n totalFiles: number;\n downloadedFiles: number;\n stubFiles: number;\n message: string;\n};\n\n/**\n * Persisted chat event summarizing a flow lifecycle milestone.\n *\n * The gateway diffs each incoming flow state_changed event against the\n * previous snapshot and emits breadcrumbs for user-meaningful transitions\n * — flow start/end, approval requests, input requests, and node failures.\n * Per-node traffic (running/complete/skipped) is NOT emitted as a\n * breadcrumb to keep the chat stream readable; that detail lives on the\n * flow execution panel.\n *\n * Breadcrumbs are persisted via the dispatcher's normal message store path\n * and rendered on the frontend as collapsed cards that expand inline.\n *\n * @docLink packages/types/events#flow-breadcrumb-event\n */\nexport type FlowBreadcrumbEvent = {\n type: \"flow_breadcrumb\";\n kind:\n | \"flow_started\"\n | \"flow_finished\"\n | \"flow_failed\"\n | \"flow_cancelled\"\n | \"approval_pending\"\n | \"input_pending\"\n | \"approval_resolved\"\n | \"input_resolved\"\n | \"node_failed\";\n runId: string;\n flowId: string;\n flowName: string;\n /** Node that triggered this breadcrumb, if the kind is node-scoped. */\n nodeId?: string;\n /** Human-readable node label (from flow definition `data.label`). */\n nodeName?: string;\n /** User ID of the actor that caused the transition (if applicable). */\n actorUserId?: string;\n /** One-line summary for the collapsed card rendering. */\n summary?: string;\n};\n\n/**\n * Persisted chat event carrying the orchestrator prompt for one flow turn.\n *\n * The flow runner reassembles the full `# Flow Execution Context` prompt on\n * every turn and hands it to the agent driver. Without this event a host\n * consuming the stream sees the agent replying to input it cannot read, so the\n * runner emits the prompt verbatim immediately before delivering it — the\n * event therefore always precedes that turn's reply events in the stream.\n *\n * `prompt` is byte-identical to the string given to the driver: never\n * redacted, truncated, or re-rendered. Everything the agent saw — user text,\n * node input, stimulus paragraph — is already inside it, which is why the\n * stimulus is carried only as its kind plus the node it concerns.\n *\n * Emitted for main-agent turns and inline sub-flow turns alike; a sub-flow turn\n * carries the **child** flow's `flowId`/`flowName`. Subprompt nodes run on their\n * own isolated driver and emit nothing here.\n *\n * Persisted via the dispatcher's normal message store path.\n *\n * @docLink packages/types/events#flow-prompt-event\n */\nexport type FlowPromptEvent = {\n type: \"flow_prompt\";\n /** Flow run this turn belongs to. */\n runId: string;\n /** Flow definition id. */\n flowId: string;\n /** Human-readable flow name from the definition, which always carries one. */\n flowName: string;\n /**\n * Why the runner drove this turn. Mirrors the runner's `TurnStimulus[\"kind\"]`,\n * re-declared here because this package must not depend on `factory-assets`.\n */\n stimulus:\n | \"flow_started\"\n | \"approval_received\"\n | \"input_received\"\n | \"retry_requested\"\n | \"user_message\"\n | \"resumed_after_hibernation\"\n | \"cancelled\"\n | \"state_changed\";\n /** Compact stimulus label for logs/telemetry, e.g. `approval_received:review:approved`. */\n stimulusLabel: string;\n /** Node the stimulus concerns, when the stimulus is node-scoped. */\n nodeId?: string;\n /** The verbatim orchestrator prompt handed to the agent driver. */\n prompt: string;\n};\n\n/**\n * The session lifecycle phase being executed. Carried in `LifecycleCompleteEvent.phase`\n * and the `lifecycle` command's `phase` field.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type LifecyclePhase = \"hibernate\" | \"close\" | \"compact\";\n\n/**\n * Per-resource result of a lifecycle phase, carried in `LifecycleCompleteEvent.results`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type LifecycleResult = {\n id: string;\n ok: boolean;\n error?: string;\n /** Human-readable detail (e.g. commit SHA, branch name). */\n detail?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Mount types\n// ---------------------------------------------------------------------------\n\n/**\n * Metadata for a mounted filesystem source, carried in `ConnectorsAvailableEvent.mounts`.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`; mirrors the\n * connector package's `MountInfo` type.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type MountInfo = {\n id: string;\n driver: string;\n /** Human-readable connection name; the resource-explorer tab renders this over `id`/`driver` when present. */\n label?: string;\n access: \"read-only\" | \"read-write\";\n mountPath: string;\n mounted: boolean;\n source: string;\n};\n\n// ---------------------------------------------------------------------------\n// Connector types (re-declared here to avoid depending on @skaile/workspaces/connectors)\n// ---------------------------------------------------------------------------\n\n/**\n * Metadata for a runner-managed MCP server, carried in `ConnectorsAvailableEvent.mcp_servers`.\n *\n * `live` indicates whether the active driver session already picked up the server's tools\n * without requiring a restart — false means the tools are registered but not yet active.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type McpServerInfo = {\n id: string;\n transport: \"stdio\" | \"sse\" | \"http\";\n live: boolean;\n toolCount: number;\n};\n\n/**\n * Operations a connector can perform. Used in `ConnectorRequestCommand.operation`\n * and `ConnectorResponseEvent.operation`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorOperation =\n | \"list\"\n | \"read\"\n | \"write\"\n | \"delete\"\n | \"search\"\n /** Create one empty directory on a filesystem mount. Since protocol 4.2.0. */\n | \"mkdir\"\n /** Describe one path on a filesystem mount ({@link ConnectorStat}). Since protocol 4.2.0. */\n | \"stat\";\n\n/**\n * Machine-readable failure class on a {@link ConnectorResponseEvent}. Hosts\n * branch on this rather than on the free-text `error`.\n *\n * A runner older than protocol 4.2.0 never sets it: it answers an operation it\n * does not know with an `error` starting `Unsupported operation`, so a host\n * feature-detecting a new operation must accept both forms.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorResponseFailureCode =\n /** The target (mount, connector or session root) does not serve this operation. */\n | \"unsupported_operation\"\n /** `mkdir` found something already at the path. */\n | \"already_exists\";\n\n/**\n * Options for a filesystem-mount `stat` operation.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type StatOptions = {\n /**\n * For a directory, walk everything below it and report\n * {@link ConnectorStat.totals}. The walk is capped (entries, time, depth); a\n * capped walk answers with `totals.partial: true` instead of failing.\n */\n recursive?: boolean;\n /** Count dotfiles and dot-directories in `totals`. Off by default, like `list`. */\n includeHidden?: boolean;\n /** Lower the runner's entry cap for this walk. Values above the runner's cap are ignored. */\n maxEntries?: number;\n /** Lower the runner's time budget (ms) for this walk. Values above the runner's budget are ignored. */\n timeoutMs?: number;\n};\n\n/**\n * Recursive totals for a directory, from a `stat` with `recursive: true`.\n *\n * When `partial` is true the counts are lower bounds (\"at least N files\"):\n * part of the tree was not seen.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorStatTotals = {\n /** Files below the directory, at any depth. Symlinks count as files and are not followed. */\n files: number;\n /** Directories below the directory, at any depth, not counting itself. */\n directories: number;\n /** Sum of the counted files' sizes in bytes. */\n bytes: number;\n /** Whether any part of the tree went uncounted: a cap was reached or a folder was unreadable. */\n partial: boolean;\n /**\n * The cap that cut the totals short. `entries` and `time` end the walk and\n * take precedence; `depth` only leaves out the folders below it. Absent when\n * nothing but unreadable folders made the totals partial.\n */\n stoppedBy?: \"entries\" | \"time\" | \"depth\";\n /** Subfolders that could not be read (e.g. permission denied) and were skipped. */\n unreadable?: number;\n};\n\n/**\n * Result of a filesystem-mount `stat` operation.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorStat = {\n /** Last path segment; empty for the mount root. */\n name: string;\n /** The requested path, relative to the mount root. */\n path: string;\n type: \"file\" | \"directory\";\n /** File size in bytes. Absent for directories — see `totals`. */\n size?: number;\n /** Last modification time, ISO 8601. */\n modifiedAt?: string;\n /** Creation time, ISO 8601, when the filesystem records one. */\n createdAt?: string;\n /** Present for a directory stat'ed with `recursive: true`. */\n totals?: ConnectorStatTotals;\n};\n\n/**\n * A single entry in a connector directory listing (result of a `list` operation).\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorEntry = {\n name: string;\n path: string;\n type: \"file\" | \"directory\" | \"key\" | \"row\" | \"message\";\n size?: number;\n modifiedAt?: string;\n};\n\n/**\n * File or key content returned by a connector `read` operation.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorContent = {\n data: string;\n encoding?: \"utf-8\" | \"binary\";\n contentType?: string;\n metadata?: Record<string, unknown>;\n};\n\n/**\n * Metadata for a connected connector, carried in `ConnectorsAvailableEvent.connectors`.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`; mirrors\n * the connector package's `ConnectorInfo` type.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorInfo = {\n id: string;\n driver: string;\n /** Human-readable connection name; the resource-explorer tab renders this over `id`/`driver` when present. */\n label?: string;\n access: \"read-only\" | \"read-write\";\n operations: string[];\n};\n\n/**\n * Options for a connector `list` operation.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ListOptions = {\n recursive?: boolean;\n glob?: string;\n limit?: number;\n /**\n * Include entries whose name starts with `.`. Off by default: a browsing\n * listing hides dotfiles. A caller materialising a build context from a\n * mount (where `.env.example`, `.npmrc`, ... must survive) opts in.\n *\n * Honored only by the runner's filesystem-mount `list`; connector drivers\n * (tool-face `list`) ignore it. It is not a security boundary: `read`\n * serves any path regardless. With `recursive` it also walks `.git`, whose\n * entries count against the listing cap, so a caller staging a tree should\n * list one directory at a time and prune before descending.\n */\n includeHidden?: boolean;\n};\n\n/**\n * Options for a connector `search` operation.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SearchOptions = {\n regex?: boolean;\n caseSensitive?: boolean;\n maxResults?: number;\n};\n\n/**\n * Persistent — a custom-typed message emitted by the agent via a capability\n * tool invocation (`platform.custom_message`). The runner's serve layer\n * forwards these so the platform can persist and render them via the\n * dynamic component pipeline.\n *\n * @category Events\n * @since 2.0.0\n * @docLink packages/types/events#agent-event\n */\nexport type CustomMessageEvent = {\n type: \"custom_message\";\n /** Plain-text summary (e.g. \"[gif: funny cat]\"). */\n content: string;\n /** Custom message type identifier (e.g. \"gif\"). */\n customType: string;\n /** Structured data — used as component props. */\n customData: Record<string, unknown>;\n};\n\n/**\n * Trigger source for a session compaction. Carried in `SnapshotEvent.trigger`\n * and `CompactionAttemptEvent.trigger`.\n *\n * @docLink packages/types/events#snapshot-event\n */\nexport type CompactionTrigger = \"threshold\" | \"hibernate\" | \"manual\";\n\n/**\n * Persistent — a compacted conversation snapshot produced by the LLM.\n * On session restore, only the last snapshot + subsequent messages are replayed.\n *\n * @docLink packages/types/events#snapshot-event\n */\nexport type SnapshotEvent = {\n type: \"snapshot\";\n /** LLM-generated structured summary of the conversation. */\n summary: string;\n /** What triggered this compaction. */\n trigger: CompactionTrigger;\n /** Seq of previous snapshot (0 if first compaction). */\n coversFromSeq: number;\n /** Last seq this snapshot covers. */\n coversToSeq: number;\n /** Estimated context token count before compaction. */\n tokensBefore: number;\n /** Token count of the summary. */\n tokensAfter: number;\n};\n\n/**\n * Persistent -- emitted on EVERY compaction attempt, success or failure.\n *\n * Replaces the in-process circuit breaker in `CompactionOrchestrator` with\n * an observable, owner-controllable record. The platform gateway listens\n * for this event and inserts a `Compaction` row plus updates the\n * `Session.lastCompactionStatus` companion field.\n *\n * `SnapshotEvent` continues to fire on success-only paths (back-compat\n * until Phase 4); both events ride alongside each other through Phase 4.\n *\n * Spec: `_devlog/specs/2026-05-05-session-resume-restart-design.md`\n *\n * @category Compaction\n * @since 3.1.0\n * @docLink packages/types/events#compaction-attempt-event\n */\nexport type CompactionAttemptEvent = {\n type: \"compaction_attempt\";\n /**\n * Outcome of the attempt:\n * - `success`: completed and validated; eligible for tier-2 resume\n * - `failed`: compaction call returned an error or output failed validation\n * - `partial`: reserved (e.g. streaming compaction emitting partial output)\n * - `dirty`: was success at write time but later flagged\n */\n status: \"success\" | \"failed\" | \"partial\" | \"dirty\";\n /**\n * When `status !== 'success'`, a stable identifier for the failure mode.\n * Standard codes:\n * - `rate_limit | auth | account | timeout | parse_error` (from bridge error classifier)\n * - `empty | too_short | poor_ratio` (from validateCompactionOutput)\n *\n * Note: `auth` covers both real credential failures AND payment-blocked\n * OAuth subscriptions that Anthropic mislabels as auth errors. `account`\n * covers a 401 that recurs after a successful credential refresh (hidden-tier\n * rate limit, billing block, anti-abuse throttle) — the credential is fine.\n * Owners investigate further when a Compaction row shows `auth` or `account`.\n *\n * Read alongside {@link CompactionAttemptEvent.elapsedMs}: `empty` at a\n * near-zero elapsed time is an infrastructure failure, not a model one.\n *\n * `null` on success.\n */\n errorCode: string | null;\n /**\n * Wall-clock ms spent inside the compaction `prompt()` call. An `empty`\n * failure at ~0 ms means the turn was settled by a stale consumer rather\n * than by the model. Optional — absent on events from older runners.\n */\n elapsedMs?: number;\n /**\n * Truncated diagnostic text for a failed attempt — the driver error the\n * classifier saw, or which validation check rejected the output. Absent on\n * success and on events from older runners.\n *\n * The same text is mirrored into {@link CompactionAttemptEvent.summary} so a\n * consumer that only persists `summary` still explains the failure. That is\n * safe because a failed attempt is never restored into a session: restoration\n * requires `status: 'success'` with `validatedAt` set.\n */\n errorMessage?: string;\n /** What triggered this attempt. */\n trigger: CompactionTrigger;\n /** LLM-generated summary text. Empty string on failure. */\n summary: string;\n /** Model name used for the call (e.g. \"claude-sonnet-4\"). null when unknown. */\n model: string | null;\n /** Provider id used for the call (e.g. \"anthropic\"). null when unknown. */\n provider: string | null;\n /** Estimated context size before the compaction call — the whole prompt, cached tokens included (= tokensBefore). */\n inputTokens: number;\n /** Output token count of the summary or 0 on failure (= tokensAfter). */\n outputTokens: number;\n /** Seq of previous successful snapshot (0 if first compaction). */\n coversFromSeq: number;\n /** Last seq this attempt covers (current message seq). */\n coversToSeq: number;\n /**\n * Driver session id at the time of the call (for tier-1 native SDK resume).\n * Captured from `driver.runtimeSessionId`. null when the driver does not\n * expose one (e.g. echo, codex).\n */\n driverSessionIdAtCompaction: string | null;\n /**\n * Model name at compaction time. Distinct from `model` (which records what\n * was used for THIS compaction call). For tier-1 resume, the wake-time\n * comparison is against the driver's CURRENT model — if mismatch, falls\n * through to tier 2.\n */\n modelAtCompaction: string | null;\n /**\n * Capability registry signature at compaction time. null in Phase 1\n * (the `computeCapabilitySignature` helper ships in Phase 3).\n */\n capabilitySignatureAtCompaction: string | null;\n /**\n * ISO timestamp set when `validateCompactionOutput` passed.\n * `null` when the attempt failed validation OR produced an error.\n */\n validatedAt: string | null;\n};\n\n// ---------------------------------------------------------------------------\n// Resume cascade events (Phase 3 — tier-1 native SDK resume)\n// ---------------------------------------------------------------------------\n\n/**\n * Transient — emitted by the runner when it honors a\n * `AgentReconfigureOptions.resumeSessionId` in a configure command.\n *\n * The runner emits this once it has decided to recreate the driver with\n * the platform-supplied session id (after capability signature validation\n * passes, if `expectedCapabilitySignature` was provided). The platform\n * gateway records the attempt on the {@link Session} so the UI can show\n * \"Resumed via SDK session\" when wake completes.\n *\n * Spec: `_devlog/specs/2026-05-05-session-resume-restart-design.md`\n * § \"Tier 1: native resume plumbing\".\n *\n * @category Resume\n * @since 3.2.0\n * @docLink packages/types/events#resume-attempted-event\n */\nexport type ResumeAttemptedEvent = {\n type: \"resume_attempted\";\n /** Driver session id the runner is resuming. */\n resumeSessionId: string;\n /** Capability signature computed at attempt time (advisory). */\n capabilitySignature: string;\n};\n\n/**\n * Transient — emitted by the runner or driver when a tier-1 native resume\n * could not be honored.\n *\n * Reasons:\n * - `signature_mismatch`: the runner's current capability signature differs\n * from {@link AgentReconfigureOptions.expectedCapabilitySignature}; the\n * runner dropped the {@link AgentReconfigureOptions.resumeSessionId} hint\n * before driver creation.\n * - `model_mismatch`: reserved — wake-time model comparison happens on the\n * platform side; runner does not currently emit this code, but it is\n * reserved for future driver-level checks.\n * - `jsonl_lost`: emitted by the runner when its pre-ack transcript probe\n * found no transcript (it then drops the hint), or by the claude-sdk driver\n * after the SDK reported \"No conversation found with session ID …\" (as a\n * thrown error or an `is_error` result); the driver replays the prompt on a\n * fresh session so the turn still completes.\n * - `jsonl_poisoned`: emitted by the claude-sdk driver after a replayed\n * resume hit a `400 invalid_request_error` from a transcript image block\n * with a wrong `media_type`. The driver repaired the on-disk JSONL\n * transcript in place (correcting media types, stubbing unprocessable\n * images) and retried the resume — conversation context is preserved.\n *\n * - `native_state_unavailable`: managed Codex positively classified unavailable\n * versioned state and completed one fresh same-binding initialization; the host\n * may restore DB history. Unknown native/auth/policy/transport errors are fatal.\n *\n * @category Resume\n * @since 3.2.0\n * @docLink packages/types/events#resume-failed-event\n */\nexport type ResumeFailedEvent = {\n type: \"resume_failed\";\n /** Driver session id the runner attempted to resume (and dropped). */\n resumeSessionId: string;\n /** Stable reason code; see TSDoc above for the enumeration. */\n reason:\n | \"signature_mismatch\"\n | \"model_mismatch\"\n | \"jsonl_lost\"\n | \"jsonl_poisoned\"\n | \"native_state_unavailable\";\n};\n\n/**\n * Emitted by the runner when the driver's SDK session id first becomes known\n * (after the first turn) and whenever it changes thereafter. Carries the\n * tier-1 native-resume token so the platform can persist it on the Session\n * itself — independently of compaction. Without this the resume token is\n * captured ONLY as a side effect of a compaction (see\n * {@link CompactionAttemptEvent}'s `driverSessionIdAtCompaction`), so a\n * session that never compacts and only auto-hibernates has no stored token\n * and falls through to lossy raw-tail resume on wake even though its JSONL\n * survives on the persistent `.claude` mount.\n *\n * Low frequency: emitted on first-known + change, not per turn. Consumers\n * that do not care ignore it (additive to the union).\n *\n * Spec: platform `_devlog/specs/2026-06-25-tier1-resume-without-compaction.md`.\n *\n * @category Resume\n * @since 3.3.0\n */\nexport type RuntimeSessionEvent = {\n type: \"runtime_session\";\n /** Driver SDK session id, usable as a native `--resume` token. */\n driverSessionId: string;\n /**\n * Model in effect at emit time. The wake-time tier-1 guard compares this\n * against the driver's current model; mismatch forces tier 2. null when\n * the driver does not expose a model.\n */\n model: string | null;\n /** Capability registry signature at emit time (wake-time signature validation). */\n capabilitySignature: string;\n};\n\n// ---------------------------------------------------------------------------\n// Resource lifecycle events (Phase 2 — dynamic resource management)\n// ---------------------------------------------------------------------------\n\n/**\n * Transient ACK emitted by the runner after processing an add_resource or\n * remove_resource command. The gateway awaits this to confirm the operation\n * completed (or failed) before returning to the caller.\n *\n * @docLink packages/types/events#resource-status-event\n */\nexport type ResourceStatusEvent = {\n type: \"resource_status\";\n resourceId: string;\n status: \"mounting\" | \"active\" | \"error\" | \"removed\";\n mountPath?: string;\n error?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Supporting types\n// ---------------------------------------------------------------------------\n\n/**\n * String union of all `AgentEvent[\"type\"]` discriminators.\n *\n * Useful for declaring event type constants or exhaustive switch coverage checks.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type AgentEventType = AgentEvent[\"type\"];\n\n/**\n * The current execution phase of the agent, carried in `StatusEvent.phase`.\n *\n * `\"cancelling\"` is store-local (never sent by the backend as a `StatusEvent.phase`\n * value): `AgentStore.cancel()` sets it optimistically, and only a later,\n * genuine `status` event carries the phase on to `\"idle\"`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type AgentPhase = \"thinking\" | \"working\" | \"idle\" | \"compacting\" | \"cancelling\";\n\n/**\n * Classification of an agent error, carried in `ErrorEvent.category`.\n *\n * The bridge's error classifier maps upstream errors to these categories so\n * consumers can apply per-category retry and display policies.\n *\n * @docLink packages/types/events#error-event\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"account\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error object used internally when classifying driver errors.\n *\n * Carries the error category, an optional HTTP status code, a retryability flag,\n * and an optional actionable hint for the user.\n *\n * @docLink packages/types/events#error-event\n */\nexport type AgentError = {\n message: string;\n category: ErrorCategory;\n statusCode?: number;\n retryable: boolean;\n hint?: string;\n};\n\n// ── Sync status (transient -- not persisted) ────────────────────────────────\n\n/**\n * Lifecycle phases of a mount's initial sync operation.\n *\n * Carried in `MountSyncStatusEvent.phase` and `SyncStatusEvent.phase`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SyncStatusPhase =\n | \"enumerating\"\n | \"stubs_ready\"\n | \"downloading\"\n | \"initial_sync_complete\"\n | \"error\";\n\n/**\n * Legacy alias for `MountSyncStatusEvent` — progress update for a mount sync operation.\n *\n * Carries the mount id, lifecycle phase, and file counts. Prefer `MountSyncStatusEvent`\n * for new code.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SyncStatusEvent = {\n type: \"sync_status\";\n mountId: string;\n phase: SyncStatusPhase;\n totalFiles: number;\n downloadedFiles: number;\n stubFiles: number;\n message: string;\n};\n\n/**\n * Transient response to a `DebugCommand` — not persisted.\n *\n * Carries the original query string and the raw diagnostic data returned\n * by the runner's debug handler.\n *\n * @docLink packages/types/events#debug-result-event\n */\nexport type DebugResultEvent = {\n type: \"debug_result\";\n query: string;\n data: unknown;\n};\n\n/**\n * Transient — a single structured log entry from the in-container LogStore.\n * Forwarded by the runner's WsLogSink over the agent transport. The gateway\n * caches a fixed-size ring of these per session for late panel openers.\n * NEVER persisted to the message store — historical reads go through SQLite.\n *\n * @docLink packages/types/events#log-entry-event\n */\nexport type LogEntryEvent = {\n type: \"log_entry\";\n entry: LogEntry;\n};\n\n// ── Asset catalog events (transient — not persisted) ─────────────────────────\n\n/**\n * Transient — emitted when an asset fails schema validation during discovery.\n *\n * Carries the asset name, reason, and an optional suggestion for fixing the issue.\n * Not persisted.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ValidationWarningEvent = {\n type: \"validation_warning\";\n asset: string;\n reason: string;\n suggestion?: string;\n};\n\n/**\n * Transient — emitted when the skills catalog changes during a session.\n *\n * Carries the list of skills that were added or removed. Not persisted.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type SkillsChangedEvent = {\n type: \"skills_changed\";\n skills: Array<{ name: string; action: string }>;\n};\n\n/**\n * Transient event carrying the agent's discovered slash commands — not persisted.\n *\n * Emitted after the runner discovers the available commands from skills and MCP servers.\n * Frontends use this to populate the slash-command picker.\n *\n * @docLink packages/types/events#commands-available-event\n */\nexport type CommandsAvailableEvent = {\n type: \"commands_available\";\n commands: Array<{\n name: string;\n description: string;\n argumentHint?: string;\n }>;\n};\n\n/**\n * Transient event emitted by the OMP driver after each turn completes.\n * Carries the OMP session ID that can be passed as `resumeSessionId` on the\n * next spawn so OMP restores its full conversation context natively — without\n * needing injected `<conversation_history>` blocks. Not persisted.\n *\n * @docLink packages/types/events#session-info-event\n */\nexport type SessionInfoEvent = {\n type: \"session_info\";\n /** The OMP session identifier (from `get_state` RPC response). */\n driverSessionId: string;\n /** Absolute path to the JSONL session file written by OMP, if known. */\n sessionFile?: string;\n};\n\n// ---------------------------------------------------------------------------\n// System prompt composition (transient — not persisted)\n// ---------------------------------------------------------------------------\n\n/**\n * One labeled section of the assembled system prompt, as broken down by\n * the runner's session-builder. Single-entry labels (`context`, `prompt`,\n * `environment`, `resources`) appear once; multi-entry labels\n * (`prompt-extensions`, `composition`, `additional`) appear once per\n * source.\n *\n * @since 2026-05\n */\nexport type SystemPromptSection = {\n label:\n | \"context\"\n | \"prompt\"\n | \"environment\"\n | \"resources\"\n | \"mcp-guidance\"\n | \"tool-activity\"\n | \"prompt-extensions\"\n | \"composition\"\n | \"additional\";\n value: string;\n /** File path, block id, or descriptor — present for multi-entry labels. */\n source?: string;\n};\n\n/**\n * Emitted by the runner after every `createAgentSession` call (initial\n * configure + every re-build path: `add_resource`, `remove_resource`,\n * `configure`). Carries the labeled section breakdown of the system\n * prompt the agent will receive. Transient — not persisted.\n *\n * @since 2026-05\n */\nexport type SystemPromptComposedEvent = {\n type: \"system_prompt_composed\";\n sections: SystemPromptSection[];\n /** ISO timestamp when the breakdown was produced. */\n composedAt: string;\n};\n\n/**\n * Transient — the runner saw the AI provider reject a live request with a 401\n * (credential) or a 429 / subscription-limit rejection, attributed to the AI\n * provider config the session is pinned to.\n *\n * Exists because the platform's per-config health counters were fed only by a\n * slow sampled cron probe: a seat could be exhausted in live traffic and still\n * read as healthy, because the probe checks auth, not capacity. This is the\n * live signal (skaile-ai/workspaces#368, skaile-ai/platform#3539).\n *\n * Fire-and-forget: the runner never waits for it and never retries it, and a\n * platform with no handler for it broadcasts it harmlessly. Every field beyond\n * `status` is optional, and consumers MUST ignore fields they do not know — the\n * two halves of this signal ship independently.\n *\n * @category Events\n * @since 3.9.0\n */\nexport type ProviderResponseSeenEvent = {\n type: \"provider_response_seen\";\n /** 401 — the credential was rejected. 429 — an upstream rate/session limit. */\n status: 401 | 429;\n /** Platform `AIProviderConfig.id` the session is pinned to, when known. */\n configId?: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /** ISO-8601 timestamp of the observation. */\n observedAt: string;\n};\n\n/**\n * Transient — one upstream quota-window reading (claude-sdk `rate_limit_event`),\n * attributed to the AI provider config the session is pinned to. Emitted for\n * every status, not only rejections, and only when the reading changed since\n * the last one the runner sent for that `(configId, window)`.\n *\n * Exists because a `claude setup-token` seat's token cannot read the OAuth\n * usage endpoint, so live traffic is the only place its quota is visible. The\n * upstream reports `utilization` on warnings and rejections only; an `allowed`\n * reading carries the window and its reset, not a percentage.\n *\n * Fire-and-forget, like {@link ProviderResponseSeenEvent}: consumers MUST\n * ignore fields they do not know, and treat `window` / `status` as open sets.\n *\n * @category Events\n * @since 4.1.0\n */\nexport type ProviderQuotaObservedEvent = {\n type: \"provider_quota_observed\";\n /** Platform `AIProviderConfig.id` the session is pinned to, when known. */\n configId?: string;\n /** Upstream window, verbatim: `five_hour`, `seven_day`, or a future value. */\n window: string;\n /** Upstream status, verbatim: `allowed`, `allowed_warning`, `rejected`, or a future value. */\n status: string;\n /** Fraction of the window consumed (0–1), only when the upstream reported it. */\n utilization?: number;\n /** Epoch seconds at which the window resets, only when reported. */\n resetsAt?: number;\n /** ISO-8601 timestamp of the observation. */\n observedAt: string;\n};\n","/**\n * Mentions — types for @-mention support in session messages.\n *\n * A Mention records who was addressed in a message, whether a specific user\n * or a well-known group. Group mentions carry a resolved array of user IDs\n * so consumers can perform membership checks without the resolver.\n */\n\n// ---------------------------------------------------------------------------\n// Groups\n// ---------------------------------------------------------------------------\n\n/**\n * Well-known group mention targets as a `const` array.\n *\n * Use this for validation or exhaustive checks against `MentionGroup`.\n *\n * @docLink packages/types/messages#mention\n */\nexport const MENTION_GROUPS = [\"agent\", \"humans\", \"humans_here\", \"here\", \"all\"] as const;\n\n/**\n * A well-known group that can be `@`-mentioned: `'agent' | 'humans' | 'humans_here' | 'here' | 'all'`.\n *\n * @docLink packages/types/messages#mention\n */\nexport type MentionGroup = (typeof MENTION_GROUPS)[number];\n\n// ---------------------------------------------------------------------------\n// Mention discriminated union\n// ---------------------------------------------------------------------------\n\n/**\n * A parsed `@`-mention in a session message. Records who was addressed — either a\n * specific user or a well-known group — along with the source text position.\n *\n * Group mentions carry a resolved array of user IDs so consumers can perform\n * membership checks without needing the resolver.\n *\n * @docLink packages/types/messages#mention\n */\nexport type Mention =\n | {\n type: \"user\";\n userId: string;\n name: string;\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n }\n | {\n type: \"group\";\n group: MentionGroup;\n /** User IDs resolved at parse time (e.g. all online users for `@here`). */\n resolved: string[];\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n }\n | {\n type: \"custom\";\n /** Consumer-defined mention kind, e.g. \"assistant\". */\n kind: string;\n /** User IDs this mention resolves to (so isMentioned works); may be empty. */\n resolved: string[];\n /** Optional consumer payload, e.g. { sessionId, ownerId }. */\n data?: Record<string, unknown>;\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n };\n","/**\n * Agent Protocol — messages exchanged between agent client and server.\n *\n * AgentCommand: sent toward the agent (client → server)\n * AgentEvent: sent from the agent (server → client) — defined in events.ts\n *\n * Protocol v3 (since `@skaile/workspaces/types@4.0.0`, shipped 2026-05-10) removed\n * the following commands from the {@link AgentCommand} union: `configure` /\n * `ConfigureCommandV2`, `provision_secrets`, `request_access_token`,\n * `add_resource`, `remove_resource`, `set_log_level`, `state_action`,\n * `lifecycle`, `remount_mount`, `compact`, `reconfigure_agent`. Their\n * semantics ride on:\n * - {@link SessionInitCommand} (one deterministic envelope at session\n * start that delivers identity, resolved config, pre-minted credentials,\n * secrets, capabilities, shared state, active flows, resume hints, and\n * logging config), and\n * - `host.*` / `runner.*` capability invocations (bidirectional\n * capability registry).\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`.\n */\n\nimport type {\n CapabilityApproveCommand,\n CapabilityDeregisterCommand,\n CapabilityRegisterCommand,\n CapabilityResultCommand,\n} from \"./capabilities.js\";\nimport type {\n ConnectorContent,\n ConnectorOperation,\n ListOptions,\n SearchOptions,\n StatOptions,\n} from \"./events.js\";\nimport type { ReplyRef } from \"./messaging.js\";\n\n/** Text and scoped attachments; unsupported drivers must reject attachments explicitly. */\nexport interface AgentPromptInput {\n text: string;\n attachments?: Array<\n | { type: \"image\"; path: string }\n | { type: \"file\"; path: string; name: string }\n | { type: \"skill\"; path: string; name: string }\n >;\n}\n\n/**\n * Discriminated union of all commands sent from client to agent server.\n *\n * Narrow via `command.type` or a `switch` statement.\n *\n * @docLink packages/types/protocol-v3#agent-command\n */\nexport type AgentCommand =\n // `messageId` is an opt-in receipt-correlation token (Protocol 3.8). When\n // present the runner MUST emit exactly one `prompt_ack` carrying it back,\n // as the first act of handling the prompt — before any readiness gate that\n // could swallow it. Absent, the prompt is fire-and-forget as in 3.7.\n | {\n type: \"prompt\";\n prompt: string;\n attachments?: AgentPromptInput[\"attachments\"];\n replyTo?: ReplyRef;\n messageId?: string;\n }\n // `question` binds the answer to the sub-question it belongs to, verbatim from\n // the `question` event that asked it. Omit it and the answer fills the next\n // unanswered slot in order — correct only while the host answers top-down.\n | { type: \"reply\"; answer: string; question?: string; requestId?: string }\n | { type: \"cancel\" }\n | { type: \"shutdown\" }\n | ConnectorRequestCommand\n | DebugCommand\n | ConnectorMutateCommand\n | ConnectorQueryCommand\n | ConnectorConfigCommand\n | StateUpdateCommand\n | CustomMessageCommand\n // Protocol v2 capability commands.\n | CapabilityRegisterCommand\n | CapabilityDeregisterCommand\n | CapabilityResultCommand\n | CapabilityApproveCommand;\n\n// ---------------------------------------------------------------------------\n// Resource declaration types (retained for capability inputs)\n// ---------------------------------------------------------------------------\n\n/**\n * A resource declaration carried by `runner.add_mount` / `runner.add_connector`\n * capability invocations. Mirrors the `skaile.yaml` mount/connector schema\n * but flattened for transport.\n *\n * Used by:\n * - {@link ResolvedSkaileConfig.mounts} / `.connectors` (lifecycle.ts)\n * - `runner.add_mount.input.declaration` / `runner.add_connector.input.declaration`\n *\n * @docLink packages/types/protocol-v3#resource-declaration\n */\nexport type ResourceDeclaration = {\n id: string;\n driver: string;\n source: string;\n target?: string;\n access: \"read-only\" | \"read-write\";\n auth?: string;\n /**\n * Identifier of the `ProviderLink` this resource is bound to when\n * `auth: 'backend'`. Read by the platform credential mediator to dispatch\n * the mint (and re-read by the runner when an `exposeAccessToken` git\n * mount needs to surface a managed-gitconfig credential helper). Optional\n * because not every backend-auth driver is provider-linked, and not every\n * resource uses backend auth.\n */\n providerLinkId?: string;\n options?: Record<string, unknown>;\n};\n\n/**\n * Migration strategy carried by `runner.add_mount.input.migration` when\n * replacing the workspace mount of an empty project.\n *\n * @docLink packages/types/protocol-v3#resource-migration\n */\nexport type ResourceMigration =\n | { strategy: \"replace-workspace\"; targetFolder?: string | null }\n | { strategy: \"none\" };\n\n// ---------------------------------------------------------------------------\n// Generic connector mutation / query (Protocol 2.2 — kept in v3)\n// ---------------------------------------------------------------------------\n//\n// Phase 4 of the flow-connector extraction removed the 6 typed flow commands\n// (`start_flow`, `approve_flow_node`, `provide_flow_input`, `cancel_flow`,\n// `set_flow_autonomous_mode`, `retry_flow_node`) plus the implicit\n// `configure.activeFlows` rehydration. Every removed command is reachable\n// via `connector_mutate` against the `flow` connector — see\n// `MIGRATION-flow-connector.md` for the per-op mapping table.\n\n/**\n * Generic connector mutation. Routes to ConnectorManager.executeOp(id, op, payload).\n * Replaces the typed flow commands in Protocol 2.2 — see\n * MIGRATION-flow-connector.md for the per-op mapping table.\n *\n * @docLink packages/types/protocol-v3#connector-mutate-command\n * @since 2.2.0\n */\nexport type ConnectorMutateCommand = {\n type: \"connector_mutate\";\n /** Target connector id (matches `connectors[].id` in skaile.yaml). */\n id: string;\n /** Operation name as declared by the adapter's describeOperations(). */\n op: string;\n /** Operation arguments. Adapter-specific shape. Optional for nullary ops. */\n payload?: Record<string, unknown>;\n /**\n * Opt-in acknowledgement correlation (Protocol 3.7). When present the runner\n * MUST emit exactly one `connector_mutate_response` carrying this `requestId`.\n * When absent the command is fire-and-forget, byte-identical to 3.6 behaviour.\n */\n requestId?: string;\n};\n\n/**\n * Generic connector read. Same dispatch as connector_mutate but the result\n * is returned to the caller as a `connector_query_response` event correlated\n * by `requestId`. Use for read-only queries that should not kick a turn.\n *\n * @since 2.2.0\n */\nexport type ConnectorQueryCommand = {\n type: \"connector_query\";\n requestId: string;\n id: string;\n op: string;\n payload?: Record<string, unknown>;\n};\n\n/**\n * Query the internal state of a running agent server for diagnostics.\n *\n * @docLink packages/types/protocol-v3#debug-command\n */\nexport type DebugCommand = {\n type: \"debug\";\n query: \"tools\" | \"connectors\" | \"mcp\" | \"config\" | \"state\" | \"commands\";\n args?: Record<string, unknown>;\n};\n\n/**\n * Reserved `ConnectorRequestCommand.connectorId` that addresses the session's\n * own root directory (the runner's project dir, `/skaile` in a container)\n * rather than a mount. Only `write` and `delete` are served, and only for\n * `skaile.yaml`, `.skaile/assets/**` and `.skaile/chat-files/**`. It is never\n * registered as a connector, so the agent's prompt and the\n * `resources_available` lists do not show it. The runner routes this id\n * before any connector lookup, so a connector declared with it is unreachable\n * through `resource_request`.\n */\nexport const SESSION_ROOT_CONNECTOR_ID = \"@session\";\n\n/**\n * Browse or modify connectors from the frontend.\n *\n * The wire `type:` string is `\"resource_request\"` for protocol stability.\n * The server responds with a `ConnectorResponseEvent` correlated by `requestId`.\n *\n * @docLink packages/types/protocol-v3#connector-request-command\n */\nexport type ConnectorRequestCommand = {\n type: \"resource_request\";\n /** UUID for request/response correlation. */\n requestId: string;\n /** Connector ID (e.g. \"docs\", \"project-db\"). */\n connectorId: string;\n /** Operation to perform. */\n operation: ConnectorOperation;\n /** Target path (directory, file, key, etc.). */\n path?: string;\n /** Operation-specific options (ListOptions, SearchOptions, StatOptions). */\n options?: ListOptions | SearchOptions | StatOptions;\n /** Content payload for write operations. */\n content?: ConnectorContent;\n};\n\n/**\n * Sent by the frontend to add, remove, or refresh connectors at runtime without a session restart.\n *\n * @docLink packages/types/protocol-v3#connector-config-command\n */\nexport interface ConnectorConfigCommand {\n type: \"connector_config\";\n action: \"add\" | \"remove\" | \"refresh\";\n /** Required when action === \"add\". */\n declaration?: {\n id: string;\n driver: string;\n access?: \"read-only\" | \"read-write\";\n options?: Record<string, unknown>;\n };\n /** Required when action === \"remove\". */\n connectorId?: string;\n}\n\n/**\n * Client/component writes shared state to the runtime.\n *\n * Store namespace must start with `\"app\"` or `\"component:\"` when sent from the client.\n *\n * @docLink packages/types/protocol-v3#state-update-command\n */\nexport type StateUpdateCommand = {\n type: \"state_update\";\n /** Store namespace — must start with \"app\" or \"component:\" from client. */\n store: string;\n /** Full state snapshot (replaces previous). */\n state: Record<string, unknown>;\n};\n\n/**\n * User-originated message with a custom type (from input extensions).\n *\n * Unlike a plain `prompt`, a custom message carries structured data\n * (`customType` + `customData`) alongside the text content. The agent\n * receives these on the `finished` event as `customType`/`customData`\n * fields. On the frontend, the custom message is rendered by the\n * matching dynamic component (or its fallback template).\n *\n * @docLink packages/types/protocol-v3#custom-message-command\n */\nexport type CustomMessageCommand = {\n type: \"custom_message\";\n /** Plain-text content (backward-compatible summary). */\n content: string;\n /** Custom message type identifier (e.g. \"gif\"). */\n customType: string;\n /** Structured data for the custom message type. */\n customData: Record<string, unknown>;\n};\n","/**\n * Reactions -- emoji reactions on session messages.\n *\n * Any session participant (user or agent) can react to any message.\n * Reactions are persisted in a dedicated DB model and broadcast as\n * transient events for real-time updates.\n */\n\n/**\n * A single emoji reaction on a message, set by any session participant (user or agent).\n *\n * Reactions are persisted in a dedicated DB model and broadcast as transient events\n * for real-time updates.\n *\n * @docLink packages/types/messages#reaction\n */\nexport type Reaction = {\n /** Unicode emoji character (e.g. \"thumbs up\", not \":thumbsup:\"). */\n emoji: string;\n /** ID of the user (or \"agent\" for agent reactions). */\n userId: string;\n /** Display name at reaction time (avoids extra lookups for tooltip rendering). */\n userName: string;\n /** Unix epoch milliseconds. */\n timestamp: number;\n};\n\n/**\n * Quick-access emojis shown in the reaction bar picker.\n *\n * An `as const` array of eight Unicode emoji characters in display order.\n *\n * @docLink packages/types/messages#reaction\n */\nexport const QUICK_REACTIONS = [\n \"\\u{1F44D}\",\n \"\\u{1F440}\",\n \"\\u2705\",\n \"\\u2764\\uFE0F\",\n \"\\u{1F914}\",\n \"\\u{1FAE1}\",\n \"\\u{1F44F}\",\n \"\\u{1F389}\",\n] as const;\n","/**\n * Capability layer — Protocol v2's unified registry of LLM-invokable entry points.\n *\n * A {@link Capability} is a named, schema-typed entry point that the LLM can call\n * during a session. Capabilities are registered into a per-session\n * registry by either side (host platform via `side: 'client'` or runtime via\n * `side: 'agent'`) and routed by the bridge at invocation time.\n *\n * This module defines the wire types only; the runtime registry, the\n * `defineCapability` helper, and the per-handler logger live in\n * `@skaile/workspaces/runner`.\n *\n * @see {@link MessageV2} envelope that carries capability commands and events\n * @see {@link ProtocolVersion} for the version contract\n *\n * @category Capabilities\n * @since 2.0.0\n */\n\n// ---------------------------------------------------------------------------\n// Capability shape\n// ---------------------------------------------------------------------------\n\n/**\n * Visibility scope for a capability. Determines which surfaces the capability\n * appears on and which callers can invoke it.\n *\n * - `'llm'`: registered as an LLM tool, surfaced in the `<CAPABILITIES>` system\n * prompt section. The agent driver can invoke it.\n * - `'user'`: appears in user-facing surfaces — the command palette (cmdK),\n * debug menus, capability lists.\n * - `'runtime'`: invocable only by trusted runner / platform code paths. Never\n * reaches the LLM tool list. Never reaches the command palette. Used for\n * host RPCs (`host.refresh_credential`, `host.audit`, `host.notify_user`,\n * `host.persist_compaction_attempt`) and runner RPCs (`runner.add_mount`,\n * `runner.set_log_level`, `runner.lifecycle`, ...).\n *\n * Multiple audiences are allowed (e.g. `['llm', 'user']`). The default when\n * {@link Capability.audience} is omitted is `['llm', 'user']`, preserving the\n * v2.x default visibility for capabilities that haven't migrated yet.\n *\n * @category Capabilities\n * @since 3.0.0\n * @docLink packages/types/capabilities#capability-audience\n */\nexport type CapabilityAudience = \"llm\" | \"user\" | \"runtime\";\n\n/**\n * Source of truth for who registered a capability. Used for trust enforcement\n * (the bridge rejects mismatches between registering side and origin kind)\n * and for the `capability:<origin>:<name>` log taxonomy.\n *\n * Variants:\n * - `framework`: built-in (e.g. `__capabilities.list`)\n * - `client`: host platform (e.g. `platform.react`)\n * - `agent`: self-registered by the agent runtime\n * - `flow`: injected by an active flow execution\n * - `skill`: from a skill's MCP surface\n * - `mcp`: from a generic MCP server\n * - `connector`: from a connector (e.g. `postgres.query`)\n * - `mount`: surfaced by a filesystem mount\n * - `app`: from an embedded, agent-controllable app (carries the originating\n * `appId`). Handlers run in the app itself — see {@link Capability.side} `'app'`.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-origin\n */\nexport type CapabilityOrigin =\n | { kind: \"framework\" }\n | { kind: \"client\" }\n | { kind: \"agent\" }\n | { kind: \"flow\"; flowId: string }\n | { kind: \"skill\"; skillId: string }\n | { kind: \"mcp\"; serverId: string }\n | { kind: \"connector\"; connectorId: string }\n | { kind: \"mount\"; mountId: string }\n | { kind: \"app\"; appId: string };\n\n/**\n * Render contract for a capability that produces a UI surface when invoked.\n *\n * When the LLM invokes a capability whose `render` is set, the bridge emits\n * a {@link RenderInvokedEvent} carrying the capability name and props. The\n * client renders the configured `source` at the chosen `target`. Clients\n * without a render layer can fall back to the markdown `fallback` template.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-spec\n */\nexport type RenderSpec = {\n /** Where the rendered component lives. */\n source: { kind: \"web-component\"; url: string; tagName: string } | { kind: \"iframe\"; url: string };\n /** Render placements supported by the component. */\n targets: (\"chat\" | \"preview\" | \"modal\" | \"input-extension\")[];\n /** Markdown template with `{{prop}}` placeholders for clients without a render layer. */\n fallback?: string;\n /** True when props may be partial during streaming. */\n streaming?: boolean;\n /** Interaction names the rendered component may fire back as state events. */\n interactions?: string[];\n};\n\n/**\n * A named, schema-typed entry point that the LLM can invoke during a session.\n *\n * Capabilities can be declared statically (via `ConfigureCommand.capabilities`)\n * or dynamically (via {@link CapabilityRegisterCommand} /\n * {@link CapabilityRegisterEvent}). They are cached for replay across\n * subscriber reconnects and session hibernation.\n *\n * @example Defining a client-side fire-and-forget tool (uses the runner's\n * `defineCapability` helper, which serializes a {@link Capability} to the wire):\n * ```ts\n * const reactTool = defineCapability({\n * name: 'platform.react',\n * description: 'Acknowledge a user message with a Unicode emoji.',\n * side: 'client',\n * origin: { kind: 'client' },\n * fireAndForget: true,\n * input: z.object({ emoji: z.string(), targetSeq: z.number().optional() }),\n * handler: async ({ emoji, targetSeq }, ctx) => { ... },\n * });\n * ```\n *\n * @see {@link RenderCapability} for capabilities that render UI components\n * @see {@link CapabilityOrigin} for who-registered-it metadata\n * @see {@link isRenderCapability} for the type-guard\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability\n */\nexport type Capability = {\n /** Unique within a session. Convention: namespaced as `<origin>.<name>` (e.g. `platform.react`, `ui.gif`). */\n name: string;\n /**\n * Human-readable label for user-facing surfaces (cmdK action palette,\n * capability menus, debug panels). Falls back to {@link Capability.name}\n * when omitted. Pure presentation — the LLM sees `name`, not `displayName`.\n */\n displayName?: string;\n /** Human/LLM-readable summary. Shown to the LLM as part of tool registration. */\n description: string;\n /** JSON Schema validating the invocation arguments. Authored as Zod, converted at register time. */\n inputSchema: Record<string, unknown>;\n /** Optional return shape. Omit for fire-and-forget effects. */\n outputSchema?: Record<string, unknown>;\n /** Where the handler runs. `client` = host platform, `agent` = runtime/skill/connector, `app` = embedded app. */\n side: \"client\" | \"agent\" | \"app\";\n /** Discriminated tag identifying who registered the capability. Used for trust enforcement and audit. */\n origin: CapabilityOrigin;\n /** Lifetime: `session` survives the whole session, `turn` is dropped at end-of-turn. */\n scope?: \"session\" | \"turn\";\n /** When true, the bridge auto-resolves with `{}` immediately and runs the handler in the background. */\n fireAndForget?: boolean;\n /** When true, the platform shows a confirm UI before dispatch and waits for {@link CapabilityApproveCommand}. */\n requiresApproval?: boolean;\n /** Documentation hint (not enforced) describing whether this is a side-effect, render, or pure query. */\n kind?: \"effect\" | \"render\" | \"query\";\n /**\n * Whether this capability should be exposed in user-facing surfaces (cmdK\n * action palette, capability menus). When omitted, the consumer applies a\n * default per-origin via {@link isUserInvokable}.\n *\n * - `true`: surface in cmdK and capability menus.\n * - `false`: hide from user surfaces (LLM-only or low-level).\n * - `undefined`: defer to {@link isUserInvokable}'s inference rules.\n *\n * @deprecated Set {@link Capability.audience} instead. `userInvokable` is\n * kept as a read-only shim for v2.x consumers and is honoured by\n * {@link isUserInvokable} when {@link Capability.audience} is absent.\n */\n userInvokable?: boolean;\n /**\n * Audience scoping for this capability. See {@link CapabilityAudience} for\n * the meaning of each value and combinations.\n *\n * When omitted, consumers treat the capability as `['llm', 'user']` (the\n * v2.x default). Host RPCs and runner RPCs MUST set this to `['runtime']`\n * so they never leak to the LLM tool list or the user-facing surfaces.\n *\n * @category Capabilities\n * @since 3.0.0\n */\n audience?: CapabilityAudience[];\n /** Appended to the system prompt's `<CAPABILITIES>` section. Use for usage hints the LLM should always see. */\n promptFragment?: string;\n /**\n * Per-capability override for how long the runner waits on the\n * `capability_result` round-trip before timing out. When omitted the\n * runner applies its default (`DEFAULT_CAPABILITY_CALL_TIMEOUT_MS`, 60s).\n *\n * Set this for capabilities that legitimately block far longer than a\n * normal tool call — e.g. `platform.ask_session` suspends the caller's\n * turn until a peer session answers, which can take minutes.\n *\n * @category Capabilities\n * @since 3.3.0\n */\n callTimeoutMs?: number;\n /** Present iff this is a render capability — see {@link RenderCapability}. */\n render?: RenderSpec;\n};\n\n/**\n * A {@link Capability} that produces a UI surface when invoked. The narrowed\n * type guarantees `render` is set, which simplifies frontend lookup.\n *\n * @see {@link isRenderCapability}\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-capability\n */\nexport type RenderCapability = Capability & { render: NonNullable<Capability[\"render\"]> };\n\n/**\n * Type-guard for {@link RenderCapability}. Use after {@link Capability}\n * lookup to narrow the type before reading `render`.\n *\n * @example\n * ```ts\n * for (const cap of registry.list()) {\n * if (isRenderCapability(cap)) console.log(cap.render.targets);\n * }\n * ```\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#is-render-capability\n */\nexport function isRenderCapability(cap: Capability): cap is RenderCapability {\n return cap.render !== undefined;\n}\n\n/**\n * Decide whether a capability should be surfaced in user-facing actions\n * (cmdK action palette, capability menus).\n *\n * Resolution order (first match wins):\n *\n * 1. {@link Capability.audience} is set — return `audience.includes('user')`.\n * Capabilities scoped to `'runtime'` only never appear in user surfaces.\n * 2. {@link Capability.userInvokable} is set (v2.x shim) — return that value.\n * 3. Default per-origin inference table below.\n *\n * Default-inference rules (when both `audience` and `userInvokable` are\n * omitted):\n * | Origin | Default |\n * | ------------ | ---------------------------------------------------------------------- |\n * | `framework` | `false` (LLM discovery surfaces, e.g. `__capabilities.list`) |\n * | `client` | `false` (platform ack tools — `platform.react`, `platform.pass`) |\n * | `agent` | `false` (agent-defined; assume internal unless flagged) |\n * | `flow` | `false` (per-cap opt-in) |\n * | `connector` | `false` (low-level FS / data ops) |\n * | `mount` | `false` (low-level FS ops) |\n * | `app` | `false` (LLM-only; app authors opt in via `audience: ['llm','user']`) |\n * | `mcp` | `true` if `kind === 'effect'`, else `false` |\n * | `skill` | `true` if `kind` ∈ {`effect`, `render`}, else `false` |\n *\n * @example\n * ```ts\n * for (const cap of capabilities.values()) {\n * if (isUserInvokable(cap)) registerCommandPaletteAction(cap);\n * }\n * ```\n *\n * @category Capabilities\n * @since 2.1.0\n * @docLink packages/types/capabilities#is-user-invokable\n */\nexport function isUserInvokable(cap: Capability): boolean {\n if (cap.audience !== undefined) {\n return cap.audience.includes(\"user\");\n }\n if (cap.userInvokable !== undefined) {\n return cap.userInvokable;\n }\n switch (cap.origin.kind) {\n case \"framework\":\n case \"client\":\n case \"agent\":\n case \"flow\":\n case \"connector\":\n case \"mount\":\n case \"app\":\n return false;\n case \"mcp\":\n return cap.kind === \"effect\";\n case \"skill\":\n return cap.kind === \"effect\" || cap.kind === \"render\";\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Capability commands (client → agent)\n// ---------------------------------------------------------------------------\n\n/**\n * Register one or more capabilities mid-session (client → agent).\n *\n * The platform sends this when a new client-side tool becomes available\n * after `configure` has already returned (e.g. a user installs a new\n * extension during the session).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-register-command\n */\nexport type CapabilityRegisterCommand = {\n type: \"capability_register\";\n capabilities: Capability[];\n};\n\n/**\n * Deregister capabilities by name (client → agent). Names that are not\n * currently registered are ignored silently.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-deregister-command\n */\nexport type CapabilityDeregisterCommand = {\n type: \"capability_deregister\";\n names: string[];\n};\n\n/**\n * Return the result of a previously {@link CapabilityInvokedEvent | invoked} client-side\n * capability (client → agent). Bridges that registered the capability with\n * `fireAndForget: true` MAY skip this command; the bridge auto-resolves with `{}`.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-result-command\n */\nexport type CapabilityResultCommand = {\n type: \"capability_result\";\n /** Correlation token matching the {@link CapabilityInvokedEvent.callId}. */\n callId: string;\n /** Successful result payload, or an error envelope. */\n result: unknown | { error: string };\n};\n\n/**\n * Invoke an **agent-side** capability (client → agent). The host names the\n * capability and supplies its input; the runner answers with a matching\n * {@link CapabilityResultEvent}. The mirror of {@link CapabilityInvokedEvent},\n * which reports the LLM invoking a client-side capability in the opposite\n * direction and shares this discriminant.\n *\n * @category Capabilities\n * @since 3.23.0\n * @docLink packages/types/capabilities#capability-invoke-command\n */\nexport type CapabilityInvokeCommand = {\n type: \"capability_invoked\";\n /** Correlation token the answering {@link CapabilityResultEvent} echoes. */\n callId: string;\n /** Name of the {@link Capability} to invoke. */\n name: string;\n /** Input payload, validated against the capability's schema by the registry. */\n input: unknown;\n};\n\n/**\n * Return the result of a platform-invoked **agent-side** capability\n * (agent → client). The mirror of {@link CapabilityResultCommand}, which\n * carries the same shape in the opposite direction for client-side\n * capabilities; `runner.attach_instance` and its `runner.*` siblings answer\n * with this one.\n *\n * Both directions share the `capability_result` discriminant, so the sender\n * decides which type applies — they are never both valid on one hop.\n *\n * @category Capabilities\n * @since 3.23.0\n * @docLink packages/types/capabilities#capability-result-event\n */\nexport type CapabilityResultEvent = {\n type: \"capability_result\";\n /** Correlation token matching the invoking call. */\n callId: string;\n /** Successful result payload, or an error envelope. */\n result: unknown | { error: string };\n};\n\n/**\n * Approve or reject a capability call that was invoked with\n * `requiresApproval: true` (client → agent). The platform shows a confirm\n * UI and forwards the user's decision via this command.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-approve-command\n */\nexport type CapabilityApproveCommand = {\n type: \"capability_approve\";\n /** Correlation token matching the {@link CapabilityInvokedEvent.callId}. */\n callId: string;\n /** User's decision. */\n decision: \"approved\" | \"rejected\";\n /** Optional rationale stored alongside the decision for audit. */\n feedback?: string;\n /** User ID of the decider (informational — framework enforces no policy). */\n decidedBy: string;\n};\n\n// ---------------------------------------------------------------------------\n// Capability events (agent → client)\n// ---------------------------------------------------------------------------\n\n/**\n * Register one or more capabilities mid-session (agent → client). Mirrors\n * {@link CapabilityRegisterCommand} for the agent-initiated direction; used\n * when the runtime adds a capability after `configure` (e.g. when a flow\n * starts and injects flow-scoped tools).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-register-event\n */\nexport type CapabilityRegisterEvent = {\n type: \"capability_register\";\n capabilities: Capability[];\n};\n\n/**\n * Deregister capabilities by name (agent → client).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-deregister-event\n */\nexport type CapabilityDeregisterEvent = {\n type: \"capability_deregister\";\n names: string[];\n};\n\n/**\n * Notify the client that a capability has been invoked by the LLM (agent →\n * client). For client-side capabilities the platform's handler runs in\n * response to this event and replies with {@link CapabilityResultCommand}.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-invoked-event\n */\nexport type CapabilityInvokedEvent = {\n type: \"capability_invoked\";\n /** Correlation token for the eventual {@link CapabilityResultCommand}. */\n callId: string;\n /** Name of the invoked {@link Capability}. */\n name: string;\n /** Validated input payload (already conforms to the capability's `inputSchema`). */\n input: unknown;\n /** In v2.0.0 the LLM is the only invoker. */\n invokedBy: \"agent\";\n};\n\n/**\n * Notify the client that a render capability should be drawn (agent →\n * client). Emitted alongside {@link CapabilityInvokedEvent} when the\n * invoked capability's `render` block is populated.\n *\n * Clients without a render layer can fall back to the capability's\n * `render.fallback` markdown template.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-invoked-event\n */\nexport type RenderInvokedEvent = {\n type: \"render_invoked\";\n /** Name of the invoked render capability. */\n capabilityName: string;\n /** Props passed to the rendered component (already conforms to `inputSchema`). */\n props: unknown;\n /** Correlation token shared with the matching {@link CapabilityInvokedEvent}. */\n callId: string;\n};\n","/**\n * Agent-authored tool-call activity labels.\n *\n * Every tool the runtime advertises to the model carries one extra optional\n * string parameter, {@link TOOL_ACTIVITY_LABEL_PARAM}, in which the agent\n * describes the call in plain language (\"Reading the Q3 budget spreadsheet\").\n * The normalizer surfaces it as `ToolCallEvent.label` so the chat can show it\n * instead of the raw tool name and arguments.\n *\n * The parameter is added at the ADVERTISE layer only and stripped before the\n * real handler runs. It never enters a capability's registered `inputSchema`,\n * because that schema is hashed into the resume signature.\n *\n * Zod is passed in rather than imported: the Claude SDK and the bridge each\n * bring their own zod instance, and the schema must be built with the one the\n * SDK validates against.\n *\n * @category Tools\n * @since 3.24.0\n */\n\n/** Name of the optional parameter injected into every advertised tool schema. */\nexport const TOOL_ACTIVITY_LABEL_PARAM = \"activity_label\";\n\n/** Longest label the normalizer passes on; longer text is truncated with an ellipsis. */\nexport const TOOL_ACTIVITY_LABEL_MAX_CHARS = 120;\n\n/** LLM-facing description of {@link TOOL_ACTIVITY_LABEL_PARAM}. */\nexport const TOOL_ACTIVITY_LABEL_DESCRIPTION =\n \"Short plain-language description (under ~12 words, present tense) of what this call does, \" +\n \"shown to the user while it runs, e.g. 'Reading the Q3 budget spreadsheet'. \" +\n \"Never include secrets.\";\n\n/** System-prompt guidance telling the agent to fill the label on every call. */\nexport const TOOL_ACTIVITY_PROMPT_SECTION = [\n \"## Tool-call activity labels\",\n \"\",\n `Whenever a tool offers an \\`${TOOL_ACTIVITY_LABEL_PARAM}\\` parameter, always fill it. For the Bash tool, always fill its \\`description\\` parameter.`,\n \"The text is shown to the user while the call runs, in place of the tool's technical details, so write it for a non-technical reader:\",\n \"under ~12 words, present tense, naming the thing being worked on (e.g. 'Reading the Q3 budget spreadsheet', 'Checking which invoices are overdue').\",\n \"Never put secrets, tokens or raw file contents in it.\",\n].join(\"\\n\");\n\n/**\n * Add {@link TOOL_ACTIVITY_LABEL_PARAM} to a zod raw shape (a record of zod\n * fields, as `createSdkMcpServer` accepts). Returns the shape unchanged when\n * the tool already declares a property of that name.\n */\nexport function withActivityLabelShape(\n shape: Record<string, unknown>,\n z: any,\n): Record<string, unknown> {\n if (Object.hasOwn(shape, TOOL_ACTIVITY_LABEL_PARAM)) return shape;\n return {\n ...shape,\n [TOOL_ACTIVITY_LABEL_PARAM]: z.string().optional().describe(TOOL_ACTIVITY_LABEL_DESCRIPTION),\n };\n}\n\n/**\n * Add {@link TOOL_ACTIVITY_LABEL_PARAM} to a JSON Schema object's top-level\n * `properties`. Returns the schema unchanged when it already declares the\n * property.\n */\nexport function withActivityLabelJsonSchema(\n schema: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const base = schema ?? {};\n if (declaresActivityLabel(base)) return base;\n const props = (base.properties ?? {}) as Record<string, unknown>;\n return {\n ...base,\n properties: {\n ...props,\n [TOOL_ACTIVITY_LABEL_PARAM]: { type: \"string\", description: TOOL_ACTIVITY_LABEL_DESCRIPTION },\n },\n };\n}\n\n/** True when a JSON Schema object itself declares {@link TOOL_ACTIVITY_LABEL_PARAM}. */\nexport function declaresActivityLabel(schema: unknown): boolean {\n if (!schema || typeof schema !== \"object\") return false;\n const props = (schema as Record<string, unknown>).properties;\n return !!props && typeof props === \"object\" && Object.hasOwn(props, TOOL_ACTIVITY_LABEL_PARAM);\n}\n\n/**\n * Remove {@link TOOL_ACTIVITY_LABEL_PARAM} from a tool input before it reaches\n * the handler. Returns a shallow copy; non-object inputs and inputs without\n * the key are returned as-is.\n */\nexport function stripActivityLabel<T>(input: T): T {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return input;\n if (!Object.hasOwn(input, TOOL_ACTIVITY_LABEL_PARAM)) return input;\n const { [TOOL_ACTIVITY_LABEL_PARAM]: _label, ...rest } = input as Record<string, unknown>;\n return rest as T;\n}\n\n/**\n * Wrap in-process SDK tool defs: advertise {@link TOOL_ACTIVITY_LABEL_PARAM}\n * and strip it before each handler runs. A def that already declares the\n * property is returned untouched — the value is then the tool's own argument.\n */\nexport function withActivityLabelDefs<\n T extends { inputSchema: Record<string, unknown>; handler: (args: any) => unknown },\n>(defs: T[], z: any): T[] {\n return defs.map((def) => {\n if (Object.hasOwn(def.inputSchema, TOOL_ACTIVITY_LABEL_PARAM)) return def;\n return {\n ...def,\n inputSchema: withActivityLabelShape(def.inputSchema, z),\n // Forward the SDK's trailing args (`extra`) untouched.\n handler: (args: unknown, ...rest: unknown[]) =>\n (def.handler as (a: unknown, ...r: unknown[]) => unknown)(\n stripActivityLabel(args),\n ...rest,\n ),\n };\n });\n}\n","/**\n * Protocol versioning primitives for Skaile Agent Protocol v2.\n *\n * The protocol is versioned by a structured {@link ProtocolVersion} record\n * (`major.minor.patch`). The compatibility rule applied at handshake is\n * **major-equality**: a runner emits {@link IncompatibleProtocolEvent} and\n * shuts down when its declared major does not match the platform's announced\n * major. Minor and patch differences ride through transparently because\n * unknown fields are preserved on round-trip (see `MessageMeta` round-trip\n * contract in `messaging.ts`).\n *\n * @category Protocol\n * @since 2.0.0\n */\n\n/**\n * Structured semantic version triple for the agent protocol.\n *\n * @example\n * ```ts\n * const v: ProtocolVersion = { major: 2, minor: 0, patch: 0 };\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#protocol-version\n */\nexport type ProtocolVersion = {\n /** Incremented on breaking wire-format changes (field removed, semantics changed, required field added). */\n major: number;\n /** Incremented on additive wire-format changes (new optional fields, new event types). */\n minor: number;\n /** Incremented on bug-fix or doc-only changes that do not affect the wire. */\n patch: number;\n};\n\n/**\n * The protocol version the framework currently speaks. Runners and platforms\n * compare this against the peer's announced version at session boot via\n * `SessionInitCommand.protocolVersion`.\n *\n * @example\n * ```ts\n * import { PROTOCOL_VERSION } from '@skaile/workspaces/types';\n * if (cmd.protocolVersion.major !== PROTOCOL_VERSION.major) {\n * emit({ type: 'incompatible_protocol', agentVersion: PROTOCOL_VERSION, platformVersion: cmd.protocolVersion });\n * }\n * ```\n *\n * @category Protocol\n * @since 3.0.0\n *\n * Changed in 4.3.0:\n * Additive `text_retract` event: the runner takes back the unfinished text of\n * an attempt it is about to replay, as the exact suffix of the `text` it\n * already streamed. A host that buffers or persists streamed text must cut\n * that suffix rather than treat the event as an unknown non-text event (which\n * would commit the fragment). A 4.2 runner never sends it.\n *\n * Changed in 4.2.0:\n * Two additive `resource_request` operations for filesystem mounts: `mkdir`\n * (create one empty directory, parents included; something already at the path\n * fails with `code: \"already_exists\"`) and `stat` (type, size, modified and\n * created time, and with `options.recursive` capped recursive `totals` that\n * report `partial` instead of failing). `resource_response` gains an optional\n * `code` (`ConnectorResponseFailureCode`). A 4.1 runner answers either op with\n * an `error` starting `Unsupported operation` and no `code`; a host must\n * feature-detect on `major === 4 && minor >= 2` or accept that error form.\n *\n * Changed in 4.1.0:\n * Additive `provider_quota_observed` event: one upstream quota-window reading\n * (window, status, optional utilization and reset) per change, attributed to\n * the pinned `AIProviderConfig`. A host with no handler broadcasts it\n * harmlessly. A 4.1 host against a 4.0 runner sees none and must not read\n * that as \"no quota used\" (feature-detect on `major === 4 && minor >= 1`).\n *\n * Changed in 4.0.0 (breaking):\n * The AI provider registry is the only provider surface on the wire.\n * `ResolvedAgentConfig` **loses** `provider`, `cloud` and `cloudConfig`; what\n * remains is `registry?` (the merged AI provider registry — `id → entry`, or\n * the merged view with registry order and merge provenance) and `modelRef?`\n * (`\"<providerId>/<modelId>\"`, a bare model id, or `\"@role\"`). Registry\n * entries never carry a literal secret: a control-plane-injected credential\n * is named by a `credential.ref` of the form `platform:<configId>` and\n * resolved against the sibling `secrets` map, which the platform keys by the\n * bare config id. A `session_init` whose `resolvedConfig.agentConfig` still\n * carries one of the removed fields is **rejected** with a fatal `error`\n * naming the replacement — silently ignoring them would run the session\n * against a different endpoint than the control plane resolved. Peers\n * negotiate on `major`, so a 3.x platform and a 4.x runner refuse each other\n * at boot rather than degrading.\n *\n * Changed in 3.15.0:\n * Classifier nodes. A new runtime-audience capability, `host.classify`\n * (`HostClassifyInput` → `HostClassifyResult`), which the runner invokes for a\n * classifier-shaped subprompt node, and an optional `classification` on\n * `NodeOutput`. A host without `host.classify` makes every classifier node run on\n * the generative fallback; older peers ignore the new output field.\n *\n * Changed in 3.14.0:\n * Optional `sessionRoot` flag on `resources_available`, advertising the\n * reserved `SESSION_ROOT_CONNECTOR_ID` write target for session-owned files.\n * Older peers ignore the flag and never send the reserved id.\n *\n * Changed in 3.13.0:\n * Optional agent-authored `label` on the `tool_call` event, and a new\n * `\"tool-activity\"` member of `SystemPromptSection.label`. Older peers ignore\n * both; a host that renders `label` can feature-detect it by this minor.\n *\n * Changed in 3.12.0:\n * Optional structured prompt attachments and question/reply requestId correlation.\n * Older peers retain text prompts and ignore unknown optional fields. Managed\n * question hosts must echo requestId; this minor does not advertise or admit the\n * separately gated codex-app-server-v1 runtime.\n *\n * Changed in 3.10.0:\n * Additive rejection cause on the AI-credential refresh input. The\n * `host.refresh_credential` `ai-credentials` input gains an optional\n * `rejection?: CredentialRejection` (`'auth' | 'usage-limit'`), sent only\n * alongside `reason: 'retry-401'` and only from the two runner call sites that\n * genuinely classified the failure — the driver's auth self-heal (`'auth'`) and\n * its usage-limit failover (`'usage-limit'`). `reason: 'retry-401'` collapsed\n * both, so a limit-blocked session on a config that is not opted into\n * `autoActivate` never re-resolved; the field is what lets the platform tell\n * them apart. `auth` asserts only that the rejection was auth-shaped, never\n * that capacity is fine (Anthropic mislabels OAuth quota exhaustion as\n * `authentication_error`); only `usage-limit` is a positive assertion. The\n * connector and MCP refresh paths classify nothing and keep emitting exactly\n * today's bytes. There is no peer-version gate, so a 3.9 peer does receive the\n * key on those two inputs; it is unaffected because nothing was removed or\n * reshaped and it must ignore an unknown key — and an unrecognised value —\n * rather than reject the input, which is also what allows a third rejection\n * later without a major bump. A 3.10 host against a 3.9 runner never sees the\n * field and must not read its absence as \"not a limit\" (feature-detect on\n * `major === 3 && minor >= 10`).\n * Spec: skaile-ai/platform#3562.\n *\n * Changed in 3.9.0:\n * Additive live AI-provider-seat signals, all optional under the\n * major-equality rule:\n * - `AgentEvent` gains `provider_response_seen`, emitted when the runner\n * observes a 401 or a 429 / subscription-limit rejection from the AI\n * provider, attributed to the pinned `AIProviderConfig`. A platform with\n * no handler broadcasts it harmlessly; consumers must ignore unknown\n * fields, since the platform half ships independently.\n * - The `CredentialMint` success branch gains an optional `configId` — the\n * seat the platform actually minted for. When it differs from the one the\n * runner asked for, the runner repoints the live session at it. A platform\n * that omits the field produces exactly 3.8 behaviour (no switch is ever\n * detected).\n * - The `credentialRotated` broadcast may carry `entry.data.configId` to\n * move a running session to a different seat rather than merely rotating\n * the token on the current one. Absent → today's re-pull.\n * A 3.8 peer is unaffected: nothing was removed or re-shaped, every addition is\n * opt-in on a field a 3.8 peer never sets. A 3.9 host against a 3.8 runner sees\n * no `provider_response_seen` and must not read that as \"no limits were hit\"\n * (feature-detect on `major === 3 && minor >= 9`).\n *\n * Changed in 3.8.0:\n * Additive `prompt` receipt acknowledgement. The `prompt` command gains an\n * optional `messageId`; when set the runner emits exactly one new `prompt_ack`\n * event echoing it, as the first act of handling the frame — before the\n * session-readiness gate, the secrets check and the driver start, each of which\n * could previously drop a prompt with no trace at all. When absent nothing is\n * emitted, so a 3.7 host sees byte-identical behaviour. A 3.8 host against a\n * 3.7 runner gets no ack and must not read that as a lost prompt — feature-detect\n * on `major === 3 && minor >= 8`. The ack is receipt-only: it says the frame\n * arrived, never that the turn ran.\n *\n * Changed in 3.7.0:\n * Additive `connector_mutate` acknowledgement + flow-hydrate reconciliation.\n * Three changes, all additive under the major-equality rule:\n * - `ConnectorMutateCommand` gains an optional `requestId`. When set, the\n * runner emits exactly one new `connector_mutate_response` event (with\n * `ok` / `result` / `error` / `code` / `reconciled`) on every terminal path,\n * including the paths that previously only logged. When absent nothing is\n * emitted, so a 3.6 host sees byte-identical behaviour.\n * - `flow.hydrate` accepts an optional `payload.pendingDecisions` —\n * `PendingGateDecision[]` the runner replays against the snapshot in the\n * same invocation that creates the flow connector, reporting the outcome as\n * `reconciled`. A host that omits the key gets today's hydrate.\n * - A flow-targeted mutate whose connector is not yet registered now waits\n * (bounded, `SKAILE_FLOW_MUTATE_CONNECTOR_WAIT_MS`, default 8000 ms) and\n * re-plans instead of failing — a behaviour change on a path that used to\n * fail silently, visible to a 3.6 host only as the op succeeding.\n * A 3.6 peer is unaffected: no symbol was removed or re-shaped, the ack is\n * opt-in on a field a 3.6 host never sets, and unknown fields ride through the\n * round-trip. A 3.7 host against a 3.6 runner sees `requestId` ignored and no\n * response, which it must treat as \"unacknowledged\" (feature-detect on\n * `major === 3 && minor >= 7`). Spec: `runner/MIGRATION-flow-connector.md`.\n *\n * Changed in 3.6.0:\n * Additive resolved-agent-config wire field. `ResolvedSkaileConfig` gains an\n * optional `agentConfig?: ResolvedAgentConfig` carrying the platform-resolved\n * driver / model / registry / modelRef / thinking / effort — the\n * same values the platform bakes into the generated skaile.yaml\n * `agent-config.default`. The runner applies it disk-first: any on-disk\n * `agent-config` profile with at least one agent setting disables the wire\n * value outright, so yaml-on-disk (docker-mode) sessions are byte-identical.\n * Additive under the major-equality rule: an older runner ignores the field\n * and an older platform simply omits it.\n *\n * Changed in 3.5.0:\n * Flow-connector host-contract fix (workspaces#379). Three coordinated changes,\n * all additive under the major-equality rule:\n * - `op:\"hydrate\"` on the bare `\"flow\"` connector now auto-creates the\n * `flow:<runId>` connector on a cold container from its `{ state, flow }`\n * payload, so a persisted run rehydrates in one op. A peer that still issues\n * `start` then `hydrate` keeps working unchanged.\n * - The dead `SessionInit.activeFlows` field (never read by the runner) and its\n * `ActiveFlowRehydration` type are removed — wire-compatible (nothing produced\n * or consumed them) but source-breaking for typed hosts, hence the bump.\n * - Malformed / conflicting flow `start` and `hydrate` payloads now fail loudly\n * (warn with a reason) instead of silently falling through.\n * Because the handshake compares only `major`, a 3.4 host and a 3.5 runner\n * interoperate: the auto-create path is opt-in on the payload the host sends, and\n * the removed field was already inert. Spec: `runner/MIGRATION-flow-connector.md`.\n *\n * Changed in 3.4.0:\n * Additive embedded-app capability source. `CapabilityOrigin` gains a\n * `{ kind: 'app'; appId: string }` variant and `Capability.side` gains `'app'`\n * (\"the handler runs in the embedded app\"). Both are additive: a peer that does\n * not understand `origin:'app'` / `side:'app'` never produces or routes them, so\n * they ride through transparently under the major-equality rule. No new message\n * types — `capability_register` / `capability_invoked` / `capability_result` /\n * `capability_approve` / `render_invoked` are reused verbatim. Spec:\n * `_devlog/specs/2026-07-07-app-capability-source.md`.\n *\n * Changed in 3.3.0:\n * Additive agent-to-agent (session-to-session) communication extension.\n * `AgentEvent` gains an `a2a_message` variant carrying cross-session messages\n * (`direction`, `peerSessionId`, `peerName`, `exchangeId`, `text`). `Capability`\n * gains an optional `callTimeoutMs?: number` so a long-running capability call\n * (e.g. a 5-minute `platform.ask_session`) can exceed the default capability-call\n * timeout. Both are additive: a peer that does not understand them ignores the\n * event / falls back to the default timeout, so they ride through transparently\n * under the major-equality rule.\n *\n * Changed in 3.2.0:\n * Additive wake-time resume cascade. `AgentReconfigureOptions` gains optional\n * `resumeSessionId` and `expectedCapabilitySignature` fields driving the tier-1\n * native SDK resume path; `AgentEvent` gains `ResumeAttemptedEvent` and\n * `ResumeFailedEvent`. `FinishedEvent` gains optional `customType` /\n * `customData` for capability-routed custom payloads. All additive — clients\n * that omit the resume hint or ignore the new events keep working unchanged.\n *\n * Changed in 3.1.0:\n * Additive cost / token usage extension. `FinishedEvent` gains an optional\n * `tokens?: TokenUsage` field carrying per-turn input / output / cache-read /\n * cache-creation / reasoning token counts. `AgentDriver.getTokenUsage()` is\n * widened to return the same `TokenUsage` shape (existing consumers reading\n * `inputTokens` / `outputTokens` keep working unchanged). Drivers that do not\n * surface token usage continue to return `null` / omit the field.\n *\n * Changed in 3.0.0:\n * Major bump for the deterministic session bootstrap rewrite. `ConfigureCommandV2`,\n * `provision_secrets`, `request_access_token`, `add_resource`, `remove_resource`,\n * `set_log_level`, `state_action`, `lifecycle`, `remount_mount`, `compact`, and\n * `reconfigure_agent` are removed from the `AgentCommand` union. Their semantics\n * are reachable through:\n * - `session_init` (one deterministic envelope at session start that delivers\n * identity, resolved config, pre-minted credentials, secrets, capabilities,\n * shared state, active flows, resume hints, and logging config),\n * - `host.refresh_credential` (capability invocation that replaces the\n * refresh-on-401 path of `request_access_token`), and\n * - `runner.*` capabilities (`runner.add_mount`, `runner.add_connector`,\n * `runner.remove_resource`, `runner.update_credential`, `runner.set_log_level`,\n * `runner.set_state`, `runner.lifecycle`) invoked by the platform via the\n * bidirectional capability registry.\n *\n * Capabilities gain an `audience: ('llm' | 'user' | 'runtime')[]` field that\n * scopes visibility: host RPCs (`host.*`) and runner RPCs (`runner.*`) are\n * `['runtime']` and never reach the LLM tool list or the user-facing command\n * palette. v2.x capabilities without an explicit `audience` default to\n * `['llm', 'user']`, preserving prior behaviour.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`.\n *\n * @docLink packages/types/protocol-v3#protocol-version\n */\nexport const PROTOCOL_VERSION: ProtocolVersion = { major: 4, minor: 3, patch: 0 };\n\n/**\n * String form of {@link PROTOCOL_VERSION}, kept in lock-step. Useful for\n * `package.json` version fields and HTTP `User-Agent` strings.\n *\n * @category Protocol\n * @since 3.0.0\n * @docLink packages/types/protocol-v3#protocol-version\n */\nexport const PROTOCOL_VERSION_STRING = \"4.3.0\";\n\n/**\n * Parse a `\"major.minor.patch\"` string into a {@link ProtocolVersion}.\n *\n * @param s - the version string to parse, exactly three dot-separated non-negative integers\n * @returns the parsed protocol version\n * @throws {Error} if the string is not exactly three dot-separated non-negative integers\n *\n * @example\n * ```ts\n * parseVersion('2.0.0'); // { major: 2, minor: 0, patch: 0 }\n * parseVersion('2.1'); // throws\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#parse-version\n */\nexport function parseVersion(s: string): ProtocolVersion {\n const parts = s.split(\".\");\n if (parts.length !== 3) {\n throw new Error(`Invalid ProtocolVersion: \"${s}\" (expected \"major.minor.patch\")`);\n }\n const [maj, min, pat] = parts;\n const major = Number(maj);\n const minor = Number(min);\n const patch = Number(pat);\n if (\n !Number.isInteger(major) ||\n !Number.isInteger(minor) ||\n !Number.isInteger(patch) ||\n major < 0 ||\n minor < 0 ||\n patch < 0\n ) {\n throw new Error(`Invalid ProtocolVersion: \"${s}\" (each part must be a non-negative integer)`);\n }\n return { major, minor, patch };\n}\n\n/**\n * Format a {@link ProtocolVersion} record into its `\"major.minor.patch\"` string form.\n *\n * @param v - the protocol version to format\n * @returns the dot-joined string form\n *\n * @example\n * ```ts\n * formatVersion({ major: 2, minor: 0, patch: 0 }); // '2.0.0'\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#format-version\n */\nexport function formatVersion(v: ProtocolVersion): string {\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { getProviderPreset, resolvePresetBaseUrl, expandPreset, resolveProbeUrl, buildCredentialHeaders, presetBaseUrl } from './chunk-C2CYBRYJ.js';
1
+ import { getProviderPreset, resolvePresetBaseUrl, expandPreset, resolveProbeUrl, buildCredentialHeaders, presetBaseUrl } from './chunk-KMFZVPYR.js';
2
2
  import { resolveEntryBaseUrl, entryTransport, parseModelRef, registryEntries } from './chunk-ILG4BXYE.js';
3
3
  import { modelIdSchemaForTarget } from './chunk-N7B3LZ7V.js';
4
4
 
@@ -323,5 +323,5 @@ function resolveModelTier(tier, sessionModel, options = {}) {
323
323
  }
324
324
 
325
325
  export { ModelTierResolutionError, PROVIDER_MODEL_TIERS, STATIC_MODELS, fetchProviderModels, getModels, getStaticModels, modelIdTargetForEntry, resolveManifestModel, resolveModelCapabilities, resolveModelTier };
326
- //# sourceMappingURL=chunk-VP2CACF2.js.map
327
- //# sourceMappingURL=chunk-VP2CACF2.js.map
326
+ //# sourceMappingURL=chunk-QVTROHEZ.js.map
327
+ //# sourceMappingURL=chunk-QVTROHEZ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../bridge/src/models.ts"],"names":[],"mappings":"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","file":"chunk-VP2CACF2.js","sourcesContent":["/**\n * Model catalog — static fallback + live provider API fetching.\n *\n * Provides `fetchProviderModels(provider, apiKey)` for live model lists and\n * `getStaticModels(provider)` as an offline fallback.\n * OMP model listing is handled by `OmpDriver.listModels()` in the bridge driver.\n */\n\nimport {\n type AIProviderCapabilities,\n type AIProviderLlmEntry,\n type AIProviderRegistry,\n entryTransport,\n type MergedAIProviderRegistry,\n parseModelRef,\n registryEntries,\n resolveEntryBaseUrl,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport { type ModelIdTarget, modelIdSchemaForTarget } from \"@skaile/workspaces/types/manifests\";\nimport {\n buildCredentialHeaders,\n expandPreset,\n getProviderPreset,\n presetBaseUrl,\n resolvePresetBaseUrl,\n resolveProbeUrl,\n} from \"./provider-catalog.js\";\n\n/**\n * A single LLM model entry returned by the model catalog.\n *\n * Used by `getModels`, `getStaticModels`, and `fetchProviderModels` to represent\n * an available model for a provider.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport interface ModelEntry {\n /** Provider-specific model identifier used in API calls (e.g. `\"claude-sonnet-4-5\"`). */\n id: string;\n /** Human-readable display name for UIs and logs (e.g. `\"Claude Sonnet 4.5\"`). */\n name: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider API configs (for fetching model lists)\n// ---------------------------------------------------------------------------\n\n/** Extract ModelEntry[] from a provider's parsed models-list JSON response. */\ntype ParseModels = (body: any) => ModelEntry[];\n\n/** Humanize a model ID into a display name (e.g. \"claude-sonnet-4-6\" → \"Claude Sonnet 4 6\") */\nfunction humanize(id: string): string {\n return id\n .replace(/^accounts\\/[^/]+\\/models\\//, \"\")\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Filter function used by providers that return the OpenAI-style /v1/models list.\n * Keeps only chat/completion models, skips embeddings, moderation, tts, whisper, dall-e, etc.\n */\nfunction isLikelyChatModel(id: string): boolean {\n const skip = /embed|moderat|tts|whisper|dall-e|davinci|babbage|ada-00|text-/i;\n return !skip.test(id);\n}\n\n// Per-provider response parsers. The endpoint URL and the credential header\n// come from the catalog preset (provider-catalog.ts), joined in\n// fetchProviderModels.\nconst PROVIDER_PARSERS: Record<string, ParseModels> = {\n anthropic: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && !m.id.includes(\"embed\"))\n .map((m: any) => ({\n id: m.id,\n name: m.display_name ?? humanize(m.id),\n }));\n },\n openai: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n openrouter: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id)\n .map((m: any) => ({ id: m.id, name: m.name ?? humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n mistral: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n groq: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n deepseek: (body) => {\n const models = body?.data ?? [];\n return models\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n xai: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n together: (body) => {\n const models = body?.data ?? body ?? [];\n const arr = Array.isArray(models) ? models : [];\n return arr\n .filter((m: any) => m.id && m.type === \"chat\")\n .map((m: any) => ({ id: m.id, name: m.display_name ?? humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n fireworks: (body) => {\n const models = body?.data ?? [];\n return models\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n google: (body) => {\n const models = body?.models ?? [];\n return models\n .filter((m: any) => m.supportedGenerationMethods?.includes(\"generateContent\"))\n .map((m: any) => ({\n id: (m.name ?? \"\").replace(/^models\\//, \"\"),\n name: m.displayName ?? humanize(m.name ?? \"\"),\n }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n};\n\n// ---------------------------------------------------------------------------\n// Live fetch\n// ---------------------------------------------------------------------------\n\n/**\n * Result of a model-list fetch operation, with source attribution.\n *\n * Returned by {@link fetchProviderModels} and {@link getModels}. When `ok` is `false`,\n * `models` is empty and `error` describes the failure. The `source` field indicates\n * whether the list came from a live API call or the offline static catalog.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport interface FetchModelsResult {\n /** `true` when the fetch succeeded and `models` is populated. */\n ok: boolean;\n /** Fetched model list; empty on failure. */\n models: ModelEntry[];\n /** Human-readable error description when `ok` is `false`. */\n error?: string;\n /** Whether the result came from a live API call or the static fallback. */\n source: \"api\" | \"static\";\n}\n\n/**\n * Options controlling where a model-list fetch is addressed.\n *\n * @since 1.5.0\n */\nexport interface FetchModelsOptions {\n /**\n * Base URL to resolve the provider's models endpoint against — e.g. the\n * gateway a session already routes completions through. Overrides the\n * provider's `baseUrlEnv` value.\n */\n baseUrl?: string;\n /**\n * Environment consulted for the provider's base-URL env var\n * (`ANTHROPIC_BASE_URL` for `anthropic`). Defaults to `process.env`; pass an\n * explicit record to keep a call hermetic.\n */\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Fetch the model list from a provider's REST API.\n *\n * Returns `{ ok: true, models, source: 'api' }` on success, or\n * `{ ok: false, models: [], error }` on any HTTP or network failure — the\n * caller should fall back to {@link getStaticModels} in that case.\n *\n * The endpoint, the credential header and the response path all come from the\n * catalog preset named by `provider` ({@link resolvePresetBaseUrl},\n * {@link resolveProbeUrl}, {@link buildCredentialHeaders}), so discovery hits\n * the same host dispatch does — including a gateway named by `baseUrl` or by\n * the vendor's own `*_BASE_URL` variable.\n *\n * @param provider - Catalog preset id (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * @param apiKey - API key presented in the preset's credential header.\n * @param options - Optional base-URL / environment overrides.\n * @returns Resolved model list with source attribution.\n * @docLink packages/bridge/api-reference#models\n */\nexport async function fetchProviderModels(\n provider: string,\n apiKey: string,\n options: FetchModelsOptions = {},\n): Promise<FetchModelsResult> {\n const preset = getProviderPreset(provider);\n const parse = PROVIDER_PARSERS[provider];\n if (!preset || !parse) {\n return {\n ok: false,\n models: [],\n error: `No API config for provider: ${provider}`,\n source: \"static\",\n };\n }\n\n const baseUrl = resolvePresetBaseUrl(preset, {\n ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),\n env: options.env ?? process.env,\n });\n const entry = expandPreset(preset, baseUrl ? { baseUrl } : {});\n const url = resolveProbeUrl(entry);\n if (!url) {\n return {\n ok: false,\n models: [],\n error: `Provider ${provider} exposes no models endpoint`,\n source: \"static\",\n };\n }\n // Static non-secret headers (Anthropic's `anthropic-version`) plus the\n // credential carrier the preset's `auth_header` names.\n const headers = { ...entry.headers, ...buildCredentialHeaders(entry, apiKey) };\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n return {\n ok: false,\n models: [],\n error: `API returned HTTP ${response.status}`,\n source: \"static\",\n };\n }\n\n const body = await response.json();\n const models = parse(body);\n\n return { ok: true, models, source: \"api\" };\n } catch (err: any) {\n const msg =\n err.name === \"AbortError\" ? \"Request timed out (10s)\" : (err.message ?? \"Network error\");\n return { ok: false, models: [], error: msg, source: \"static\" };\n }\n}\n\n/**\n * Get models for a provider, trying the live API first and falling back to the static catalog.\n *\n * When no `apiKey` is provided the static catalog is returned immediately without\n * a network call. When the live API fails or returns an empty list, the static\n * catalog is used as a fallback — the result's `source` field indicates which was used.\n *\n * @param provider - Provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * @param apiKey - Optional API key; omit to skip the live fetch and use the static catalog.\n * @param options - Optional base-URL / environment overrides (see {@link FetchModelsOptions}).\n * @returns Resolved model list with source attribution.\n * @docLink packages/bridge/api-reference#models\n */\nexport async function getModels(\n provider: string,\n apiKey?: string,\n options: FetchModelsOptions = {},\n): Promise<FetchModelsResult> {\n if (!apiKey) {\n const models = getStaticModels(provider);\n return { ok: true, models, source: \"static\" };\n }\n\n const result = await fetchProviderModels(provider, apiKey, options);\n if (result.ok && result.models.length > 0) {\n return result;\n }\n\n // Fall back to static\n const staticModels = getStaticModels(provider);\n if (staticModels.length > 0) {\n return { ok: true, models: staticModels, source: \"static\", error: result.error };\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Static catalog (offline fallback)\n// ---------------------------------------------------------------------------\n\n/**\n * Offline model catalog keyed by provider name.\n *\n * Used as a fallback by {@link getModels} when the live provider API is unreachable or\n * returns an empty list. Covers Anthropic, OpenAI, Google, Mistral, Groq, DeepSeek,\n * xAI, Together, Fireworks, and OpenRouter. Update this list when providers add new\n * models and a live fetch is not available.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport const STATIC_MODELS: Record<string, ModelEntry[]> = {\n anthropic: [\n { id: \"claude-opus-4-6\", name: \"Claude Opus 4.6\" },\n { id: \"claude-sonnet-4-6\", name: \"Claude Sonnet 4.6\" },\n { id: \"claude-haiku-4-5-20251001\", name: \"Claude Haiku 4.5\" },\n { id: \"claude-opus-4-5\", name: \"Claude Opus 4.5\" },\n { id: \"claude-sonnet-4-5\", name: \"Claude Sonnet 4.5\" },\n ],\n openai: [\n { id: \"gpt-4o\", name: \"GPT-4o\" },\n { id: \"gpt-4o-mini\", name: \"GPT-4o Mini\" },\n { id: \"gpt-4.1\", name: \"GPT-4.1\" },\n { id: \"gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n { id: \"o3\", name: \"o3\" },\n { id: \"o4-mini\", name: \"o4-mini\" },\n ],\n google: [\n { id: \"gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" },\n { id: \"gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n { id: \"gemini-2.0-flash\", name: \"Gemini 2.0 Flash\" },\n ],\n mistral: [\n { id: \"mistral-large-latest\", name: \"Mistral Large\" },\n { id: \"mistral-small-latest\", name: \"Mistral Small\" },\n { id: \"codestral-latest\", name: \"Codestral\" },\n ],\n groq: [\n { id: \"llama-3.3-70b-versatile\", name: \"Llama 3.3 70B\" },\n { id: \"llama-3.1-8b-instant\", name: \"Llama 3.1 8B\" },\n { id: \"mixtral-8x7b-32768\", name: \"Mixtral 8x7B\" },\n ],\n deepseek: [\n { id: \"deepseek-chat\", name: \"DeepSeek Chat\" },\n { id: \"deepseek-reasoner\", name: \"DeepSeek Reasoner\" },\n ],\n xai: [\n { id: \"grok-3\", name: \"Grok 3\" },\n { id: \"grok-3-mini\", name: \"Grok 3 Mini\" },\n ],\n together: [\n { id: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\", name: \"Llama 3.3 70B Turbo\" },\n { id: \"mistralai/Mixtral-8x7B-Instruct-v0.1\", name: \"Mixtral 8x7B\" },\n ],\n fireworks: [\n { id: \"accounts/fireworks/models/llama-v3p3-70b-instruct\", name: \"Llama 3.3 70B\" },\n { id: \"accounts/fireworks/models/deepseek-v3\", name: \"DeepSeek v3\" },\n ],\n openrouter: [\n { id: \"anthropic/claude-sonnet-4.6\", name: \"Claude Sonnet 4.6\" },\n { id: \"anthropic/claude-opus-4.6\", name: \"Claude Opus 4.6\" },\n { id: \"anthropic/claude-haiku-4.5\", name: \"Claude Haiku 4.5\" },\n { id: \"anthropic/claude-sonnet-4.5\", name: \"Claude Sonnet 4.5\" },\n { id: \"anthropic/claude-3.7-sonnet\", name: \"Claude 3.7 Sonnet\" },\n { id: \"openai/gpt-4o\", name: \"GPT-4o\" },\n { id: \"openai/gpt-4.1\", name: \"GPT-4.1\" },\n { id: \"openai/gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n { id: \"google/gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" },\n { id: \"google/gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n { id: \"meta-llama/llama-4-maverick\", name: \"Llama 4 Maverick\" },\n { id: \"meta-llama/llama-3.3-70b-instruct\", name: \"Llama 3.3 70B\" },\n { id: \"deepseek/deepseek-chat-v3-0324\", name: \"DeepSeek v3\" },\n { id: \"deepseek/deepseek-r1\", name: \"DeepSeek R1\" },\n { id: \"mistralai/mistral-large-2411\", name: \"Mistral Large 2\" },\n ],\n};\n\n/**\n * Get models for a specific provider from the static catalog, or empty array if unknown.\n *\n * Pure synchronous lookup — no network call. Use when the provider API is unavailable\n * or when a fast offline fallback is needed (e.g. in the UI before credentials are configured).\n *\n * @param provider - Provider name matching a key in {@link STATIC_MODELS}.\n * @returns Offline model list, or `[]` for unknown providers.\n * @docLink packages/bridge/api-reference#models\n */\nexport function getStaticModels(provider: string): ModelEntry[] {\n return STATIC_MODELS[provider] ?? [];\n}\n\n// ---------------------------------------------------------------------------\n// Registry-backed model identity (§2.4)\n// ---------------------------------------------------------------------------\n\n/** A registry in either of the two shapes consumers hold. */\nexport type ProviderRegistryView = AIProviderRegistry | MergedAIProviderRegistry;\n\n/**\n * Where a model selector is resolved. `registry` absent means no registry is\n * configured at all — every resolver here then returns `undefined` and the\n * caller keeps its pre-registry behaviour.\n */\nexport interface ModelRegistryContext {\n /** The merged registry (`mergeRegistries`), or a single layer. */\n registry?: ProviderRegistryView;\n /** `skaile.yaml` `roles`: role name → model selector (`smol` → `groq/llama-3.1-8b`). */\n roles?: Record<string, string>;\n /**\n * Entry the session already runs on. Scopes `model_map` lookups to it;\n * absent lets the selector pick in registry order.\n */\n providerId?: string;\n}\n\n/** The `llm`/`embed` entry registered under `id`, if any. */\nfunction llmEntry(registry: ProviderRegistryView, id: string): AIProviderLlmEntry | undefined {\n const entry = registryEntries(registry).find(([entryId]) => entryId === id)?.[1];\n if (!entry || (entry.kind !== \"llm\" && entry.kind !== \"embed\")) return undefined;\n return entry;\n}\n\n/**\n * The wire facts that decide which model-id vocabulary an entry enforces\n * (`modelIdSchemaForTarget`).\n *\n * `surface` and `base_url` fall back to the entry's preset: an entry written as\n * `{kind: llm, preset: anthropic}` carries neither of its own until the catalog\n * merge layer expands it, and validation must not depend on having been handed\n * a merged registry.\n */\nexport function modelIdTargetForEntry(entry: AIProviderLlmEntry): ModelIdTarget {\n const preset = entry.preset ? getProviderPreset(entry.preset) : undefined;\n const surface = entry.surface ?? preset?.surface;\n const base_url = resolveEntryBaseUrl(entry) ?? (preset ? presetBaseUrl(preset) : undefined);\n return {\n ...(surface ? { surface } : {}),\n ...(entryTransport(entry) ? { transport: entryTransport(entry) } : {}),\n ...(base_url ? { base_url } : {}),\n };\n}\n\n/** A manifest model preference resolved against the registry. */\nexport interface ResolvedManifestModel {\n /** Entry the preference routes to. */\n providerId: string;\n /** Logical id, after `@role` expansion and before `model_map`. */\n modelId?: string;\n /** Provider-side id — what goes on the wire: `model_map[modelId] ?? modelId`. */\n providerModelId?: string;\n /** Role name, when the preference was `@role`. */\n role?: string;\n /** The wire target `providerModelId` was checked against. */\n target: ModelIdTarget;\n /** Non-fatal notes: a dangling role, a disabled provider, a stale preset. */\n warnings: string[];\n /**\n * Set when `providerModelId` is not a legal id for `target` — in practice,\n * a non-Anthropic id on the first-party Anthropic Messages API. Never\n * thrown: the caller decides whether a manifest that names a model its\n * endpoint cannot serve is a warning or a failure.\n */\n error?: string;\n}\n\n/**\n * Resolve an agent manifest's `model.preferred` (or any single entry of\n * `model.fallback`) against the provider registry, then check the id it\n * produces against the selected entry's own vocabulary.\n *\n * The three selector forms — `@role`, `<providerId>/<modelId>`, bare id — are\n * resolved by `parseModelRef` (`@skaile/workspaces/core/provider-registry`),\n * which owns that grammar; this adds the per-surface id check on top.\n *\n * Returns `undefined` when there is nothing to resolve: no preference, or no\n * registry that can serve one.\n */\nexport function resolveManifestModel(\n preference: string | undefined,\n context: ModelRegistryContext = {},\n): ResolvedManifestModel | undefined {\n if (!preference || !context.registry) return undefined;\n const ref = parseModelRef(preference, context.registry, context.roles);\n if (!ref) return undefined;\n\n const entry = llmEntry(context.registry, ref.providerId);\n const target = entry ? modelIdTargetForEntry(entry) : {};\n const resolved: ResolvedManifestModel = {\n providerId: ref.providerId,\n ...(ref.modelId !== undefined ? { modelId: ref.modelId } : {}),\n ...(ref.providerModelId !== undefined ? { providerModelId: ref.providerModelId } : {}),\n ...(ref.role !== undefined ? { role: ref.role } : {}),\n target,\n warnings: [...ref.warnings],\n };\n if (ref.providerModelId === undefined) return resolved;\n\n const check = modelIdSchemaForTarget(target).safeParse(ref.providerModelId);\n if (!check.success) {\n resolved.error =\n `model \"${ref.providerModelId}\" is not valid for provider \"${ref.providerId}\" ` +\n `(surface ${target.surface ?? \"unknown\"}, transport ${target.transport ?? \"direct\"}` +\n `${target.base_url ? `, ${target.base_url}` : \"\"}): ` +\n (check.error.issues[0]?.message ?? \"invalid model id\");\n }\n return resolved;\n}\n\n/**\n * Resolve a model's capability facts — context window, thinking ceiling, tool\n * and image support — from the registry entry that serves it.\n *\n * `capabilities` is keyed by the *logical* id (the `model_map` key), so a\n * selector is resolved first and the record is read under both the logical and\n * the provider-side id. `fallback` is the caller's own per-model table (the\n * compaction window defaults, the platform's thinking limits); the entry wins\n * field by field, and a field the entry does not state falls through.\n *\n * Returns `undefined` when neither source knows anything about the model.\n */\nexport function resolveModelCapabilities(\n selector: string | undefined,\n context: ModelRegistryContext & {\n /** Per-model-id capability table consulted for fields the entry omits. */\n fallback?: Record<string, AIProviderCapabilities>;\n } = {},\n): AIProviderCapabilities | undefined {\n if (!selector) return undefined;\n const ref = context.registry\n ? parseModelRef(selector, context.registry, context.roles)\n : undefined;\n const entry = ref && context.registry ? llmEntry(context.registry, ref.providerId) : undefined;\n const ids = [ref?.modelId, ref?.providerModelId, selector].filter(\n (id): id is string => id !== undefined,\n );\n const entryCaps = ids.map((id) => entry?.capabilities?.[id]).find((caps) => caps !== undefined);\n const fallbackCaps = ids.map((id) => context.fallback?.[id]).find((caps) => caps !== undefined);\n\n const context_window = entryCaps?.context_window ?? fallbackCaps?.context_window;\n const thinking_max = entryCaps?.thinking_max ?? fallbackCaps?.thinking_max;\n const tools = entryCaps?.tools ?? fallbackCaps?.tools;\n const images = entryCaps?.images ?? fallbackCaps?.images;\n if (\n context_window === undefined &&\n thinking_max === undefined &&\n tools === undefined &&\n images === undefined\n ) {\n return undefined;\n }\n return {\n ...(context_window !== undefined ? { context_window } : {}),\n ...(thinking_max !== undefined ? { thinking_max } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(images !== undefined ? { images } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Model tier resolution (Flow v2 `run.model`)\n// ---------------------------------------------------------------------------\n\n/** Per-tier concrete model ids for one provider. */\nexport interface ModelTierOverrides {\n small?: string;\n default?: string;\n deep?: string;\n}\n\n/**\n * Tier→model mapping per provider, for deployments with **no provider\n * registry**. This is the point of the closed `small | default | deep`\n * vocabulary: an authored flow names an intent and the runtime owns which\n * concrete model serves it, so flows stay portable across model-lineup changes.\n *\n * It is no longer the source of truth for what a tier means. Where a registry\n * exists, a tier resolves through `roles` and the selected entry's `model_map`\n * (see {@link resolveModelTier}) — which works for every provider, names the\n * ids that deployment actually serves, and is editable without a release. This\n * table survives only for the pre-registry path, where nothing else can answer\n * the question; a vendor missing from it there is a `ModelTierResolutionError`,\n * not a guess.\n *\n * These are **direct provider-API ids**. A gateway transport (Bedrock, Vertex,\n * Azure) addresses the same models by different ids — Bedrock prefixes\n * `us.anthropic.`, for instance — and that translation belongs to whoever owns\n * the deployment, not here. {@link resolveModelTier} therefore consults this\n * table only on the direct API and demands an explicit override otherwise,\n * rather than handing a gateway an id it cannot serve.\n *\n * Every id here must also appear in {@link STATIC_MODELS} — a test asserts it,\n * so the two cannot drift into naming a model the catalog disowns. That check\n * proves internal consistency only; it cannot tell you an id is still current\n * with a provider's live lineup.\n *\n * Where a provider's lineup has no genuinely distinct model for a tier, the\n * entry deliberately repeats the neighbouring one. That is a reviewable\n * property of that lineup, unlike inheriting whatever model the session\n * happened to start with — which is how `small` could silently mean Opus.\n */\nexport const PROVIDER_MODEL_TIERS: Record<string, Required<ModelTierOverrides>> = {\n anthropic: {\n small: \"claude-haiku-4-5-20251001\",\n default: \"claude-sonnet-4-6\",\n deep: \"claude-opus-4-6\",\n },\n openai: { small: \"gpt-4o-mini\", default: \"gpt-4.1\", deep: \"o3\" },\n google: { small: \"gemini-2.0-flash\", default: \"gemini-2.5-flash\", deep: \"gemini-2.5-pro\" },\n mistral: {\n small: \"mistral-small-latest\",\n default: \"mistral-large-latest\",\n deep: \"mistral-large-latest\",\n },\n groq: {\n small: \"llama-3.1-8b-instant\",\n default: \"llama-3.3-70b-versatile\",\n deep: \"llama-3.3-70b-versatile\",\n },\n deepseek: { small: \"deepseek-chat\", default: \"deepseek-chat\", deep: \"deepseek-reasoner\" },\n xai: { small: \"grok-3-mini\", default: \"grok-3\", deep: \"grok-3\" },\n together: {\n small: \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n default: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n deep: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n },\n fireworks: {\n small: \"accounts/fireworks/models/llama-v3p3-70b-instruct\",\n default: \"accounts/fireworks/models/llama-v3p3-70b-instruct\",\n deep: \"accounts/fireworks/models/deepseek-v3\",\n },\n openrouter: {\n small: \"anthropic/claude-haiku-4.5\",\n default: \"anthropic/claude-sonnet-4.6\",\n deep: \"anthropic/claude-opus-4.6\",\n },\n};\n\n/** Raised when a tier names an intent this provider cannot serve. */\nexport class ModelTierResolutionError extends Error {\n constructor(\n readonly tier: \"small\" | \"deep\",\n readonly provider: string | undefined,\n ) {\n super(\n `cannot resolve model tier \"${tier}\" for provider \"${provider ?? \"(none)\"}\": no built-in mapping and no configured override. ` +\n `Configure a \"${tier}\" model override for this provider, or author the node as model: \"default\" to inherit the session model.`,\n );\n this.name = \"ModelTierResolutionError\";\n }\n}\n\n/**\n * Resolve a tier for a deployment that has a registry: through `roles[tier]`\n * first, then the selected entry's `model_map[tier]`.\n *\n * A `model_map` **miss is a miss**. `parseModelRef` falls back to the literal\n * selector when nothing maps it, and no provider serves a model called\n * `\"small\"` — so only a genuine mapping counts, and an unmapped tier is left\n * for the caller to fail on.\n */\nfunction resolveTierThroughRegistry(\n tier: keyof ModelTierOverrides,\n options: ModelRegistryContext,\n): string | undefined {\n const { registry, roles, providerId } = options;\n if (!registry) return undefined;\n if (roles?.[tier] !== undefined) {\n const viaRole = parseModelRef(`@${tier}`, registry, roles);\n if (viaRole?.providerModelId) return viaRole.providerModelId;\n }\n const ref = parseModelRef(providerId ? `${providerId}/${tier}` : tier, registry, roles);\n if (!ref?.modelId) return undefined;\n return llmEntry(registry, ref.providerId)?.model_map?.[ref.modelId];\n}\n\n/** Options {@link resolveModelTier} reads. */\nexport interface ResolveModelTierOptions extends ModelRegistryContext {\n /** Legacy provider id, keying {@link PROVIDER_MODEL_TIERS}. */\n provider?: string;\n /** Legacy cloud transport; anything but `default` disables the built-in table. */\n cloud?: string;\n /** Per-tier ids configured for this deployment. Wins over everything. */\n overrides?: ModelTierOverrides;\n}\n\n/**\n * Resolve a Flow v2 `run.model` tier to a concrete model id.\n *\n * Precedence, highest first: a configured `overrides` entry; the registry —\n * `roles[tier]`, then the selected entry's `model_map[tier]`, which is how a\n * tier is defined for *any* provider; and finally, **only when no registry is\n * configured**, {@link PROVIDER_MODEL_TIERS} on the direct provider API.\n *\n * `\"default\"` and an absent tier **inherit `sessionModel` first**. The session\n * model is the one id known to work for this deployment — it already carries\n * whatever provider, lineup and gateway translation the host configured — so\n * preferring any table over it would silently downgrade a configured model\n * and, on a gateway transport, substitute an id that provider cannot serve.\n *\n * `\"small\"` and `\"deep\"` never fall back to `sessionModel`; when nothing above\n * resolves them they throw {@link ModelTierResolutionError}. Inheriting there\n * would run an arbitrary model behind an author's explicit request for a cheap\n * or a strong one — a cost or quality surprise that shows up only in the bill\n * or the output. Failing names it at the node instead.\n *\n * Pure: no I/O, no environment reads.\n */\nexport function resolveModelTier(\n tier: \"small\" | \"default\" | \"deep\" | undefined,\n sessionModel: string | undefined,\n options: ResolveModelTierOptions = {},\n): string | undefined {\n // Built-in ids address the provider's own API; a gateway renames them. And a\n // registry answers the question properly, so the table is its fallback only.\n const directApi = !options.cloud || options.cloud === \"default\";\n const builtIn =\n !options.registry && directApi && options.provider\n ? PROVIDER_MODEL_TIERS[options.provider]\n : undefined;\n if (tier === \"small\" || tier === \"deep\") {\n const resolved =\n options.overrides?.[tier] ?? resolveTierThroughRegistry(tier, options) ?? builtIn?.[tier];\n if (!resolved) throw new ModelTierResolutionError(tier, options.provider);\n return resolved;\n }\n return (\n options.overrides?.default ??\n sessionModel ??\n resolveTierThroughRegistry(\"default\", options) ??\n builtIn?.default\n );\n}\n"]}
1
+ {"version":3,"sources":["../bridge/src/models.ts"],"names":[],"mappings":"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","file":"chunk-QVTROHEZ.js","sourcesContent":["/**\n * Model catalog — static fallback + live provider API fetching.\n *\n * Provides `fetchProviderModels(provider, apiKey)` for live model lists and\n * `getStaticModels(provider)` as an offline fallback.\n * OMP model listing is handled by `OmpDriver.listModels()` in the bridge driver.\n */\n\nimport {\n type AIProviderCapabilities,\n type AIProviderLlmEntry,\n type AIProviderRegistry,\n entryTransport,\n type MergedAIProviderRegistry,\n parseModelRef,\n registryEntries,\n resolveEntryBaseUrl,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport { type ModelIdTarget, modelIdSchemaForTarget } from \"@skaile/workspaces/types/manifests\";\nimport {\n buildCredentialHeaders,\n expandPreset,\n getProviderPreset,\n presetBaseUrl,\n resolvePresetBaseUrl,\n resolveProbeUrl,\n} from \"./provider-catalog.js\";\n\n/**\n * A single LLM model entry returned by the model catalog.\n *\n * Used by `getModels`, `getStaticModels`, and `fetchProviderModels` to represent\n * an available model for a provider.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport interface ModelEntry {\n /** Provider-specific model identifier used in API calls (e.g. `\"claude-sonnet-4-5\"`). */\n id: string;\n /** Human-readable display name for UIs and logs (e.g. `\"Claude Sonnet 4.5\"`). */\n name: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider API configs (for fetching model lists)\n// ---------------------------------------------------------------------------\n\n/** Extract ModelEntry[] from a provider's parsed models-list JSON response. */\ntype ParseModels = (body: any) => ModelEntry[];\n\n/** Humanize a model ID into a display name (e.g. \"claude-sonnet-4-6\" → \"Claude Sonnet 4 6\") */\nfunction humanize(id: string): string {\n return id\n .replace(/^accounts\\/[^/]+\\/models\\//, \"\")\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Filter function used by providers that return the OpenAI-style /v1/models list.\n * Keeps only chat/completion models, skips embeddings, moderation, tts, whisper, dall-e, etc.\n */\nfunction isLikelyChatModel(id: string): boolean {\n const skip = /embed|moderat|tts|whisper|dall-e|davinci|babbage|ada-00|text-/i;\n return !skip.test(id);\n}\n\n// Per-provider response parsers. The endpoint URL and the credential header\n// come from the catalog preset (provider-catalog.ts), joined in\n// fetchProviderModels.\nconst PROVIDER_PARSERS: Record<string, ParseModels> = {\n anthropic: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && !m.id.includes(\"embed\"))\n .map((m: any) => ({\n id: m.id,\n name: m.display_name ?? humanize(m.id),\n }));\n },\n openai: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n openrouter: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id)\n .map((m: any) => ({ id: m.id, name: m.name ?? humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n mistral: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n groq: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n deepseek: (body) => {\n const models = body?.data ?? [];\n return models\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n xai: (body) => {\n const models = body?.data ?? [];\n return models\n .filter((m: any) => m.id && isLikelyChatModel(m.id))\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n together: (body) => {\n const models = body?.data ?? body ?? [];\n const arr = Array.isArray(models) ? models : [];\n return arr\n .filter((m: any) => m.id && m.type === \"chat\")\n .map((m: any) => ({ id: m.id, name: m.display_name ?? humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n fireworks: (body) => {\n const models = body?.data ?? [];\n return models\n .map((m: any) => ({ id: m.id, name: humanize(m.id) }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n google: (body) => {\n const models = body?.models ?? [];\n return models\n .filter((m: any) => m.supportedGenerationMethods?.includes(\"generateContent\"))\n .map((m: any) => ({\n id: (m.name ?? \"\").replace(/^models\\//, \"\"),\n name: m.displayName ?? humanize(m.name ?? \"\"),\n }))\n .sort((a: ModelEntry, b: ModelEntry) => a.id.localeCompare(b.id));\n },\n};\n\n// ---------------------------------------------------------------------------\n// Live fetch\n// ---------------------------------------------------------------------------\n\n/**\n * Result of a model-list fetch operation, with source attribution.\n *\n * Returned by {@link fetchProviderModels} and {@link getModels}. When `ok` is `false`,\n * `models` is empty and `error` describes the failure. The `source` field indicates\n * whether the list came from a live API call or the offline static catalog.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport interface FetchModelsResult {\n /** `true` when the fetch succeeded and `models` is populated. */\n ok: boolean;\n /** Fetched model list; empty on failure. */\n models: ModelEntry[];\n /** Human-readable error description when `ok` is `false`. */\n error?: string;\n /** Whether the result came from a live API call or the static fallback. */\n source: \"api\" | \"static\";\n}\n\n/**\n * Options controlling where a model-list fetch is addressed.\n *\n * @since 1.5.0\n */\nexport interface FetchModelsOptions {\n /**\n * Base URL to resolve the provider's models endpoint against — e.g. the\n * gateway a session already routes completions through. Overrides the\n * provider's `baseUrlEnv` value.\n */\n baseUrl?: string;\n /**\n * Environment consulted for the provider's base-URL env var\n * (`ANTHROPIC_BASE_URL` for `anthropic`). Defaults to `process.env`; pass an\n * explicit record to keep a call hermetic.\n */\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Fetch the model list from a provider's REST API.\n *\n * Returns `{ ok: true, models, source: 'api' }` on success, or\n * `{ ok: false, models: [], error }` on any HTTP or network failure — the\n * caller should fall back to {@link getStaticModels} in that case.\n *\n * The endpoint, the credential header and the response path all come from the\n * catalog preset named by `provider` ({@link resolvePresetBaseUrl},\n * {@link resolveProbeUrl}, {@link buildCredentialHeaders}), so discovery hits\n * the same host dispatch does — including a gateway named by `baseUrl` or by\n * the vendor's own `*_BASE_URL` variable.\n *\n * @param provider - Catalog preset id (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * @param apiKey - API key presented in the preset's credential header.\n * @param options - Optional base-URL / environment overrides.\n * @returns Resolved model list with source attribution.\n * @docLink packages/bridge/api-reference#models\n */\nexport async function fetchProviderModels(\n provider: string,\n apiKey: string,\n options: FetchModelsOptions = {},\n): Promise<FetchModelsResult> {\n const preset = getProviderPreset(provider);\n const parse = PROVIDER_PARSERS[provider];\n if (!preset || !parse) {\n return {\n ok: false,\n models: [],\n error: `No API config for provider: ${provider}`,\n source: \"static\",\n };\n }\n\n const baseUrl = resolvePresetBaseUrl(preset, {\n ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),\n env: options.env ?? process.env,\n });\n const entry = expandPreset(preset, baseUrl ? { baseUrl } : {});\n const url = resolveProbeUrl(entry);\n if (!url) {\n return {\n ok: false,\n models: [],\n error: `Provider ${provider} exposes no models endpoint`,\n source: \"static\",\n };\n }\n // Static non-secret headers (Anthropic's `anthropic-version`) plus the\n // credential carrier the preset's `auth_header` names.\n const headers = { ...entry.headers, ...buildCredentialHeaders(entry, apiKey) };\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10_000);\n\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n return {\n ok: false,\n models: [],\n error: `API returned HTTP ${response.status}`,\n source: \"static\",\n };\n }\n\n const body = await response.json();\n const models = parse(body);\n\n return { ok: true, models, source: \"api\" };\n } catch (err: any) {\n const msg =\n err.name === \"AbortError\" ? \"Request timed out (10s)\" : (err.message ?? \"Network error\");\n return { ok: false, models: [], error: msg, source: \"static\" };\n }\n}\n\n/**\n * Get models for a provider, trying the live API first and falling back to the static catalog.\n *\n * When no `apiKey` is provided the static catalog is returned immediately without\n * a network call. When the live API fails or returns an empty list, the static\n * catalog is used as a fallback — the result's `source` field indicates which was used.\n *\n * @param provider - Provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * @param apiKey - Optional API key; omit to skip the live fetch and use the static catalog.\n * @param options - Optional base-URL / environment overrides (see {@link FetchModelsOptions}).\n * @returns Resolved model list with source attribution.\n * @docLink packages/bridge/api-reference#models\n */\nexport async function getModels(\n provider: string,\n apiKey?: string,\n options: FetchModelsOptions = {},\n): Promise<FetchModelsResult> {\n if (!apiKey) {\n const models = getStaticModels(provider);\n return { ok: true, models, source: \"static\" };\n }\n\n const result = await fetchProviderModels(provider, apiKey, options);\n if (result.ok && result.models.length > 0) {\n return result;\n }\n\n // Fall back to static\n const staticModels = getStaticModels(provider);\n if (staticModels.length > 0) {\n return { ok: true, models: staticModels, source: \"static\", error: result.error };\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Static catalog (offline fallback)\n// ---------------------------------------------------------------------------\n\n/**\n * Offline model catalog keyed by provider name.\n *\n * Used as a fallback by {@link getModels} when the live provider API is unreachable or\n * returns an empty list. Covers Anthropic, OpenAI, Google, Mistral, Groq, DeepSeek,\n * xAI, Together, Fireworks, and OpenRouter. Update this list when providers add new\n * models and a live fetch is not available.\n *\n * @docLink packages/bridge/api-reference#models\n */\nexport const STATIC_MODELS: Record<string, ModelEntry[]> = {\n anthropic: [\n { id: \"claude-opus-4-6\", name: \"Claude Opus 4.6\" },\n { id: \"claude-sonnet-4-6\", name: \"Claude Sonnet 4.6\" },\n { id: \"claude-haiku-4-5-20251001\", name: \"Claude Haiku 4.5\" },\n { id: \"claude-opus-4-5\", name: \"Claude Opus 4.5\" },\n { id: \"claude-sonnet-4-5\", name: \"Claude Sonnet 4.5\" },\n ],\n openai: [\n { id: \"gpt-4o\", name: \"GPT-4o\" },\n { id: \"gpt-4o-mini\", name: \"GPT-4o Mini\" },\n { id: \"gpt-4.1\", name: \"GPT-4.1\" },\n { id: \"gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n { id: \"o3\", name: \"o3\" },\n { id: \"o4-mini\", name: \"o4-mini\" },\n ],\n google: [\n { id: \"gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" },\n { id: \"gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n { id: \"gemini-2.0-flash\", name: \"Gemini 2.0 Flash\" },\n ],\n mistral: [\n { id: \"mistral-large-latest\", name: \"Mistral Large\" },\n { id: \"mistral-small-latest\", name: \"Mistral Small\" },\n { id: \"codestral-latest\", name: \"Codestral\" },\n ],\n groq: [\n { id: \"llama-3.3-70b-versatile\", name: \"Llama 3.3 70B\" },\n { id: \"llama-3.1-8b-instant\", name: \"Llama 3.1 8B\" },\n { id: \"mixtral-8x7b-32768\", name: \"Mixtral 8x7B\" },\n ],\n deepseek: [\n { id: \"deepseek-chat\", name: \"DeepSeek Chat\" },\n { id: \"deepseek-reasoner\", name: \"DeepSeek Reasoner\" },\n ],\n xai: [\n { id: \"grok-3\", name: \"Grok 3\" },\n { id: \"grok-3-mini\", name: \"Grok 3 Mini\" },\n ],\n together: [\n { id: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\", name: \"Llama 3.3 70B Turbo\" },\n { id: \"mistralai/Mixtral-8x7B-Instruct-v0.1\", name: \"Mixtral 8x7B\" },\n ],\n fireworks: [\n { id: \"accounts/fireworks/models/llama-v3p3-70b-instruct\", name: \"Llama 3.3 70B\" },\n { id: \"accounts/fireworks/models/deepseek-v3\", name: \"DeepSeek v3\" },\n ],\n openrouter: [\n { id: \"anthropic/claude-sonnet-4.6\", name: \"Claude Sonnet 4.6\" },\n { id: \"anthropic/claude-opus-4.6\", name: \"Claude Opus 4.6\" },\n { id: \"anthropic/claude-haiku-4.5\", name: \"Claude Haiku 4.5\" },\n { id: \"anthropic/claude-sonnet-4.5\", name: \"Claude Sonnet 4.5\" },\n { id: \"anthropic/claude-3.7-sonnet\", name: \"Claude 3.7 Sonnet\" },\n { id: \"openai/gpt-4o\", name: \"GPT-4o\" },\n { id: \"openai/gpt-4.1\", name: \"GPT-4.1\" },\n { id: \"openai/gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n { id: \"google/gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" },\n { id: \"google/gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n { id: \"meta-llama/llama-4-maverick\", name: \"Llama 4 Maverick\" },\n { id: \"meta-llama/llama-3.3-70b-instruct\", name: \"Llama 3.3 70B\" },\n { id: \"deepseek/deepseek-chat-v3-0324\", name: \"DeepSeek v3\" },\n { id: \"deepseek/deepseek-r1\", name: \"DeepSeek R1\" },\n { id: \"mistralai/mistral-large-2411\", name: \"Mistral Large 2\" },\n ],\n};\n\n/**\n * Get models for a specific provider from the static catalog, or empty array if unknown.\n *\n * Pure synchronous lookup — no network call. Use when the provider API is unavailable\n * or when a fast offline fallback is needed (e.g. in the UI before credentials are configured).\n *\n * @param provider - Provider name matching a key in {@link STATIC_MODELS}.\n * @returns Offline model list, or `[]` for unknown providers.\n * @docLink packages/bridge/api-reference#models\n */\nexport function getStaticModels(provider: string): ModelEntry[] {\n return STATIC_MODELS[provider] ?? [];\n}\n\n// ---------------------------------------------------------------------------\n// Registry-backed model identity (§2.4)\n// ---------------------------------------------------------------------------\n\n/** A registry in either of the two shapes consumers hold. */\nexport type ProviderRegistryView = AIProviderRegistry | MergedAIProviderRegistry;\n\n/**\n * Where a model selector is resolved. `registry` absent means no registry is\n * configured at all — every resolver here then returns `undefined` and the\n * caller keeps its pre-registry behaviour.\n */\nexport interface ModelRegistryContext {\n /** The merged registry (`mergeRegistries`), or a single layer. */\n registry?: ProviderRegistryView;\n /** `skaile.yaml` `roles`: role name → model selector (`smol` → `groq/llama-3.1-8b`). */\n roles?: Record<string, string>;\n /**\n * Entry the session already runs on. Scopes `model_map` lookups to it;\n * absent lets the selector pick in registry order.\n */\n providerId?: string;\n}\n\n/** The `llm`/`embed` entry registered under `id`, if any. */\nfunction llmEntry(registry: ProviderRegistryView, id: string): AIProviderLlmEntry | undefined {\n const entry = registryEntries(registry).find(([entryId]) => entryId === id)?.[1];\n if (!entry || (entry.kind !== \"llm\" && entry.kind !== \"embed\")) return undefined;\n return entry;\n}\n\n/**\n * The wire facts that decide which model-id vocabulary an entry enforces\n * (`modelIdSchemaForTarget`).\n *\n * `surface` and `base_url` fall back to the entry's preset: an entry written as\n * `{kind: llm, preset: anthropic}` carries neither of its own until the catalog\n * merge layer expands it, and validation must not depend on having been handed\n * a merged registry.\n */\nexport function modelIdTargetForEntry(entry: AIProviderLlmEntry): ModelIdTarget {\n const preset = entry.preset ? getProviderPreset(entry.preset) : undefined;\n const surface = entry.surface ?? preset?.surface;\n const base_url = resolveEntryBaseUrl(entry) ?? (preset ? presetBaseUrl(preset) : undefined);\n return {\n ...(surface ? { surface } : {}),\n ...(entryTransport(entry) ? { transport: entryTransport(entry) } : {}),\n ...(base_url ? { base_url } : {}),\n };\n}\n\n/** A manifest model preference resolved against the registry. */\nexport interface ResolvedManifestModel {\n /** Entry the preference routes to. */\n providerId: string;\n /** Logical id, after `@role` expansion and before `model_map`. */\n modelId?: string;\n /** Provider-side id — what goes on the wire: `model_map[modelId] ?? modelId`. */\n providerModelId?: string;\n /** Role name, when the preference was `@role`. */\n role?: string;\n /** The wire target `providerModelId` was checked against. */\n target: ModelIdTarget;\n /** Non-fatal notes: a dangling role, a disabled provider, a stale preset. */\n warnings: string[];\n /**\n * Set when `providerModelId` is not a legal id for `target` — in practice,\n * a non-Anthropic id on the first-party Anthropic Messages API. Never\n * thrown: the caller decides whether a manifest that names a model its\n * endpoint cannot serve is a warning or a failure.\n */\n error?: string;\n}\n\n/**\n * Resolve an agent manifest's `model.preferred` (or any single entry of\n * `model.fallback`) against the provider registry, then check the id it\n * produces against the selected entry's own vocabulary.\n *\n * The three selector forms — `@role`, `<providerId>/<modelId>`, bare id — are\n * resolved by `parseModelRef` (`@skaile/workspaces/core/provider-registry`),\n * which owns that grammar; this adds the per-surface id check on top.\n *\n * Returns `undefined` when there is nothing to resolve: no preference, or no\n * registry that can serve one.\n */\nexport function resolveManifestModel(\n preference: string | undefined,\n context: ModelRegistryContext = {},\n): ResolvedManifestModel | undefined {\n if (!preference || !context.registry) return undefined;\n const ref = parseModelRef(preference, context.registry, context.roles);\n if (!ref) return undefined;\n\n const entry = llmEntry(context.registry, ref.providerId);\n const target = entry ? modelIdTargetForEntry(entry) : {};\n const resolved: ResolvedManifestModel = {\n providerId: ref.providerId,\n ...(ref.modelId !== undefined ? { modelId: ref.modelId } : {}),\n ...(ref.providerModelId !== undefined ? { providerModelId: ref.providerModelId } : {}),\n ...(ref.role !== undefined ? { role: ref.role } : {}),\n target,\n warnings: [...ref.warnings],\n };\n if (ref.providerModelId === undefined) return resolved;\n\n const check = modelIdSchemaForTarget(target).safeParse(ref.providerModelId);\n if (!check.success) {\n resolved.error =\n `model \"${ref.providerModelId}\" is not valid for provider \"${ref.providerId}\" ` +\n `(surface ${target.surface ?? \"unknown\"}, transport ${target.transport ?? \"direct\"}` +\n `${target.base_url ? `, ${target.base_url}` : \"\"}): ` +\n (check.error.issues[0]?.message ?? \"invalid model id\");\n }\n return resolved;\n}\n\n/**\n * Resolve a model's capability facts — context window, thinking ceiling, tool\n * and image support — from the registry entry that serves it.\n *\n * `capabilities` is keyed by the *logical* id (the `model_map` key), so a\n * selector is resolved first and the record is read under both the logical and\n * the provider-side id. `fallback` is the caller's own per-model table (the\n * compaction window defaults, the platform's thinking limits); the entry wins\n * field by field, and a field the entry does not state falls through.\n *\n * Returns `undefined` when neither source knows anything about the model.\n */\nexport function resolveModelCapabilities(\n selector: string | undefined,\n context: ModelRegistryContext & {\n /** Per-model-id capability table consulted for fields the entry omits. */\n fallback?: Record<string, AIProviderCapabilities>;\n } = {},\n): AIProviderCapabilities | undefined {\n if (!selector) return undefined;\n const ref = context.registry\n ? parseModelRef(selector, context.registry, context.roles)\n : undefined;\n const entry = ref && context.registry ? llmEntry(context.registry, ref.providerId) : undefined;\n const ids = [ref?.modelId, ref?.providerModelId, selector].filter(\n (id): id is string => id !== undefined,\n );\n const entryCaps = ids.map((id) => entry?.capabilities?.[id]).find((caps) => caps !== undefined);\n const fallbackCaps = ids.map((id) => context.fallback?.[id]).find((caps) => caps !== undefined);\n\n const context_window = entryCaps?.context_window ?? fallbackCaps?.context_window;\n const thinking_max = entryCaps?.thinking_max ?? fallbackCaps?.thinking_max;\n const tools = entryCaps?.tools ?? fallbackCaps?.tools;\n const images = entryCaps?.images ?? fallbackCaps?.images;\n if (\n context_window === undefined &&\n thinking_max === undefined &&\n tools === undefined &&\n images === undefined\n ) {\n return undefined;\n }\n return {\n ...(context_window !== undefined ? { context_window } : {}),\n ...(thinking_max !== undefined ? { thinking_max } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(images !== undefined ? { images } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Model tier resolution (Flow v2 `run.model`)\n// ---------------------------------------------------------------------------\n\n/** Per-tier concrete model ids for one provider. */\nexport interface ModelTierOverrides {\n small?: string;\n default?: string;\n deep?: string;\n}\n\n/**\n * Tier→model mapping per provider, for deployments with **no provider\n * registry**. This is the point of the closed `small | default | deep`\n * vocabulary: an authored flow names an intent and the runtime owns which\n * concrete model serves it, so flows stay portable across model-lineup changes.\n *\n * It is no longer the source of truth for what a tier means. Where a registry\n * exists, a tier resolves through `roles` and the selected entry's `model_map`\n * (see {@link resolveModelTier}) — which works for every provider, names the\n * ids that deployment actually serves, and is editable without a release. This\n * table survives only for the pre-registry path, where nothing else can answer\n * the question; a vendor missing from it there is a `ModelTierResolutionError`,\n * not a guess.\n *\n * These are **direct provider-API ids**. A gateway transport (Bedrock, Vertex,\n * Azure) addresses the same models by different ids — Bedrock prefixes\n * `us.anthropic.`, for instance — and that translation belongs to whoever owns\n * the deployment, not here. {@link resolveModelTier} therefore consults this\n * table only on the direct API and demands an explicit override otherwise,\n * rather than handing a gateway an id it cannot serve.\n *\n * Every id here must also appear in {@link STATIC_MODELS} — a test asserts it,\n * so the two cannot drift into naming a model the catalog disowns. That check\n * proves internal consistency only; it cannot tell you an id is still current\n * with a provider's live lineup.\n *\n * Where a provider's lineup has no genuinely distinct model for a tier, the\n * entry deliberately repeats the neighbouring one. That is a reviewable\n * property of that lineup, unlike inheriting whatever model the session\n * happened to start with — which is how `small` could silently mean Opus.\n */\nexport const PROVIDER_MODEL_TIERS: Record<string, Required<ModelTierOverrides>> = {\n anthropic: {\n small: \"claude-haiku-4-5-20251001\",\n default: \"claude-sonnet-4-6\",\n deep: \"claude-opus-4-6\",\n },\n openai: { small: \"gpt-4o-mini\", default: \"gpt-4.1\", deep: \"o3\" },\n google: { small: \"gemini-2.0-flash\", default: \"gemini-2.5-flash\", deep: \"gemini-2.5-pro\" },\n mistral: {\n small: \"mistral-small-latest\",\n default: \"mistral-large-latest\",\n deep: \"mistral-large-latest\",\n },\n groq: {\n small: \"llama-3.1-8b-instant\",\n default: \"llama-3.3-70b-versatile\",\n deep: \"llama-3.3-70b-versatile\",\n },\n deepseek: { small: \"deepseek-chat\", default: \"deepseek-chat\", deep: \"deepseek-reasoner\" },\n xai: { small: \"grok-3-mini\", default: \"grok-3\", deep: \"grok-3\" },\n together: {\n small: \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n default: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n deep: \"meta-llama/Llama-3.3-70B-Instruct-Turbo\",\n },\n fireworks: {\n small: \"accounts/fireworks/models/llama-v3p3-70b-instruct\",\n default: \"accounts/fireworks/models/llama-v3p3-70b-instruct\",\n deep: \"accounts/fireworks/models/deepseek-v3\",\n },\n openrouter: {\n small: \"anthropic/claude-haiku-4.5\",\n default: \"anthropic/claude-sonnet-4.6\",\n deep: \"anthropic/claude-opus-4.6\",\n },\n};\n\n/** Raised when a tier names an intent this provider cannot serve. */\nexport class ModelTierResolutionError extends Error {\n constructor(\n readonly tier: \"small\" | \"deep\",\n readonly provider: string | undefined,\n ) {\n super(\n `cannot resolve model tier \"${tier}\" for provider \"${provider ?? \"(none)\"}\": no built-in mapping and no configured override. ` +\n `Configure a \"${tier}\" model override for this provider, or author the node as model: \"default\" to inherit the session model.`,\n );\n this.name = \"ModelTierResolutionError\";\n }\n}\n\n/**\n * Resolve a tier for a deployment that has a registry: through `roles[tier]`\n * first, then the selected entry's `model_map[tier]`.\n *\n * A `model_map` **miss is a miss**. `parseModelRef` falls back to the literal\n * selector when nothing maps it, and no provider serves a model called\n * `\"small\"` — so only a genuine mapping counts, and an unmapped tier is left\n * for the caller to fail on.\n */\nfunction resolveTierThroughRegistry(\n tier: keyof ModelTierOverrides,\n options: ModelRegistryContext,\n): string | undefined {\n const { registry, roles, providerId } = options;\n if (!registry) return undefined;\n if (roles?.[tier] !== undefined) {\n const viaRole = parseModelRef(`@${tier}`, registry, roles);\n if (viaRole?.providerModelId) return viaRole.providerModelId;\n }\n const ref = parseModelRef(providerId ? `${providerId}/${tier}` : tier, registry, roles);\n if (!ref?.modelId) return undefined;\n return llmEntry(registry, ref.providerId)?.model_map?.[ref.modelId];\n}\n\n/** Options {@link resolveModelTier} reads. */\nexport interface ResolveModelTierOptions extends ModelRegistryContext {\n /** Legacy provider id, keying {@link PROVIDER_MODEL_TIERS}. */\n provider?: string;\n /** Legacy cloud transport; anything but `default` disables the built-in table. */\n cloud?: string;\n /** Per-tier ids configured for this deployment. Wins over everything. */\n overrides?: ModelTierOverrides;\n}\n\n/**\n * Resolve a Flow v2 `run.model` tier to a concrete model id.\n *\n * Precedence, highest first: a configured `overrides` entry; the registry —\n * `roles[tier]`, then the selected entry's `model_map[tier]`, which is how a\n * tier is defined for *any* provider; and finally, **only when no registry is\n * configured**, {@link PROVIDER_MODEL_TIERS} on the direct provider API.\n *\n * `\"default\"` and an absent tier **inherit `sessionModel` first**. The session\n * model is the one id known to work for this deployment — it already carries\n * whatever provider, lineup and gateway translation the host configured — so\n * preferring any table over it would silently downgrade a configured model\n * and, on a gateway transport, substitute an id that provider cannot serve.\n *\n * `\"small\"` and `\"deep\"` never fall back to `sessionModel`; when nothing above\n * resolves them they throw {@link ModelTierResolutionError}. Inheriting there\n * would run an arbitrary model behind an author's explicit request for a cheap\n * or a strong one — a cost or quality surprise that shows up only in the bill\n * or the output. Failing names it at the node instead.\n *\n * Pure: no I/O, no environment reads.\n */\nexport function resolveModelTier(\n tier: \"small\" | \"default\" | \"deep\" | undefined,\n sessionModel: string | undefined,\n options: ResolveModelTierOptions = {},\n): string | undefined {\n // Built-in ids address the provider's own API; a gateway renames them. And a\n // registry answers the question properly, so the table is its fallback only.\n const directApi = !options.cloud || options.cloud === \"default\";\n const builtIn =\n !options.registry && directApi && options.provider\n ? PROVIDER_MODEL_TIERS[options.provider]\n : undefined;\n if (tier === \"small\" || tier === \"deep\") {\n const resolved =\n options.overrides?.[tier] ?? resolveTierThroughRegistry(tier, options) ?? builtIn?.[tier];\n if (!resolved) throw new ModelTierResolutionError(tier, options.provider);\n return resolved;\n }\n return (\n options.overrides?.default ??\n sessionModel ??\n resolveTierThroughRegistry(\"default\", options) ??\n builtIn?.default\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { MENTION_GROUPS } from './chunk-U4AA7MOV.js';
1
+ import { MENTION_GROUPS } from './chunk-QAH24E5U.js';
2
2
  import { createHash } from 'crypto';
3
3
 
4
4
  var MAX_DIGEST_ENTRIES = 100;
@@ -751,5 +751,5 @@ function isAgentAddressed(mentions) {
751
751
  }
752
752
 
753
753
  export { SessionDispatcher, isAddressedByKind, isAgentAddressed, isMentioned, parseMentions };
754
- //# sourceMappingURL=chunk-CNYIITSZ.js.map
755
- //# sourceMappingURL=chunk-CNYIITSZ.js.map
754
+ //# sourceMappingURL=chunk-R4OMDCGZ.js.map
755
+ //# sourceMappingURL=chunk-R4OMDCGZ.js.map