@skaile/workspaces 3.7.2 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +146 -0
- package/dist/app-sdk/index.js +1 -1
- package/dist/{asset-feeds-44M2GV2W.js → asset-feeds-7HM3HONM.js} +4 -4
- package/dist/{asset-feeds-44M2GV2W.js.map → asset-feeds-7HM3HONM.js.map} +1 -1
- package/dist/asset-manager/index.js +1 -1
- package/dist/bridge/drivers/claude-sdk.js +231 -24
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +1 -1
- package/dist/bridge/drivers/continue.js +2 -2
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +3 -3
- package/dist/bridge/drivers/goose.js +2 -2
- package/dist/bridge/drivers/omp.js +1 -1
- package/dist/bridge/drivers/opencode.js +2 -2
- package/dist/bridge/drivers/qwen.js +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/bridge/src/drivers/claude-sdk.d.ts +96 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/types.d.ts +103 -0
- package/dist/bridge/src/types.d.ts.map +1 -1
- package/dist/{chunk-IKNQW3AW.js → chunk-2GREL3OD.js} +3 -3
- package/dist/{chunk-IKNQW3AW.js.map → chunk-2GREL3OD.js.map} +1 -1
- package/dist/{chunk-Z7ILXHIT.js → chunk-2JW5SWIU.js} +6 -6
- package/dist/{chunk-Z7ILXHIT.js.map → chunk-2JW5SWIU.js.map} +1 -1
- package/dist/{chunk-J4I2YPGE.js → chunk-4WTC6BSV.js} +3 -3
- package/dist/{chunk-J4I2YPGE.js.map → chunk-4WTC6BSV.js.map} +1 -1
- package/dist/{chunk-JTBF4OB2.js → chunk-6GDVGAIZ.js} +587 -114
- package/dist/chunk-6GDVGAIZ.js.map +1 -0
- package/dist/{chunk-SID35UAK.js → chunk-7SHXLJQP.js} +3 -3
- package/dist/{chunk-SID35UAK.js.map → chunk-7SHXLJQP.js.map} +1 -1
- package/dist/{chunk-JF73DP5W.js → chunk-B7TA2XI7.js} +2 -2
- package/dist/{chunk-JF73DP5W.js.map → chunk-B7TA2XI7.js.map} +1 -1
- package/dist/{chunk-32TJ55W5.js → chunk-BGAAZMBK.js} +2 -2
- package/dist/chunk-BGAAZMBK.js.map +1 -0
- package/dist/{chunk-XCG63ZNJ.js → chunk-DGDELPOD.js} +3 -3
- package/dist/{chunk-XCG63ZNJ.js.map → chunk-DGDELPOD.js.map} +1 -1
- package/dist/{chunk-26L2B6P6.js → chunk-FUCYTGAE.js} +4 -4
- package/dist/chunk-FUCYTGAE.js.map +1 -0
- package/dist/{chunk-F7S6NDIW.js → chunk-IH2KJYAU.js} +142 -13
- package/dist/chunk-IH2KJYAU.js.map +1 -0
- package/dist/{chunk-VXITGB7G.js → chunk-KNPBMR2P.js} +3 -3
- package/dist/{chunk-VXITGB7G.js.map → chunk-KNPBMR2P.js.map} +1 -1
- package/dist/{chunk-BCXI27BH.js → chunk-NVYEK4FI.js} +3 -3
- package/dist/{chunk-BCXI27BH.js.map → chunk-NVYEK4FI.js.map} +1 -1
- package/dist/{chunk-D4VHBAJC.js → chunk-O3LEV6KB.js} +4 -4
- package/dist/{chunk-D4VHBAJC.js.map → chunk-O3LEV6KB.js.map} +1 -1
- package/dist/{chunk-2GA2UGQI.js → chunk-OZZCPTOG.js} +6 -6
- package/dist/{chunk-2GA2UGQI.js.map → chunk-OZZCPTOG.js.map} +1 -1
- package/dist/{chunk-NXHRSUKL.js → chunk-PRUCNSBI.js} +4 -4
- package/dist/{chunk-NXHRSUKL.js.map → chunk-PRUCNSBI.js.map} +1 -1
- package/dist/{chunk-J7SEUNPD.js → chunk-QVQH6GV2.js} +2 -2
- package/dist/{chunk-J7SEUNPD.js.map → chunk-QVQH6GV2.js.map} +1 -1
- package/dist/{chunk-I5TSXDTD.js → chunk-RVXBOKHK.js} +3 -3
- package/dist/{chunk-I5TSXDTD.js.map → chunk-RVXBOKHK.js.map} +1 -1
- package/dist/cli/index.js +30 -30
- package/dist/connectors/index.js +3 -3
- package/dist/connectors/src/connector-manager.d.ts +34 -2
- package/dist/connectors/src/connector-manager.d.ts.map +1 -1
- package/dist/connectors/src/connector-prompt.d.ts.map +1 -1
- package/dist/connectors/src/connector-types.d.ts +25 -0
- package/dist/connectors/src/connector-types.d.ts.map +1 -1
- package/dist/connectors/src/credential-helper-script.d.ts +48 -0
- package/dist/connectors/src/credential-helper-script.d.ts.map +1 -1
- package/dist/connectors/src/index.d.ts +3 -3
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/connectors/src/managed-gitconfig.d.ts +80 -0
- package/dist/connectors/src/managed-gitconfig.d.ts.map +1 -1
- package/dist/{connectors-DY7UBBV5.js → connectors-2OHRZDJZ.js} +3 -3
- package/dist/{connectors-DY7UBBV5.js.map → connectors-2OHRZDJZ.js.map} +1 -1
- package/dist/{ensure-sources-QRURV6JB.js → ensure-sources-42LTJ5QI.js} +4 -4
- package/dist/{ensure-sources-QRURV6JB.js.map → ensure-sources-42LTJ5QI.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +3 -3
- package/dist/factory-assets/connectors/deploy.js +3 -3
- package/dist/factory-assets/connectors/devserver.js +3 -3
- package/dist/factory-assets/connectors/flow/adapter.js +3 -3
- package/dist/factory-assets/connectors/flow/run-flow.js +4 -4
- package/dist/factory-assets/connectors/flow.js +3 -3
- package/dist/factory-assets/connectors/git/driver.d.ts +64 -1
- package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +3 -3
- package/dist/factory-assets/connectors/gmail.js +3 -3
- package/dist/factory-assets/connectors/googledrive.js +3 -3
- package/dist/factory-assets/connectors/local.js +3 -3
- package/dist/factory-assets/connectors/mattermost.js +3 -3
- package/dist/factory-assets/connectors/memory.js +3 -3
- package/dist/factory-assets/connectors/minio.js +3 -3
- package/dist/factory-assets/connectors/postgres.js +3 -3
- package/dist/factory-assets/connectors/s3.js +3 -3
- package/dist/factory-assets/connectors/sharepoint.js +3 -3
- package/dist/factory-assets/connectors/sqlite.js +3 -3
- package/dist/factory-assets/connectors/static-server.js +3 -3
- package/dist/factory-assets/connectors/tunnel.js +3 -3
- package/dist/factory-assets/connectors/webdav.js +3 -3
- package/dist/factory-assets/connectors/xstate-store.js +3 -3
- package/dist/factory-assets/connectors/xstate.js +3 -3
- package/dist/{helpers-TLTVVZRR.js → helpers-BP7FX6CO.js} +4 -4
- package/dist/{helpers-TLTVVZRR.js.map → helpers-BP7FX6CO.js.map} +1 -1
- package/dist/{library-publish-6HXFLOXC.js → library-publish-X5Z32WJY.js} +6 -6
- package/dist/{library-publish-6HXFLOXC.js.map → library-publish-X5Z32WJY.js.map} +1 -1
- package/dist/{open-library-FMVJICL5.js → open-library-PHUMBYHP.js} +5 -5
- package/dist/{open-library-FMVJICL5.js.map → open-library-PHUMBYHP.js.map} +1 -1
- package/dist/{project-BG3N4I3V.js → project-HAMCXPNE.js} +5 -5
- package/dist/{project-BG3N4I3V.js.map → project-HAMCXPNE.js.map} +1 -1
- package/dist/runner/index.js +7 -7
- package/dist/runner/src/ai-provider-switch.d.ts +95 -0
- package/dist/runner/src/ai-provider-switch.d.ts.map +1 -0
- package/dist/runner/src/credential-rotated.d.ts +23 -4
- package/dist/runner/src/credential-rotated.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-builder.d.ts +19 -0
- package/dist/runner/src/session-builder.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/bridge.js +2 -2
- package/dist/sdk/index.js +7 -7
- package/dist/sdk/runner.js +7 -7
- package/dist/sdk/session.js +2 -2
- package/dist/sdk/types.js +1 -1
- package/dist/session/index.js +2 -2
- package/dist/{setup-O2N6PA7I.js → setup-IOOGR3EL.js} +4 -4
- package/dist/{setup-O2N6PA7I.js.map → setup-IOOGR3EL.js.map} +1 -1
- package/dist/{source-JDIBJZ3X.js → source-772GLNM6.js} +6 -6
- package/dist/{source-JDIBJZ3X.js.map → source-772GLNM6.js.map} +1 -1
- package/dist/{source-manifest-publish-567T25M6.js → source-manifest-publish-LAUGDQ5G.js} +7 -7
- package/dist/{source-manifest-publish-567T25M6.js.map → source-manifest-publish-LAUGDQ5G.js.map} +1 -1
- package/dist/tui/index.js +7 -7
- package/dist/types/index.js +1 -1
- package/dist/types/src/events.d.ts +34 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/lifecycle.d.ts +13 -0
- package/dist/types/src/lifecycle.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +22 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +2 -2
- package/dist/workspace-plugin/adapters/mcp.js.map +1 -1
- package/dist/workspace-plugin/adapters/omp.js +8 -8
- package/dist/workspace-plugin/adapters/omp.js.map +1 -1
- package/dist/workspace-plugin/index.js +1 -1
- package/dist/workspace-plugin/src/adapters/mcp.d.ts.map +1 -1
- package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
- package/dist/workspace-plugin/src/tools/connectors.d.ts +7 -3
- package/dist/workspace-plugin/src/tools/connectors.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-26L2B6P6.js.map +0 -1
- package/dist/chunk-32TJ55W5.js.map +0 -1
- package/dist/chunk-F7S6NDIW.js.map +0 -1
- package/dist/chunk-JTBF4OB2.js.map +0 -1
|
@@ -307,5 +307,5 @@ async function listModelsForDriver(driverId, apiKeys) {
|
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
export { AgentDriver, BUILTIN_DRIVER_CATALOG, DRIVER_CATALOG, createDriver, getBridgeLogger, listDrivers, listModelsForDriver, registerBuiltinDrivers };
|
|
310
|
-
//# sourceMappingURL=chunk-
|
|
311
|
-
//# sourceMappingURL=chunk-
|
|
310
|
+
//# sourceMappingURL=chunk-BGAAZMBK.js.map
|
|
311
|
+
//# sourceMappingURL=chunk-BGAAZMBK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/types.ts","../bridge/src/registry.ts"],"names":[],"mappings":"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","file":"chunk-BGAAZMBK.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each driver creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given driver subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each driver calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Driver id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n Capability,\n CredentialMint,\n FlowExecution,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Test-only hook injected by the runner so a no-LLM driver (the echo driver's\n * scripted-flow mode) can read flow state and drive flow-adapter mutations\n * without an SDK/MCP round-trip. The runner wires this in `createActiveFlow`\n * from the active FlowAdapter + handle.\n *\n * This is an internal runner↔driver interface — NOT part of any wire\n * protocol or flow contract. Production drivers ignore it.\n *\n * @see packages/bridge/drivers/echo — scripted-flow mode\n * @since 3.6.0\n */\nexport interface FlowTestDriverHook {\n /** Current flow execution snapshot, or `null` when no flow is active. */\n getState(): FlowExecution | null;\n /**\n * Execute a flow-adapter operation (`start_node`, `request_approval`,\n * `complete_node`, `request_input`, `skip_node`, `fail_node`, …). Returns\n * the adapter's JSON string result (or rejects on an illegal transition).\n */\n execute(op: string, args: Record<string, unknown>): Promise<string>;\n /**\n * Node IDs marked as mandatory approval gates. The scripted policy resolves\n * `auto` to `request_approval` for these even in autonomous mode, so hosts\n * can drive a mandatory gate deterministically. Optional — absent hooks\n * behave as if no node is mandatory.\n */\n mandatoryGates?(): string[];\n}\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so drivers can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the driver via\n * `AgentConfig.capabilities`; the driver routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Drivers that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /** Validate input + dispatch through the registry. Logging is wired by the registry. */\n invoke(name: string, input: unknown): Promise<unknown>;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent driver backend.\n *\n * Returned by {@link listDrivers} and exposed on every {@link AgentDriver} instance\n * via `driverInfo`.\n *\n * @docLink packages/bridge/concepts#driver-info\n */\nexport interface DriverInfo {\n /** Stable machine identifier used to look up the driver in the registry (e.g. `\"omp\"`, `\"claude-sdk\"`). */\n id: string;\n /** Human-readable display name shown in UIs and logs. */\n name: string;\n /** `true` when the driver can target any LLM provider; `false` for Anthropic-only drivers. */\n modelAgnostic: boolean;\n /**\n * `true` when the driver supports mid-stream abort via `abort()` without killing the process.\n * Drivers that return `false` can only be stopped via `kill()`.\n */\n supportsInBandAbort: boolean;\n}\n\n/**\n * Codex-specific tuning options passed through `DriverOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex driver and have no effect on other drivers.\n * @docLink packages/bridge/concepts#codex-driver-options\n */\nexport interface CodexDriverOptions {\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * Driver-specific configuration bag.\n *\n * Fields are keyed by driver ID so that callers can pass driver-specific options\n * through the common {@link AgentConfig} without breaking other drivers.\n *\n * @docLink packages/bridge/concepts#driver-options\n */\nexport interface DriverOptions {\n /** Codex-specific options. Ignored by all other drivers. */\n codex?: CodexDriverOptions;\n}\n\n/**\n * What the driver tells the host about a turn blocked by an upstream usage\n * limit. Everything but `configId` is best-effort: the SDK reports the limit\n * window only on its structured telemetry, not on the error result text.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitBlockedContext {\n /** The AI provider config the blocked turn ran on (`\"\"` when unmediated). */\n configId: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n}\n\n/**\n * The host's verdict on a limit-blocked turn. `switched: true` is a promise\n * that a different seat's credential is already on disk — the driver acts on it\n * by respawning the CLI and replaying the prompt, so returning it without\n * having rewritten the credential file would just replay onto the dead seat.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitFailoverResult {\n /** Whether the session was repointed at a different AI provider config. */\n switched: boolean;\n /** The config id now in effect. Informational — used for logs. */\n configId?: string;\n /**\n * Why no switch happened: `same-config`, `standalone`,\n * `platform-omitted-config-id` (the mint succeeded but named no seat, so a\n * re-resolution is indistinguishable from none), or a `CredentialMint`\n * failure code. Diagnostic only — the driver branches on `switched`.\n */\n reason?: string;\n}\n\n/**\n * One observed AI-provider rejection, reported to the host for per-seat health\n * attribution. Fire-and-forget — see {@link AgentConfig.onProviderResponse}.\n *\n * @category Configuration\n * @since 3.9.0\n */\nexport interface ProviderResponseObservation {\n /** 401 — the credential was rejected. 429 — an upstream rate/session limit. */\n status: 401 | 429;\n /** The AI provider config the observation is attributed 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}\n\n/**\n * Configuration passed to a driver when it is created via {@link createDriver}.\n *\n * All fields are shared across drivers; driver-specific behaviour is documented\n * per field. Fields that are silently ignored by a driver are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * Combined with `model` as `provider/model` for omp's `--model` flag.\n * Ignored by claude-sdk (always Anthropic).\n */\n provider?: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n * For omp: passed as `--model [provider/]model`.\n * For claude-sdk: passed as the `model` query option.\n */\n model?: string;\n /**\n * Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Drivers inject the relevant key into the environment or SDK options.\n */\n apiKeys?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process environment.\n * For omp: merged with `process.env` before spawn. For claude-sdk: accessed\n * via `env.ANTHROPIC_API_KEY` as an alternative to `apiKeys.anthropic`.\n */\n env?: Record<string, string>;\n /**\n * AI cloud transport for claude-sdk: `default | bedrock | vertex | azure |\n * gateway`. Absent (or `\"default\"`) preserves today's behavior — the\n * provider's native API. Typed as `string` for forward compatibility; the\n * driver falls back to `default` on unrecognized values (with a warning).\n * Ignored by all other drivers.\n *\n * @since 1.3.0\n */\n cloud?: string;\n /**\n * Non-secret transport settings for the selected `cloud` (camelCase — the\n * skaile.yaml `cloud_config` wire shape is snake_case and converted once at\n * the settings/serve boundary). Ignored when `cloud` is absent/default.\n *\n * @since 1.3.0\n */\n cloudConfig?: { region?: string; projectId?: string; resource?: string; baseUrl?: string };\n /**\n * Resolved credential env bundle for the selected `cloud` — runner-provided\n * (platform `session_init` secrets, or runner-materialized file paths such\n * as the Vertex service-account file). Values are secrets: never logged.\n *\n * @since 1.3.0\n */\n cloudSecrets?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp driver) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp driver) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other drivers) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level for Claude models. */\n effort?: \"low\" | \"medium\" | \"high\" | \"max\";\n /** Driver-specific configuration bag. */\n driverOptions?: DriverOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the driver uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this driver. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The driver itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the driver when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The driver inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * driver re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The driver surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the driver\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the driver throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the driver means every consumer of\n * `driver.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n /**\n * Optional callback invoked by the driver when a turn is blocked by an\n * upstream **usage limit** rather than a bad credential — the subscription\n * five-hour / seven-day ceiling, or any `rate_limit` the classifier\n * recognises. Called at most once per logical turn, and only after the\n * blocked attempt has already failed, so it never runs mid-turn.\n *\n * The runner implements it by asking the platform to re-resolve the seat:\n *\n * - `switched: true` — the session was repointed at a DIFFERENT AI\n * provider config and `.credentials.json` was rewritten. The driver\n * drops its query (forcing a fresh CLI spawn, which is what clears a\n * resident CLI's cached \"blocked until <reset>\" state — a hot file\n * rewrite alone does not) and replays the prompt once.\n * - `switched: false` — no alternative seat was available. The driver\n * surfaces the original limit error unchanged.\n *\n * Left unset by standalone runners (CLI / forge / Claude plugin): there is\n * no platform mediator to re-resolve a seat, so the limit error surfaces\n * exactly as it does today.\n *\n * Companion to {@link onAuthError}: that one covers 401s, this one covers\n * the rejection path, which previously reached no failover at all\n * (skaile-ai/workspaces#567, skaile-ai/platform#2976).\n *\n * @since 3.9.0\n */\n onLimitBlocked?: (ctx: LimitBlockedContext) => Promise<LimitFailoverResult>;\n /**\n * Optional fire-and-forget hook invoked when the driver observes a 401 or a\n * 429 / subscription-limit rejection from the AI provider. The runner\n * forwards it to the platform as a `provider_response_seen` event so the\n * owning `AIProviderConfig`'s live health counters can be bumped — the cron\n * health probe only samples auth, never capacity\n * (skaile-ai/workspaces#368, skaile-ai/platform#3539).\n *\n * Never awaited and never retried; the driver swallows a throwing\n * implementation so telemetry can never fail a turn.\n *\n * @since 3.9.0\n */\n onProviderResponse?: (observation: ProviderResponseObservation) => void;\n /**\n * Test-only flow driver hook. When present, the echo driver's scripted-flow\n * mode uses it to advance flow nodes deterministically (no LLM). The runner\n * injects it in `createActiveFlow`; every other driver ignores it.\n *\n * @see FlowTestDriverHook\n * @since 3.6.0\n */\n flowTestDriver?: FlowTestDriverHook;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is driver-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\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 payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a driver on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `driver.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows drivers to attach\n * driver-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the driver tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n errors?: string[];\n [k: string]: any;\n }\n | { type: \"error\"; error: string; detail?: AgentError; fatal?: boolean; [k: string]: any }\n | { type: \"tool_call\"; name?: string; tool?: { name: string }; [k: string]: any }\n | { type: \"tool_execution_end\"; toolName?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; driverSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — driver-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason: \"signature_mismatch\" | \"model_mismatch\" | \"jsonl_lost\" | \"jsonl_poisoned\";\n [k: string]: any;\n };\n\n/**\n * Abstract base class for agent driver backends.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All drivers emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * driver-private.\n *\n * @example\n * ```ts\n * const driver = createDriver('omp', config);\n * driver.on('agent-event', (event) => console.log(event.type));\n * await driver.start();\n * await driver.prompt('Refactor the auth module');\n * driver.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-driver\n */\nexport abstract class AgentDriver extends EventEmitter {\n /** Static metadata describing this driver's capabilities. */\n abstract readonly driverInfo: DriverInfo;\n\n /**\n * Initialises the driver backend — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the backend is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running driver is a no-op.\n *\n * @throws {Error} When the backend binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the driver is not running or the underlying backend reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The driver remains usable after `abort()`.\n *\n * @remarks Only meaningful when `driverInfo.supportsInBandAbort` is `true`.\n * For other drivers, prefer `kill()` followed by creating a new driver instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent backend immediately (SIGTERM for subprocess drivers,\n * `close()` for in-process drivers). The driver instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** `true` when the backend is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in drivers that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Interactive questions (AskUserQuestion) ──────────────────────────────\n\n /**\n * `true` while the driver is paused on an interactive question and waiting\n * for the user's answer rather than a new prompt. The runner routes a\n * `reply` command to {@link answerQuestion} instead of {@link prompt} when\n * this returns `true`. Drivers without interactive-question support return\n * `false` (the default), so a `reply` falls back to `prompt`.\n */\n hasPendingQuestion(): boolean {\n return false;\n }\n\n /**\n * Deliver the user's answer to the question the driver is currently paused\n * on. This resumes the in-flight turn — it does NOT start a new one. When a\n * single tool call asks several questions, the driver resolves the underlying\n * call only once every sub-question has an answer.\n *\n * @param answer - The user's reply text (an option label, free text, or for\n * multi-select a comma-joined list).\n * @param question - The sub-question this answers, verbatim from the\n * `question` event that asked it. Supply it whenever the host lets the user\n * answer out of order — without it the answer fills the next unanswered\n * slot in order, which silently mismatches a non-sequential reply.\n * @returns `true` when the answer was consumed by a pending question; `false`\n * when no question was pending (caller should treat the reply as a prompt).\n */\n answerQuestion(answer: string, question?: string): boolean {\n void answer;\n void question;\n return false;\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update driver configuration. The new values take effect on the next\n * prompt() call. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Subclasses that store config locally should override this to apply the\n * patch to their own config field. The base implementation is a no-op.\n */\n reconfigure(patch: Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>): void {\n // No-op — subclasses override to apply to their own config.\n void patch;\n }\n\n /**\n * Returns the model identifier currently configured on this driver.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. driver doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * drivers can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Prompt tokens occupying the context window as of the most recent API\n * request — i.e. how full the context actually is right now.\n *\n * Deliberately NOT the same number as {@link getTokenUsage}, whose usage is\n * cumulative over every API call in the turn and therefore overstates the\n * context by 10-40x on any multi-tool turn. Callers measuring context fill\n * (compaction thresholds) must prefer this; callers billing a turn\n * (usage ledgers, the `finished` event) must keep using `getTokenUsage()`.\n *\n * Returns `null` both when the driver cannot report a per-call figure at all\n * and when it can but has no reading yet. Falling back to `getTokenUsage()`\n * is safe in either case only because a driver clears the two in lockstep: no\n * reading means no API call landed, so there is no cumulative usage to\n * overstate. A driver implementing this must preserve that invariant.\n */\n getContextTokens(): number | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * Returns the list of models available to this driver without starting a session.\n * Drivers that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The driver remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this driver.\n * Called by the runner after creating the driver but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the driver base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the driver registry.\n *\n * @param config - Configuration for the new driver instance.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @docLink packages/bridge/concepts#driver-factory\n */\nexport type DriverFactory = (config: AgentConfig) => AgentDriver;\n","import type { DriverContext } from \"@skaile/workspaces/plugin-registry\";\nimport { type PluginRegistry, pluginRegistry } from \"@skaile/workspaces/plugin-registry\";\nimport type { ModelEntry } from \"./models.js\";\nimport type { AgentConfig, AgentDriver, DriverInfo } from \"./types.js\";\n\n// Build-time backend gating. `bun build --compile --define:__INCLUDE_*__=...`\n// folds these to literal booleans so an excluded backend's driver module and\n// its SDK are dead-code-stripped from the binary. Under tsup / vitest / bun\n// run-on-source no `--define` runs and the `typeof` guard defaults to `true` —\n// every backend is available (the SDKs stay optional peers).\ndeclare const __INCLUDE_CLAUDE_SDK__: boolean;\ndeclare const __INCLUDE_CODEX__: boolean;\nconst INCLUDE_CLAUDE_SDK =\n typeof __INCLUDE_CLAUDE_SDK__ === \"undefined\" ? true : __INCLUDE_CLAUDE_SDK__;\nconst INCLUDE_CODEX = typeof __INCLUDE_CODEX__ === \"undefined\" ? true : __INCLUDE_CODEX__;\n\n/**\n * Static capability metadata for every built-in backend.\n *\n * Pure data — this object imports no driver module and references no backend\n * SDK. {@link listDrivers} returns it (merged with any third-party drivers)\n * so selection UIs can enumerate every backend without loading a single\n * driver module. The matching driver module's `DriverTarget` is registered\n * into the plugin registry by {@link registerBuiltinDrivers}.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const BUILTIN_DRIVER_CATALOG: Record<string, DriverInfo> = {\n omp: {\n id: \"omp\",\n name: \"omp (oh-my-pi)\",\n modelAgnostic: true,\n supportsInBandAbort: true,\n },\n \"claude-sdk\": {\n id: \"claude-sdk\",\n name: \"Claude Agent SDK\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n codex: {\n id: \"codex\",\n name: \"OpenAI Codex\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n echo: {\n id: \"echo\",\n name: \"Echo (E2E mock)\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n gemini: {\n id: \"gemini\",\n name: \"Gemini CLI\",\n modelAgnostic: false,\n supportsInBandAbort: false,\n },\n qwen: {\n id: \"qwen\",\n name: \"Qwen Code\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n opencode: {\n id: \"opencode\",\n name: \"OpenCode\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n goose: {\n id: \"goose\",\n name: \"Goose\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n continue: {\n id: \"continue\",\n name: \"Continue CLI\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n};\n\n/**\n * Back-compat alias for {@link BUILTIN_DRIVER_CATALOG}. Consumers and tests that\n * predate the plugin-registry refactor still import `DRIVER_CATALOG`.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const DRIVER_CATALOG = BUILTIN_DRIVER_CATALOG;\n\nlet _driversRegistered = false;\n\n/**\n * Register every built-in driver's `DriverTarget` into the plugin registry.\n *\n * This is the single id → module map in bridge core. Every specifier is a\n * literal string so `bun --compile` can statically bundle the driver module\n * (and, transitively, its SDK). The in-process-SDK backends (`claude-sdk`,\n * `codex`) are wrapped in build-constant guards so an excluded backend's\n * `await import` folds to dead code in the compiled binary. `omp` and `echo`\n * carry no SDK weight and are always available.\n *\n * **Static import discipline.** Every `import()` specifier below must be a\n * string literal — never aliased through a variable. Indirection defeats\n * `bun --compile`'s static analysis and silently drops the module from the\n * binary.\n *\n * Idempotent: guarded by a module flag so a second call is a no-op (a duplicate\n * `register` would otherwise throw `RegistrationError`).\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function registerBuiltinDrivers(\n registry: PluginRegistry = pluginRegistry,\n): Promise<void> {\n if (registry === pluginRegistry && _driversRegistered) return;\n\n if (!registry.get(\"driver\", \"omp\")) {\n const m = await import(\"@skaile/workspaces/drivers/omp\");\n registry.register(\"driver\", m.ompDriverTarget);\n }\n if (!registry.get(\"driver\", \"echo\")) {\n const m = await import(\"@skaile/workspaces/drivers/echo\");\n registry.register(\"driver\", m.echoDriverTarget);\n }\n if (INCLUDE_CLAUDE_SDK && !registry.get(\"driver\", \"claude-sdk\")) {\n const m = await import(\"@skaile/workspaces/drivers/claude-sdk\");\n registry.register(\"driver\", m.claudeSdkDriverTarget);\n }\n if (INCLUDE_CODEX && !registry.get(\"driver\", \"codex\")) {\n const m = await import(\"@skaile/workspaces/drivers/codex\");\n registry.register(\"driver\", m.codexDriverTarget);\n }\n // Subprocess CLI backends spawn an external binary the user installs\n // separately — no bundled SDK to dead-code-strip, so (like omp/echo) they\n // carry no build constant and are always registered.\n if (!registry.get(\"driver\", \"gemini\")) {\n const m = await import(\"@skaile/workspaces/drivers/gemini\");\n registry.register(\"driver\", m.geminiDriverTarget);\n }\n if (!registry.get(\"driver\", \"qwen\")) {\n const m = await import(\"@skaile/workspaces/drivers/qwen\");\n registry.register(\"driver\", m.qwenDriverTarget);\n }\n if (!registry.get(\"driver\", \"opencode\")) {\n const m = await import(\"@skaile/workspaces/drivers/opencode\");\n registry.register(\"driver\", m.opencodeDriverTarget);\n }\n if (!registry.get(\"driver\", \"goose\")) {\n const m = await import(\"@skaile/workspaces/drivers/goose\");\n registry.register(\"driver\", m.gooseDriverTarget);\n }\n if (!registry.get(\"driver\", \"continue\")) {\n const m = await import(\"@skaile/workspaces/drivers/continue\");\n registry.register(\"driver\", m.continueDriverTarget);\n }\n\n if (registry === pluginRegistry) _driversRegistered = true;\n}\n\n/**\n * Creates a new driver instance for the given backend id.\n *\n * Ensures the built-in driver targets are registered (idempotent), then looks\n * up the target in the plugin registry and calls its `create()`. The returned\n * driver has not been started yet — call `driver.start()` before sending\n * prompts.\n *\n * @param id - Registered driver identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @param config - Configuration forwarded to the driver constructor.\n * @param ctx - Optional driver context (logger / abort signal). Defaults to `{}`.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function createDriver(\n id: string,\n config: AgentConfig,\n ctx?: DriverContext,\n): Promise<AgentDriver> {\n const target = await resolveDriverTarget(id);\n return target.create(config, ctx ?? {});\n}\n\n/**\n * Resolve a registered driver target by id, ensuring the built-ins are\n * registered first. Throws the canonical \"not bundled\" / \"unknown driver\"\n * errors so every caller (`createDriver`, `listModelsForDriver`) reports an\n * unrecognized id the same way instead of silently degrading.\n *\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n */\nasync function resolveDriverTarget(id: string) {\n await registerBuiltinDrivers();\n const target = pluginRegistry.get(\"driver\", id);\n if (!target) {\n if (id in BUILTIN_DRIVER_CATALOG) {\n throw new Error(`Agent driver \"${id}\" is not bundled in this build.`);\n }\n throw new Error(\n `Unknown agent driver: \"${id}\". Available: ${listDrivers()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n return target;\n}\n\n/**\n * Returns the capability metadata for every available driver.\n *\n * Enumerates every built-in backend from {@link BUILTIN_DRIVER_CATALOG} without\n * loading a single driver module or backend SDK, then merges in any third-party\n * driver targets registered into the plugin registry that are not already in\n * the catalog. Use this to populate driver selection UIs.\n *\n * @returns Array of {@link DriverInfo} objects, one per available driver.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function listDrivers(): DriverInfo[] {\n const merged = new Map<string, DriverInfo>();\n for (const info of Object.values(BUILTIN_DRIVER_CATALOG)) {\n merged.set(info.id, info);\n }\n for (const meta of pluginRegistry.list(\"driver\")) {\n if (!merged.has(meta.id)) {\n // Third-party drivers carry no DriverInfo row; read the capability flags\n // off the registered target (defaulting to conservative false) so a\n // model-agnostic / in-band-abort backend can still advertise them.\n const target = pluginRegistry.get(\"driver\", meta.id);\n merged.set(meta.id, {\n id: meta.id,\n name: meta.displayName,\n modelAgnostic: target?.modelAgnostic ?? false,\n supportsInBandAbort: target?.supportsInBandAbort ?? false,\n });\n }\n }\n return [...merged.values()];\n}\n\n/**\n * List models available to a specific driver without starting a full agent session.\n *\n * Ensures the built-in driver targets are registered (idempotent), then\n * delegates to the target's optional `listModels()`. API keys are forwarded so\n * drivers can authenticate against provider REST APIs if needed. Throws on an\n * unknown / not-bundled id (same contract as {@link createDriver}); returns `[]`\n * only when the target exists but exposes no `listModels`.\n *\n * @param driverId - Registered driver id (e.g. `\"omp\"`, `\"claude-sdk\"`, `\"codex\"`).\n * @param apiKeys - Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Pass `settings.apiKeys ?? {}` from forge-assistant's resolved settings.\n * @throws {Error} When `driverId` is unknown or excluded from this build.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function listModelsForDriver(\n driverId: string,\n apiKeys: Record<string, string>,\n): Promise<ModelEntry[]> {\n const target = await resolveDriverTarget(driverId);\n return (await target.listModels?.(apiKeys)) ?? [];\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getStoreConfig, getStoreToken, storeFetch } from './chunk-WAFHQDLK.js';
|
|
2
|
-
import { S, logErr, logWarn, logOk, logInfo } from './chunk-
|
|
2
|
+
import { S, logErr, logWarn, logOk, logInfo } from './chunk-4WTC6BSV.js';
|
|
3
3
|
|
|
4
4
|
// cli/src/store-publisher.ts
|
|
5
5
|
function makeHttpPublisherClient(config = getStoreConfig(), timeoutMs = 2e4) {
|
|
@@ -154,5 +154,5 @@ async function publishToStore(opts) {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
export { bareName, formatNamespaceAvailability, makeHttpPublisherClient, preflightNamespace, publishToStore, refFor };
|
|
157
|
-
//# sourceMappingURL=chunk-
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
157
|
+
//# sourceMappingURL=chunk-DGDELPOD.js.map
|
|
158
|
+
//# sourceMappingURL=chunk-DGDELPOD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/src/store-publisher.ts","../cli/src/commands/publish-core.ts"],"names":[],"mappings":"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","file":"chunk-XCG63ZNJ.js","sourcesContent":["/**\n * Typed REST client for the AI Asset Store **publisher** surface — the\n * curator-publish flow (`skaile source manifest publish` / `yank`). Thin\n * wrappers over {@link storeFetch}; every method maps 1:1 to an `/api/v1/…`\n * endpoint. The {@link PublisherClient} interface is injectable so the\n * orchestration in `commands/source-manifest-publish.ts` can be unit-tested\n * against a fake without a live store.\n *\n * @docLink cli/dev-guide#store-publisher\n */\n\nimport { getStoreConfig, getStoreToken, type StoreConfig, storeFetch } from \"./store-client.ts\";\n\n/**\n * The publisher REST surface used by the curator-publish flow. Kept minimal —\n * only the endpoints `runPublish` / `runYank` actually call. Response shapes\n * are narrowed to the fields the orchestration reads (the server returns more).\n */\nexport interface PublisherClient {\n /**\n * Identity of the caller. `username` is the Keycloak login (personal-tier\n * namespace); `githubLogin` is the verified GitHub handle when connected —\n * the namespace to publish under when it differs from the login.\n */\n me(): Promise<{ username: string; githubLogin?: string | null }>;\n /** Register (or re-register) a source; returns the created/existing row id. */\n sourcesAdd(body: {\n url: string;\n ref: string;\n sidecarUrl?: string;\n sidecarRef?: string;\n /**\n * Target publisher namespace (the manifest's `publisher`). When it differs\n * from the caller's login username, the store resolves the CLAIMED Publisher\n * for it (the store must already have the claim). Omitted → the store\n * defaults to `@<username>` (personal).\n */\n namespace?: string;\n }): Promise<{ id: string }>;\n /** List sources — used to recover an id when `sourcesAdd` rejects a dup url. */\n sourcesList(): Promise<Array<{ id: string; url: string }>>;\n /** Kick off a source sync; returns the async job id to poll. */\n sourceSync(id: string): Promise<{ jobId: string }>;\n /** Poll a job's terminal status + per-item results. */\n jobGet(\n jobId: string,\n ): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }>;\n /** Discovered publishable candidates for a synced source. */\n sourceCandidates(id: string): Promise<\n Array<{\n id: string;\n name: string;\n version: string;\n kind: string;\n published: boolean;\n assetRoot: string;\n }>\n >;\n /** Per-asset preview — the discovered file set + resolved candidate metadata. */\n assetPreview(id: string): Promise<{\n discoveredFiles: string[];\n candidate: { name: string; version: string; kind: string; publisherNamespace: string };\n }>;\n /**\n * Publish one asset. `dryRun` returns the would-be `{ manifest }` without\n * launching a job; the normal path returns `{ jobId }`.\n */\n assetPublish(\n id: string,\n body: { ref: string; files: string[] },\n dryRun?: boolean,\n ): Promise<{ jobId?: string; manifest?: unknown }>;\n /** Retract a published asset. Response body is ignored. */\n assetUnpublish(id: string): Promise<unknown>;\n /**\n * Read-only \"can I publish under `@<ns>` right now, and if not, what's the\n * path?\" probe. Backs the `publish --dry-run` namespace status line; its\n * `message` is store-authored and meant to be surfaced verbatim.\n */\n namespaceAvailability(ns: string): Promise<{\n namespace: string;\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n claimMethod?: string;\n message: string;\n }>;\n}\n\n/**\n * Construct the real HTTP-backed {@link PublisherClient}. Every call carries a\n * longer timeout than the default store client because publish/sync trigger\n * server-side clone work.\n *\n * @param config - Store connection config; defaults to {@link getStoreConfig}.\n * @param timeoutMs - Per-request abort timeout (default 20s).\n */\nexport function makeHttpPublisherClient(\n config: StoreConfig = getStoreConfig(),\n timeoutMs = 20_000,\n): PublisherClient {\n // Acquire a fresh Keycloak token per call (device-flow session in\n // ~/.skaile/auth.json, refreshed on demand) rather than a static config.jwt.\n const call = async <T>(\n path: string,\n opts?: { method?: string; body?: unknown; params?: Record<string, string> },\n ): Promise<T> => {\n const jwt = await getStoreToken();\n return storeFetch<T>({ ...config, jwt }, path, { timeoutMs, ...opts });\n };\n return {\n me: () => call(\"/api/v1/me\"),\n sourcesAdd: (body) => call(\"/api/v1/sources\", { method: \"POST\", body }),\n sourcesList: () => call(\"/api/v1/sources\"),\n sourceSync: (id) => call(`/api/v1/sources/${id}/sync`, { method: \"POST\", body: {} }),\n jobGet: (jobId) => call(`/api/v1/jobs/${jobId}`),\n sourceCandidates: (id) => call(`/api/v1/sources/${id}/candidates`),\n assetPreview: (id) => call(`/api/v1/assets/${id}/preview`),\n assetPublish: (id, body, dryRun) =>\n call(`/api/v1/assets/${id}/publish`, {\n method: \"POST\",\n body,\n ...(dryRun ? { params: { dryRun: \"1\" } } : {}),\n }),\n assetUnpublish: (id) => call(`/api/v1/assets/${id}/unpublish`, { method: \"POST\", body: {} }),\n namespaceAvailability: (ns) =>\n call(`/api/v1/namespaces/${encodeURIComponent(ns)}/availability`),\n };\n}\n","/**\n * Shared store-interaction core for the two publish front-ends — the curator\n * sidecar flow (`source manifest publish`) and the first-party library flow\n * (`library publish`). Both differ only in their git side-effects + how they\n * resolve the source repo; the store orchestration below (register → sync →\n * candidates → per-asset preview+publish) is identical.\n *\n * The store REST surface is reached through the injectable {@link PublisherClient}\n * so the orchestration stays unit/integration-testable without a live store.\n *\n * @docLink cli/commands/source#manifest-publish\n */\n\nimport type { SkPublishManifest } from \"@skaile/workspaces/core\";\nimport { logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\nimport type { PublisherClient } from \"../store-publisher.ts\";\n\n/**\n * One-line rendering of a namespace-availability probe for a `--dry-run` plan.\n * The `message` is store-authored (identical to what a real publish would echo)\n * — we only prepend a status glyph so the reader sees green/amber/red at a\n * glance without the CLI re-deriving any authorization logic.\n */\nexport function formatNamespaceAvailability(a: {\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n message: string;\n}): string {\n switch (a.status) {\n case \"owned-by-you\":\n case \"available\":\n return `${S.ok(\"✓\")} ${a.message}`;\n case \"claimable-by-you\":\n return `${S.warn(\"!\")} ${a.message}`;\n default:\n return `${S.err(\"✗\")} ${a.message}`;\n }\n}\n\n/**\n * Preflight the target namespace against the store's availability probe BEFORE a\n * publish does any irreversible work (a public git push). Returns `{ ok: false }`\n * with a guided message for `reserved` (not yours) and `claimable-by-you` (must\n * claim first) — the two states a real publish would reject — so the caller can\n * abort with actionable guidance instead of a raw 422 after pushing bytes.\n *\n * The probe is advisory: any failure (offline, older store) returns `{ ok: true }`\n * so the store stays the authority and a valid publish is never blocked.\n */\nexport async function preflightNamespace(\n client: PublisherClient,\n namespace: string,\n): Promise<{ ok: boolean; message?: string }> {\n let a: Awaited<ReturnType<PublisherClient[\"namespaceAvailability\"]>>;\n try {\n a = await client.namespaceAvailability(namespace);\n } catch {\n return { ok: true };\n }\n switch (a.status) {\n case \"owned-by-you\":\n case \"available\":\n return { ok: true };\n case \"claimable-by-you\":\n return {\n ok: false,\n message:\n `@${namespace} isn't yours yet — claim it in the store first` +\n `${a.claimMethod ? ` (${a.claimMethod})` : \"\"}, then re-run. ${a.message}`,\n };\n default: // reserved, or any unrecognized future status (fail safe → block)\n return { ok: false, message: `Cannot publish under @${namespace} — ${a.message}` };\n }\n}\n\n/** One candidate row shape the matcher operates on (kind + name are the key). */\ninterface CandidateLike {\n kind: string;\n name: string;\n}\n\n/**\n * Keep only candidates whose `(kind, name)` pair is declared in the manifest.\n * The backend may merge extra assets from the base repo into the candidate\n * list; a publish only touches what the manifest curated/declared.\n */\nexport function matchCandidatesToManifest<T extends CandidateLike>(\n candidates: T[],\n manifest: SkPublishManifest,\n): T[] {\n const wanted = new Set((manifest.assets ?? []).map((a) => `${a.kind}:${a.name}`));\n return candidates.filter((c) => wanted.has(`${c.kind}:${c.name}`));\n}\n\n/** A canonical ref string `kind:@publisher/name[#version]` for reporting. */\nexport function refFor(kind: string, publisher: string, name: string, version?: string): string {\n const base = `${kind}:@${publisher}/${name}`;\n return version ? `${base}#${version}` : base;\n}\n\n/** The bare asset name from a `kind:@publisher/name#version` ref or a plain name. */\nexport function bareName(ref: string): string {\n const afterKind = ref.includes(\":\") ? ref.slice(ref.indexOf(\":\") + 1) : ref;\n const afterScope = afterKind.includes(\"/\")\n ? afterKind.slice(afterKind.indexOf(\"/\") + 1)\n : afterKind;\n return afterScope.split(\"#\")[0];\n}\n\n/**\n * Poll a job until it leaves `running` or the deadline passes. Returns the last\n * observed state — the caller MUST treat a still-`running` result as a timeout\n * (not success), since it means the deadline was hit before the job finished.\n */\nexport async function pollJob(\n client: PublisherClient,\n jobId: string,\n intervalMs = 1_500,\n timeoutMs = 60_000,\n): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }> {\n const deadline = Date.now() + timeoutMs;\n let job = await client.jobGet(jobId);\n while (job.status === \"running\" && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, intervalMs));\n job = await client.jobGet(jobId);\n }\n return job;\n}\n\n/**\n * True when a `sourcesAdd` rejection is a duplicate-URL conflict (the source is\n * already registered) — the only error the publish flow recovers from by looking\n * the existing row up. Every other failure (auth, 5xx, network) must propagate.\n */\nexport function isDupSourceError(err: unknown): boolean {\n const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();\n return /\\b409\\b|conflict|duplicate|already exists|already registered|unique/.test(msg);\n}\n\n/**\n * Register + sync the source, then publish its curated/declared candidates —\n * the store-side steps shared by both publish front-ends. Git side-effects (the\n * sidecar push, or the library commit+push) happen in the caller *before* this;\n * this function is purely store interaction.\n *\n * The sidecar front-end passes `sidecar` (so `sourcesAdd` carries the sidecar\n * pin); the library front-end omits it (the source repo IS the manifest host).\n * `assetName`, when set, narrows publication to the single candidate of that\n * name. Fatal store states (`sourcesAdd` non-dup failure) surface; sync failures\n * and empty candidate sets `process.exit(1)` with the same messages as before.\n */\nexport async function publishToStore(opts: {\n sourceUrl: string;\n ref: string;\n sidecar?: { url: string; ref: string };\n manifest: SkPublishManifest;\n assetName?: string;\n client: PublisherClient;\n}): Promise<{ published: string[] }> {\n const { sourceUrl, ref, sidecar, manifest, assetName, client: pub } = opts;\n\n let sourceId: string;\n try {\n const added = await pub.sourcesAdd({\n url: sourceUrl,\n ref,\n ...(sidecar ? { sidecarUrl: sidecar.url, sidecarRef: sidecar.ref } : {}),\n // Publish under the manifest's declared namespace; the store resolves a\n // claimed Publisher when it differs from the caller's login, else defaults\n // to `@<username>`. Omitted when the manifest carries no publisher.\n ...(manifest.publisher ? { namespace: manifest.publisher } : {}),\n });\n sourceId = added.id;\n } catch (err) {\n // Only a duplicate-url conflict is recoverable (source already registered);\n // auth/5xx/network failures must surface, not silently reuse a stale row.\n if (!isDupSourceError(err)) throw err;\n const rows = await pub.sourcesList();\n const found = rows.find((r) => r.url === sourceUrl);\n if (!found) {\n throw new Error(\n `Source ${sourceUrl} looked already-registered but no owned row matched: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n );\n }\n sourceId = found.id;\n }\n\n const { jobId } = await pub.sourceSync(sourceId);\n const job = await pollJob(pub, jobId);\n if (job.status === \"failed\" || job.status === \"cancelled\") {\n const failed = (job.items ?? []).filter((i) => i.status === \"failed\");\n for (const i of failed) logErr(`sync: ${i.label}: ${i.error ?? \"failed\"}`);\n logErr(`Source sync ${job.status}.`);\n process.exit(1);\n }\n // A still-`running` job means the poll deadline was hit — do NOT proceed on an\n // unfinished sync (it would read incomplete candidates).\n if (job.status === \"running\") {\n logErr(\"Source sync timed out before completing — re-run `publish`, or check the store.\");\n process.exit(1);\n }\n\n let candidates = matchCandidatesToManifest(await pub.sourceCandidates(sourceId), manifest);\n if (assetName) candidates = candidates.filter((c) => c.name === assetName);\n if (candidates.length === 0) {\n logWarn(\"No candidates discovered — check the manifest and the source ref.\");\n process.exit(1);\n }\n\n const published: string[] = [];\n for (const c of candidates) {\n try {\n const preview = await pub.assetPreview(c.id);\n const res = await pub.assetPublish(c.id, { ref, files: preview.discoveredFiles });\n // Publish is async — wait for the job so we only report refs that actually\n // landed, not ones whose import is still in flight or about to fail.\n if (res.jobId) {\n const pubJob = await pollJob(pub, res.jobId);\n if (pubJob.status !== \"succeeded\") {\n const errs = (pubJob.items ?? [])\n .filter((i) => i.status === \"failed\")\n .map((i) => i.error)\n .filter(Boolean);\n logWarn(\n `Publish of ${c.kind}:${c.name} did not succeed (${pubJob.status})` +\n (errs.length ? `: ${errs.join(\"; \")}` : \"\"),\n );\n continue;\n }\n }\n published.push(refFor(c.kind, preview.candidate.publisherNamespace, c.name, c.version));\n } catch (err) {\n logWarn(\n `Failed to publish ${c.kind}:${c.name}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n logOk(`Published ${published.length} asset(s):`);\n for (const r of published) logInfo(` ${r}`);\n return { published };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../cli/src/store-publisher.ts","../cli/src/commands/publish-core.ts"],"names":[],"mappings":"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","file":"chunk-DGDELPOD.js","sourcesContent":["/**\n * Typed REST client for the AI Asset Store **publisher** surface — the\n * curator-publish flow (`skaile source manifest publish` / `yank`). Thin\n * wrappers over {@link storeFetch}; every method maps 1:1 to an `/api/v1/…`\n * endpoint. The {@link PublisherClient} interface is injectable so the\n * orchestration in `commands/source-manifest-publish.ts` can be unit-tested\n * against a fake without a live store.\n *\n * @docLink cli/dev-guide#store-publisher\n */\n\nimport { getStoreConfig, getStoreToken, type StoreConfig, storeFetch } from \"./store-client.ts\";\n\n/**\n * The publisher REST surface used by the curator-publish flow. Kept minimal —\n * only the endpoints `runPublish` / `runYank` actually call. Response shapes\n * are narrowed to the fields the orchestration reads (the server returns more).\n */\nexport interface PublisherClient {\n /**\n * Identity of the caller. `username` is the Keycloak login (personal-tier\n * namespace); `githubLogin` is the verified GitHub handle when connected —\n * the namespace to publish under when it differs from the login.\n */\n me(): Promise<{ username: string; githubLogin?: string | null }>;\n /** Register (or re-register) a source; returns the created/existing row id. */\n sourcesAdd(body: {\n url: string;\n ref: string;\n sidecarUrl?: string;\n sidecarRef?: string;\n /**\n * Target publisher namespace (the manifest's `publisher`). When it differs\n * from the caller's login username, the store resolves the CLAIMED Publisher\n * for it (the store must already have the claim). Omitted → the store\n * defaults to `@<username>` (personal).\n */\n namespace?: string;\n }): Promise<{ id: string }>;\n /** List sources — used to recover an id when `sourcesAdd` rejects a dup url. */\n sourcesList(): Promise<Array<{ id: string; url: string }>>;\n /** Kick off a source sync; returns the async job id to poll. */\n sourceSync(id: string): Promise<{ jobId: string }>;\n /** Poll a job's terminal status + per-item results. */\n jobGet(\n jobId: string,\n ): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }>;\n /** Discovered publishable candidates for a synced source. */\n sourceCandidates(id: string): Promise<\n Array<{\n id: string;\n name: string;\n version: string;\n kind: string;\n published: boolean;\n assetRoot: string;\n }>\n >;\n /** Per-asset preview — the discovered file set + resolved candidate metadata. */\n assetPreview(id: string): Promise<{\n discoveredFiles: string[];\n candidate: { name: string; version: string; kind: string; publisherNamespace: string };\n }>;\n /**\n * Publish one asset. `dryRun` returns the would-be `{ manifest }` without\n * launching a job; the normal path returns `{ jobId }`.\n */\n assetPublish(\n id: string,\n body: { ref: string; files: string[] },\n dryRun?: boolean,\n ): Promise<{ jobId?: string; manifest?: unknown }>;\n /** Retract a published asset. Response body is ignored. */\n assetUnpublish(id: string): Promise<unknown>;\n /**\n * Read-only \"can I publish under `@<ns>` right now, and if not, what's the\n * path?\" probe. Backs the `publish --dry-run` namespace status line; its\n * `message` is store-authored and meant to be surfaced verbatim.\n */\n namespaceAvailability(ns: string): Promise<{\n namespace: string;\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n claimMethod?: string;\n message: string;\n }>;\n}\n\n/**\n * Construct the real HTTP-backed {@link PublisherClient}. Every call carries a\n * longer timeout than the default store client because publish/sync trigger\n * server-side clone work.\n *\n * @param config - Store connection config; defaults to {@link getStoreConfig}.\n * @param timeoutMs - Per-request abort timeout (default 20s).\n */\nexport function makeHttpPublisherClient(\n config: StoreConfig = getStoreConfig(),\n timeoutMs = 20_000,\n): PublisherClient {\n // Acquire a fresh Keycloak token per call (device-flow session in\n // ~/.skaile/auth.json, refreshed on demand) rather than a static config.jwt.\n const call = async <T>(\n path: string,\n opts?: { method?: string; body?: unknown; params?: Record<string, string> },\n ): Promise<T> => {\n const jwt = await getStoreToken();\n return storeFetch<T>({ ...config, jwt }, path, { timeoutMs, ...opts });\n };\n return {\n me: () => call(\"/api/v1/me\"),\n sourcesAdd: (body) => call(\"/api/v1/sources\", { method: \"POST\", body }),\n sourcesList: () => call(\"/api/v1/sources\"),\n sourceSync: (id) => call(`/api/v1/sources/${id}/sync`, { method: \"POST\", body: {} }),\n jobGet: (jobId) => call(`/api/v1/jobs/${jobId}`),\n sourceCandidates: (id) => call(`/api/v1/sources/${id}/candidates`),\n assetPreview: (id) => call(`/api/v1/assets/${id}/preview`),\n assetPublish: (id, body, dryRun) =>\n call(`/api/v1/assets/${id}/publish`, {\n method: \"POST\",\n body,\n ...(dryRun ? { params: { dryRun: \"1\" } } : {}),\n }),\n assetUnpublish: (id) => call(`/api/v1/assets/${id}/unpublish`, { method: \"POST\", body: {} }),\n namespaceAvailability: (ns) =>\n call(`/api/v1/namespaces/${encodeURIComponent(ns)}/availability`),\n };\n}\n","/**\n * Shared store-interaction core for the two publish front-ends — the curator\n * sidecar flow (`source manifest publish`) and the first-party library flow\n * (`library publish`). Both differ only in their git side-effects + how they\n * resolve the source repo; the store orchestration below (register → sync →\n * candidates → per-asset preview+publish) is identical.\n *\n * The store REST surface is reached through the injectable {@link PublisherClient}\n * so the orchestration stays unit/integration-testable without a live store.\n *\n * @docLink cli/commands/source#manifest-publish\n */\n\nimport type { SkPublishManifest } from \"@skaile/workspaces/core\";\nimport { logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\nimport type { PublisherClient } from \"../store-publisher.ts\";\n\n/**\n * One-line rendering of a namespace-availability probe for a `--dry-run` plan.\n * The `message` is store-authored (identical to what a real publish would echo)\n * — we only prepend a status glyph so the reader sees green/amber/red at a\n * glance without the CLI re-deriving any authorization logic.\n */\nexport function formatNamespaceAvailability(a: {\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n message: string;\n}): string {\n switch (a.status) {\n case \"owned-by-you\":\n case \"available\":\n return `${S.ok(\"✓\")} ${a.message}`;\n case \"claimable-by-you\":\n return `${S.warn(\"!\")} ${a.message}`;\n default:\n return `${S.err(\"✗\")} ${a.message}`;\n }\n}\n\n/**\n * Preflight the target namespace against the store's availability probe BEFORE a\n * publish does any irreversible work (a public git push). Returns `{ ok: false }`\n * with a guided message for `reserved` (not yours) and `claimable-by-you` (must\n * claim first) — the two states a real publish would reject — so the caller can\n * abort with actionable guidance instead of a raw 422 after pushing bytes.\n *\n * The probe is advisory: any failure (offline, older store) returns `{ ok: true }`\n * so the store stays the authority and a valid publish is never blocked.\n */\nexport async function preflightNamespace(\n client: PublisherClient,\n namespace: string,\n): Promise<{ ok: boolean; message?: string }> {\n let a: Awaited<ReturnType<PublisherClient[\"namespaceAvailability\"]>>;\n try {\n a = await client.namespaceAvailability(namespace);\n } catch {\n return { ok: true };\n }\n switch (a.status) {\n case \"owned-by-you\":\n case \"available\":\n return { ok: true };\n case \"claimable-by-you\":\n return {\n ok: false,\n message:\n `@${namespace} isn't yours yet — claim it in the store first` +\n `${a.claimMethod ? ` (${a.claimMethod})` : \"\"}, then re-run. ${a.message}`,\n };\n default: // reserved, or any unrecognized future status (fail safe → block)\n return { ok: false, message: `Cannot publish under @${namespace} — ${a.message}` };\n }\n}\n\n/** One candidate row shape the matcher operates on (kind + name are the key). */\ninterface CandidateLike {\n kind: string;\n name: string;\n}\n\n/**\n * Keep only candidates whose `(kind, name)` pair is declared in the manifest.\n * The backend may merge extra assets from the base repo into the candidate\n * list; a publish only touches what the manifest curated/declared.\n */\nexport function matchCandidatesToManifest<T extends CandidateLike>(\n candidates: T[],\n manifest: SkPublishManifest,\n): T[] {\n const wanted = new Set((manifest.assets ?? []).map((a) => `${a.kind}:${a.name}`));\n return candidates.filter((c) => wanted.has(`${c.kind}:${c.name}`));\n}\n\n/** A canonical ref string `kind:@publisher/name[#version]` for reporting. */\nexport function refFor(kind: string, publisher: string, name: string, version?: string): string {\n const base = `${kind}:@${publisher}/${name}`;\n return version ? `${base}#${version}` : base;\n}\n\n/** The bare asset name from a `kind:@publisher/name#version` ref or a plain name. */\nexport function bareName(ref: string): string {\n const afterKind = ref.includes(\":\") ? ref.slice(ref.indexOf(\":\") + 1) : ref;\n const afterScope = afterKind.includes(\"/\")\n ? afterKind.slice(afterKind.indexOf(\"/\") + 1)\n : afterKind;\n return afterScope.split(\"#\")[0];\n}\n\n/**\n * Poll a job until it leaves `running` or the deadline passes. Returns the last\n * observed state — the caller MUST treat a still-`running` result as a timeout\n * (not success), since it means the deadline was hit before the job finished.\n */\nexport async function pollJob(\n client: PublisherClient,\n jobId: string,\n intervalMs = 1_500,\n timeoutMs = 60_000,\n): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }> {\n const deadline = Date.now() + timeoutMs;\n let job = await client.jobGet(jobId);\n while (job.status === \"running\" && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, intervalMs));\n job = await client.jobGet(jobId);\n }\n return job;\n}\n\n/**\n * True when a `sourcesAdd` rejection is a duplicate-URL conflict (the source is\n * already registered) — the only error the publish flow recovers from by looking\n * the existing row up. Every other failure (auth, 5xx, network) must propagate.\n */\nexport function isDupSourceError(err: unknown): boolean {\n const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();\n return /\\b409\\b|conflict|duplicate|already exists|already registered|unique/.test(msg);\n}\n\n/**\n * Register + sync the source, then publish its curated/declared candidates —\n * the store-side steps shared by both publish front-ends. Git side-effects (the\n * sidecar push, or the library commit+push) happen in the caller *before* this;\n * this function is purely store interaction.\n *\n * The sidecar front-end passes `sidecar` (so `sourcesAdd` carries the sidecar\n * pin); the library front-end omits it (the source repo IS the manifest host).\n * `assetName`, when set, narrows publication to the single candidate of that\n * name. Fatal store states (`sourcesAdd` non-dup failure) surface; sync failures\n * and empty candidate sets `process.exit(1)` with the same messages as before.\n */\nexport async function publishToStore(opts: {\n sourceUrl: string;\n ref: string;\n sidecar?: { url: string; ref: string };\n manifest: SkPublishManifest;\n assetName?: string;\n client: PublisherClient;\n}): Promise<{ published: string[] }> {\n const { sourceUrl, ref, sidecar, manifest, assetName, client: pub } = opts;\n\n let sourceId: string;\n try {\n const added = await pub.sourcesAdd({\n url: sourceUrl,\n ref,\n ...(sidecar ? { sidecarUrl: sidecar.url, sidecarRef: sidecar.ref } : {}),\n // Publish under the manifest's declared namespace; the store resolves a\n // claimed Publisher when it differs from the caller's login, else defaults\n // to `@<username>`. Omitted when the manifest carries no publisher.\n ...(manifest.publisher ? { namespace: manifest.publisher } : {}),\n });\n sourceId = added.id;\n } catch (err) {\n // Only a duplicate-url conflict is recoverable (source already registered);\n // auth/5xx/network failures must surface, not silently reuse a stale row.\n if (!isDupSourceError(err)) throw err;\n const rows = await pub.sourcesList();\n const found = rows.find((r) => r.url === sourceUrl);\n if (!found) {\n throw new Error(\n `Source ${sourceUrl} looked already-registered but no owned row matched: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n );\n }\n sourceId = found.id;\n }\n\n const { jobId } = await pub.sourceSync(sourceId);\n const job = await pollJob(pub, jobId);\n if (job.status === \"failed\" || job.status === \"cancelled\") {\n const failed = (job.items ?? []).filter((i) => i.status === \"failed\");\n for (const i of failed) logErr(`sync: ${i.label}: ${i.error ?? \"failed\"}`);\n logErr(`Source sync ${job.status}.`);\n process.exit(1);\n }\n // A still-`running` job means the poll deadline was hit — do NOT proceed on an\n // unfinished sync (it would read incomplete candidates).\n if (job.status === \"running\") {\n logErr(\"Source sync timed out before completing — re-run `publish`, or check the store.\");\n process.exit(1);\n }\n\n let candidates = matchCandidatesToManifest(await pub.sourceCandidates(sourceId), manifest);\n if (assetName) candidates = candidates.filter((c) => c.name === assetName);\n if (candidates.length === 0) {\n logWarn(\"No candidates discovered — check the manifest and the source ref.\");\n process.exit(1);\n }\n\n const published: string[] = [];\n for (const c of candidates) {\n try {\n const preview = await pub.assetPreview(c.id);\n const res = await pub.assetPublish(c.id, { ref, files: preview.discoveredFiles });\n // Publish is async — wait for the job so we only report refs that actually\n // landed, not ones whose import is still in flight or about to fail.\n if (res.jobId) {\n const pubJob = await pollJob(pub, res.jobId);\n if (pubJob.status !== \"succeeded\") {\n const errs = (pubJob.items ?? [])\n .filter((i) => i.status === \"failed\")\n .map((i) => i.error)\n .filter(Boolean);\n logWarn(\n `Publish of ${c.kind}:${c.name} did not succeed (${pubJob.status})` +\n (errs.length ? `: ${errs.join(\"; \")}` : \"\"),\n );\n continue;\n }\n }\n published.push(refFor(c.kind, preview.candidate.publisherNamespace, c.name, c.version));\n } catch (err) {\n logWarn(\n `Failed to publish ${c.kind}:${c.name}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n logOk(`Published ${published.length} asset(s):`);\n for (const r of published) logInfo(` ${r}`);\n return { published };\n}\n"]}
|
|
@@ -46,8 +46,8 @@ async function mountRead(manager, mountId, filePath) {
|
|
|
46
46
|
async function connectorList(manager) {
|
|
47
47
|
if (!manager) return err("No connectors configured in skaile.yaml");
|
|
48
48
|
try {
|
|
49
|
-
const
|
|
50
|
-
return okJson(
|
|
49
|
+
const failed = typeof manager.listFailedConnectors === "function" ? manager.listFailedConnectors() : [];
|
|
50
|
+
return okJson({ connected: manager.listConnectors(), failed });
|
|
51
51
|
} catch (e) {
|
|
52
52
|
return err(e instanceof Error ? e.message : String(e));
|
|
53
53
|
}
|
|
@@ -111,5 +111,5 @@ async function connectorDescribe(manager, id) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
export { connectorDescribe, connectorExec, connectorList, connectorLoadSkill, connectorRead, connectorSearch, connectorWrite, mountList, mountRead, mountStatus, mountSync };
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
115
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-FUCYTGAE.js.map
|
|
115
|
+
//# sourceMappingURL=chunk-FUCYTGAE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../workspace-plugin/src/tools/connectors.ts"],"names":[],"mappings":";;;;AAwBA,SAAS,cAAc,OAAA,EAAiD;AACtE,EAAA,OAAO,OAAA,CACJ,gBAAe,CACf,MAAA,CAAO,CAAC,CAAA,KAA+B,OAAO,CAAA,CAAE,SAAA,KAAc,QAAQ,CAAA;AAC3E;AAUA,eAAsB,UAAU,OAAA,EAAuD;AACrF,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,OAAO,MAAA,CAAO,aAAA,CAAc,OAAO,CAAC,CAAA;AAAA,EACtC,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAUA,eAAsB,SAAA,CACpB,SACA,OAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AACzC,IAAA,OAAO,OAAO,MAAM,CAAA;AAAA,EACtB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAUA,eAAsB,WAAA,CACpB,SACA,OAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,cAAc,OAAO,CAAA,CAAE,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA;AACjE,IAAA,IAAI,CAAC,KAAA,EAAO,OAAO,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAO,CAAA,CAAA,CAAG,CAAA;AACtD,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAYA,eAAsB,SAAA,CACpB,OAAA,EACA,OAAA,EACA,QAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,cAAc,OAAO,CAAA,CAAE,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA;AACjE,IAAA,IAAI,CAAC,KAAA,EAAO,OAAO,GAAA,CAAI,CAAA,kBAAA,EAAqB,OAAO,CAAA,CAAA,CAAG,CAAA;AACtD,IAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,CAAK,MAAM,SAAA,EAAW,QAAQ,GAAG,OAAO,CAAA;AACvE,IAAA,OAAO,GAAG,OAAO,CAAA;AAAA,EACnB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAiBA,eAAsB,cAAc,OAAA,EAAuD;AACzF,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GACJ,OAAO,OAAA,CAAQ,oBAAA,KAAyB,aAAa,OAAA,CAAQ,oBAAA,KAAyB,EAAC;AACzF,IAAA,OAAO,OAAO,EAAE,SAAA,EAAW,QAAQ,cAAA,EAAe,EAAG,QAAQ,CAAA;AAAA,EAC/D,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAcA,eAAsB,aAAA,CACpB,OAAA,EACA,EAAA,EACA,IAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,OAAA,KAAY,MAAM,OAAO,GAAA,CAAI,uBAAuB,IAAI,CAAA,gBAAA,EAAmB,EAAE,CAAA,CAAA,CAAG,CAAA;AACpF,IAAA,OAAO,OAAO,OAAO,CAAA;AAAA,EACvB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAcA,eAAsB,cAAA,CACpB,OAAA,EACA,EAAA,EACA,IAAA,EACA,OAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,KAAA,CAAM,EAAA,EAAI,MAAM,EAAE,IAAA,EAAM,SAAS,CAAA;AAC/C,IAAA,OAAO,EAAA,CAAG,CAAA,YAAA,EAAe,IAAI,CAAA,gBAAA,EAAmB,EAAE,CAAA,CAAA,CAAG,CAAA;AAAA,EACvD,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAaA,eAAsB,eAAA,CACpB,OAAA,EACA,EAAA,EACA,KAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAK,CAAA;AAC9C,IAAA,OAAO,OAAO,OAAO,CAAA;AAAA,EACvB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAgBA,eAAsB,aAAA,CACpB,OAAA,EACA,EAAA,EACA,SAAA,EACA,IAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,OAAA,CAAQ,SAAA,CAAU,EAAA,EAAI,WAAW,IAAI,CAAA;AAC1D,IAAA,OAAO,GAAG,MAAM,CAAA;AAAA,EAClB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAcA,eAAsB,kBAAA,CACpB,SACA,EAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,EAAE,CAAA;AAClC,IAAA,OAAO,GAAG,KAAK,CAAA;AAAA,EACjB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAcA,eAAsB,iBAAA,CACpB,SACA,EAAA,EACqB;AACrB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,GAAA,CAAI,yCAAyC,CAAA;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,QAAQ,UAAA,EAAW;AAClC,IAAA,MAAM,aAAa,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AACjD,IAAA,IAAI,CAAC,UAAA,EAAY,OAAO,GAAA,CAAI,CAAA,mCAAA,EAAsC,EAAE,CAAA,CAAA,CAAG,CAAA;AACvE,IAAA,OAAO,OAAO,UAAU,CAAA;AAAA,EAC1B,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF","file":"chunk-FUCYTGAE.js","sourcesContent":["// src/tools/connectors.ts\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConnectorManager } from \"@skaile/workspaces/connectors\";\nimport type { ToolResult } from \"../types.js\";\nimport { err, ok, okJson } from \"../types.js\";\n\n// ── Mountable-connector helpers ──────────────────────────────────────────────\n//\n// The unified ConnectorManager owns mountable (filesystem-face) connectors too.\n// A connector is mountable when its `listConnectors()` summary carries a\n// `mountPath`. The `mount*` helpers below project that subset for the legacy\n// `mount_*` tool surface.\n\n/**\n * A connector summary that carries a projected filesystem path. Unlike the raw\n * `listConnectors()` summary, `mountPath` is non-optional here — `listMountable()`\n * runtime-filters to exactly those entries before narrowing to this type.\n */\ntype MountableConnector = ReturnType<ConnectorManager[\"listConnectors\"]>[number] & {\n mountPath: string;\n};\n\n/** Return the mountable (filesystem-face) connectors from a manager. */\nfunction listMountable(manager: ConnectorManager): MountableConnector[] {\n return manager\n .listConnectors()\n .filter((c): c is MountableConnector => typeof c.mountPath === \"string\");\n}\n\n/**\n * List all mountable (filesystem-face) connectors declared in `skaile.yaml`\n * with their current mount status.\n *\n * @param manager - Active `ConnectorManager` or `null` when not configured.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function mountList(manager: ConnectorManager | null): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n return okJson(listMountable(manager));\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Sync a mountable connector — pull the latest content from its remote source.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param mountId - Connector ID declared in `skaile.yaml`.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function mountSync(\n manager: ConnectorManager | null,\n mountId: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const result = await manager.sync(mountId);\n return okJson(result);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Get the current status and metadata for a single mountable connector.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param mountId - Connector ID declared in `skaile.yaml`.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function mountStatus(\n manager: ConnectorManager | null,\n mountId: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const mount = listMountable(manager).find((v) => v.id === mountId);\n if (!mount) return err(`Mount not found: \"${mountId}\"`);\n return okJson(mount);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Read a file from within a mountable connector's projected directory by its\n * relative path.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param mountId - Connector ID declared in `skaile.yaml`.\n * @param filePath - Relative path within the projected mount directory.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function mountRead(\n manager: ConnectorManager | null,\n mountId: string,\n filePath: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const mount = listMountable(manager).find((v) => v.id === mountId);\n if (!mount) return err(`Mount not found: \"${mountId}\"`);\n const content = await readFile(join(mount.mountPath, filePath), \"utf-8\");\n return ok(content);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * List all connectors registered with the `ConnectorManager`.\n *\n * Returns `{ connected, failed }` — `connected` from `manager.listConnectors()`,\n * `failed` from `manager.listFailedConnectors()`. A connector that threw during\n * `connect()` never enters the active map, so it is absent from the first list\n * entirely; without the second one an agent driven through MCP or OMP has no\n * way to learn that a mount it is about to write into is dead. Returns an error\n * result when no manager is configured (i.e. `skaile.yaml` has no `connectors`\n * section).\n *\n * @param manager - Active `ConnectorManager` or `null` when not configured.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorList(manager: ConnectorManager | null): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n // Defensive: a host may pass an older manager or a test double.\n const failed =\n typeof manager.listFailedConnectors === \"function\" ? manager.listFailedConnectors() : [];\n return okJson({ connected: manager.listConnectors(), failed });\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Read content from a connector at the given path.\n *\n * Delegates to `manager.read(id, path)`. Returns an error result when the\n * path yields `null` (not found) or the manager is absent.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n * @param path - Resource path within the connector (connector-specific format).\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorRead(\n manager: ConnectorManager | null,\n id: string,\n path: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const content = await manager.read(id, path);\n if (content === null) return err(`No content at path \"${path}\" in connector \"${id}\"`);\n return okJson(content);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Write string content to a connector at the given path.\n *\n * Delegates to `manager.write(id, path, { data: content })`.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n * @param path - Destination path within the connector.\n * @param content - String payload to write.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorWrite(\n manager: ConnectorManager | null,\n id: string,\n path: string,\n content: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n await manager.write(id, path, { data: content });\n return ok(`Written to \"${path}\" in connector \"${id}\"`);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Search a connector's data using a query string.\n *\n * Delegates to `manager.search(id, query)` and returns the result set as JSON.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n * @param query - Free-text or structured query (connector-specific format).\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorSearch(\n manager: ConnectorManager | null,\n id: string,\n query: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const results = await manager.search(id, query);\n return okJson(results);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Execute a named operation on a connector.\n *\n * Delegates to `manager.executeOp(id, operation, args)`. Operations and\n * their argument shapes are connector-specific; use {@link connectorDescribe}\n * to discover what operations a connector supports.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n * @param operation - Operation name (from the connector's `RuntimeSkillDescriptor`).\n * @param args - Named arguments for the operation.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorExec(\n manager: ConnectorManager | null,\n id: string,\n operation: string,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const result = await manager.executeOp(id, operation, args);\n return ok(result);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Load the rendered skill body for a connector.\n *\n * Delegates to `manager.loadSkill(id)` and returns the skill content as\n * plain text. Useful when the agent needs the connector's operations and\n * usage instructions injected as prompt context.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorLoadSkill(\n manager: ConnectorManager | null,\n id: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const skill = manager.loadSkill(id);\n return ok(skill);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Describe a connector's capabilities via its `RuntimeSkillDescriptor`.\n *\n * Finds the matching skill descriptor from `manager.listSkills()` and returns\n * it as JSON. The descriptor includes the connector's operations, argument\n * shapes, and usage instructions.\n *\n * @param manager - Active `ConnectorManager` or `null`.\n * @param id - Connector ID declared in `skaile.yaml`.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function connectorDescribe(\n manager: ConnectorManager | null,\n id: string,\n): Promise<ToolResult> {\n if (!manager) return err(\"No connectors configured in skaile.yaml\");\n try {\n const skills = manager.listSkills();\n const descriptor = skills.find((s) => s.id === id);\n if (!descriptor) return err(`No skill descriptor for connector \"${id}\"`);\n return okJson(descriptor);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n"]}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { WorkspacePlugin } from './chunk-
|
|
1
|
+
import { WorkspacePlugin } from './chunk-QVQH6GV2.js';
|
|
2
2
|
import { assembleSystemPrompt, buildCapabilitiesPromptSection } from './chunk-W3UDISS2.js';
|
|
3
3
|
import { WebSocketServerTransport } from './chunk-WQ7DE5UC.js';
|
|
4
|
-
import { resolveFlowPath } from './chunk-
|
|
4
|
+
import { resolveFlowPath } from './chunk-2GREL3OD.js';
|
|
5
5
|
import { findAiAssetsRoot, deployCatalogEntry, undeployCatalogEntry } from './chunk-GHWJHOYX.js';
|
|
6
|
-
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools, driveOrchestratorTurn, SessionNodeExecutor, SessionSubpromptRunner, SessionInlineSubFlowRunner, buildSdkFlowTools } from './chunk-
|
|
6
|
+
import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools, driveOrchestratorTurn, SessionNodeExecutor, SessionSubpromptRunner, SessionInlineSubFlowRunner, buildSdkFlowTools } from './chunk-6GDVGAIZ.js';
|
|
7
7
|
import { loadConnectorDeclarations, SecretProviderChain, PreMintedSecretProvider, InMemorySecretProvider, resolvedConfigToDeclarations, isKnownSecretRef, deriveSingleMaterializedConnectorDeclaration } from './chunk-3UU3D2Q3.js';
|
|
8
|
-
import { EventNormalizer } from './chunk-
|
|
8
|
+
import { EventNormalizer } from './chunk-KNPBMR2P.js';
|
|
9
9
|
import { SUPPORTED_CLOUDS, probeResumeTranscript, CLOUD_SECRET_ENV_KEYS } from './chunk-RUFTB7QN.js';
|
|
10
10
|
import { classifyClaudeSdkError } from './chunk-GAH4YRCI.js';
|
|
11
|
-
import { createDriver } from './chunk-
|
|
11
|
+
import { createDriver } from './chunk-BGAAZMBK.js';
|
|
12
12
|
import { loadFlow } from './chunk-OYZIURPH.js';
|
|
13
13
|
import { parseFlowDefinition } from './chunk-HY6CIKFH.js';
|
|
14
14
|
import { renderStimulusPrompt } from './chunk-HGFKNJA5.js';
|
|
15
|
-
import { PROTOCOL_VERSION } from './chunk-
|
|
15
|
+
import { PROTOCOL_VERSION } from './chunk-O3LEV6KB.js';
|
|
16
16
|
import { resolveSettings, resolveApiKey, providerEnvKey } from './chunk-AZPXCHDK.js';
|
|
17
17
|
import { resolveDriverPaths } from './chunk-K5GBV4SA.js';
|
|
18
18
|
import { resolveRuntimeAssets } from './chunk-SH572OBN.js';
|
|
@@ -2103,6 +2103,8 @@ function createSessionDriver(args) {
|
|
|
2103
2103
|
...config.capabilities ? { capabilities: config.capabilities } : {},
|
|
2104
2104
|
...config.aiProviderConfigId ? { aiProviderConfigId: config.aiProviderConfigId } : {},
|
|
2105
2105
|
...config.onAuthError ? { onAuthError: config.onAuthError } : {},
|
|
2106
|
+
...config.onLimitBlocked ? { onLimitBlocked: config.onLimitBlocked } : {},
|
|
2107
|
+
...config.onProviderResponse ? { onProviderResponse: config.onProviderResponse } : {},
|
|
2106
2108
|
// Always forward agentDir/agentName for native identity handling
|
|
2107
2109
|
...agentDir ? { agentDir, agentName: manifest?.name } : {}
|
|
2108
2110
|
});
|
|
@@ -2974,6 +2976,61 @@ function createAiCredentialRefreshScheduler(deps) {
|
|
|
2974
2976
|
};
|
|
2975
2977
|
}
|
|
2976
2978
|
|
|
2979
|
+
// runner/src/ai-provider-switch.ts
|
|
2980
|
+
function createAiProviderConfigSwitcher(deps) {
|
|
2981
|
+
let inFlight = null;
|
|
2982
|
+
function reasonSatisfies(inFlightReason, requestedReason) {
|
|
2983
|
+
return inFlightReason === requestedReason || inFlightReason === "retry-401";
|
|
2984
|
+
}
|
|
2985
|
+
function applyMint(mint, args) {
|
|
2986
|
+
const previous = deps.getConfigId();
|
|
2987
|
+
const unchanged = {
|
|
2988
|
+
mint,
|
|
2989
|
+
switched: false,
|
|
2990
|
+
...previous ? { configId: previous } : {}
|
|
2991
|
+
};
|
|
2992
|
+
if (!mint.ok) return unchanged;
|
|
2993
|
+
const next = mint.configId ?? args.requestedConfigId ?? previous;
|
|
2994
|
+
if (!next || next === previous) return unchanged;
|
|
2995
|
+
deps.setConfigId(next);
|
|
2996
|
+
deps.logWarn(
|
|
2997
|
+
`[serve] AI provider config switched ${previous ?? "none"} -> ${next} (${args.trigger})`
|
|
2998
|
+
);
|
|
2999
|
+
deps.scheduleRestart("AI provider config switch");
|
|
3000
|
+
return { mint, switched: true, configId: next };
|
|
3001
|
+
}
|
|
3002
|
+
async function run(args) {
|
|
3003
|
+
const mint = await deps.mint({
|
|
3004
|
+
...args.configId ? { configId: args.configId } : {},
|
|
3005
|
+
reason: args.reason ?? "refresh"
|
|
3006
|
+
});
|
|
3007
|
+
return applyMint(mint, {
|
|
3008
|
+
trigger: args.trigger,
|
|
3009
|
+
...args.configId ? { requestedConfigId: args.configId } : {}
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
return {
|
|
3013
|
+
applyMint,
|
|
3014
|
+
repull(args) {
|
|
3015
|
+
const pending = inFlight;
|
|
3016
|
+
const reason = args.reason ?? "refresh";
|
|
3017
|
+
if (pending && pending.target === args.configId && reasonSatisfies(pending.reason, reason)) {
|
|
3018
|
+
deps.log(`[serve] ${args.trigger}: coalescing into the in-flight ai-credential re-pull`);
|
|
3019
|
+
return pending.promise;
|
|
3020
|
+
}
|
|
3021
|
+
const started = pending ? pending.promise.then(
|
|
3022
|
+
() => run(args),
|
|
3023
|
+
() => run(args)
|
|
3024
|
+
) : run(args);
|
|
3025
|
+
const entry = { target: args.configId, reason, promise: started };
|
|
3026
|
+
inFlight = entry;
|
|
3027
|
+
return started.finally(() => {
|
|
3028
|
+
if (inFlight === entry) inFlight = null;
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
|
|
2977
3034
|
// runner/src/credential-rotated.ts
|
|
2978
3035
|
var AI_PROVIDER_CREDENTIAL_SUBKIND = "ai-provider-credential";
|
|
2979
3036
|
function isCredentialRotatedSignal(msg) {
|
|
@@ -2984,10 +3041,17 @@ function isCredentialRotatedSignal(msg) {
|
|
|
2984
3041
|
if (!entry || typeof entry !== "object") return false;
|
|
2985
3042
|
return entry.source?.subkind === AI_PROVIDER_CREDENTIAL_SUBKIND && entry.data?.credentialRotated === true;
|
|
2986
3043
|
}
|
|
3044
|
+
function readCredentialRotatedConfigId(msg) {
|
|
3045
|
+
if (!msg || typeof msg !== "object") return void 0;
|
|
3046
|
+
const configId = msg.entry?.data?.configId;
|
|
3047
|
+
return typeof configId === "string" && configId.length > 0 ? configId : void 0;
|
|
3048
|
+
}
|
|
2987
3049
|
async function handleCredentialRotatedSignal(deps) {
|
|
2988
|
-
deps.log(
|
|
3050
|
+
deps.log(
|
|
3051
|
+
deps.configId ? `[serve] credentialRotated broadcast received (configId=${deps.configId}); re-pulling ai-credentials` : "[serve] credentialRotated broadcast received; re-pulling ai-credentials"
|
|
3052
|
+
);
|
|
2989
3053
|
try {
|
|
2990
|
-
const result = await deps.repull();
|
|
3054
|
+
const result = await deps.repull(deps.configId);
|
|
2991
3055
|
if (result.ok) {
|
|
2992
3056
|
deps.log("[serve] credentialRotated: re-pulled fresh token and rewrote .credentials.json");
|
|
2993
3057
|
} else {
|
|
@@ -5015,6 +5079,55 @@ async function startAgentServer(opts) {
|
|
|
5015
5079
|
return { ok: false, code: "backend-error", message: errMsg };
|
|
5016
5080
|
}
|
|
5017
5081
|
}
|
|
5082
|
+
const aiProviderConfigSwitcher = createAiProviderConfigSwitcher({
|
|
5083
|
+
mint: mintAndPersistAiCredential,
|
|
5084
|
+
getConfigId: () => aiProviderConfigId,
|
|
5085
|
+
setConfigId: (next) => {
|
|
5086
|
+
aiProviderConfigId = next;
|
|
5087
|
+
const live = sessionConfig;
|
|
5088
|
+
if (live) live.aiProviderConfigId = next;
|
|
5089
|
+
},
|
|
5090
|
+
scheduleRestart: (reason) => scheduleDriverRestartForToolChanges(reason),
|
|
5091
|
+
log,
|
|
5092
|
+
logWarn: (line) => serverLog.warn(line)
|
|
5093
|
+
});
|
|
5094
|
+
const onLimitBlocked = async (ctx) => {
|
|
5095
|
+
if (!transport.connected || aiProviderConfigId === void 0) {
|
|
5096
|
+
return { switched: false, reason: "standalone" };
|
|
5097
|
+
}
|
|
5098
|
+
const resetsAtIso = ctx.resetsAt && ctx.resetsAt > 1e9 && ctx.resetsAt < 1e11 ? new Date(ctx.resetsAt * 1e3).toISOString() : ctx.resetsAt ? `raw ${ctx.resetsAt}` : void 0;
|
|
5099
|
+
const limitWindow = [ctx.limitType, resetsAtIso ? `resets ${resetsAtIso}` : void 0].filter(Boolean).join(", ");
|
|
5100
|
+
serverLog.warn(
|
|
5101
|
+
`[serve] usage limit blocked the turn on config ${ctx.configId || aiProviderConfigId}${limitWindow ? ` (${limitWindow})` : ""}`
|
|
5102
|
+
);
|
|
5103
|
+
const outcome = await aiProviderConfigSwitcher.repull({
|
|
5104
|
+
trigger: "limit-blocked",
|
|
5105
|
+
reason: "retry-401"
|
|
5106
|
+
});
|
|
5107
|
+
if (outcome.switched) {
|
|
5108
|
+
return { switched: true, ...outcome.configId ? { configId: outcome.configId } : {} };
|
|
5109
|
+
}
|
|
5110
|
+
return {
|
|
5111
|
+
switched: false,
|
|
5112
|
+
...outcome.configId ? { configId: outcome.configId } : {},
|
|
5113
|
+
// A platform that does not yet return `configId` on the mint is
|
|
5114
|
+
// indistinguishable from one that re-resolved — say so rather than
|
|
5115
|
+
// claiming the seat was unchanged.
|
|
5116
|
+
reason: !outcome.mint.ok ? outcome.mint.code : outcome.mint.configId ? "same-config" : "platform-omitted-config-id"
|
|
5117
|
+
};
|
|
5118
|
+
};
|
|
5119
|
+
const onProviderResponse = (observation) => {
|
|
5120
|
+
const configId = aiProviderConfigId ?? observation.configId;
|
|
5121
|
+
sendEvent({
|
|
5122
|
+
type: "provider_response_seen",
|
|
5123
|
+
status: observation.status,
|
|
5124
|
+
...configId ? { configId } : {},
|
|
5125
|
+
...observation.limitType ? { limitType: observation.limitType } : {},
|
|
5126
|
+
...typeof observation.utilization === "number" ? { utilization: observation.utilization } : {},
|
|
5127
|
+
...typeof observation.resetsAt === "number" ? { resetsAt: observation.resetsAt } : {},
|
|
5128
|
+
observedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5129
|
+
});
|
|
5130
|
+
};
|
|
5018
5131
|
const connectorTokenMediator = buildConnectorTokenMediator({
|
|
5019
5132
|
isConnected: () => transport.connected,
|
|
5020
5133
|
invokeRemote: (name, input) => capabilityRegistry.invokeRemote(name, input),
|
|
@@ -5022,7 +5135,9 @@ async function startAgentServer(opts) {
|
|
|
5022
5135
|
});
|
|
5023
5136
|
const aiCredentialRefreshScheduler = createAiCredentialRefreshScheduler({
|
|
5024
5137
|
refresh: async () => {
|
|
5025
|
-
const result = await
|
|
5138
|
+
const { mint: result } = await aiProviderConfigSwitcher.repull({
|
|
5139
|
+
trigger: "proactive-refresh"
|
|
5140
|
+
});
|
|
5026
5141
|
if (result.ok) {
|
|
5027
5142
|
return { status: "ok", expiresAt: result.expiresAt ?? null };
|
|
5028
5143
|
}
|
|
@@ -5035,8 +5150,12 @@ async function startAgentServer(opts) {
|
|
|
5035
5150
|
});
|
|
5036
5151
|
const onAuthError = async (args) => {
|
|
5037
5152
|
log("[serve] auth error: invoking host.refresh_credential capability");
|
|
5153
|
+
const configId = aiProviderConfigId ?? args.configId;
|
|
5154
|
+
if (args.configId && configId !== args.configId) {
|
|
5155
|
+
log(`[serve] auth error: driver holds stale config ${args.configId}; refreshing ${configId}`);
|
|
5156
|
+
}
|
|
5038
5157
|
const result = await retryTransientMint(
|
|
5039
|
-
() => mintAndPersistAiCredential({ configId
|
|
5158
|
+
() => mintAndPersistAiCredential({ configId, reason: "retry-401" }),
|
|
5040
5159
|
{
|
|
5041
5160
|
sleep,
|
|
5042
5161
|
onRetry: ({ attempt, nextDelayMs, code }) => serverLog.error(
|
|
@@ -5049,6 +5168,10 @@ async function startAgentServer(opts) {
|
|
|
5049
5168
|
} else {
|
|
5050
5169
|
log("[serve] auth error: rewrote .credentials.json with mediated accessToken");
|
|
5051
5170
|
}
|
|
5171
|
+
aiProviderConfigSwitcher.applyMint(result, {
|
|
5172
|
+
trigger: "retry-401",
|
|
5173
|
+
...configId ? { requestedConfigId: configId } : {}
|
|
5174
|
+
});
|
|
5052
5175
|
return result;
|
|
5053
5176
|
};
|
|
5054
5177
|
const APPROVAL_REQUIRED_CAPABILITY_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
@@ -5121,6 +5244,8 @@ async function startAgentServer(opts) {
|
|
|
5121
5244
|
externalPromptFile: process.env.SKAILE_SYSTEM_PROMPT_FILE,
|
|
5122
5245
|
secretProvider: secretProvider2,
|
|
5123
5246
|
onAuthError,
|
|
5247
|
+
onLimitBlocked,
|
|
5248
|
+
onProviderResponse,
|
|
5124
5249
|
...apiKey ? { apiKey } : {},
|
|
5125
5250
|
// Non-default cloud transport from skaile.yaml agent-config.default,
|
|
5126
5251
|
// plus the platform-resolved credential bundle (Vertex SA JSON already
|
|
@@ -6541,7 +6666,11 @@ async function startAgentServer(opts) {
|
|
|
6541
6666
|
const inbound = cmd;
|
|
6542
6667
|
if (isCredentialRotatedSignal(cmd)) {
|
|
6543
6668
|
await handleCredentialRotatedSignal({
|
|
6544
|
-
|
|
6669
|
+
configId: readCredentialRotatedConfigId(cmd),
|
|
6670
|
+
repull: async (configId) => (await aiProviderConfigSwitcher.repull({
|
|
6671
|
+
trigger: "credentialRotated",
|
|
6672
|
+
...configId ? { configId } : {}
|
|
6673
|
+
})).mint,
|
|
6545
6674
|
log,
|
|
6546
6675
|
logError: (line) => serverLog.error(line)
|
|
6547
6676
|
});
|
|
@@ -6835,5 +6964,5 @@ function touchSession(state) {
|
|
|
6835
6964
|
}
|
|
6836
6965
|
|
|
6837
6966
|
export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, DEFAULT_FLOW_MUTATE_CONNECTOR_WAIT_MS, MOUNT_LIST_MAX_DEPTH, MOUNT_LIST_MAX_ENTRIES, MOUNT_READ_DEADLINE_FACTOR, MOUNT_TREE_OP_DEADLINE_FACTOR, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, buildStoreSnapshotReplay, builtinCapabilities, capabilityLogInstance, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createFlowConnectorReadiness, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, executeConnectorMutate, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, hasNonTerminalFlow, hostOpResumeStimulus, installPreInitRingSink, isTerminalFlowStatus, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, pickRepointedManager, planFlowMutate, reconcilePendingDecisions, registerActiveFlow, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveFlowMutateConnectorWaitMs, resolveMixin, runAgentChat, saveSession, setCurrentSession, setUpFlowConnector, startAgentServer, stimulusFromMetas, touchSession, validateInputResponse, writeClaudeCodeCredentialsFile };
|
|
6838
|
-
//# sourceMappingURL=chunk-
|
|
6839
|
-
//# sourceMappingURL=chunk-
|
|
6967
|
+
//# sourceMappingURL=chunk-IH2KJYAU.js.map
|
|
6968
|
+
//# sourceMappingURL=chunk-IH2KJYAU.js.map
|