@skaile/workspaces 4.30.1 → 4.31.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 +8 -0
- package/dist/{asset-feeds-YB5ROSAE.js → asset-feeds-XNL4NQBM.js} +7 -7
- package/dist/{asset-feeds-YB5ROSAE.js.map → asset-feeds-XNL4NQBM.js.map} +1 -1
- package/dist/asset-manager/catalog-deployer.js +3 -3
- package/dist/asset-manager/index.js +6 -6
- package/dist/asset-manager/installer.js +4 -4
- package/dist/bridge/drivers/claude-sdk.js +7 -7
- package/dist/bridge/drivers/codex.js +6 -6
- package/dist/bridge/drivers/continue.js +6 -6
- package/dist/bridge/drivers/echo.js +3 -3
- package/dist/bridge/drivers/gemini.js +7 -7
- package/dist/bridge/drivers/goose.js +6 -6
- package/dist/bridge/drivers/omp.js +5 -5
- package/dist/bridge/drivers/opencode.js +6 -6
- package/dist/bridge/drivers/qwen.js +7 -7
- package/dist/bridge/index.js +8 -8
- package/dist/{chunk-ECTQR7IM.js → chunk-2RIM7HAG.js} +8 -8
- package/dist/{chunk-ECTQR7IM.js.map → chunk-2RIM7HAG.js.map} +1 -1
- package/dist/{chunk-IJTEDXWQ.js → chunk-3ZE7X5Y6.js} +3 -3
- package/dist/{chunk-IJTEDXWQ.js.map → chunk-3ZE7X5Y6.js.map} +1 -1
- package/dist/{chunk-3TK7CZVL.js → chunk-4UGEZIMA.js} +4 -4
- package/dist/{chunk-3TK7CZVL.js.map → chunk-4UGEZIMA.js.map} +1 -1
- package/dist/{chunk-UQ3JFN4N.js → chunk-54A5QAIV.js} +2 -2
- package/dist/{chunk-UQ3JFN4N.js.map → chunk-54A5QAIV.js.map} +1 -1
- package/dist/{chunk-7VQGUNXJ.js → chunk-5KJLMR23.js} +5 -5
- package/dist/{chunk-7VQGUNXJ.js.map → chunk-5KJLMR23.js.map} +1 -1
- package/dist/{chunk-3AX5PZRA.js → chunk-7ZXENJLO.js} +3 -3
- package/dist/{chunk-3AX5PZRA.js.map → chunk-7ZXENJLO.js.map} +1 -1
- package/dist/{chunk-2ICKARYU.js → chunk-A62RPNIZ.js} +4 -4
- package/dist/{chunk-2ICKARYU.js.map → chunk-A62RPNIZ.js.map} +1 -1
- package/dist/{chunk-ZVVZ67EH.js → chunk-ATRQ2PKM.js} +2 -2
- package/dist/{chunk-ZVVZ67EH.js.map → chunk-ATRQ2PKM.js.map} +1 -1
- package/dist/{chunk-UKIL4XH5.js → chunk-AVXSY4WO.js} +4 -4
- package/dist/{chunk-UKIL4XH5.js.map → chunk-AVXSY4WO.js.map} +1 -1
- package/dist/{chunk-UFWADBG6.js → chunk-BR2IXOWX.js} +3 -3
- package/dist/{chunk-UFWADBG6.js.map → chunk-BR2IXOWX.js.map} +1 -1
- package/dist/{chunk-PM6DO25W.js → chunk-CMHRZOHQ.js} +3 -3
- package/dist/{chunk-PM6DO25W.js.map → chunk-CMHRZOHQ.js.map} +1 -1
- package/dist/{chunk-NQCQTAMQ.js → chunk-D6L7RQGP.js} +7 -7
- package/dist/{chunk-NQCQTAMQ.js.map → chunk-D6L7RQGP.js.map} +1 -1
- package/dist/{chunk-TJRNJVGU.js → chunk-EINLFFP6.js} +3 -3
- package/dist/{chunk-TJRNJVGU.js.map → chunk-EINLFFP6.js.map} +1 -1
- package/dist/{chunk-SM3UPDXE.js → chunk-GH3BHLBF.js} +6 -6
- package/dist/{chunk-SM3UPDXE.js.map → chunk-GH3BHLBF.js.map} +1 -1
- package/dist/{chunk-PE3A6FFW.js → chunk-HCYS7GFP.js} +3 -3
- package/dist/{chunk-PE3A6FFW.js.map → chunk-HCYS7GFP.js.map} +1 -1
- package/dist/{chunk-XFWB3KFV.js → chunk-HL6SZ7Z3.js} +3 -3
- package/dist/{chunk-XFWB3KFV.js.map → chunk-HL6SZ7Z3.js.map} +1 -1
- package/dist/{chunk-DPLIN2RA.js → chunk-ICSCSM5D.js} +3 -3
- package/dist/{chunk-DPLIN2RA.js.map → chunk-ICSCSM5D.js.map} +1 -1
- package/dist/{chunk-FRX2BO3V.js → chunk-J3UD57GK.js} +27 -17
- package/dist/chunk-J3UD57GK.js.map +1 -0
- package/dist/{chunk-YVWUHPQW.js → chunk-JULFGNQN.js} +3 -3
- package/dist/{chunk-YVWUHPQW.js.map → chunk-JULFGNQN.js.map} +1 -1
- package/dist/{chunk-DDCRSE5P.js → chunk-JV2YHKOY.js} +7 -7
- package/dist/{chunk-DDCRSE5P.js.map → chunk-JV2YHKOY.js.map} +1 -1
- package/dist/{chunk-RXTKWTZV.js → chunk-JXTW3VCT.js} +3 -3
- package/dist/{chunk-RXTKWTZV.js.map → chunk-JXTW3VCT.js.map} +1 -1
- package/dist/{chunk-6S5KL76M.js → chunk-LX3FKVLL.js} +3 -3
- package/dist/{chunk-6S5KL76M.js.map → chunk-LX3FKVLL.js.map} +1 -1
- package/dist/{chunk-GZZPKAV5.js → chunk-MJHSLODD.js} +20 -3
- package/dist/chunk-MJHSLODD.js.map +1 -0
- package/dist/{chunk-LUC6OEWM.js → chunk-NHABMUXY.js} +5 -5
- package/dist/{chunk-LUC6OEWM.js.map → chunk-NHABMUXY.js.map} +1 -1
- package/dist/{chunk-7HJ3YLRF.js → chunk-OGPNWRWU.js} +5 -5
- package/dist/{chunk-7HJ3YLRF.js.map → chunk-OGPNWRWU.js.map} +1 -1
- package/dist/{chunk-NP3WH7JF.js → chunk-RTQTWQHW.js} +3 -3
- package/dist/{chunk-NP3WH7JF.js.map → chunk-RTQTWQHW.js.map} +1 -1
- package/dist/{chunk-FAQRNZ44.js → chunk-WORPEN3X.js} +4 -4
- package/dist/{chunk-FAQRNZ44.js.map → chunk-WORPEN3X.js.map} +1 -1
- package/dist/{chunk-UWU572Q6.js → chunk-WPISSDEI.js} +3 -3
- package/dist/{chunk-UWU572Q6.js.map → chunk-WPISSDEI.js.map} +1 -1
- package/dist/{chunk-L2GKM47Q.js → chunk-XSVWRISC.js} +7 -7
- package/dist/{chunk-L2GKM47Q.js.map → chunk-XSVWRISC.js.map} +1 -1
- package/dist/cli/index.js +61 -52
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/serve.d.ts +5 -0
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/connectors/index.js +10 -10
- package/dist/core/index.js +3 -3
- package/dist/core/provider-registry-credentials.js +2 -2
- package/dist/core/provider-registry.js +1 -1
- package/dist/core/src/index.d.ts +1 -1
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/provider-registry.d.ts +10 -0
- package/dist/core/src/provider-registry.d.ts.map +1 -1
- package/dist/deploy/index.js +3 -3
- package/dist/{ensure-sources-3VOIO6IM.js → ensure-sources-NEZZ6YY7.js} +9 -9
- package/dist/{ensure-sources-3VOIO6IM.js.map → ensure-sources-NEZZ6YY7.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +10 -10
- package/dist/factory-assets/connectors/deploy.js +10 -10
- package/dist/factory-assets/connectors/devserver.js +10 -10
- package/dist/factory-assets/connectors/flow/adapter.js +10 -10
- package/dist/factory-assets/connectors/flow/engine.js +4 -4
- package/dist/factory-assets/connectors/flow/run-flow.js +11 -11
- package/dist/factory-assets/connectors/flow.js +10 -10
- package/dist/factory-assets/connectors/git.js +10 -10
- package/dist/factory-assets/connectors/gmail.js +10 -10
- package/dist/factory-assets/connectors/googledrive.js +10 -10
- package/dist/factory-assets/connectors/local.js +10 -10
- package/dist/factory-assets/connectors/mattermost.js +10 -10
- package/dist/factory-assets/connectors/memory.js +10 -10
- package/dist/factory-assets/connectors/minio.js +10 -10
- package/dist/factory-assets/connectors/postgres.js +10 -10
- package/dist/factory-assets/connectors/s3.js +10 -10
- package/dist/factory-assets/connectors/sharepoint.js +10 -10
- package/dist/factory-assets/connectors/sqlite.js +10 -10
- package/dist/factory-assets/connectors/static-server.js +10 -10
- package/dist/factory-assets/connectors/tunnel.js +10 -10
- package/dist/factory-assets/connectors/webdav.js +10 -10
- package/dist/factory-assets/connectors/xstate-store.js +10 -10
- package/dist/factory-assets/connectors/xstate.js +10 -10
- package/dist/{flows-6WUQ2J4X.js → flows-QTUSWYKY.js} +6 -6
- package/dist/{flows-6WUQ2J4X.js.map → flows-QTUSWYKY.js.map} +1 -1
- package/dist/{helpers-G7AQV3NN.js → helpers-XJEFDCMQ.js} +9 -9
- package/dist/{helpers-G7AQV3NN.js.map → helpers-XJEFDCMQ.js.map} +1 -1
- package/dist/library/index.js +4 -4
- package/dist/{library-publish-YOF75HVC.js → library-publish-N726WYMF.js} +13 -13
- package/dist/{library-publish-YOF75HVC.js.map → library-publish-N726WYMF.js.map} +1 -1
- package/dist/{open-library-DAIEAPNR.js → open-library-D6ACC3TX.js} +11 -11
- package/dist/{open-library-DAIEAPNR.js.map → open-library-D6ACC3TX.js.map} +1 -1
- package/dist/{paths-6VH76QLZ.js → paths-IOOMNHTC.js} +5 -5
- package/dist/{paths-6VH76QLZ.js.map → paths-IOOMNHTC.js.map} +1 -1
- package/dist/{plugin-store-4MXOIEHP.js → plugin-store-OIIPB2MQ.js} +5 -5
- package/dist/{plugin-store-4MXOIEHP.js.map → plugin-store-OIIPB2MQ.js.map} +1 -1
- package/dist/{project-IKHGSG4I.js → project-NRCGUOM4.js} +10 -10
- package/dist/{project-IKHGSG4I.js.map → project-NRCGUOM4.js.map} +1 -1
- package/dist/resolver/index.js +3 -3
- package/dist/runner/index.js +16 -16
- package/dist/runner/src/serve.d.ts +6 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-builder.d.ts +7 -1
- package/dist/runner/src/session-builder.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +6 -6
- package/dist/sdk/bridge.js +8 -8
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/flow.js +4 -4
- package/dist/sdk/index.js +16 -16
- package/dist/sdk/resolver.js +3 -3
- package/dist/sdk/runner.js +16 -16
- package/dist/{setup-234UBMJX.js → setup-3GHCXHOO.js} +15 -15
- package/dist/{setup-234UBMJX.js.map → setup-3GHCXHOO.js.map} +1 -1
- package/dist/{skills-FA4VQEO7.js → skills-DH75K326.js} +5 -5
- package/dist/{skills-FA4VQEO7.js.map → skills-DH75K326.js.map} +1 -1
- package/dist/{source-VAKNCLQY.js → source-OAIEGNQB.js} +12 -12
- package/dist/{source-VAKNCLQY.js.map → source-OAIEGNQB.js.map} +1 -1
- package/dist/{source-manifest-publish-FEFRWILI.js → source-manifest-publish-DQTXHT4V.js} +14 -14
- package/dist/{source-manifest-publish-FEFRWILI.js.map → source-manifest-publish-DQTXHT4V.js.map} +1 -1
- package/dist/tui/index.js +16 -16
- package/dist/workspace-plugin/adapters/mcp.js +5 -5
- package/dist/workspace-plugin/adapters/omp.js +7 -7
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-FRX2BO3V.js.map +0 -1
- package/dist/chunk-GZZPKAV5.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../bridge/src/cloud.ts","../bridge/src/drivers/scrub-transcript.ts","../bridge/src/agent-transcript.ts","../bridge/src/drivers/resume-probe.ts"],"names":["join"],"mappings":"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","file":"chunk-6S5KL76M.js","sourcesContent":["/**\n * AI endpoint transport for the `claude-sdk` driver — the Claude Agent SDK's\n * child-process environment.\n *\n * {@link buildClaudeEndpointEnv} takes an **AI provider registry entry** and\n * is what the driver calls, on every transport. It is plan §2.3's\n * `buildEndpointEnv` for the claude-sdk row (named for the driver because the\n * vars it emits — `CLAUDE_CODE_USE_*`, `ANTHROPIC_*` — are the Claude Agent\n * SDK's own contract, not a portable one).\n *\n * A registry entry says what the deleted `cloud` axis said — Amazon Bedrock,\n * Google Vertex AI, Azure AI Foundry, a generic gateway — with `surface` +\n * `transport` + `base_url` + `credential`, and says it for the direct\n * endpoint too, which the `cloud` axis could not address at all.\n *\n * Cross-repo contract: env key names and semantics here are load-bearing —\n * the platform resolves credential bundles against the same key set.\n */\n\nimport {\n type AIProviderEntry,\n type AIProviderLlmEntry,\n entryTransport,\n normalizeAnthropicBaseUrl,\n resolveEntryBaseUrl,\n} from \"@skaile/workspaces/core/provider-registry\";\n\n/**\n * Env vars scrubbed from the inherited environment before an endpoint env is\n * assembled. Ambient first-party credentials or a stale `CLAUDE_CODE_USE_*`\n * flag must never leak into a session whose entry points elsewhere (the\n * ambient carriers are restored explicitly when the entry has none of its\n * own).\n *\n * Deliberately NOT exhaustive: ambient transport-specific vars (AWS_*,\n * GOOGLE_*, ANTHROPIC_VERTEX_PROJECT_ID, ANTHROPIC_FOUNDRY_*) survive so a\n * standalone CLI inherits its own signing chain; the SDK ignores vars whose\n * transport flag is unset.\n */\nconst SCRUBBED_ENV_KEYS = [\"ANTHROPIC_API_KEY\", \"ANTHROPIC_AUTH_TOKEN\", \"ANTHROPIC_BASE_URL\"];\n\n/**\n * The Anthropic first-party endpoint. An entry that resolves to exactly this\n * host needs no `ANTHROPIC_BASE_URL`: the SDK already points there, and an\n * explicit value would make every default session look like a third-party\n * redirect to Claude Code's own telemetry and auth heuristics.\n */\nexport const ANTHROPIC_DEFAULT_BASE_URL = \"https://api.anthropic.com\";\n\n/**\n * Headers the SDK owns and an entry must not restate through\n * `ANTHROPIC_CUSTOM_HEADERS`: the protocol version it was built against, and\n * the two credential carriers (which are `credential.ref`'s job — a literal\n * secret in `headers` is a validation error anyway).\n */\nconst SDK_OWNED_HEADERS: Record<string, true> = {\n \"anthropic-version\": true,\n authorization: true,\n \"x-api-key\": true,\n};\n\n/**\n * Which of the Claude Agent SDK's four native transports an entry addresses.\n *\n * The SDK has no `transport` field: it switches on a `CLAUDE_CODE_USE_*` flag.\n * Bedrock and Vertex are their own wire surfaces, so they are recognized by\n * `surface` as well as by `transport` — a legacy-derived entry that had no\n * region (and therefore no `params`, and therefore no `transport`) is still a\n * Bedrock session, exactly as it was before the registry existed.\n */\nexport type ClaudeEndpointMode = \"anthropic\" | \"bedrock\" | \"vertex\" | \"foundry\";\n\n/** Classify a registry entry into its {@link ClaudeEndpointMode}. */\nexport function claudeEndpointMode(entry: AIProviderEntry): ClaudeEndpointMode {\n const surface = (entry as AIProviderLlmEntry).surface;\n const transport = entryTransport(entry);\n if (surface === \"bedrock-converse-stream\" || transport === \"bedrock\") return \"bedrock\";\n if (surface === \"google-vertex\" || transport === \"vertex\") return \"vertex\";\n if (transport === \"foundry\") return \"foundry\";\n return \"anthropic\";\n}\n\n/** Arguments for {@link buildClaudeEndpointEnv}. */\nexport interface ClaudeEndpointEnvInput {\n /** The selected registry entry — the whole endpoint definition. */\n entry: AIProviderEntry;\n /**\n * The entry's credential, already resolved from its `credential.ref`\n * (`resolveEntryCredential`). Absent for `kind: none`, for an ambient\n * `sigv4` / `google_adc` / `azure_entra` chain, for `oauth` (whose blob the\n * runner writes to the Claude credentials file, never to the env), and for a\n * reference that did not resolve.\n */\n credential?: string;\n /**\n * The driver's base environment — `process.env` with `undefined` dropped.\n * The endpoint vars are layered **on top** of it, never instead of it, so\n * `PATH`, `HOME` and `SKAILE_SESSION_ID` reach the child.\n */\n baseEnv: Record<string, string>;\n /** `AgentConfig.env` plus any credential material the session carried. */\n configEnv?: Record<string, string>;\n}\n\n/**\n * Assemble the Claude Agent SDK child env for one registry entry (plan §2.3).\n *\n * Pure (no external state read, no input mutated). Starts from `baseEnv`\n * merged with `configEnv`, scrubs the inherited Anthropic credential/routing\n * vars and every `CLAUDE_CODE_USE_*` flag, then writes exactly what the entry\n * describes: at most one transport flag, the endpoint, and the credential in\n * the carrier its `kind` names.\n *\n * Credential kinds (§1.4): `api_key_header` → `ANTHROPIC_API_KEY` (the SDK\n * sends it as `x-api-key`); `bearer` → `ANTHROPIC_AUTH_TOKEN` (sent as\n * `Authorization: Bearer`); `sigv4` / `google_adc` / `azure_entra` emit\n * nothing and let the AWS/Google/Azure chain sign — which is why the scrub\n * deliberately spares ambient `AWS_*` / `GOOGLE_*` values; `oauth` and `none`\n * emit nothing, and the pre-scrub ambient carriers are restored so an OAuth or\n * shell-configured session keeps the auth it had.\n *\n * Never returns `undefined` or empty values; absent settings are omitted.\n */\nexport function buildClaudeEndpointEnv(args: ClaudeEndpointEnvInput): Record<string, string> {\n const { entry, credential, baseEnv, configEnv } = args;\n const env: Record<string, string> = { ...baseEnv, ...(configEnv ?? {}) };\n\n // Captured before the scrub — an entry with no credential material of its\n // own falls back to these, the way the gateway branch always has.\n const ambient = { authToken: env.ANTHROPIC_AUTH_TOKEN, apiKey: env.ANTHROPIC_API_KEY };\n\n for (const key of Object.keys(env)) {\n if (SCRUBBED_ENV_KEYS.includes(key) || key.startsWith(\"CLAUDE_CODE_USE_\")) {\n delete env[key];\n }\n }\n\n const set = (key: string, value: string | undefined) => {\n // Falsy check is deliberate: an empty-string credential/setting is never\n // valid env — dropping it beats shipping a key the SDK treats as set.\n if (value) env[key] = value;\n };\n\n const kind = entry.credential?.kind ?? \"none\";\n const params = (entry as AIProviderLlmEntry).params as Record<string, string> | undefined;\n\n // Static headers ride as ANTHROPIC_CUSTOM_HEADERS (`Name: Value` per line),\n // the only channel the SDK offers. An entry with none leaves an ambient\n // value alone.\n const headers = Object.entries(entry.headers ?? {}).filter(\n ([name]) => !SDK_OWNED_HEADERS[name.toLowerCase()],\n );\n if (headers.length > 0) {\n env.ANTHROPIC_CUSTOM_HEADERS = headers.map(([name, value]) => `${name}: ${value}`).join(\"\\n\");\n }\n\n switch (claudeEndpointMode(entry)) {\n case \"bedrock\": {\n env.CLAUDE_CODE_USE_BEDROCK = \"1\";\n // The AWS credential bundle itself is `configEnv` material (AWS_*), and\n // ambient AWS_* survived the scrub, so a standalone CLI keeps its own.\n set(\"AWS_REGION\", params?.region);\n break;\n }\n case \"vertex\": {\n env.CLAUDE_CODE_USE_VERTEX = \"1\";\n // GOOGLE_APPLICATION_CREDENTIALS is a path the runner materialized; it\n // arrives through `configEnv` or ambient, never from `credential`.\n set(\"ANTHROPIC_VERTEX_PROJECT_ID\", params?.project);\n set(\"CLOUD_ML_REGION\", params?.location);\n break;\n }\n case \"foundry\": {\n env.CLAUDE_CODE_USE_FOUNDRY = \"1\";\n // §1.3: an explicit `base_url` wins over the resource-derived endpoint,\n // and the SDK has a separate var for each form.\n if (entry.base_url) set(\"ANTHROPIC_FOUNDRY_BASE_URL\", entry.base_url);\n else set(\"ANTHROPIC_FOUNDRY_RESOURCE\", params?.resource);\n set(\"ANTHROPIC_FOUNDRY_API_KEY\", credential);\n break;\n }\n case \"anthropic\": {\n const baseUrl = normalizeAnthropicBaseUrl(resolveEntryBaseUrl(entry));\n if (baseUrl && baseUrl.toLowerCase() !== ANTHROPIC_DEFAULT_BASE_URL) {\n env.ANTHROPIC_BASE_URL = baseUrl;\n }\n if (kind === \"bearer\") set(\"ANTHROPIC_AUTH_TOKEN\", credential);\n else if (kind === \"api_key_header\") set(\"ANTHROPIC_API_KEY\", credential);\n if (!credential) {\n // `oauth` / `none` / an unresolved ref: the ambient carriers are the\n // only auth this session has, and the scrub just removed them.\n if (ambient.authToken) env.ANTHROPIC_AUTH_TOKEN = ambient.authToken;\n else set(\"ANTHROPIC_API_KEY\", ambient.apiKey);\n }\n break;\n }\n }\n\n return env;\n}\n","/**\n * Poisoned-transcript repair for the Claude Agent SDK driver.\n *\n * The Anthropic Messages API can permanently reject a conversation once its\n * persisted history contains a malformed content block. Because the bad block\n * lives in the SDK's on-disk JSONL transcript, every replayed turn fails with\n * the same `400 invalid_request_error` and the session is bricked with no\n * in-band recovery.\n *\n * This module repairs the transcript in place, covering three known poison\n * classes:\n *\n * 1. **Image `media_type` mismatch / omission.** An image block whose declared\n * `media_type` does not match — or is missing for — the actual bytes:\n * `... The image was specified using the image/png media type, but the\n * image appears to be a image/jpeg image`. Produced by the Claude Code\n * `Read` tool's format fallback (anthropics/claude-code#55338, #30124,\n * #33179). Repaired by sniffing the base64 magic bytes and correcting\n * `media_type`.\n * 2. **Oversized image.** An image whose decoded payload exceeds the API's\n * 5 MB per-image limit (anthropics/claude-code#34566). Replaced with a\n * text stub — the byte budget cannot be recovered any other way.\n * 3. **`cache_control` on an empty text block.** A text block carrying a\n * `cache_control` marker with empty/whitespace `text`\n * (anthropics/claude-code#59626). The `cache_control` field is stripped.\n *\n * Genuinely unidentifiable image blocks are also replaced with a text stub.\n *\n * Recovering by content scan (rather than parsing the API's `messages.N`\n * index) is deliberate: the index addresses the assembled API request, not a\n * JSONL line, and reproducing the SDK's message-assembly is fragile. A full\n * scan is index-free and repairs every poisoned block in one pass.\n *\n * **Async and line-streaming since #454.** A Claude Code transcript is routinely\n * multi-megabyte (base64 images inline in `tool_result` blocks), and this runs on\n * a failed turn *and before every resume* — inside the single-threaded `skaile\n * serve` loop. The previous `readFileSync` + `writeFileSync` + `renameSync` held\n * the loop for the whole file and materialised it twice over as one string. Both\n * passes now stream line by line off a `createReadStream`, so the loop is yielded\n * between lines and peak memory is one JSONL line rather than the whole file, and\n * every I/O phase is deadline-bounded.\n *\n * Streaming was chosen over a worker thread: the work is I/O-bound rather than\n * CPU-bound (per-line `JSON.parse` on a yielded loop is not what stalls a turn),\n * and a worker would add a structured-clone of the same multi-MB payload plus a\n * thread lifecycle to a path that must never block a turn.\n *\n * @module\n */\n\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport { readdir, rename, stat, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\n\n/**\n * Minimal logger shape accepted by {@link scrubPoisonedTranscript}. Compatible\n * with the bridge `Logger`, but narrowed so the helper stays unit-testable\n * without a real logger instance.\n *\n * @category Transcript repair\n */\nexport interface ScrubLogger {\n info(message: string, data?: Record<string, unknown>): void;\n warn(message: string, data?: Record<string, unknown>): void;\n}\n\n/**\n * Options for {@link scrubPoisonedTranscript}.\n *\n * @category Transcript repair\n */\nexport interface ScrubTranscriptOptions {\n /**\n * Claude Code config directory — the parent of `projects/`. Resolve from\n * `CLAUDE_CONFIG_DIR`, falling back to `~/.claude`.\n */\n configDir: string;\n /** SDK session id whose transcript JSONL should be repaired. */\n sessionId: string;\n /** Optional logger for diagnostics. */\n log?: ScrubLogger;\n /**\n * Where the transcript is read and written. Defaults to this process's own\n * filesystem access ({@link localTranscriptStore}); with the agent uid split\n * the transcript belongs to the agent uid and must be reached through it.\n */\n store?: TranscriptStore;\n}\n\n/**\n * Filesystem access to Claude Code transcripts. The CLI creates them 0600 in\n * 0700 dirs, so when it runs as a different uid than the runner, only that uid\n * can locate, read or rewrite them (see `agent-transcript.ts`).\n *\n * @category Transcript repair\n */\nexport interface TranscriptStore {\n /** Path of `<sessionId>.jsonl` under `<configDir>/projects/`, or `null` when absent. */\n locate(configDir: string, sessionId: string, timeoutMs?: number): Promise<string | null>;\n /** The file's contents as UTF-8 chunks. */\n read(filePath: string): AsyncIterable<string>;\n /** Atomically replace the file with `chunks` via a `.scrub-tmp` sibling. */\n replace(filePath: string, chunks: AsyncIterable<string>): Promise<void>;\n /** Remove the sibling a failed or abandoned {@link replace} left (best effort). */\n discardTemp(filePath: string): Promise<void>;\n}\n\n/**\n * Outcome of a {@link scrubPoisonedTranscript} pass.\n *\n * @category Transcript repair\n */\nexport interface ScrubTranscriptResult {\n /** The located JSONL transcript path, or `null` when not found. */\n filePath: string | null;\n /** Image blocks whose `media_type` was corrected (or filled in) to match the bytes. */\n corrected: number;\n /**\n * Image blocks replaced with a text stub — either unidentifiable bytes or a\n * payload over the API's 5 MB per-image limit.\n */\n stubbed: number;\n /** Empty text blocks from which a rejected `cache_control` marker was stripped. */\n cacheStripped: number;\n /**\n * `true` when the transcript was located, contained at least one poisoned\n * block, and was rewritten. `false` means nothing needed repair (or the\n * file was not found) — the caller should not retry the resume.\n */\n changed: boolean;\n}\n\n/** Text inserted in place of an image block whose format cannot be identified. */\nconst STUB_TEXT = \"[image removed: unprocessable image data]\";\n\n/** Text inserted in place of an image block that exceeds the API size limit. */\nconst STUB_TEXT_OVERSIZED = \"[image removed: image too large]\";\n\n/**\n * The Anthropic Messages API rejects any single image whose decoded payload\n * exceeds 5 MB. An image at or under this is left alone; a larger one is\n * stubbed (its byte budget cannot be recovered).\n */\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\n/**\n * Identify an image's media type from the leading bytes of its base64 payload.\n *\n * Recognises the four formats the Anthropic API accepts. Returns `null` when\n * the magic bytes match no known format — the caller treats that as a\n * genuinely corrupt block and stubs it.\n *\n * @param base64 - Base64-encoded image data (only the prefix is inspected).\n * @returns An `image/*` media type, or `null` when unrecognised.\n * @category Transcript repair\n */\nexport function sniffImageMediaType(base64: string): string | null {\n let buf: Buffer;\n try {\n // 32 base64 chars decode to 24 bytes — enough for the WebP check at 12.\n buf = Buffer.from(base64.slice(0, 32), \"base64\");\n } catch {\n return null;\n }\n if (buf.length < 4) {\n return null;\n }\n // JPEG — SOI marker `FF D8`. Third byte varies (and may be corrupt), so a\n // two-byte check is intentional: it still matches malformed JPEGs, which is\n // exactly the poison case the API flags as \"appears to be image/jpeg\".\n if (buf[0] === 0xff && buf[1] === 0xd8) {\n return \"image/jpeg\";\n }\n // PNG — `89 50 4E 47`.\n if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47) {\n return \"image/png\";\n }\n // GIF — `47 49 46 38` (\"GIF8\").\n if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x38) {\n return \"image/gif\";\n }\n // WebP — `RIFF` at 0..3 and `WEBP` at 8..11.\n if (\n buf.length >= 12 &&\n buf[0] === 0x52 &&\n buf[1] === 0x49 &&\n buf[2] === 0x46 &&\n buf[3] === 0x46 &&\n buf[8] === 0x57 &&\n buf[9] === 0x45 &&\n buf[10] === 0x42 &&\n buf[11] === 0x50\n ) {\n return \"image/webp\";\n }\n return null;\n}\n\n/** A base64 image source on a content block (shape is SDK-defined). */\ninterface Base64ImageSource {\n type?: string;\n media_type?: string;\n data?: string;\n}\n\n/** Loosely-typed content block from a transcript message. */\ninterface ContentBlockLike {\n type?: string;\n source?: Base64ImageSource;\n content?: unknown;\n [k: string]: unknown;\n}\n\n/** Mutable counters threaded through one scrub pass. */\ninterface ScrubCounters {\n corrected: number;\n stubbed: number;\n cacheStripped: number;\n}\n\n/** Total repairs recorded in a counter set — used to detect per-line changes. */\nfunction totalChanges(c: ScrubCounters): number {\n return c.corrected + c.stubbed + c.cacheStripped;\n}\n\n/**\n * Repair a single content block. Returns the (possibly replaced) block.\n *\n * - A `tool_result` block recurses into its `content` array.\n * - A text block carrying a `cache_control` marker whose `text` is empty or\n * whitespace has the marker stripped (the API rejects `cache_control` on\n * empty text blocks).\n * - An image block whose decoded payload exceeds the API's 5 MB limit is\n * replaced with a text stub.\n * - An image block whose bytes match no known format is replaced with a text\n * stub (an image cannot simply be dropped — a `tool_result` must keep at\n * least one content entry, and a bare `image` block is replaced 1:1).\n * - An image block whose declared `media_type` mismatches (or is missing for)\n * the sniffed type is corrected in place.\n * - Every other block is returned untouched.\n */\nfunction scrubBlock(block: ContentBlockLike, counters: ScrubCounters): ContentBlockLike {\n if (block.type === \"tool_result\" && Array.isArray(block.content)) {\n return {\n ...block,\n content: (block.content as ContentBlockLike[]).map((inner) => scrubBlock(inner, counters)),\n };\n }\n\n // A `cache_control` marker on a text block whose text is empty or whitespace\n // is rejected by the API (\"cache_control cannot be set for empty text\n // blocks\"). Strip the marker — the empty block itself is harmless.\n if (block.type === \"text\" && block.cache_control != null) {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n if (text.trim() === \"\") {\n counters.cacheStripped++;\n const clone = { ...block };\n delete clone.cache_control;\n return clone;\n }\n }\n\n if (\n block.type === \"image\" &&\n block.source?.type === \"base64\" &&\n typeof block.source.data === \"string\"\n ) {\n const data = block.source.data;\n // The API rejects any image whose decoded payload exceeds 5 MB. The byte\n // budget cannot be salvaged, so the whole block becomes a text stub.\n // base64 encodes 3 bytes per 4 chars, so decoded length ≈ len * 3 / 4.\n if (Math.floor((data.length * 3) / 4) > MAX_IMAGE_BYTES) {\n counters.stubbed++;\n return { type: \"text\", text: STUB_TEXT_OVERSIZED };\n }\n const sniffed = sniffImageMediaType(data);\n if (sniffed === null) {\n counters.stubbed++;\n return { type: \"text\", text: STUB_TEXT };\n }\n if (sniffed !== block.source.media_type) {\n counters.corrected++;\n return { ...block, source: { ...block.source, media_type: sniffed } };\n }\n }\n\n return block;\n}\n\n/**\n * Locate the JSONL transcript for `sessionId` under `<configDir>/projects/`.\n *\n * Claude Code encodes the project directory into the `projects/` subfolder\n * name; rather than reproduce that encoding, this scans every subfolder for\n * `<sessionId>.jsonl` (the session id is a UUID — globally unique).\n *\n * Async and deadline-bounded since #454. The `existsSync(projectsDir)` probe is\n * gone: `readdir` already fails on a missing directory, so the probe was a\n * second stat on the same path for no information.\n *\n * `timeoutMs` defaults to {@link fsDeadlineMs} so callers that only need the\n * path (the resume probe) can omit it.\n *\n * @category Transcript repair\n */\nexport async function locateTranscriptPath(\n configDir: string,\n sessionId: string,\n timeoutMs: number = fsDeadlineMs(),\n): Promise<string | null> {\n const projectsDir = join(configDir, \"projects\");\n const entries = await tryWithFsDeadline(\n `readdir ${projectsDir}`,\n () => readdir(projectsDir),\n null,\n timeoutMs,\n );\n if (!entries) return null;\n for (const entry of entries) {\n const candidate = join(projectsDir, entry, `${sessionId}.jsonl`);\n const found = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isFile(),\n false,\n timeoutMs,\n );\n if (found) return candidate;\n }\n return null;\n}\n\n/**\n * Yield a file's contents line by line, reproducing `readFileSync(...).split(\"\\n\")`\n * exactly — including the final (possibly empty) segment, so a trailing newline\n * survives a rewrite byte for byte.\n *\n * Splits on `\\n` alone, so a line out of a CRLF transcript arrives with its\n * `\\r` still attached. That carrier byte is part of the line here, and\n * {@link repairLine} re-attaches it to a line it rewrites — the file keeps the\n * terminator style it arrived with. Deliberately not `node:readline`:\n * `crlfDelay` strips the `\\r` outright (rewriting a CRLF transcript to LF) and\n * the interface swallows the trailing-newline distinction, either of which\n * would make the \"clean transcript is left byte-for-byte untouched\" guarantee\n * false. Only one line is held in memory at a time, so a multi-MB transcript\n * never materialises as a single string.\n */\nasync function* streamLines(chunks: AsyncIterable<string>): AsyncGenerator<string> {\n let pending = \"\";\n for await (const chunk of chunks) {\n pending += chunk;\n let idx = pending.indexOf(\"\\n\");\n while (idx !== -1) {\n yield pending.slice(0, idx);\n pending = pending.slice(idx + 1);\n idx = pending.indexOf(\"\\n\");\n }\n }\n yield pending;\n}\n\n/**\n * The runner's own filesystem access: the default {@link TranscriptStore}.\n *\n * @category Transcript repair\n */\nexport const localTranscriptStore: TranscriptStore = {\n locate: (configDir, sessionId, timeoutMs) =>\n locateTranscriptPath(configDir, sessionId, timeoutMs),\n async *read(filePath) {\n const stream = createReadStream(filePath, { encoding: \"utf8\" });\n try {\n for await (const chunk of stream) yield chunk as string;\n } finally {\n stream.destroy();\n }\n },\n async replace(filePath, chunks) {\n const tmpPath = `${filePath}.scrub-tmp`;\n await pipeline(chunks, createWriteStream(tmpPath, { encoding: \"utf8\" }));\n await rename(tmpPath, filePath);\n },\n async discardTemp(filePath) {\n const tmpPath = `${filePath}.scrub-tmp`;\n await tryWithFsDeadline(`unlink ${tmpPath}`, () => unlink(tmpPath), undefined, fsDeadlineMs());\n },\n};\n\n/**\n * Repair one JSONL line, returning the (possibly rewritten) line and mutating\n * `counters`. A non-JSON, blank, or content-less line is returned untouched.\n *\n * The reader splits on `\\n` only, so a line from a CRLF transcript still carries\n * its trailing `\\r`. An untouched line is returned verbatim and keeps it; a\n * rewritten one is rebuilt by `JSON.stringify`, which would drop it — leaving a\n * repaired CRLF transcript with mixed line endings. So the terminator is split\n * off before the parse and re-appended to the rewritten line.\n */\nfunction repairLine(line: string, counters: ScrubCounters): string {\n if (line.trim() === \"\") return line;\n const eol = line.endsWith(\"\\r\") ? \"\\r\" : \"\";\n const body = eol === \"\" ? line : line.slice(0, -1);\n let entry: { message?: { content?: unknown } };\n try {\n entry = JSON.parse(body);\n } catch {\n return line; // Not JSON — leave untouched.\n }\n const content = entry.message?.content;\n if (!Array.isArray(content)) return line;\n const before = totalChanges(counters);\n const scrubbed = (content as ContentBlockLike[]).map((block) => scrubBlock(block, counters));\n if (totalChanges(counters) === before) return line; // Nothing changed on this line.\n return `${JSON.stringify({ ...entry, message: { ...entry.message, content: scrubbed } })}${eol}`;\n}\n\n/**\n * Scan a Claude Code SDK transcript for image content blocks whose declared\n * `media_type` does not match the actual bytes, repair them, and atomically\n * rewrite the file.\n *\n * Safe to call after a turn has failed: the SDK query is dead at that point,\n * and the next resume re-reads the transcript from disk.\n *\n * **Async since #454.** Two streaming passes rather than one whole-file read:\n * pass 1 counts repairs without writing anything, and pass 2 runs only when\n * pass 1 found something. The common case — the preventive scrub of a clean\n * transcript before every resume — is therefore one streaming read and zero\n * writes, and a clean transcript is still left byte-for-byte untouched.\n *\n * @param opts - Config directory, session id, and an optional logger.\n * @returns A {@link ScrubTranscriptResult}. When `changed` is `true` the\n * caller may retry the resume with the same session id.\n * @category Transcript repair\n */\nexport async function scrubPoisonedTranscript(\n opts: ScrubTranscriptOptions,\n): Promise<ScrubTranscriptResult> {\n const { configDir, sessionId, log } = opts;\n const store = opts.store ?? localTranscriptStore;\n const timeoutMs = fsDeadlineMs();\n const result: ScrubTranscriptResult = {\n filePath: null,\n corrected: 0,\n stubbed: 0,\n cacheStripped: 0,\n changed: false,\n };\n\n let filePath: string | null;\n try {\n filePath = await store.locate(configDir, sessionId, timeoutMs);\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to locate transcript\", {\n configDir,\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n return result;\n }\n if (!filePath) {\n log?.warn(\"scrub-transcript: no transcript found\", { configDir, sessionId });\n return result;\n }\n result.filePath = filePath;\n\n // ── Pass 1: detect. Streams the transcript, counting repairs, writing nothing.\n const counters: ScrubCounters = { corrected: 0, stubbed: 0, cacheStripped: 0 };\n try {\n await withFsDeadline(\n `scan transcript ${filePath}`,\n async () => {\n for await (const line of streamLines(store.read(filePath))) repairLine(line, counters);\n },\n timeoutMs,\n );\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to read transcript\", {\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n return result;\n }\n\n result.corrected = counters.corrected;\n result.stubbed = counters.stubbed;\n result.cacheStripped = counters.cacheStripped;\n\n if (totalChanges(counters) === 0) {\n return result;\n }\n\n // ── Pass 2: rewrite. Atomic: stream a sibling temp file, then rename over the\n // original. Line separators are re-emitted exactly as pass 1 split them, so a\n // trailing newline and any blank lines survive verbatim.\n const source = filePath;\n try {\n await withFsDeadline(\n `rewrite transcript ${source}`,\n async () => {\n const discard: ScrubCounters = { corrected: 0, stubbed: 0, cacheStripped: 0 };\n await store.replace(\n source,\n (async function* () {\n let first = true;\n for await (const line of streamLines(store.read(source))) {\n yield first ? repairLine(line, discard) : `\\n${repairLine(line, discard)}`;\n first = false;\n }\n })(),\n );\n },\n timeoutMs,\n );\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to rewrite transcript\", {\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n // Never leave a half-written `.scrub-tmp` in the SDK's projects dir, also\n // when the deadline abandoned the replace mid-write.\n await store.discardTemp(source).catch(() => {});\n return result;\n }\n\n result.changed = true;\n log?.info(\"scrub-transcript: repaired poisoned transcript\", {\n filePath,\n corrected: result.corrected,\n stubbed: result.stubbed,\n cacheStripped: result.cacheStripped,\n });\n return result;\n}\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { fsDeadlineMs, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { resolveAgentExec } from \"./agent-exec.js\";\nimport { localTranscriptStore, type TranscriptStore } from \"./drivers/scrub-transcript.js\";\n\n/**\n * Transcripts reached through the agent launch shim.\n *\n * With the uid split on, the Claude CLI runs as the agent uid and creates its\n * transcripts 0600 in 0700 dirs, so the runner can no longer list, read or\n * rewrite them itself. This store runs plain tools (`find`, `cat`, `sh`, `mv`)\n * as the agent uid through the shim instead. The child gets only `PATH` and\n * `LC_ALL`, never the runner's environment, and runs in `/` because the\n * runner's own cwd may not be enterable by the agent uid.\n */\nexport function agentTranscriptStore(shim: string): TranscriptStore {\n // A replace the scrub's deadline abandoned keeps running; discardTemp stops\n // it before removing its temp file.\n const inFlight = new Map<string, ChildProcess>();\n // Paths whose rewrite discardTemp gave up on: their rename must never run.\n const cancelled = new Set<string>();\n const track = (filePath: string, child: ChildProcess) => {\n inFlight.set(filePath, child);\n child.once(\"close\", () => {\n if (inFlight.get(filePath) === child) inFlight.delete(filePath);\n });\n };\n return {\n async locate(configDir, sessionId, timeoutMs = 10_000) {\n // A session id is a UUID; anything glob- or path-shaped is not ours.\n if (!/^[A-Za-z0-9._-]+$/.test(sessionId)) return null;\n const projectsDir = join(configDir, \"projects\");\n // Markers on stdout, not exit codes, carry the answer: a shim or launcher\n // failure has exit codes of its own and must never read as \"not found\".\n const { stdout } = await collect(\n runAsAgent(shim, [\n \"sh\",\n \"-c\",\n '[ -d \"$1\" ] || { echo \"@@no-projects\"; exit 0; }; ' +\n 'find \"$1\" -mindepth 2 -maxdepth 2 -type f -name \"$2\" -print -quit; echo \"@@find:$?\"',\n \"sh\",\n projectsDir,\n `${sessionId}.jsonl`,\n ]),\n timeoutMs,\n );\n const lines = stdout.split(\"\\n\").map((l) => l.trim());\n // A missing projects/ is the same \"not found\" as a failed readdir locally.\n if (lines.includes(\"@@no-projects\")) return null;\n const status = lines.find((l) => l.startsWith(\"@@find:\"));\n if (status === undefined)\n throw new Error(\"locating a transcript as the agent uid failed (no answer from the shim)\");\n // A path find printed counts even if it later hit an unreadable sibling.\n const found = lines.find((l) => l.startsWith(\"/\"));\n if (found) return found;\n if (status !== \"@@find:0\")\n throw new Error(`locating a transcript as the agent uid failed (${status.slice(2)})`);\n return null;\n },\n\n async *read(filePath) {\n const child = runAsAgent(shim, [\"cat\", \"--\", filePath]);\n const exited = exitOf(child);\n exited.catch(() => {}); // awaited below; this only stops an unhandled rejection\n const stderr = drain(child);\n child.stdout?.setEncoding(\"utf8\");\n for await (const chunk of child.stdout as AsyncIterable<string>) yield chunk;\n const code = await exited;\n if (code !== 0)\n throw new Error(`reading ${filePath} as the agent uid failed: ${await stderr}`);\n },\n\n async replace(filePath, chunks) {\n const child = runAsAgent(shim, [\n \"sh\",\n \"-c\",\n // 0600 like the CLI's own files. Only writes the temp file: the rename\n // is a separate step below, run only after the input was fully sent,\n // so a killed or starved writer can never commit a partial transcript.\n 'umask 077; cat > \"$1.scrub-tmp\"',\n \"sh\",\n filePath,\n ]);\n cancelled.delete(filePath);\n track(filePath, child);\n const exited = exitOf(child);\n exited.catch(() => {}); // awaited below; this only stops an unhandled rejection\n const stderr = drain(child);\n const stdin = child.stdin;\n if (!stdin) throw new Error(\"agent shim has no stdin\");\n // A child that dies early surfaces through its exit code, not an EPIPE crash.\n stdin.on(\"error\", () => {});\n const gone = exited.then(\n () => undefined,\n () => undefined,\n );\n // Stop pulling input as soon as the child is gone (killed by discardTemp,\n // or failed), instead of waiting on a producer that may never resume.\n const input = chunks[Symbol.asyncIterator]();\n let drained = false;\n try {\n for (;;) {\n const next = await Promise.race([\n input.next(),\n gone.then(() => ({ dead: true as const })),\n ]);\n if (\"dead\" in next || stdin.destroyed) break;\n if (next.done) {\n drained = true;\n break;\n }\n if (!stdin.write(next.value)) {\n await Promise.race([new Promise((resolve) => stdin.once(\"drain\", resolve)), gone]);\n }\n }\n } finally {\n stdin.end();\n // Close the producer too, so the reader feeding it (a `cat` through\n // the shim) is torn down rather than left blocked on a full pipe.\n if (!drained) void input.return?.()?.catch(() => {});\n }\n const code = await exited;\n if (code !== 0 || !drained)\n throw new Error(`rewriting ${filePath} as the agent uid failed: ${await stderr}`);\n if (cancelled.has(filePath)) throw new Error(`rewrite of ${filePath} was abandoned`);\n const mover = runAsAgent(shim, [\"mv\", \"-f\", \"--\", `${filePath}.scrub-tmp`, filePath]);\n track(filePath, mover);\n const moved = await collect(mover, 10_000);\n if (moved.code !== 0) throw new Error(`renaming the rewritten ${filePath} failed`);\n },\n\n async discardTemp(filePath) {\n // Before anything else, so a writer that is just finishing never renames.\n cancelled.add(filePath);\n const pending = inFlight.get(filePath);\n if (pending && pending.exitCode === null && pending.signalCode === null) {\n // The writer cannot commit (the rename is a separate step), so this only\n // stops it; bounded, since a writer stuck on a hung mount may never die.\n const closed = new Promise((resolve) => pending.once(\"close\", resolve));\n pending.kill(\"SIGKILL\");\n await withFsDeadline(`stop the rewrite of ${filePath}`, () => closed, fsDeadlineMs());\n }\n await collect(runAsAgent(shim, [\"rm\", \"-f\", \"--\", `${filePath}.scrub-tmp`]), 10_000);\n },\n };\n}\n\n/**\n * The transcript store for this runner: through the agent shim when\n * `SKAILE_AGENT_EXEC` is set, the runner's own filesystem otherwise.\n */\nexport function transcriptStoreForRuntime(\n env: Record<string, string | undefined> = process.env,\n): TranscriptStore {\n const shim = resolveAgentExec(env);\n return shim ? agentTranscriptStore(shim) : localTranscriptStore;\n}\n\nfunction runAsAgent(shim: string, argv: string[]): ChildProcess {\n return spawn(shim, [\"--\", ...argv], {\n cwd: \"/\",\n env: { PATH: process.env.PATH ?? \"/usr/bin:/bin\", LC_ALL: \"C\" },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n}\n\nfunction exitOf(child: ChildProcess): Promise<number> {\n return new Promise((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\n/** Keep the last 1 KiB of stderr for the error message, and keep the pipe drained. */\nfunction drain(child: ChildProcess): Promise<string> {\n return new Promise((resolve) => {\n let tail = \"\";\n child.stderr?.setEncoding(\"utf8\");\n child.stderr?.on(\"data\", (c: string) => {\n tail = (tail + c).slice(-1024);\n });\n child.stderr?.once(\"close\", () => resolve(tail.trim()));\n });\n}\n\nasync function collect(\n child: ChildProcess,\n timeoutMs: number,\n): Promise<{ code: number; stdout: string }> {\n let stdout = \"\";\n child.stdout?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (c: string) => {\n stdout += c;\n });\n void drain(child);\n child.stdin?.end();\n let timer: NodeJS.Timeout | undefined;\n try {\n const code = await Promise.race([\n exitOf(child),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n reject(new Error(`agent shim did not answer within ${timeoutMs} ms`));\n }, timeoutMs);\n }),\n ]);\n return { code, stdout };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Pre-first-turn resume probe for the Claude Agent SDK driver.\n *\n * A tier-1 native resume only hands its session id to the SDK inside the first\n * real turn, so the `jsonl_lost` outcome (\"No conversation found\") is invisible\n * until a turn is consumed. The runner shares the container filesystem with the\n * SDK, so a cheap `stat` of the on-disk JSONL transcript is an authoritative,\n * side-effect-free signal of whether the resume will find its history — no\n * probe query, no spurious model turn.\n *\n * @module\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { withFsDeadline } from \"@skaile/workspaces/core\";\nimport { locateTranscriptPath } from \"./scrub-transcript.js\";\n\n/**\n * Overall wall-clock budget for the probe. Deliberately a small fraction of the\n * platform's `session_init_ack` timeout (`DEFAULT_INIT_ACK_TIMEOUT_MS`, 15s):\n * the probe runs synchronously on the pre-ack path, so a wedged\n * `CLAUDE_CONFIG_DIR` mount must never push the ack past its deadline.\n */\nconst RESUME_PROBE_TIMEOUT_MS = 2_000;\n\n/**\n * Outcome of {@link probeResumeTranscript}: whether the SDK transcript for a\n * requested tier-1 resume exists on disk.\n *\n * @category Resume probe\n */\nexport type ResumeProbeOutcome = \"transcript_found\" | \"jsonl_lost\";\n\n/**\n * Resolve the Claude Code config directory — the parent of `projects/` — from\n * an explicit env map, the process environment, or the `~/.claude` default.\n *\n * The runner's probe and the claude-sdk driver share this one resolver, so they\n * agree as long as they see the same `CLAUDE_CONFIG_DIR`. Today they do:\n * `CLAUDE_CONFIG_DIR` is container-scoped and neither side threads a per-session\n * override through `config.env`, so both fall through to `process.env`. If a\n * future change ever set the driver's `config.env.CLAUDE_CONFIG_DIR` to a\n * divergent path, the reactive `resume_failed { jsonl_lost }` turn remains the\n * safety net.\n *\n * @category Resume probe\n */\nexport function resolveClaudeConfigDir(env?: Record<string, string | undefined>): string {\n return env?.CLAUDE_CONFIG_DIR || process.env.CLAUDE_CONFIG_DIR || join(homedir(), \".claude\");\n}\n\n/**\n * Probe whether the SDK JSONL transcript for `sessionId` exists on disk.\n *\n * Non-null locator result → `transcript_found`; null → `jsonl_lost`;\n * `undefined` → outcome unknown (the probe exceeded its budget or errored). The\n * caller leaves the ack field ABSENT on `undefined` so the reactive\n * `resume_failed { jsonl_lost }` turn stays the safety net — a timed-out probe\n * must never masquerade as a genuine `jsonl_lost` and force a needless downgrade.\n *\n * `opts.timeoutMs` overrides {@link RESUME_PROBE_TIMEOUT_MS}; `opts.locate`\n * overrides the transcript locator (used by tests / alternate stores).\n *\n * @category Resume probe\n */\nexport async function probeResumeTranscript(\n sessionId: string,\n opts?: {\n env?: Record<string, string | undefined>;\n timeoutMs?: number;\n locate?: (configDir: string, sessionId: string) => Promise<string | null>;\n },\n): Promise<ResumeProbeOutcome | undefined> {\n const configDir = resolveClaudeConfigDir(opts?.env);\n const timeoutMs = opts?.timeoutMs ?? RESUME_PROBE_TIMEOUT_MS;\n const locate = opts?.locate ?? locateTranscriptPath;\n try {\n // Bound the whole probe on wall-clock and THROW on expiry: the inner per-op\n // deadline swallows a timeout into a null path (a false `jsonl_lost`), so a\n // wedged mount must yield \"unknown\" here rather than a spurious downgrade.\n const filePath = await withFsDeadline(\n `resume-probe ${sessionId}`,\n () => locate(configDir, sessionId),\n timeoutMs,\n );\n return filePath ? \"transcript_found\" : \"jsonl_lost\";\n } catch {\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../bridge/src/cloud.ts","../bridge/src/drivers/scrub-transcript.ts","../bridge/src/agent-transcript.ts","../bridge/src/drivers/resume-probe.ts"],"names":["join"],"mappings":"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","file":"chunk-LX3FKVLL.js","sourcesContent":["/**\n * AI endpoint transport for the `claude-sdk` driver — the Claude Agent SDK's\n * child-process environment.\n *\n * {@link buildClaudeEndpointEnv} takes an **AI provider registry entry** and\n * is what the driver calls, on every transport. It is plan §2.3's\n * `buildEndpointEnv` for the claude-sdk row (named for the driver because the\n * vars it emits — `CLAUDE_CODE_USE_*`, `ANTHROPIC_*` — are the Claude Agent\n * SDK's own contract, not a portable one).\n *\n * A registry entry says what the deleted `cloud` axis said — Amazon Bedrock,\n * Google Vertex AI, Azure AI Foundry, a generic gateway — with `surface` +\n * `transport` + `base_url` + `credential`, and says it for the direct\n * endpoint too, which the `cloud` axis could not address at all.\n *\n * Cross-repo contract: env key names and semantics here are load-bearing —\n * the platform resolves credential bundles against the same key set.\n */\n\nimport {\n type AIProviderEntry,\n type AIProviderLlmEntry,\n entryTransport,\n normalizeAnthropicBaseUrl,\n resolveEntryBaseUrl,\n} from \"@skaile/workspaces/core/provider-registry\";\n\n/**\n * Env vars scrubbed from the inherited environment before an endpoint env is\n * assembled. Ambient first-party credentials or a stale `CLAUDE_CODE_USE_*`\n * flag must never leak into a session whose entry points elsewhere (the\n * ambient carriers are restored explicitly when the entry has none of its\n * own).\n *\n * Deliberately NOT exhaustive: ambient transport-specific vars (AWS_*,\n * GOOGLE_*, ANTHROPIC_VERTEX_PROJECT_ID, ANTHROPIC_FOUNDRY_*) survive so a\n * standalone CLI inherits its own signing chain; the SDK ignores vars whose\n * transport flag is unset.\n */\nconst SCRUBBED_ENV_KEYS = [\"ANTHROPIC_API_KEY\", \"ANTHROPIC_AUTH_TOKEN\", \"ANTHROPIC_BASE_URL\"];\n\n/**\n * The Anthropic first-party endpoint. An entry that resolves to exactly this\n * host needs no `ANTHROPIC_BASE_URL`: the SDK already points there, and an\n * explicit value would make every default session look like a third-party\n * redirect to Claude Code's own telemetry and auth heuristics.\n */\nexport const ANTHROPIC_DEFAULT_BASE_URL = \"https://api.anthropic.com\";\n\n/**\n * Headers the SDK owns and an entry must not restate through\n * `ANTHROPIC_CUSTOM_HEADERS`: the protocol version it was built against, and\n * the two credential carriers (which are `credential.ref`'s job — a literal\n * secret in `headers` is a validation error anyway).\n */\nconst SDK_OWNED_HEADERS: Record<string, true> = {\n \"anthropic-version\": true,\n authorization: true,\n \"x-api-key\": true,\n};\n\n/**\n * Which of the Claude Agent SDK's four native transports an entry addresses.\n *\n * The SDK has no `transport` field: it switches on a `CLAUDE_CODE_USE_*` flag.\n * Bedrock and Vertex are their own wire surfaces, so they are recognized by\n * `surface` as well as by `transport` — a legacy-derived entry that had no\n * region (and therefore no `params`, and therefore no `transport`) is still a\n * Bedrock session, exactly as it was before the registry existed.\n */\nexport type ClaudeEndpointMode = \"anthropic\" | \"bedrock\" | \"vertex\" | \"foundry\";\n\n/** Classify a registry entry into its {@link ClaudeEndpointMode}. */\nexport function claudeEndpointMode(entry: AIProviderEntry): ClaudeEndpointMode {\n const surface = (entry as AIProviderLlmEntry).surface;\n const transport = entryTransport(entry);\n if (surface === \"bedrock-converse-stream\" || transport === \"bedrock\") return \"bedrock\";\n if (surface === \"google-vertex\" || transport === \"vertex\") return \"vertex\";\n if (transport === \"foundry\") return \"foundry\";\n return \"anthropic\";\n}\n\n/** Arguments for {@link buildClaudeEndpointEnv}. */\nexport interface ClaudeEndpointEnvInput {\n /** The selected registry entry — the whole endpoint definition. */\n entry: AIProviderEntry;\n /**\n * The entry's credential, already resolved from its `credential.ref`\n * (`resolveEntryCredential`). Absent for `kind: none`, for an ambient\n * `sigv4` / `google_adc` / `azure_entra` chain, for `oauth` (whose blob the\n * runner writes to the Claude credentials file, never to the env), and for a\n * reference that did not resolve.\n */\n credential?: string;\n /**\n * The driver's base environment — `process.env` with `undefined` dropped.\n * The endpoint vars are layered **on top** of it, never instead of it, so\n * `PATH`, `HOME` and `SKAILE_SESSION_ID` reach the child.\n */\n baseEnv: Record<string, string>;\n /** `AgentConfig.env` plus any credential material the session carried. */\n configEnv?: Record<string, string>;\n}\n\n/**\n * Assemble the Claude Agent SDK child env for one registry entry (plan §2.3).\n *\n * Pure (no external state read, no input mutated). Starts from `baseEnv`\n * merged with `configEnv`, scrubs the inherited Anthropic credential/routing\n * vars and every `CLAUDE_CODE_USE_*` flag, then writes exactly what the entry\n * describes: at most one transport flag, the endpoint, and the credential in\n * the carrier its `kind` names.\n *\n * Credential kinds (§1.4): `api_key_header` → `ANTHROPIC_API_KEY` (the SDK\n * sends it as `x-api-key`); `bearer` → `ANTHROPIC_AUTH_TOKEN` (sent as\n * `Authorization: Bearer`); `sigv4` / `google_adc` / `azure_entra` emit\n * nothing and let the AWS/Google/Azure chain sign — which is why the scrub\n * deliberately spares ambient `AWS_*` / `GOOGLE_*` values; `oauth` and `none`\n * emit nothing, and the pre-scrub ambient carriers are restored so an OAuth or\n * shell-configured session keeps the auth it had.\n *\n * Never returns `undefined` or empty values; absent settings are omitted.\n */\nexport function buildClaudeEndpointEnv(args: ClaudeEndpointEnvInput): Record<string, string> {\n const { entry, credential, baseEnv, configEnv } = args;\n const env: Record<string, string> = { ...baseEnv, ...(configEnv ?? {}) };\n\n // Captured before the scrub — an entry with no credential material of its\n // own falls back to these, the way the gateway branch always has.\n const ambient = { authToken: env.ANTHROPIC_AUTH_TOKEN, apiKey: env.ANTHROPIC_API_KEY };\n\n for (const key of Object.keys(env)) {\n if (SCRUBBED_ENV_KEYS.includes(key) || key.startsWith(\"CLAUDE_CODE_USE_\")) {\n delete env[key];\n }\n }\n\n const set = (key: string, value: string | undefined) => {\n // Falsy check is deliberate: an empty-string credential/setting is never\n // valid env — dropping it beats shipping a key the SDK treats as set.\n if (value) env[key] = value;\n };\n\n const kind = entry.credential?.kind ?? \"none\";\n const params = (entry as AIProviderLlmEntry).params as Record<string, string> | undefined;\n\n // Static headers ride as ANTHROPIC_CUSTOM_HEADERS (`Name: Value` per line),\n // the only channel the SDK offers. An entry with none leaves an ambient\n // value alone.\n const headers = Object.entries(entry.headers ?? {}).filter(\n ([name]) => !SDK_OWNED_HEADERS[name.toLowerCase()],\n );\n if (headers.length > 0) {\n env.ANTHROPIC_CUSTOM_HEADERS = headers.map(([name, value]) => `${name}: ${value}`).join(\"\\n\");\n }\n\n switch (claudeEndpointMode(entry)) {\n case \"bedrock\": {\n env.CLAUDE_CODE_USE_BEDROCK = \"1\";\n // The AWS credential bundle itself is `configEnv` material (AWS_*), and\n // ambient AWS_* survived the scrub, so a standalone CLI keeps its own.\n set(\"AWS_REGION\", params?.region);\n break;\n }\n case \"vertex\": {\n env.CLAUDE_CODE_USE_VERTEX = \"1\";\n // GOOGLE_APPLICATION_CREDENTIALS is a path the runner materialized; it\n // arrives through `configEnv` or ambient, never from `credential`.\n set(\"ANTHROPIC_VERTEX_PROJECT_ID\", params?.project);\n set(\"CLOUD_ML_REGION\", params?.location);\n break;\n }\n case \"foundry\": {\n env.CLAUDE_CODE_USE_FOUNDRY = \"1\";\n // §1.3: an explicit `base_url` wins over the resource-derived endpoint,\n // and the SDK has a separate var for each form.\n if (entry.base_url) set(\"ANTHROPIC_FOUNDRY_BASE_URL\", entry.base_url);\n else set(\"ANTHROPIC_FOUNDRY_RESOURCE\", params?.resource);\n set(\"ANTHROPIC_FOUNDRY_API_KEY\", credential);\n break;\n }\n case \"anthropic\": {\n const baseUrl = normalizeAnthropicBaseUrl(resolveEntryBaseUrl(entry));\n if (baseUrl && baseUrl.toLowerCase() !== ANTHROPIC_DEFAULT_BASE_URL) {\n env.ANTHROPIC_BASE_URL = baseUrl;\n }\n if (kind === \"bearer\") set(\"ANTHROPIC_AUTH_TOKEN\", credential);\n else if (kind === \"api_key_header\") set(\"ANTHROPIC_API_KEY\", credential);\n if (!credential) {\n // `oauth` / `none` / an unresolved ref: the ambient carriers are the\n // only auth this session has, and the scrub just removed them.\n if (ambient.authToken) env.ANTHROPIC_AUTH_TOKEN = ambient.authToken;\n else set(\"ANTHROPIC_API_KEY\", ambient.apiKey);\n }\n break;\n }\n }\n\n return env;\n}\n","/**\n * Poisoned-transcript repair for the Claude Agent SDK driver.\n *\n * The Anthropic Messages API can permanently reject a conversation once its\n * persisted history contains a malformed content block. Because the bad block\n * lives in the SDK's on-disk JSONL transcript, every replayed turn fails with\n * the same `400 invalid_request_error` and the session is bricked with no\n * in-band recovery.\n *\n * This module repairs the transcript in place, covering three known poison\n * classes:\n *\n * 1. **Image `media_type` mismatch / omission.** An image block whose declared\n * `media_type` does not match — or is missing for — the actual bytes:\n * `... The image was specified using the image/png media type, but the\n * image appears to be a image/jpeg image`. Produced by the Claude Code\n * `Read` tool's format fallback (anthropics/claude-code#55338, #30124,\n * #33179). Repaired by sniffing the base64 magic bytes and correcting\n * `media_type`.\n * 2. **Oversized image.** An image whose decoded payload exceeds the API's\n * 5 MB per-image limit (anthropics/claude-code#34566). Replaced with a\n * text stub — the byte budget cannot be recovered any other way.\n * 3. **`cache_control` on an empty text block.** A text block carrying a\n * `cache_control` marker with empty/whitespace `text`\n * (anthropics/claude-code#59626). The `cache_control` field is stripped.\n *\n * Genuinely unidentifiable image blocks are also replaced with a text stub.\n *\n * Recovering by content scan (rather than parsing the API's `messages.N`\n * index) is deliberate: the index addresses the assembled API request, not a\n * JSONL line, and reproducing the SDK's message-assembly is fragile. A full\n * scan is index-free and repairs every poisoned block in one pass.\n *\n * **Async and line-streaming since #454.** A Claude Code transcript is routinely\n * multi-megabyte (base64 images inline in `tool_result` blocks), and this runs on\n * a failed turn *and before every resume* — inside the single-threaded `skaile\n * serve` loop. The previous `readFileSync` + `writeFileSync` + `renameSync` held\n * the loop for the whole file and materialised it twice over as one string. Both\n * passes now stream line by line off a `createReadStream`, so the loop is yielded\n * between lines and peak memory is one JSONL line rather than the whole file, and\n * every I/O phase is deadline-bounded.\n *\n * Streaming was chosen over a worker thread: the work is I/O-bound rather than\n * CPU-bound (per-line `JSON.parse` on a yielded loop is not what stalls a turn),\n * and a worker would add a structured-clone of the same multi-MB payload plus a\n * thread lifecycle to a path that must never block a turn.\n *\n * @module\n */\n\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport { readdir, rename, stat, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\n\n/**\n * Minimal logger shape accepted by {@link scrubPoisonedTranscript}. Compatible\n * with the bridge `Logger`, but narrowed so the helper stays unit-testable\n * without a real logger instance.\n *\n * @category Transcript repair\n */\nexport interface ScrubLogger {\n info(message: string, data?: Record<string, unknown>): void;\n warn(message: string, data?: Record<string, unknown>): void;\n}\n\n/**\n * Options for {@link scrubPoisonedTranscript}.\n *\n * @category Transcript repair\n */\nexport interface ScrubTranscriptOptions {\n /**\n * Claude Code config directory — the parent of `projects/`. Resolve from\n * `CLAUDE_CONFIG_DIR`, falling back to `~/.claude`.\n */\n configDir: string;\n /** SDK session id whose transcript JSONL should be repaired. */\n sessionId: string;\n /** Optional logger for diagnostics. */\n log?: ScrubLogger;\n /**\n * Where the transcript is read and written. Defaults to this process's own\n * filesystem access ({@link localTranscriptStore}); with the agent uid split\n * the transcript belongs to the agent uid and must be reached through it.\n */\n store?: TranscriptStore;\n}\n\n/**\n * Filesystem access to Claude Code transcripts. The CLI creates them 0600 in\n * 0700 dirs, so when it runs as a different uid than the runner, only that uid\n * can locate, read or rewrite them (see `agent-transcript.ts`).\n *\n * @category Transcript repair\n */\nexport interface TranscriptStore {\n /** Path of `<sessionId>.jsonl` under `<configDir>/projects/`, or `null` when absent. */\n locate(configDir: string, sessionId: string, timeoutMs?: number): Promise<string | null>;\n /** The file's contents as UTF-8 chunks. */\n read(filePath: string): AsyncIterable<string>;\n /** Atomically replace the file with `chunks` via a `.scrub-tmp` sibling. */\n replace(filePath: string, chunks: AsyncIterable<string>): Promise<void>;\n /** Remove the sibling a failed or abandoned {@link replace} left (best effort). */\n discardTemp(filePath: string): Promise<void>;\n}\n\n/**\n * Outcome of a {@link scrubPoisonedTranscript} pass.\n *\n * @category Transcript repair\n */\nexport interface ScrubTranscriptResult {\n /** The located JSONL transcript path, or `null` when not found. */\n filePath: string | null;\n /** Image blocks whose `media_type` was corrected (or filled in) to match the bytes. */\n corrected: number;\n /**\n * Image blocks replaced with a text stub — either unidentifiable bytes or a\n * payload over the API's 5 MB per-image limit.\n */\n stubbed: number;\n /** Empty text blocks from which a rejected `cache_control` marker was stripped. */\n cacheStripped: number;\n /**\n * `true` when the transcript was located, contained at least one poisoned\n * block, and was rewritten. `false` means nothing needed repair (or the\n * file was not found) — the caller should not retry the resume.\n */\n changed: boolean;\n}\n\n/** Text inserted in place of an image block whose format cannot be identified. */\nconst STUB_TEXT = \"[image removed: unprocessable image data]\";\n\n/** Text inserted in place of an image block that exceeds the API size limit. */\nconst STUB_TEXT_OVERSIZED = \"[image removed: image too large]\";\n\n/**\n * The Anthropic Messages API rejects any single image whose decoded payload\n * exceeds 5 MB. An image at or under this is left alone; a larger one is\n * stubbed (its byte budget cannot be recovered).\n */\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\n/**\n * Identify an image's media type from the leading bytes of its base64 payload.\n *\n * Recognises the four formats the Anthropic API accepts. Returns `null` when\n * the magic bytes match no known format — the caller treats that as a\n * genuinely corrupt block and stubs it.\n *\n * @param base64 - Base64-encoded image data (only the prefix is inspected).\n * @returns An `image/*` media type, or `null` when unrecognised.\n * @category Transcript repair\n */\nexport function sniffImageMediaType(base64: string): string | null {\n let buf: Buffer;\n try {\n // 32 base64 chars decode to 24 bytes — enough for the WebP check at 12.\n buf = Buffer.from(base64.slice(0, 32), \"base64\");\n } catch {\n return null;\n }\n if (buf.length < 4) {\n return null;\n }\n // JPEG — SOI marker `FF D8`. Third byte varies (and may be corrupt), so a\n // two-byte check is intentional: it still matches malformed JPEGs, which is\n // exactly the poison case the API flags as \"appears to be image/jpeg\".\n if (buf[0] === 0xff && buf[1] === 0xd8) {\n return \"image/jpeg\";\n }\n // PNG — `89 50 4E 47`.\n if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47) {\n return \"image/png\";\n }\n // GIF — `47 49 46 38` (\"GIF8\").\n if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x38) {\n return \"image/gif\";\n }\n // WebP — `RIFF` at 0..3 and `WEBP` at 8..11.\n if (\n buf.length >= 12 &&\n buf[0] === 0x52 &&\n buf[1] === 0x49 &&\n buf[2] === 0x46 &&\n buf[3] === 0x46 &&\n buf[8] === 0x57 &&\n buf[9] === 0x45 &&\n buf[10] === 0x42 &&\n buf[11] === 0x50\n ) {\n return \"image/webp\";\n }\n return null;\n}\n\n/** A base64 image source on a content block (shape is SDK-defined). */\ninterface Base64ImageSource {\n type?: string;\n media_type?: string;\n data?: string;\n}\n\n/** Loosely-typed content block from a transcript message. */\ninterface ContentBlockLike {\n type?: string;\n source?: Base64ImageSource;\n content?: unknown;\n [k: string]: unknown;\n}\n\n/** Mutable counters threaded through one scrub pass. */\ninterface ScrubCounters {\n corrected: number;\n stubbed: number;\n cacheStripped: number;\n}\n\n/** Total repairs recorded in a counter set — used to detect per-line changes. */\nfunction totalChanges(c: ScrubCounters): number {\n return c.corrected + c.stubbed + c.cacheStripped;\n}\n\n/**\n * Repair a single content block. Returns the (possibly replaced) block.\n *\n * - A `tool_result` block recurses into its `content` array.\n * - A text block carrying a `cache_control` marker whose `text` is empty or\n * whitespace has the marker stripped (the API rejects `cache_control` on\n * empty text blocks).\n * - An image block whose decoded payload exceeds the API's 5 MB limit is\n * replaced with a text stub.\n * - An image block whose bytes match no known format is replaced with a text\n * stub (an image cannot simply be dropped — a `tool_result` must keep at\n * least one content entry, and a bare `image` block is replaced 1:1).\n * - An image block whose declared `media_type` mismatches (or is missing for)\n * the sniffed type is corrected in place.\n * - Every other block is returned untouched.\n */\nfunction scrubBlock(block: ContentBlockLike, counters: ScrubCounters): ContentBlockLike {\n if (block.type === \"tool_result\" && Array.isArray(block.content)) {\n return {\n ...block,\n content: (block.content as ContentBlockLike[]).map((inner) => scrubBlock(inner, counters)),\n };\n }\n\n // A `cache_control` marker on a text block whose text is empty or whitespace\n // is rejected by the API (\"cache_control cannot be set for empty text\n // blocks\"). Strip the marker — the empty block itself is harmless.\n if (block.type === \"text\" && block.cache_control != null) {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n if (text.trim() === \"\") {\n counters.cacheStripped++;\n const clone = { ...block };\n delete clone.cache_control;\n return clone;\n }\n }\n\n if (\n block.type === \"image\" &&\n block.source?.type === \"base64\" &&\n typeof block.source.data === \"string\"\n ) {\n const data = block.source.data;\n // The API rejects any image whose decoded payload exceeds 5 MB. The byte\n // budget cannot be salvaged, so the whole block becomes a text stub.\n // base64 encodes 3 bytes per 4 chars, so decoded length ≈ len * 3 / 4.\n if (Math.floor((data.length * 3) / 4) > MAX_IMAGE_BYTES) {\n counters.stubbed++;\n return { type: \"text\", text: STUB_TEXT_OVERSIZED };\n }\n const sniffed = sniffImageMediaType(data);\n if (sniffed === null) {\n counters.stubbed++;\n return { type: \"text\", text: STUB_TEXT };\n }\n if (sniffed !== block.source.media_type) {\n counters.corrected++;\n return { ...block, source: { ...block.source, media_type: sniffed } };\n }\n }\n\n return block;\n}\n\n/**\n * Locate the JSONL transcript for `sessionId` under `<configDir>/projects/`.\n *\n * Claude Code encodes the project directory into the `projects/` subfolder\n * name; rather than reproduce that encoding, this scans every subfolder for\n * `<sessionId>.jsonl` (the session id is a UUID — globally unique).\n *\n * Async and deadline-bounded since #454. The `existsSync(projectsDir)` probe is\n * gone: `readdir` already fails on a missing directory, so the probe was a\n * second stat on the same path for no information.\n *\n * `timeoutMs` defaults to {@link fsDeadlineMs} so callers that only need the\n * path (the resume probe) can omit it.\n *\n * @category Transcript repair\n */\nexport async function locateTranscriptPath(\n configDir: string,\n sessionId: string,\n timeoutMs: number = fsDeadlineMs(),\n): Promise<string | null> {\n const projectsDir = join(configDir, \"projects\");\n const entries = await tryWithFsDeadline(\n `readdir ${projectsDir}`,\n () => readdir(projectsDir),\n null,\n timeoutMs,\n );\n if (!entries) return null;\n for (const entry of entries) {\n const candidate = join(projectsDir, entry, `${sessionId}.jsonl`);\n const found = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isFile(),\n false,\n timeoutMs,\n );\n if (found) return candidate;\n }\n return null;\n}\n\n/**\n * Yield a file's contents line by line, reproducing `readFileSync(...).split(\"\\n\")`\n * exactly — including the final (possibly empty) segment, so a trailing newline\n * survives a rewrite byte for byte.\n *\n * Splits on `\\n` alone, so a line out of a CRLF transcript arrives with its\n * `\\r` still attached. That carrier byte is part of the line here, and\n * {@link repairLine} re-attaches it to a line it rewrites — the file keeps the\n * terminator style it arrived with. Deliberately not `node:readline`:\n * `crlfDelay` strips the `\\r` outright (rewriting a CRLF transcript to LF) and\n * the interface swallows the trailing-newline distinction, either of which\n * would make the \"clean transcript is left byte-for-byte untouched\" guarantee\n * false. Only one line is held in memory at a time, so a multi-MB transcript\n * never materialises as a single string.\n */\nasync function* streamLines(chunks: AsyncIterable<string>): AsyncGenerator<string> {\n let pending = \"\";\n for await (const chunk of chunks) {\n pending += chunk;\n let idx = pending.indexOf(\"\\n\");\n while (idx !== -1) {\n yield pending.slice(0, idx);\n pending = pending.slice(idx + 1);\n idx = pending.indexOf(\"\\n\");\n }\n }\n yield pending;\n}\n\n/**\n * The runner's own filesystem access: the default {@link TranscriptStore}.\n *\n * @category Transcript repair\n */\nexport const localTranscriptStore: TranscriptStore = {\n locate: (configDir, sessionId, timeoutMs) =>\n locateTranscriptPath(configDir, sessionId, timeoutMs),\n async *read(filePath) {\n const stream = createReadStream(filePath, { encoding: \"utf8\" });\n try {\n for await (const chunk of stream) yield chunk as string;\n } finally {\n stream.destroy();\n }\n },\n async replace(filePath, chunks) {\n const tmpPath = `${filePath}.scrub-tmp`;\n await pipeline(chunks, createWriteStream(tmpPath, { encoding: \"utf8\" }));\n await rename(tmpPath, filePath);\n },\n async discardTemp(filePath) {\n const tmpPath = `${filePath}.scrub-tmp`;\n await tryWithFsDeadline(`unlink ${tmpPath}`, () => unlink(tmpPath), undefined, fsDeadlineMs());\n },\n};\n\n/**\n * Repair one JSONL line, returning the (possibly rewritten) line and mutating\n * `counters`. A non-JSON, blank, or content-less line is returned untouched.\n *\n * The reader splits on `\\n` only, so a line from a CRLF transcript still carries\n * its trailing `\\r`. An untouched line is returned verbatim and keeps it; a\n * rewritten one is rebuilt by `JSON.stringify`, which would drop it — leaving a\n * repaired CRLF transcript with mixed line endings. So the terminator is split\n * off before the parse and re-appended to the rewritten line.\n */\nfunction repairLine(line: string, counters: ScrubCounters): string {\n if (line.trim() === \"\") return line;\n const eol = line.endsWith(\"\\r\") ? \"\\r\" : \"\";\n const body = eol === \"\" ? line : line.slice(0, -1);\n let entry: { message?: { content?: unknown } };\n try {\n entry = JSON.parse(body);\n } catch {\n return line; // Not JSON — leave untouched.\n }\n const content = entry.message?.content;\n if (!Array.isArray(content)) return line;\n const before = totalChanges(counters);\n const scrubbed = (content as ContentBlockLike[]).map((block) => scrubBlock(block, counters));\n if (totalChanges(counters) === before) return line; // Nothing changed on this line.\n return `${JSON.stringify({ ...entry, message: { ...entry.message, content: scrubbed } })}${eol}`;\n}\n\n/**\n * Scan a Claude Code SDK transcript for image content blocks whose declared\n * `media_type` does not match the actual bytes, repair them, and atomically\n * rewrite the file.\n *\n * Safe to call after a turn has failed: the SDK query is dead at that point,\n * and the next resume re-reads the transcript from disk.\n *\n * **Async since #454.** Two streaming passes rather than one whole-file read:\n * pass 1 counts repairs without writing anything, and pass 2 runs only when\n * pass 1 found something. The common case — the preventive scrub of a clean\n * transcript before every resume — is therefore one streaming read and zero\n * writes, and a clean transcript is still left byte-for-byte untouched.\n *\n * @param opts - Config directory, session id, and an optional logger.\n * @returns A {@link ScrubTranscriptResult}. When `changed` is `true` the\n * caller may retry the resume with the same session id.\n * @category Transcript repair\n */\nexport async function scrubPoisonedTranscript(\n opts: ScrubTranscriptOptions,\n): Promise<ScrubTranscriptResult> {\n const { configDir, sessionId, log } = opts;\n const store = opts.store ?? localTranscriptStore;\n const timeoutMs = fsDeadlineMs();\n const result: ScrubTranscriptResult = {\n filePath: null,\n corrected: 0,\n stubbed: 0,\n cacheStripped: 0,\n changed: false,\n };\n\n let filePath: string | null;\n try {\n filePath = await store.locate(configDir, sessionId, timeoutMs);\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to locate transcript\", {\n configDir,\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n return result;\n }\n if (!filePath) {\n log?.warn(\"scrub-transcript: no transcript found\", { configDir, sessionId });\n return result;\n }\n result.filePath = filePath;\n\n // ── Pass 1: detect. Streams the transcript, counting repairs, writing nothing.\n const counters: ScrubCounters = { corrected: 0, stubbed: 0, cacheStripped: 0 };\n try {\n await withFsDeadline(\n `scan transcript ${filePath}`,\n async () => {\n for await (const line of streamLines(store.read(filePath))) repairLine(line, counters);\n },\n timeoutMs,\n );\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to read transcript\", {\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n return result;\n }\n\n result.corrected = counters.corrected;\n result.stubbed = counters.stubbed;\n result.cacheStripped = counters.cacheStripped;\n\n if (totalChanges(counters) === 0) {\n return result;\n }\n\n // ── Pass 2: rewrite. Atomic: stream a sibling temp file, then rename over the\n // original. Line separators are re-emitted exactly as pass 1 split them, so a\n // trailing newline and any blank lines survive verbatim.\n const source = filePath;\n try {\n await withFsDeadline(\n `rewrite transcript ${source}`,\n async () => {\n const discard: ScrubCounters = { corrected: 0, stubbed: 0, cacheStripped: 0 };\n await store.replace(\n source,\n (async function* () {\n let first = true;\n for await (const line of streamLines(store.read(source))) {\n yield first ? repairLine(line, discard) : `\\n${repairLine(line, discard)}`;\n first = false;\n }\n })(),\n );\n },\n timeoutMs,\n );\n } catch (err) {\n log?.warn(\"scrub-transcript: failed to rewrite transcript\", {\n filePath,\n error: err instanceof Error ? err.message : String(err),\n });\n // Never leave a half-written `.scrub-tmp` in the SDK's projects dir, also\n // when the deadline abandoned the replace mid-write.\n await store.discardTemp(source).catch(() => {});\n return result;\n }\n\n result.changed = true;\n log?.info(\"scrub-transcript: repaired poisoned transcript\", {\n filePath,\n corrected: result.corrected,\n stubbed: result.stubbed,\n cacheStripped: result.cacheStripped,\n });\n return result;\n}\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport { fsDeadlineMs, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { resolveAgentExec } from \"./agent-exec.js\";\nimport { localTranscriptStore, type TranscriptStore } from \"./drivers/scrub-transcript.js\";\n\n/**\n * Transcripts reached through the agent launch shim.\n *\n * With the uid split on, the Claude CLI runs as the agent uid and creates its\n * transcripts 0600 in 0700 dirs, so the runner can no longer list, read or\n * rewrite them itself. This store runs plain tools (`find`, `cat`, `sh`, `mv`)\n * as the agent uid through the shim instead. The child gets only `PATH` and\n * `LC_ALL`, never the runner's environment, and runs in `/` because the\n * runner's own cwd may not be enterable by the agent uid.\n */\nexport function agentTranscriptStore(shim: string): TranscriptStore {\n // A replace the scrub's deadline abandoned keeps running; discardTemp stops\n // it before removing its temp file.\n const inFlight = new Map<string, ChildProcess>();\n // Paths whose rewrite discardTemp gave up on: their rename must never run.\n const cancelled = new Set<string>();\n const track = (filePath: string, child: ChildProcess) => {\n inFlight.set(filePath, child);\n child.once(\"close\", () => {\n if (inFlight.get(filePath) === child) inFlight.delete(filePath);\n });\n };\n return {\n async locate(configDir, sessionId, timeoutMs = 10_000) {\n // A session id is a UUID; anything glob- or path-shaped is not ours.\n if (!/^[A-Za-z0-9._-]+$/.test(sessionId)) return null;\n const projectsDir = join(configDir, \"projects\");\n // Markers on stdout, not exit codes, carry the answer: a shim or launcher\n // failure has exit codes of its own and must never read as \"not found\".\n const { stdout } = await collect(\n runAsAgent(shim, [\n \"sh\",\n \"-c\",\n '[ -d \"$1\" ] || { echo \"@@no-projects\"; exit 0; }; ' +\n 'find \"$1\" -mindepth 2 -maxdepth 2 -type f -name \"$2\" -print -quit; echo \"@@find:$?\"',\n \"sh\",\n projectsDir,\n `${sessionId}.jsonl`,\n ]),\n timeoutMs,\n );\n const lines = stdout.split(\"\\n\").map((l) => l.trim());\n // A missing projects/ is the same \"not found\" as a failed readdir locally.\n if (lines.includes(\"@@no-projects\")) return null;\n const status = lines.find((l) => l.startsWith(\"@@find:\"));\n if (status === undefined)\n throw new Error(\"locating a transcript as the agent uid failed (no answer from the shim)\");\n // A path find printed counts even if it later hit an unreadable sibling.\n const found = lines.find((l) => l.startsWith(\"/\"));\n if (found) return found;\n if (status !== \"@@find:0\")\n throw new Error(`locating a transcript as the agent uid failed (${status.slice(2)})`);\n return null;\n },\n\n async *read(filePath) {\n const child = runAsAgent(shim, [\"cat\", \"--\", filePath]);\n const exited = exitOf(child);\n exited.catch(() => {}); // awaited below; this only stops an unhandled rejection\n const stderr = drain(child);\n child.stdout?.setEncoding(\"utf8\");\n for await (const chunk of child.stdout as AsyncIterable<string>) yield chunk;\n const code = await exited;\n if (code !== 0)\n throw new Error(`reading ${filePath} as the agent uid failed: ${await stderr}`);\n },\n\n async replace(filePath, chunks) {\n const child = runAsAgent(shim, [\n \"sh\",\n \"-c\",\n // 0600 like the CLI's own files. Only writes the temp file: the rename\n // is a separate step below, run only after the input was fully sent,\n // so a killed or starved writer can never commit a partial transcript.\n 'umask 077; cat > \"$1.scrub-tmp\"',\n \"sh\",\n filePath,\n ]);\n cancelled.delete(filePath);\n track(filePath, child);\n const exited = exitOf(child);\n exited.catch(() => {}); // awaited below; this only stops an unhandled rejection\n const stderr = drain(child);\n const stdin = child.stdin;\n if (!stdin) throw new Error(\"agent shim has no stdin\");\n // A child that dies early surfaces through its exit code, not an EPIPE crash.\n stdin.on(\"error\", () => {});\n const gone = exited.then(\n () => undefined,\n () => undefined,\n );\n // Stop pulling input as soon as the child is gone (killed by discardTemp,\n // or failed), instead of waiting on a producer that may never resume.\n const input = chunks[Symbol.asyncIterator]();\n let drained = false;\n try {\n for (;;) {\n const next = await Promise.race([\n input.next(),\n gone.then(() => ({ dead: true as const })),\n ]);\n if (\"dead\" in next || stdin.destroyed) break;\n if (next.done) {\n drained = true;\n break;\n }\n if (!stdin.write(next.value)) {\n await Promise.race([new Promise((resolve) => stdin.once(\"drain\", resolve)), gone]);\n }\n }\n } finally {\n stdin.end();\n // Close the producer too, so the reader feeding it (a `cat` through\n // the shim) is torn down rather than left blocked on a full pipe.\n if (!drained) void input.return?.()?.catch(() => {});\n }\n const code = await exited;\n if (code !== 0 || !drained)\n throw new Error(`rewriting ${filePath} as the agent uid failed: ${await stderr}`);\n if (cancelled.has(filePath)) throw new Error(`rewrite of ${filePath} was abandoned`);\n const mover = runAsAgent(shim, [\"mv\", \"-f\", \"--\", `${filePath}.scrub-tmp`, filePath]);\n track(filePath, mover);\n const moved = await collect(mover, 10_000);\n if (moved.code !== 0) throw new Error(`renaming the rewritten ${filePath} failed`);\n },\n\n async discardTemp(filePath) {\n // Before anything else, so a writer that is just finishing never renames.\n cancelled.add(filePath);\n const pending = inFlight.get(filePath);\n if (pending && pending.exitCode === null && pending.signalCode === null) {\n // The writer cannot commit (the rename is a separate step), so this only\n // stops it; bounded, since a writer stuck on a hung mount may never die.\n const closed = new Promise((resolve) => pending.once(\"close\", resolve));\n pending.kill(\"SIGKILL\");\n await withFsDeadline(`stop the rewrite of ${filePath}`, () => closed, fsDeadlineMs());\n }\n await collect(runAsAgent(shim, [\"rm\", \"-f\", \"--\", `${filePath}.scrub-tmp`]), 10_000);\n },\n };\n}\n\n/**\n * The transcript store for this runner: through the agent shim when\n * `SKAILE_AGENT_EXEC` is set, the runner's own filesystem otherwise.\n */\nexport function transcriptStoreForRuntime(\n env: Record<string, string | undefined> = process.env,\n): TranscriptStore {\n const shim = resolveAgentExec(env);\n return shim ? agentTranscriptStore(shim) : localTranscriptStore;\n}\n\nfunction runAsAgent(shim: string, argv: string[]): ChildProcess {\n return spawn(shim, [\"--\", ...argv], {\n cwd: \"/\",\n env: { PATH: process.env.PATH ?? \"/usr/bin:/bin\", LC_ALL: \"C\" },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n}\n\nfunction exitOf(child: ChildProcess): Promise<number> {\n return new Promise((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\n/** Keep the last 1 KiB of stderr for the error message, and keep the pipe drained. */\nfunction drain(child: ChildProcess): Promise<string> {\n return new Promise((resolve) => {\n let tail = \"\";\n child.stderr?.setEncoding(\"utf8\");\n child.stderr?.on(\"data\", (c: string) => {\n tail = (tail + c).slice(-1024);\n });\n child.stderr?.once(\"close\", () => resolve(tail.trim()));\n });\n}\n\nasync function collect(\n child: ChildProcess,\n timeoutMs: number,\n): Promise<{ code: number; stdout: string }> {\n let stdout = \"\";\n child.stdout?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (c: string) => {\n stdout += c;\n });\n void drain(child);\n child.stdin?.end();\n let timer: NodeJS.Timeout | undefined;\n try {\n const code = await Promise.race([\n exitOf(child),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n reject(new Error(`agent shim did not answer within ${timeoutMs} ms`));\n }, timeoutMs);\n }),\n ]);\n return { code, stdout };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Pre-first-turn resume probe for the Claude Agent SDK driver.\n *\n * A tier-1 native resume only hands its session id to the SDK inside the first\n * real turn, so the `jsonl_lost` outcome (\"No conversation found\") is invisible\n * until a turn is consumed. The runner shares the container filesystem with the\n * SDK, so a cheap `stat` of the on-disk JSONL transcript is an authoritative,\n * side-effect-free signal of whether the resume will find its history — no\n * probe query, no spurious model turn.\n *\n * @module\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { withFsDeadline } from \"@skaile/workspaces/core\";\nimport { locateTranscriptPath } from \"./scrub-transcript.js\";\n\n/**\n * Overall wall-clock budget for the probe. Deliberately a small fraction of the\n * platform's `session_init_ack` timeout (`DEFAULT_INIT_ACK_TIMEOUT_MS`, 15s):\n * the probe runs synchronously on the pre-ack path, so a wedged\n * `CLAUDE_CONFIG_DIR` mount must never push the ack past its deadline.\n */\nconst RESUME_PROBE_TIMEOUT_MS = 2_000;\n\n/**\n * Outcome of {@link probeResumeTranscript}: whether the SDK transcript for a\n * requested tier-1 resume exists on disk.\n *\n * @category Resume probe\n */\nexport type ResumeProbeOutcome = \"transcript_found\" | \"jsonl_lost\";\n\n/**\n * Resolve the Claude Code config directory — the parent of `projects/` — from\n * an explicit env map, the process environment, or the `~/.claude` default.\n *\n * The runner's probe and the claude-sdk driver share this one resolver, so they\n * agree as long as they see the same `CLAUDE_CONFIG_DIR`. Today they do:\n * `CLAUDE_CONFIG_DIR` is container-scoped and neither side threads a per-session\n * override through `config.env`, so both fall through to `process.env`. If a\n * future change ever set the driver's `config.env.CLAUDE_CONFIG_DIR` to a\n * divergent path, the reactive `resume_failed { jsonl_lost }` turn remains the\n * safety net.\n *\n * @category Resume probe\n */\nexport function resolveClaudeConfigDir(env?: Record<string, string | undefined>): string {\n return env?.CLAUDE_CONFIG_DIR || process.env.CLAUDE_CONFIG_DIR || join(homedir(), \".claude\");\n}\n\n/**\n * Probe whether the SDK JSONL transcript for `sessionId` exists on disk.\n *\n * Non-null locator result → `transcript_found`; null → `jsonl_lost`;\n * `undefined` → outcome unknown (the probe exceeded its budget or errored). The\n * caller leaves the ack field ABSENT on `undefined` so the reactive\n * `resume_failed { jsonl_lost }` turn stays the safety net — a timed-out probe\n * must never masquerade as a genuine `jsonl_lost` and force a needless downgrade.\n *\n * `opts.timeoutMs` overrides {@link RESUME_PROBE_TIMEOUT_MS}; `opts.locate`\n * overrides the transcript locator (used by tests / alternate stores).\n *\n * @category Resume probe\n */\nexport async function probeResumeTranscript(\n sessionId: string,\n opts?: {\n env?: Record<string, string | undefined>;\n timeoutMs?: number;\n locate?: (configDir: string, sessionId: string) => Promise<string | null>;\n },\n): Promise<ResumeProbeOutcome | undefined> {\n const configDir = resolveClaudeConfigDir(opts?.env);\n const timeoutMs = opts?.timeoutMs ?? RESUME_PROBE_TIMEOUT_MS;\n const locate = opts?.locate ?? locateTranscriptPath;\n try {\n // Bound the whole probe on wall-clock and THROW on expiry: the inner per-op\n // deadline swallows a timeout into a null path (a false `jsonl_lost`), so a\n // wedged mount must yield \"unknown\" here rather than a spurious downgrade.\n const filePath = await withFsDeadline(\n `resume-probe ${sessionId}`,\n () => locate(configDir, sessionId),\n timeoutMs,\n );\n return filePath ? \"transcript_found\" : \"jsonl_lost\";\n } catch {\n return undefined;\n }\n}\n"]}
|
|
@@ -858,6 +858,23 @@ function validateMergedRegistry(merged, options = {}) {
|
|
|
858
858
|
diagnostics: ctx.diagnostics
|
|
859
859
|
};
|
|
860
860
|
}
|
|
861
|
+
function pickRegistryEntries(merged, ids) {
|
|
862
|
+
const wanted = new Set(ids);
|
|
863
|
+
const order = merged.order.filter((id) => wanted.has(id) && merged.providers[id] !== void 0);
|
|
864
|
+
const providers = {};
|
|
865
|
+
const origin = {};
|
|
866
|
+
for (const id of order) {
|
|
867
|
+
providers[id] = merged.providers[id];
|
|
868
|
+
origin[id] = merged.origin[id];
|
|
869
|
+
}
|
|
870
|
+
return {
|
|
871
|
+
version: 1,
|
|
872
|
+
providers,
|
|
873
|
+
order,
|
|
874
|
+
origin,
|
|
875
|
+
locked: merged.locked.filter((id) => providers[id] !== void 0)
|
|
876
|
+
};
|
|
877
|
+
}
|
|
861
878
|
function registryEntries(registry) {
|
|
862
879
|
if (isMergedRegistry(registry)) {
|
|
863
880
|
return registry.order.map((id) => [id, registry.providers[id]]);
|
|
@@ -955,6 +972,6 @@ function parseModelRef(ref, registry, roles) {
|
|
|
955
972
|
return resolveAgainstEntry(providerId, entry, selector, { role, warnings });
|
|
956
973
|
}
|
|
957
974
|
|
|
958
|
-
export { AI_PROVIDER_BASE_URL_TEMPLATES, AI_PROVIDER_CREDENTIAL_KINDS, AI_PROVIDER_DISCOVERY_TYPES, AI_PROVIDER_KINDS, AI_PROVIDER_LAYERS, AI_PROVIDER_SURFACES, AI_PROVIDER_TRANSPORTS, AI_PROVIDER_VOICE_KINDS, entryTransport, formatCredentialRef, isEntryEnabled, isSafeProviderId, looksLikeLiteralSecret, mergeRegistries, normalizeAnthropicBaseUrl, normalizeEntryBaseUrl, parseCredentialRef, parseModelRef, registryEntries, resolveEntryBaseUrl, validateMergedRegistry, validateRegistry };
|
|
959
|
-
//# sourceMappingURL=chunk-
|
|
960
|
-
//# sourceMappingURL=chunk-
|
|
975
|
+
export { AI_PROVIDER_BASE_URL_TEMPLATES, AI_PROVIDER_CREDENTIAL_KINDS, AI_PROVIDER_DISCOVERY_TYPES, AI_PROVIDER_KINDS, AI_PROVIDER_LAYERS, AI_PROVIDER_SURFACES, AI_PROVIDER_TRANSPORTS, AI_PROVIDER_VOICE_KINDS, entryTransport, formatCredentialRef, isEntryEnabled, isSafeProviderId, looksLikeLiteralSecret, mergeRegistries, normalizeAnthropicBaseUrl, normalizeEntryBaseUrl, parseCredentialRef, parseModelRef, pickRegistryEntries, registryEntries, resolveEntryBaseUrl, validateMergedRegistry, validateRegistry };
|
|
976
|
+
//# sourceMappingURL=chunk-MJHSLODD.js.map
|
|
977
|
+
//# sourceMappingURL=chunk-MJHSLODD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../core/src/provider-registry.ts"],"names":["ok","providerId","entry"],"mappings":"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","file":"chunk-MJHSLODD.js","sourcesContent":["/**\n * The AI provider registry — one keyed definition of every LLM / voice endpoint\n * the runtime may talk to.\n *\n * This module is the **single canonical home** of the registry record: its\n * types, its validation, the layered merge (§1.5), the `base_url` derivation\n * (§1.3), the credential-reference grammar (§1.4) and the model-reference\n * parser. Nothing here is duplicated in `bridge`, `runner` or `platform` — the\n * structurally-identical-copy pattern that `CloudConfig` fell into is exactly\n * what this module exists to avoid.\n *\n * Vocabulary: this is the **AI provider** registry. It is unrelated to the\n * platform's connector `ProviderType` / `ProviderLink` (git, SharePoint,\n * Drive…). Types are named `AIProvider*` throughout, never bare `Provider*`.\n *\n * The `surface` enum is omp's `api` vocabulary verbatim, so the omp adapter is\n * a serializer rather than a translator.\n *\n * @see PROVIDER-CONFIG-PLAN.md §1\n */\n\n// No runtime imports: this module is the schema, and it must stay loadable in a\n// browser bundle. Credential *resolution* (which spawns processes and reads\n// `process.env`) lives in `./provider-registry-credentials.ts`.\n\n// ── Enums ──────────────────────────────────────────────────────────────────\n\n/**\n * What an entry produces. `llm` and `embed` carry a wire `surface`; `stt` and\n * `tts` use the reduced voice record (§1.7).\n */\nexport const AI_PROVIDER_KINDS = [\"llm\", \"stt\", \"tts\", \"embed\"] as const;\n\n/** Union of {@link AI_PROVIDER_KINDS}. */\nexport type AIProviderKind = (typeof AI_PROVIDER_KINDS)[number];\n\n/** Kinds that use the voice subset of the record (§1.7). */\nexport const AI_PROVIDER_VOICE_KINDS = [\"stt\", \"tts\"] as const;\n\n/** Union of {@link AI_PROVIDER_VOICE_KINDS}. */\nexport type AIProviderVoiceKind = (typeof AI_PROVIDER_VOICE_KINDS)[number];\n\n/**\n * Wire protocol — the discriminator a driver adapter switches on. These are\n * omp's `api` values verbatim (Codex CLI calls the same concept `wire_api`).\n */\nexport const AI_PROVIDER_SURFACES = [\n \"anthropic-messages\",\n \"openai-completions\",\n \"openai-responses\",\n \"openai-codex-responses\",\n \"azure-openai-responses\",\n \"bedrock-converse-stream\",\n \"google-generative-ai\",\n \"google-vertex\",\n] as const;\n\n/** Union of {@link AI_PROVIDER_SURFACES}. */\nexport type AIProviderSurface = (typeof AI_PROVIDER_SURFACES)[number];\n\n/** How the request reaches the surface — selects the `params` shape (§1.3). */\nexport const AI_PROVIDER_TRANSPORTS = [\n \"direct\",\n \"bedrock\",\n \"vertex\",\n \"foundry\",\n \"azure-openai\",\n] as const;\n\n/** Union of {@link AI_PROVIDER_TRANSPORTS}. */\nexport type AIProviderTransport = (typeof AI_PROVIDER_TRANSPORTS)[number];\n\n/**\n * How the credential is presented (§1.4). `command` is a reserved grammar slot:\n * the schema accepts it, no refresh loop ships yet.\n */\nexport const AI_PROVIDER_CREDENTIAL_KINDS = [\n \"api_key_header\",\n \"bearer\",\n \"sigv4\",\n \"google_adc\",\n \"azure_entra\",\n \"oauth\",\n \"none\",\n \"command\",\n] as const;\n\n/** Union of {@link AI_PROVIDER_CREDENTIAL_KINDS}. */\nexport type AIProviderCredentialKind = (typeof AI_PROVIDER_CREDENTIAL_KINDS)[number];\n\n/**\n * Credential kinds that cannot work without a `ref`. The rest either sign from\n * an ambient chain (`sigv4`, `google_adc`, `azure_entra`) or need nothing\n * (`none`).\n */\nconst CREDENTIAL_REF_REQUIRED: Partial<Record<AIProviderCredentialKind, true>> = {\n api_key_header: true,\n bearer: true,\n oauth: true,\n command: true,\n};\n\n/** omp-compatible model-discovery probes. Unknown values are tolerated with a warning. */\nexport const AI_PROVIDER_DISCOVERY_TYPES = [\n \"openai-models-list\",\n \"anthropic-models-list\",\n \"google-models-list\",\n \"none\",\n] as const;\n\n/** Union of {@link AI_PROVIDER_DISCOVERY_TYPES}. */\nexport type AIProviderDiscoveryType = (typeof AI_PROVIDER_DISCOVERY_TYPES)[number];\n\n/**\n * Configuration layers, **lowest precedence first** (§1.5). `runtime` is the\n * CLI/runtime override layer (`--model`, `--api-key`); `session` is the\n * control-plane layer the platform injects into `session_init`.\n */\nexport const AI_PROVIDER_LAYERS = [\"catalog\", \"user\", \"workspace\", \"runtime\", \"session\"] as const;\n\n/** Union of {@link AI_PROVIDER_LAYERS}. */\nexport type AIProviderLayerId = (typeof AI_PROVIDER_LAYERS)[number];\n\n// ── Record ─────────────────────────────────────────────────────────────────\n\n/** `transport: bedrock` routing parameters. */\nexport interface AIProviderBedrockParams {\n /** AWS region, e.g. `us-east-1`. */\n region: string;\n}\n\n/** `transport: vertex` routing parameters. */\nexport interface AIProviderVertexParams {\n /** GCP project id. */\n project: string;\n /** Vertex location, e.g. `europe-west4`. */\n location: string;\n /** Model publisher; defaults to `google` (use `anthropic` for Claude on Vertex). */\n publisher?: string;\n}\n\n/** `transport: foundry` routing parameters. */\nexport interface AIProviderFoundryParams {\n /** Azure AI Foundry resource name (the `{resource}` in the endpoint host). */\n resource: string;\n}\n\n/**\n * `transport: azure-openai` routing parameters. `resource` is required even\n * though the plan's §1.3 table lists only `deployment`/`api_version`: the\n * derived `base_url` in that same row interpolates `{resource}`.\n */\nexport interface AIProviderAzureOpenAIParams {\n /** Azure OpenAI resource name (the `{resource}` in the endpoint host). */\n resource: string;\n /** Deployment name the request is routed to. */\n deployment: string;\n /** `api-version` query value; mirrored into `query_params` by the adapter. */\n api_version: string;\n}\n\n/** Free-form voice parameters, typed per preset (Deepgram, ElevenLabs, …). */\nexport type AIProviderVoiceParams = Record<string, string | number | boolean>;\n\n/**\n * The `transport` → `params` discriminated union (§1.3, decision §9.9). An open\n * `Record<string, string>` would lose per-transport field rendering in the\n * admin UI, so the pairing is encoded in the type.\n */\nexport type AIProviderTransportSlice =\n | { transport?: \"direct\"; params?: Record<string, never> }\n | { transport: \"bedrock\"; params: AIProviderBedrockParams }\n | { transport: \"vertex\"; params: AIProviderVertexParams }\n | { transport: \"foundry\"; params: AIProviderFoundryParams }\n | { transport: \"azure-openai\"; params: AIProviderAzureOpenAIParams };\n\n/** Reference to a secret. Never the secret itself — see {@link parseCredentialRef}. */\nexport interface AIProviderCredential {\n kind: AIProviderCredentialKind;\n /**\n * `env:NAME` · `cmd:<shell>` · `platform:<configId>` · `keyring:<service>/<account>`.\n * A literal secret here is a validation error.\n */\n ref?: string;\n}\n\n/** Per-model capability facts; unknown ids otherwise truncate silently. */\nexport interface AIProviderCapabilities {\n context_window?: number;\n tools?: boolean;\n images?: boolean;\n thinking_max?: number;\n}\n\n/** omp-compatible discovery descriptor. */\nexport interface AIProviderDiscovery {\n type: AIProviderDiscoveryType | (string & {});\n /** Path appended to `base_url` when the surface default does not apply. */\n path?: string;\n}\n\n/** Fields every entry carries, whatever its `kind`. */\nexport interface AIProviderEntryCommon {\n /** Display name. Never load-bearing. */\n label?: string;\n /** Catalog preset this entry inherits from (`bridge/src/provider-catalog.ts`). */\n preset?: string;\n /** Literal endpoint; wins over the preset value and the transport derivation. */\n base_url?: string;\n /** Static, non-secret request headers. */\n headers?: Record<string, string>;\n credential?: AIProviderCredential;\n /** Default `true`; read it through {@link isEntryEnabled}. */\n enabled?: boolean;\n /** Set by the control plane: lower layers cannot override this entry (§1.5). */\n locked?: boolean;\n}\n\n/** An `llm`/`embed` entry — the full record. */\nexport type AIProviderLlmEntry = AIProviderEntryCommon &\n AIProviderTransportSlice & {\n kind: \"llm\" | \"embed\";\n /** Required unless a `preset` supplies it. */\n surface?: AIProviderSurface;\n /** Azure's `api-version` lives here. */\n query_params?: Record<string, string>;\n /** Logical id → provider-side id. */\n model_map?: Record<string, string>;\n /** Keyed by the *logical* id, i.e. the `model_map` key. */\n capabilities?: Record<string, AIProviderCapabilities>;\n discovery?: AIProviderDiscovery;\n };\n\n/**\n * An `stt`/`tts` entry — the reduced record (§1.7). `surface`, `transport`,\n * `model_map`, `capabilities` and `discovery` are `llm`-only and rejected here:\n * a TTS voice is not a wire protocol.\n */\nexport type AIProviderVoiceEntry = AIProviderEntryCommon & {\n kind: AIProviderVoiceKind;\n /** Preset-typed: Deepgram `{model, language}`, ElevenLabs `{voice_id, output_format}`. */\n params?: AIProviderVoiceParams;\n};\n\n/** One registry entry. */\nexport type AIProviderEntry = AIProviderLlmEntry | AIProviderVoiceEntry;\n\n/** Entry id → entry. Iteration order is registry order. */\nexport type AIProviderRegistry = Record<string, AIProviderEntry>;\n\n/**\n * Any entry's `params`: transport routing parameters (§1.3) or voice options\n * (§1.7). Which of them applies is decided by `transport` and `kind`, and a\n * layer may not carry either — so a patch holds the union and\n * {@link validateMergedRegistry} narrows it.\n */\nexport type AIProviderParams =\n | AIProviderBedrockParams\n | AIProviderVertexParams\n | AIProviderFoundryParams\n | AIProviderAzureOpenAIParams\n | AIProviderVoiceParams;\n\n/**\n * An entry as a single layer may write it (§1.5): any subset of the record,\n * `kind` included. A `<workspace>/.skaile/providers.yml` that names `base_url`\n * alone is an override of one field, not a redefinition — so a layer holds\n * patches, and completeness is gated on the merged entry\n * ({@link validateMergedRegistry}) rather than per layer.\n *\n * Every {@link AIProviderEntry} is a patch; the reverse needs the gate. The\n * `transport`/`params` pairing is deliberately un-discriminated here, because\n * the two halves may come from different layers.\n */\nexport type AIProviderEntryPatch = AIProviderEntryCommon & {\n kind?: AIProviderKind;\n surface?: AIProviderSurface;\n transport?: AIProviderTransport;\n params?: AIProviderParams;\n query_params?: Record<string, string>;\n model_map?: Record<string, string>;\n capabilities?: Record<string, AIProviderCapabilities>;\n discovery?: AIProviderDiscovery;\n};\n\n/** Entry id → partial entry: one layer's contribution to the registry. */\nexport type AIProviderRegistryPatch = Record<string, AIProviderEntryPatch>;\n\n/** A parsed `providers.yml` document — one layer, so entries may be partial. */\nexport interface AIProviderRegistryDocument {\n version: 1;\n providers: AIProviderRegistryPatch;\n}\n\n/** One input to {@link mergeRegistries}. */\nexport interface AIProviderRegistryLayer {\n layer: AIProviderLayerId;\n providers: AIProviderRegistryPatch;\n}\n\n/** The merged view every consumer reads. */\nexport interface MergedAIProviderRegistry {\n version: 1;\n providers: AIProviderRegistry;\n /**\n * Registry order: highest-precedence layer first, document order within a\n * layer. Bare model ids resolve down this list (§1.6).\n */\n order: string[];\n /** Highest-precedence layer that contributed to each entry. */\n origin: Record<string, AIProviderLayerId>;\n /** Entries frozen by `locked: true`; lower layers were ignored for these. */\n locked: string[];\n}\n\n// ── Diagnostics ────────────────────────────────────────────────────────────\n\n/** Severity of an {@link AIProviderDiagnostic}. */\nexport type AIProviderDiagnosticSeverity = \"error\" | \"warning\";\n\n/**\n * A structured note about a registry document. {@link validateRegistry} never\n * throws: every problem is reported here with the offending key in `path`, and\n * each caller (CLI, runner, platform) decides how loud to be.\n */\nexport interface AIProviderDiagnostic {\n /** Stable machine code, e.g. `\"literal_secret\"` / `\"unknown_surface\"`. */\n code: string;\n severity: AIProviderDiagnosticSeverity;\n /** Human-readable, actionable message. */\n message: string;\n /** Dotted path to the offending key, e.g. `providers.groq.headers.x-api-key`. */\n path: string;\n}\n\n/** Result of {@link validateRegistry}: the surviving document plus every note. */\nexport interface RegistryValidation {\n /** Entries that produced an error diagnostic are omitted. */\n document: AIProviderRegistryDocument;\n diagnostics: AIProviderDiagnostic[];\n}\n\n// ── Validation ─────────────────────────────────────────────────────────────\n\n/** Entry ids are file-safe, env-var-derivable keys. */\nconst SAFE_ID = /^[a-z0-9][a-z0-9_-]*$/;\n\n/** POSIX environment variable name. */\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** The four `credential.ref` forms (§1.4). */\nconst CREDENTIAL_REF = /^(env|cmd|platform|keyring):([\\s\\S]+)$/;\n\n/** Header/query keys whose value must be an indirection, never a literal. */\nconst SECRET_KEY =\n /(^|[-_])(api[-_]?key|apikey|authorization|auth|token|secret|password|passwd|credential|credentials|cookie)([-_]|$)|^key$/i;\n\n/** Value shapes that are a secret whatever the key is called. */\nconst SECRET_VALUE_PATTERNS: RegExp[] = [\n /^sk-/i,\n /^xai-/i,\n /^gsk_/,\n /^(ghp|gho|ghu|ghs)_/,\n /^github_pat_/,\n /^xox[baprs]-/,\n /^AIza[0-9A-Za-z_-]{10,}/,\n /^(Bearer|Token|Basic)\\s+\\S{8,}$/i,\n // Long opaque blob: no spaces, no dots, no scheme punctuation.\n /^[A-Za-z0-9+/_-]{40,}={0,2}$/,\n];\n\n/** `${...}` interpolation — the escape hatch for a templated, non-literal value. */\nconst INTERPOLATION = /\\$\\{[^}]+\\}/;\n\n/** Every key the `llm`/`embed` record accepts. */\nconst LLM_KEYS: Record<string, true> = {\n kind: true,\n label: true,\n preset: true,\n surface: true,\n transport: true,\n base_url: true,\n params: true,\n headers: true,\n query_params: true,\n credential: true,\n model_map: true,\n capabilities: true,\n discovery: true,\n enabled: true,\n locked: true,\n};\n\n/** Every key the `stt`/`tts` record accepts (§1.7). */\nconst VOICE_KEYS: Record<string, true> = {\n kind: true,\n label: true,\n preset: true,\n base_url: true,\n params: true,\n headers: true,\n credential: true,\n enabled: true,\n locked: true,\n};\n\n/**\n * Every key either record accepts. This is the allow-list a *layer* is read\n * against: which of the two records applies is only known once `kind` is, and\n * a layer may leave `kind` to a lower one (§1.5). The `llm`-only keys are\n * rejected on a voice entry by {@link checkEntry}, at merge time.\n */\nconst ENTRY_KEYS: Record<string, true> = { ...LLM_KEYS, ...VOICE_KEYS };\n\n/** Keys that exist only on `llm`/`embed` — named individually when rejected. */\nconst LLM_ONLY_KEYS = [\"surface\", \"transport\", \"model_map\", \"capabilities\", \"discovery\"] as const;\n\nconst CAPABILITY_KEYS: Record<string, true> = {\n context_window: true,\n tools: true,\n images: true,\n thinking_max: true,\n};\n\n/** Required `params` keys per transport (§1.3). */\nconst TRANSPORT_PARAMS: Record<\n Exclude<AIProviderTransport, \"direct\">,\n { required: string[]; optional: string[] }\n> = {\n bedrock: { required: [\"region\"], optional: [] },\n vertex: { required: [\"project\", \"location\"], optional: [\"publisher\"] },\n foundry: { required: [\"resource\"], optional: [] },\n \"azure-openai\": { required: [\"resource\", \"deployment\", \"api_version\"], optional: [] },\n};\n\n/**\n * `transport` → `base_url` template (§1.3). Placeholders are `params` keys.\n * `direct` has no template: it uses the preset literal or an explicit value.\n */\nexport const AI_PROVIDER_BASE_URL_TEMPLATES: Record<\n Exclude<AIProviderTransport, \"direct\">,\n string\n> = {\n bedrock: \"https://bedrock-runtime.{region}.amazonaws.com\",\n vertex:\n \"https://{location}-aiplatform.googleapis.com/v1/projects/{project}/locations/{location}/publishers/{publisher}\",\n foundry: \"https://{resource}.services.ai.azure.com/anthropic\",\n \"azure-openai\": \"https://{resource}.openai.azure.com/openai\",\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** True when `id` is usable as a registry key (`[a-z0-9][a-z0-9_-]*`). */\nexport function isSafeProviderId(id: string): boolean {\n return SAFE_ID.test(id);\n}\n\n/**\n * True when `value` must not appear literally under `key`.\n *\n * A value is acceptable when it is an indirection — a `${...}` interpolation or\n * one of the four `credential.ref` forms. Otherwise a value is a literal secret\n * when the key names a credential-bearing header (`authorization`, `x-api-key`,\n * the bare `key` query param Google uses…) or when the value itself has the\n * shape of a token (`sk-…`, `AIza…`, a 40-char opaque blob…).\n *\n * Non-secret literals stay legal: `anthropic-version: 2023-06-01`,\n * `api-version: 2026-01-01`, `HTTP-Referer: https://skaile.ai`.\n */\nexport function looksLikeLiteralSecret(key: string, value: string): boolean {\n const trimmed = value.trim();\n if (trimmed === \"\") return false;\n if (INTERPOLATION.test(trimmed)) return false;\n if (CREDENTIAL_REF.test(trimmed)) return false;\n if (SECRET_KEY.test(key)) return true;\n return SECRET_VALUE_PATTERNS.some((re) => re.test(trimmed));\n}\n\ninterface Ctx {\n diagnostics: AIProviderDiagnostic[];\n}\n\nfunction err(ctx: Ctx, code: string, path: string, message: string): void {\n ctx.diagnostics.push({ code, severity: \"error\", message, path });\n}\n\nfunction warn(ctx: Ctx, code: string, path: string, message: string): void {\n ctx.diagnostics.push({ code, severity: \"warning\", message, path });\n}\n\n/** Validate a `Record<string, string>` field and reject literal secrets in it. */\nfunction readStringMap(\n ctx: Ctx,\n raw: unknown,\n path: string,\n opts: { secretScan: boolean },\n): Record<string, string> | undefined {\n if (!isPlainObject(raw)) {\n err(ctx, \"invalid_type\", path, `${path} must be a map of string values`);\n return undefined;\n }\n const out: Record<string, string> = {};\n let ok = true;\n for (const [key, value] of Object.entries(raw)) {\n const keyPath = `${path}.${key}`;\n if (typeof value !== \"string\") {\n err(ctx, \"invalid_type\", keyPath, `${keyPath} must be a string`);\n ok = false;\n continue;\n }\n if (opts.secretScan && looksLikeLiteralSecret(key, value)) {\n err(\n ctx,\n \"literal_secret\",\n keyPath,\n `${keyPath} holds a literal secret — use a reference instead ` +\n `(env:NAME, cmd:<shell>, platform:<configId>, keyring:<service>/<account>) ` +\n `or a \\${...} interpolation`,\n );\n ok = false;\n continue;\n }\n out[key] = value;\n }\n return ok ? out : undefined;\n}\n\nfunction readCredential(\n ctx: Ctx,\n raw: unknown,\n path: string,\n): { value?: AIProviderCredential; ok: boolean } {\n if (!isPlainObject(raw)) {\n err(ctx, \"invalid_type\", path, `${path} must be a map with a 'kind'`);\n return { ok: false };\n }\n let ok = true;\n for (const key of Object.keys(raw)) {\n if (key !== \"kind\" && key !== \"ref\") {\n err(ctx, \"unknown_key\", `${path}.${key}`, `${path}.${key} is not a credential key`);\n ok = false;\n }\n }\n const kind = raw.kind;\n if (\n typeof kind !== \"string\" ||\n !(AI_PROVIDER_CREDENTIAL_KINDS as readonly string[]).includes(kind)\n ) {\n err(\n ctx,\n \"unknown_credential_kind\",\n `${path}.kind`,\n `${path}.kind must be one of ${AI_PROVIDER_CREDENTIAL_KINDS.join(\", \")}`,\n );\n return { ok: false };\n }\n const credentialKind = kind as AIProviderCredentialKind;\n\n const rawRef = raw.ref;\n let ref: string | undefined;\n if (rawRef !== undefined) {\n if (typeof rawRef !== \"string\") {\n err(ctx, \"invalid_type\", `${path}.ref`, `${path}.ref must be a string`);\n ok = false;\n } else if (!parseCredentialRef(rawRef)) {\n err(\n ctx,\n \"literal_secret\",\n `${path}.ref`,\n `${path}.ref must be a reference, not a literal secret — ` +\n `use env:NAME, cmd:<shell>, platform:<configId> or keyring:<service>/<account>`,\n );\n ok = false;\n } else {\n ref = rawRef;\n }\n } else if (CREDENTIAL_REF_REQUIRED[credentialKind]) {\n err(\n ctx,\n \"missing_credential_ref\",\n `${path}.ref`,\n `${path}.ref is required for credential kind '${credentialKind}'`,\n );\n ok = false;\n }\n\n if (!ok) return { ok: false };\n return {\n ok: true,\n value: ref === undefined ? { kind: credentialKind } : { kind: credentialKind, ref },\n };\n}\n\n/**\n * Validate `transport` + `params` against §1.3 and rebuild the discriminated\n * union from the merged values.\n *\n * This runs at merge time, not per layer: `params` and the `transport` that\n * types them may be written in different layers (§1.5), so a layer on its own\n * cannot tell a foreign parameter from an override of a legal one.\n *\n * @param present keys the source wrote — a `transport` or `params` that was\n * written and rejected is already reported, and must not also be reported as\n * missing.\n */\nfunction readTransportSlice(\n ctx: Ctx,\n transport: AIProviderTransport | undefined,\n params: Record<string, string | number | boolean> | undefined,\n path: string,\n present: ReadonlySet<string>,\n): { slice: AIProviderTransportSlice; ok: boolean } {\n // Re-deriving `params` against the default would bury the enum diagnostic.\n if (transport === undefined && present.has(\"transport\")) return { slice: {}, ok: false };\n const explicit = transport !== undefined;\n const effective = transport ?? \"direct\";\n const rejectedParams = params === undefined && present.has(\"params\");\n\n if (effective === \"direct\") {\n let ok = true;\n for (const key of Object.keys(params ?? {})) {\n err(\n ctx,\n \"unknown_param\",\n `${path}.params.${key}`,\n `${path}.params.${key} is not valid for transport 'direct' — it takes no parameters`,\n );\n ok = false;\n }\n return { slice: explicit ? { transport: \"direct\" } : {}, ok };\n }\n\n const spec = TRANSPORT_PARAMS[effective];\n if (params === undefined) {\n // Written and rejected by the per-layer read — its diagnostic already stands.\n if (!rejectedParams) {\n err(\n ctx,\n \"missing_params\",\n `${path}.params`,\n `${path}.params is required for transport '${effective}' (${spec.required.join(\", \")})`,\n );\n }\n return { slice: {}, ok: false };\n }\n\n let ok = true;\n const values: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (!spec.required.includes(key) && !spec.optional.includes(key)) {\n err(\n ctx,\n \"unknown_param\",\n `${path}.params.${key}`,\n `${path}.params.${key} is not valid for transport '${effective}' ` +\n `(accepted: ${[...spec.required, ...spec.optional].join(\", \")})`,\n );\n ok = false;\n continue;\n }\n if (typeof value !== \"string\") {\n err(ctx, \"invalid_type\", `${path}.params.${key}`, `${path}.params.${key} must be a string`);\n ok = false;\n continue;\n }\n values[key] = value;\n }\n for (const key of spec.required) {\n if (values[key] === undefined) {\n err(\n ctx,\n \"missing_param\",\n `${path}.params.${key}`,\n `${path}.params.${key} is required for transport '${effective}'`,\n );\n ok = false;\n }\n }\n if (!ok) return { slice: {}, ok: false };\n // Rebuilt field by field so the discriminated union narrows without a cast;\n // every `required` key is present by the check above.\n switch (effective) {\n case \"bedrock\":\n return { slice: { transport: effective, params: { region: values.region } }, ok: true };\n case \"vertex\":\n return {\n slice: {\n transport: effective,\n params: {\n project: values.project,\n location: values.location,\n ...(values.publisher === undefined ? {} : { publisher: values.publisher }),\n },\n },\n ok: true,\n };\n case \"foundry\":\n return { slice: { transport: effective, params: { resource: values.resource } }, ok: true };\n case \"azure-openai\":\n return {\n slice: {\n transport: effective,\n params: {\n resource: values.resource,\n deployment: values.deployment,\n api_version: values.api_version,\n },\n },\n ok: true,\n };\n }\n}\n\n/**\n * `params` as a layer may write them: scalars, and no literal secret. Which\n * keys are legal depends on `transport` (§1.3) or on the voice preset (§1.7),\n * so that half waits for the merge — the secret scan does not, because its\n * diagnostic has to name the file the secret was written into.\n */\nfunction readParams(\n ctx: Ctx,\n raw: unknown,\n path: string,\n): { value?: Record<string, string | number | boolean>; ok: boolean } {\n if (!isPlainObject(raw)) {\n err(ctx, \"invalid_type\", path, `${path} must be a map`);\n return { ok: false };\n }\n const out: Record<string, string | number | boolean> = {};\n let ok = true;\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value !== \"string\" && typeof value !== \"number\" && typeof value !== \"boolean\") {\n err(\n ctx,\n \"invalid_type\",\n `${path}.${key}`,\n `${path}.${key} must be a string, number or boolean`,\n );\n ok = false;\n continue;\n }\n if (typeof value === \"string\" && looksLikeLiteralSecret(key, value)) {\n err(\n ctx,\n \"literal_secret\",\n `${path}.${key}`,\n `${path}.${key} holds a literal secret — put it in credential.ref as a reference`,\n );\n ok = false;\n continue;\n }\n out[key] = value;\n }\n return ok ? { ok: true, value: out } : { ok: false };\n}\n\nfunction readBaseUrl(ctx: Ctx, raw: unknown, path: string): { value?: string; ok: boolean } {\n if (typeof raw !== \"string\") {\n err(ctx, \"invalid_type\", path, `${path} must be a string`);\n return { ok: false };\n }\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n err(ctx, \"invalid_base_url\", path, `${path} is not a valid URL: ${raw}`);\n return { ok: false };\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n err(\n ctx,\n \"invalid_base_url\",\n path,\n `${path} must use http:// or https:// (got ${parsed.protocol}//)`,\n );\n return { ok: false };\n }\n if (parsed.username || parsed.password) {\n err(\n ctx,\n \"literal_secret\",\n path,\n `${path} embeds credentials in the URL — move them to credential.ref as a reference`,\n );\n return { ok: false };\n }\n return { ok: true, value: raw };\n}\n\nfunction readBoolean(ctx: Ctx, raw: unknown, path: string): { value?: boolean; ok: boolean } {\n if (typeof raw !== \"boolean\") {\n err(ctx, \"invalid_type\", path, `${path} must be true or false`);\n return { ok: false };\n }\n return { ok: true, value: raw };\n}\n\n/** What one layer wrote for an entry, before the kind-dependent half runs. */\ninterface ReadEntryResult {\n entry: AIProviderEntryPatch;\n /**\n * Keys this layer wrote, valid or not. A field that was written and rejected\n * here must not be reported a second time as missing.\n */\n present: ReadonlySet<string>;\n}\n\n/**\n * Read one entry as a **patch**: every check that does not depend on `kind` —\n * types, URLs, the credential grammar, literal secrets, unknown keys.\n *\n * A layer may hold a partial entry (§1.5), so `kind` is optional here and the\n * checks that need it are {@link checkEntry}'s, which runs on the merged\n * entry. A `kind` that *is* written still has to be one of\n * {@link AI_PROVIDER_KINDS}: a typo is malformed input, not an override.\n */\nfunction readEntry(ctx: Ctx, raw: unknown, path: string): ReadEntryResult | undefined {\n if (!isPlainObject(raw)) {\n err(ctx, \"invalid_type\", path, `${path} must be a map`);\n return undefined;\n }\n\n const present: ReadonlySet<string> = new Set(Object.keys(raw));\n const entry: AIProviderEntryPatch = {};\n let ok = true;\n\n if (raw.kind !== undefined) {\n if (\n typeof raw.kind !== \"string\" ||\n !(AI_PROVIDER_KINDS as readonly string[]).includes(raw.kind)\n ) {\n err(\n ctx,\n \"unknown_kind\",\n `${path}.kind`,\n `${path}.kind must be one of ${AI_PROVIDER_KINDS.join(\", \")}`,\n );\n ok = false;\n } else {\n entry.kind = raw.kind as AIProviderKind;\n }\n }\n\n for (const key of present) {\n if (!ENTRY_KEYS[key]) {\n err(ctx, \"unknown_key\", `${path}.${key}`, `${path}.${key} is not a registry key`);\n ok = false;\n }\n }\n\n if (raw.label !== undefined) {\n if (typeof raw.label !== \"string\") {\n err(ctx, \"invalid_type\", `${path}.label`, `${path}.label must be a string`);\n ok = false;\n } else {\n entry.label = raw.label;\n }\n }\n if (raw.preset !== undefined) {\n if (typeof raw.preset !== \"string\" || !isSafeProviderId(raw.preset)) {\n err(\n ctx,\n \"invalid_preset\",\n `${path}.preset`,\n `${path}.preset must be a catalog preset id matching [a-z0-9][a-z0-9_-]*`,\n );\n ok = false;\n } else {\n entry.preset = raw.preset;\n }\n }\n if (raw.base_url !== undefined) {\n const res = readBaseUrl(ctx, raw.base_url, `${path}.base_url`);\n if (!res.ok) ok = false;\n else entry.base_url = res.value;\n }\n if (raw.headers !== undefined) {\n const headers = readStringMap(ctx, raw.headers, `${path}.headers`, { secretScan: true });\n if (!headers) ok = false;\n else entry.headers = headers;\n }\n if (raw.credential !== undefined) {\n const res = readCredential(ctx, raw.credential, `${path}.credential`);\n if (!res.ok) ok = false;\n else entry.credential = res.value;\n }\n if (raw.enabled !== undefined) {\n const res = readBoolean(ctx, raw.enabled, `${path}.enabled`);\n if (!res.ok) ok = false;\n else entry.enabled = res.value;\n }\n if (raw.locked !== undefined) {\n const res = readBoolean(ctx, raw.locked, `${path}.locked`);\n if (!res.ok) ok = false;\n else entry.locked = res.value;\n }\n if (raw.surface !== undefined) {\n if (\n typeof raw.surface !== \"string\" ||\n !(AI_PROVIDER_SURFACES as readonly string[]).includes(raw.surface)\n ) {\n err(\n ctx,\n \"unknown_surface\",\n `${path}.surface`,\n `${path}.surface must be one of ${AI_PROVIDER_SURFACES.join(\", \")}`,\n );\n ok = false;\n } else {\n entry.surface = raw.surface as AIProviderSurface;\n }\n }\n if (raw.transport !== undefined) {\n if (\n typeof raw.transport !== \"string\" ||\n !(AI_PROVIDER_TRANSPORTS as readonly string[]).includes(raw.transport)\n ) {\n err(\n ctx,\n \"unknown_transport\",\n `${path}.transport`,\n `${path}.transport must be one of ${AI_PROVIDER_TRANSPORTS.join(\", \")}`,\n );\n ok = false;\n } else {\n entry.transport = raw.transport as AIProviderTransport;\n }\n }\n if (raw.params !== undefined) {\n const res = readParams(ctx, raw.params, `${path}.params`);\n if (!res.ok) ok = false;\n else entry.params = res.value;\n }\n if (raw.query_params !== undefined) {\n const qp = readStringMap(ctx, raw.query_params, `${path}.query_params`, { secretScan: true });\n if (!qp) ok = false;\n else entry.query_params = qp;\n }\n if (raw.model_map !== undefined) {\n const map = readStringMap(ctx, raw.model_map, `${path}.model_map`, { secretScan: false });\n if (!map) ok = false;\n else entry.model_map = map;\n }\n if (raw.capabilities !== undefined) {\n if (!isPlainObject(raw.capabilities)) {\n err(ctx, \"invalid_type\", `${path}.capabilities`, `${path}.capabilities must be a map`);\n ok = false;\n } else {\n const caps: Record<string, AIProviderCapabilities> = {};\n for (const [modelId, value] of Object.entries(raw.capabilities)) {\n const capPath = `${path}.capabilities.${modelId}`;\n if (!isPlainObject(value)) {\n err(ctx, \"invalid_type\", capPath, `${capPath} must be a map`);\n ok = false;\n continue;\n }\n const cap: AIProviderCapabilities = {};\n for (const [capKey, capValue] of Object.entries(value)) {\n if (!CAPABILITY_KEYS[capKey]) {\n err(\n ctx,\n \"unknown_key\",\n `${capPath}.${capKey}`,\n `${capPath}.${capKey} is not a capability (${Object.keys(CAPABILITY_KEYS).join(\", \")})`,\n );\n ok = false;\n continue;\n }\n const expected = capKey === \"tools\" || capKey === \"images\" ? \"boolean\" : \"number\";\n if (typeof capValue !== expected) {\n err(\n ctx,\n \"invalid_type\",\n `${capPath}.${capKey}`,\n `${capPath}.${capKey} must be a ${expected}`,\n );\n ok = false;\n continue;\n }\n (cap as Record<string, unknown>)[capKey] = capValue;\n }\n caps[modelId] = cap;\n }\n entry.capabilities = caps;\n }\n }\n if (raw.discovery !== undefined) {\n if (!isPlainObject(raw.discovery)) {\n err(ctx, \"invalid_type\", `${path}.discovery`, `${path}.discovery must be a map`);\n ok = false;\n } else {\n const type = raw.discovery.type;\n if (typeof type !== \"string\") {\n err(\n ctx,\n \"invalid_type\",\n `${path}.discovery.type`,\n `${path}.discovery.type must be a string`,\n );\n ok = false;\n } else {\n if (!(AI_PROVIDER_DISCOVERY_TYPES as readonly string[]).includes(type)) {\n warn(\n ctx,\n \"unknown_discovery_type\",\n `${path}.discovery.type`,\n `${path}.discovery.type '${type}' is not a known probe ` +\n `(${AI_PROVIDER_DISCOVERY_TYPES.join(\", \")}) — it is kept verbatim`,\n );\n }\n const discovery: AIProviderDiscovery = { type };\n const discPath = raw.discovery.path;\n if (discPath !== undefined) {\n if (typeof discPath !== \"string\") {\n err(\n ctx,\n \"invalid_type\",\n `${path}.discovery.path`,\n `${path}.discovery.path must be a string`,\n );\n ok = false;\n } else {\n discovery.path = discPath;\n }\n }\n for (const key of Object.keys(raw.discovery)) {\n if (key !== \"type\" && key !== \"path\") {\n err(\n ctx,\n \"unknown_key\",\n `${path}.discovery.${key}`,\n `${path}.discovery.${key} is not a discovery key`,\n );\n ok = false;\n }\n }\n entry.discovery = discovery;\n }\n }\n }\n\n return ok ? { entry, present } : undefined;\n}\n\n/** The seven fields both records share, in document order. */\nfunction entryCommon(patch: AIProviderEntryPatch): AIProviderEntryCommon {\n const common: AIProviderEntryCommon = {};\n if (patch.label !== undefined) common.label = patch.label;\n if (patch.preset !== undefined) common.preset = patch.preset;\n if (patch.base_url !== undefined) common.base_url = patch.base_url;\n if (patch.headers !== undefined) common.headers = patch.headers;\n if (patch.credential !== undefined) common.credential = patch.credential;\n if (patch.enabled !== undefined) common.enabled = patch.enabled;\n if (patch.locked !== undefined) common.locked = patch.locked;\n return common;\n}\n\n/**\n * Complete a patch into an entry, or report why it cannot be one.\n *\n * This is the kind-dependent half of validation — the `stt`/`tts` record split\n * (§1.7), the `surface` requirement, the per-transport `params` union (§1.3) —\n * plus the completeness gate itself. It runs on the **merged** entry, because\n * `kind` decides which record applies and a layer is allowed to leave `kind`\n * to a lower one (§1.5).\n *\n * Diagnostics name the entry, not the layers that fed it: the caller that\n * knows the sources ({@link validateMergedRegistry}) attributes them.\n *\n * @param present keys the source wrote, valid or not.\n */\nfunction checkEntry(\n ctx: Ctx,\n patch: AIProviderEntryPatch,\n path: string,\n present: ReadonlySet<string>,\n): AIProviderEntry | undefined {\n const kind = patch.kind;\n if (kind === undefined) {\n // A written-but-rejected `kind` already has its `unknown_kind` diagnostic.\n if (!present.has(\"kind\")) {\n err(\n ctx,\n \"missing_kind\",\n `${path}.kind`,\n `${path}.kind is required and no layer supplies it — ` +\n `an entry needs one of ${AI_PROVIDER_KINDS.join(\", \")}`,\n );\n }\n return undefined;\n }\n\n let ok = true;\n const common = entryCommon(patch);\n // Re-read through the scalar/secret gate: a patch that came from a file has\n // already passed it, but a programmatically injected layer (the control\n // plane's `session`) has not — and the no-literal-secrets rule is one rule,\n // so every site the per-file read scans (`credential.ref`, `headers`,\n // `query_params`, `base_url` userinfo, `params`) is scanned here too.\n if (patch.base_url !== undefined && !readBaseUrl(ctx, patch.base_url, `${path}.base_url`).ok) {\n ok = false;\n }\n if (\n patch.headers !== undefined &&\n readStringMap(ctx, patch.headers, `${path}.headers`, { secretScan: true }) === undefined\n ) {\n ok = false;\n }\n if (\n patch.query_params !== undefined &&\n readStringMap(ctx, patch.query_params, `${path}.query_params`, { secretScan: true }) ===\n undefined\n ) {\n ok = false;\n }\n if (\n patch.credential !== undefined &&\n !readCredential(ctx, patch.credential, `${path}.credential`).ok\n ) {\n ok = false;\n }\n let params: Record<string, string | number | boolean> | undefined;\n if (patch.params !== undefined) {\n const res = readParams(ctx, patch.params, `${path}.params`);\n if (!res.ok) ok = false;\n else params = res.value;\n }\n\n if (kind === \"stt\" || kind === \"tts\") {\n // §1.7 is the whole point of the reduced record, so the message says which\n // key and why.\n for (const key of LLM_ONLY_KEYS) {\n if (!present.has(key)) continue;\n err(\n ctx,\n \"llm_only_key\",\n `${path}.${key}`,\n `${path}.${key} is llm-only and not accepted on kind '${kind}' ` +\n `(voice entries take kind, label, preset, base_url, headers, credential, params, enabled)`,\n );\n ok = false;\n }\n for (const key of present) {\n if (VOICE_KEYS[key] || (LLM_ONLY_KEYS as readonly string[]).includes(key)) continue;\n err(ctx, \"unknown_key\", `${path}.${key}`, `${path}.${key} is not a registry key`);\n ok = false;\n }\n const voice: AIProviderVoiceEntry = { kind, ...common };\n if (params !== undefined) voice.params = params;\n return ok ? voice : undefined;\n }\n\n const llm: AIProviderLlmEntry = { kind, ...common };\n\n if (patch.surface !== undefined) {\n llm.surface = patch.surface;\n } else if (!present.has(\"surface\") && patch.preset === undefined) {\n err(\n ctx,\n \"missing_surface\",\n `${path}.surface`,\n `${path}.surface is required unless the entry inherits one from a preset`,\n );\n ok = false;\n }\n\n const transportResult = readTransportSlice(ctx, patch.transport, params, path, present);\n if (!transportResult.ok) ok = false;\n else Object.assign(llm, transportResult.slice);\n\n if (patch.query_params !== undefined) llm.query_params = patch.query_params;\n if (patch.model_map !== undefined) llm.model_map = patch.model_map;\n if (patch.capabilities !== undefined) llm.capabilities = patch.capabilities;\n if (patch.discovery !== undefined) llm.discovery = patch.discovery;\n\n return ok ? llm : undefined;\n}\n\n/** Options for {@link validateRegistry}. */\nexport interface ValidateRegistryOptions {\n /** Prefix for diagnostic paths — normally the file the document came from. */\n source?: string;\n /**\n * The layer this document feeds. Given — and not `catalog` — the document is\n * read as **one layer** of the §1.5 stack: an entry may be a partial\n * override, so a `kind`, `surface` or transport `params` that another layer\n * supplies is not an error here. {@link validateMergedRegistry} gates the\n * merged entry instead.\n *\n * Omitted, the document has to stand on its own: every entry must be\n * complete, which is what a writer (`skaile providers add`) checks the entry\n * it just built against.\n */\n layer?: AIProviderLayerId;\n}\n\n/**\n * Validate a parsed `providers.yml` document (§1.1–§1.7).\n *\n * Total: never throws. Entries that produce an error are omitted from\n * `document`, mirroring the resolver's per-entry skip semantics — one bad entry\n * must not take the whole registry down. Every diagnostic names the offending\n * key in `path`.\n *\n * Enforced here whatever the mode: safe entry ids, the `kind`/`surface`/\n * `transport`/`credential.kind` enums, the value types, and the\n * no-literal-secrets rule for `credential.ref`, `headers`, `query_params`,\n * `params` and `base_url` userinfo — a secret must be caught in the file it\n * was written into, not in an anonymous merged document.\n *\n * Enforced only when {@link ValidateRegistryOptions.layer} says this document\n * is complete on its own: that an entry has a `kind`, that an `llm` entry has a\n * `surface`, the voice subset (§1.7), and the per-transport `params` union\n * (§1.3). Those depend on `kind`, which a layer may leave to a lower one.\n *\n * Defaults are deliberately **not** materialized: writing `enabled: true` or\n * `transport: direct` into a layer would let that layer's implicit default\n * override a lower layer's explicit value during the merge. Read them through\n * {@link isEntryEnabled} / {@link entryTransport}.\n */\nexport function validateRegistry(\n raw: unknown,\n options: ValidateRegistryOptions = {},\n): RegistryValidation {\n const ctx: Ctx = { diagnostics: [] };\n const document: AIProviderRegistryDocument = { version: 1, providers: {} };\n const prefix = options.source ? `${options.source}: ` : \"\";\n // The catalog layer is generated from presets, never hand-written, so it is\n // held to the same completeness bar as a standalone document.\n const partial = options.layer !== undefined && options.layer !== \"catalog\";\n\n if (raw === undefined || raw === null) return { document, diagnostics: ctx.diagnostics };\n if (!isPlainObject(raw)) {\n err(ctx, \"invalid_type\", \"\", `${prefix}registry document must be a map`);\n return { document, diagnostics: ctx.diagnostics };\n }\n\n if (raw.version !== undefined && raw.version !== 1) {\n err(ctx, \"unsupported_version\", \"version\", `version must be 1 (got ${String(raw.version)})`);\n return { document, diagnostics: ctx.diagnostics };\n }\n\n for (const key of Object.keys(raw)) {\n if (key === \"version\" || key === \"providers\") continue;\n if (key === \"roles\") {\n warn(\n ctx,\n \"roles_not_here\",\n \"roles\",\n \"roles are read from skaile.yaml, not from providers.yml — this block is ignored\",\n );\n continue;\n }\n warn(ctx, \"unknown_key\", key, `${key} is not a registry document key — ignored`);\n }\n\n if (raw.providers === undefined) return { document, diagnostics: ctx.diagnostics };\n if (!isPlainObject(raw.providers)) {\n err(ctx, \"invalid_type\", \"providers\", \"providers must be a map of entry id → entry\");\n return { document, diagnostics: ctx.diagnostics };\n }\n\n for (const [id, rawEntry] of Object.entries(raw.providers)) {\n const path = `providers.${id}`;\n if (!isSafeProviderId(id)) {\n err(\n ctx,\n \"invalid_id\",\n path,\n `'${id}' is not a valid entry id — use lowercase letters, digits, '-' and '_' ` +\n `starting with a letter or digit`,\n );\n continue;\n }\n const read = readEntry(ctx, rawEntry, path);\n if (!read) continue;\n if (partial) {\n document.providers[id] = read.entry;\n continue;\n }\n const entry = checkEntry(ctx, read.entry, path, read.present);\n if (entry) document.providers[id] = entry;\n }\n\n if (options.source) {\n for (const diagnostic of ctx.diagnostics) {\n diagnostic.message = `${prefix}${diagnostic.message}`;\n }\n }\n return { document, diagnostics: ctx.diagnostics };\n}\n\n// ── Reading defaults ───────────────────────────────────────────────────────\n\n/** `enabled` defaults to `true`. */\nexport function isEntryEnabled(entry: AIProviderEntry): boolean {\n return entry.enabled !== false;\n}\n\n/** `transport` defaults to `direct`; voice entries have none. */\nexport function entryTransport(entry: AIProviderEntry): AIProviderTransport | undefined {\n if (entry.kind !== \"llm\" && entry.kind !== \"embed\") return undefined;\n return entry.transport ?? \"direct\";\n}\n\n/**\n * Resolve an entry's endpoint (§1.3).\n *\n * An explicit `base_url` always wins. Otherwise the transport's template is\n * interpolated from `params` (`publisher` defaults to `google` for Vertex).\n * `transport: direct` has no derivation — an entry that reaches here without a\n * `base_url` inherits one from its preset, which the catalog layer supplies\n * during the merge.\n */\nexport function resolveEntryBaseUrl(entry: AIProviderEntry): string | undefined {\n if (entry.base_url) return entry.base_url;\n const transport = entryTransport(entry);\n if (!transport || transport === \"direct\") return undefined;\n const template = AI_PROVIDER_BASE_URL_TEMPLATES[transport];\n const params = (entry as AIProviderLlmEntry).params as Record<string, string> | undefined;\n if (!params) return undefined;\n const filled: Record<string, string> = { ...params };\n if (transport === \"vertex\") filled.publisher ??= \"google\";\n let out = template;\n for (const [key, value] of Object.entries(filled)) {\n out = out.replaceAll(`{${key}}`, value);\n }\n return /\\{[a-z_]+\\}/.test(out) ? undefined : out;\n}\n\n/**\n * The canonical spelling of an `anthropic-messages` endpoint: the host root\n * that `ANTHROPIC_BASE_URL` takes. Trims, then drops trailing slashes and one\n * trailing `/v1` path segment (case-insensitive), keeping any query or\n * fragment.\n *\n * The Claude CLI, the Anthropic SDK and Goose append `/v1/messages`, so a\n * stored `https://api.anthropic.com/v1` would reach `/v1/v1/messages` and 404.\n * Clients that want the versioned base (`@ai-sdk/anthropic`, Continue) add the\n * `/v1` back themselves. Never apply this to another surface: an OpenAI-style\n * base URL legitimately ends in `/v1` — use {@link normalizeEntryBaseUrl}.\n */\nexport function normalizeAnthropicBaseUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) return undefined;\n const parsed = parseHttpUrlWithoutUserinfo(trimmed);\n if (!parsed) {\n return trimmed.replace(/\\/+$/, \"\").replace(/\\/v1$/i, \"\").replace(/\\/+$/, \"\") || undefined;\n }\n // Work on the path, so a query or fragment does not hide the `/v1`. Built by\n // hand because an emptied path would serialize as \"/\".\n const path = parsed.pathname.replace(/\\/+$/, \"\").replace(/\\/v1$/i, \"\").replace(/\\/+$/, \"\");\n return `${parsed.origin}${path}${parsed.search}${parsed.hash}`;\n}\n\n/**\n * `url` parsed, when rebuilding it from `origin` loses nothing: an http(s)\n * URL without userinfo. `origin` is the string \"null\" for other schemes, and a\n * registry that skipped `readBaseUrl` can still carry either shape.\n */\nfunction parseHttpUrlWithoutUserinfo(url: string): URL | undefined {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return undefined;\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return undefined;\n if (parsed.username || parsed.password) return undefined;\n return parsed;\n}\n\n/**\n * An entry's endpoint in the registry's canonical spelling for its wire\n * `surface`: {@link normalizeAnthropicBaseUrl} for `anthropic-messages`, the\n * URL unchanged for every other surface.\n *\n * `surface` is a parameter, not read off an entry, because an entry may\n * inherit it from a catalog preset that this module cannot see.\n */\nexport function normalizeEntryBaseUrl(\n url: string | undefined,\n surface: AIProviderSurface | undefined,\n): string | undefined {\n return surface === \"anthropic-messages\" ? normalizeAnthropicBaseUrl(url) : url;\n}\n\n// ── Merge ──────────────────────────────────────────────────────────────────\n\nconst LAYER_RANK: Record<AIProviderLayerId, number> = {\n catalog: 0,\n user: 1,\n workspace: 2,\n runtime: 3,\n session: 4,\n};\n\n/**\n * Per-key deep merge with `high` winning. Plain objects recurse; everything\n * else (scalars, arrays) is taken wholesale from whichever side defines it.\n */\nfunction deepMerge(high: unknown, low: unknown): unknown {\n if (high === undefined) return low;\n if (low === undefined) return high;\n if (!isPlainObject(high) || !isPlainObject(low)) return high;\n const out: Record<string, unknown> = { ...low };\n for (const [key, value] of Object.entries(high)) {\n out[key] = deepMerge(value, low[key]);\n }\n return out;\n}\n\n/**\n * Merge registry layers into one view (§1.5).\n *\n * Precedence is taken from each layer's `layer` id, not from array position:\n * `catalog` < `user` < `workspace` < `runtime` < `session`. Two layers with the\n * same id are applied in array order, earliest winning. The merge is per key\n * and deep — a workspace entry that sets only `base_url` keeps the user\n * entry's credential, headers and model map.\n *\n * `locked: true` freezes an entry: every **lower** layer's contribution to that\n * id is dropped silently, which is what makes a control-plane-pinned endpoint\n * un-overridable from a checkout. (`skaile providers set` refuses loudly\n * instead — silence is only correct for the merge.)\n *\n * This is a fold over layer *patches* and checks nothing: an entry no layer\n * completed comes out of here incomplete. {@link validateMergedRegistry} is\n * the gate — {@link loadProviderRegistry} runs it, and any other caller that\n * merges hand-written layers has to as well.\n */\nexport function mergeRegistries(layers: AIProviderRegistryLayer[]): MergedAIProviderRegistry {\n const ordered = layers\n .map((layer, index) => ({ layer, index }))\n .sort((a, b) => {\n const rank = LAYER_RANK[b.layer.layer] - LAYER_RANK[a.layer.layer];\n return rank !== 0 ? rank : a.index - b.index;\n })\n .map((x) => x.layer);\n\n const providers: AIProviderRegistryPatch = {};\n const origin: Record<string, AIProviderLayerId> = {};\n const order: string[] = [];\n const frozen = new Set<string>();\n\n for (const { layer, providers: entries } of ordered) {\n for (const [id, entry] of Object.entries(entries)) {\n if (frozen.has(id)) continue;\n if (providers[id] === undefined) {\n providers[id] = { ...entry };\n origin[id] = layer;\n order.push(id);\n } else {\n providers[id] = deepMerge(providers[id], entry) as AIProviderEntryPatch;\n }\n if (entry.locked) frozen.add(id);\n }\n }\n\n return {\n version: 1,\n // The fold cannot narrow a patch into an entry; `validateMergedRegistry`\n // is what turns this view into one every consumer can read as complete.\n providers: providers as AIProviderRegistry,\n order,\n origin,\n locked: [...frozen],\n };\n}\n\n/** One labelled input to {@link validateMergedRegistry}. */\nexport interface AIProviderRegistrySource {\n /** Where the layer came from — the file path, for the two on-disk layers. */\n label: string;\n providers: AIProviderRegistryPatch;\n}\n\n/** Options for {@link validateMergedRegistry}. */\nexport interface ValidateMergedRegistryOptions {\n /**\n * The layers that were merged, labelled. A merge-time diagnostic names the\n * files that contributed the entry, because those are what the operator has\n * to edit — collapsing the layers into one anonymous document would lose\n * exactly the information the error is about.\n */\n sources?: AIProviderRegistrySource[];\n}\n\n/** Result of {@link validateMergedRegistry}. */\nexport interface MergedRegistryValidation {\n /** The merged view, with every entry no layer completed removed. */\n registry: MergedAIProviderRegistry;\n diagnostics: AIProviderDiagnostic[];\n}\n\n/**\n * Gate the **merged** registry (§1.5) — the completeness half of validation.\n *\n * {@link validateRegistry} in layer mode accepts a partial entry, because a\n * workspace file that names `base_url` alone is an override, not a\n * redefinition. This is where an entry has to be whole: only here has every\n * layer folded in, so only here is `kind` known and with it which record\n * applies (§1.7), whether a `surface` is missing, and which transport the\n * `params` belong to (§1.3).\n *\n * Entries that fail are dropped, so a consumer never sees a half-defined\n * endpoint. Every diagnostic names the entry id and — when `sources` are\n * given — the layers that fed the entry, whatever the check that raised it.\n */\nexport function validateMergedRegistry(\n merged: MergedAIProviderRegistry,\n options: ValidateMergedRegistryOptions = {},\n): MergedRegistryValidation {\n const ctx: Ctx = { diagnostics: [] };\n const providers: AIProviderRegistry = {};\n const origin: Record<string, AIProviderLayerId> = {};\n const order: string[] = [];\n\n for (const id of merged.order) {\n const patch: AIProviderEntryPatch | undefined = merged.providers[id];\n if (patch === undefined) continue;\n const present: ReadonlySet<string> = new Set(\n Object.entries(patch)\n .filter(([, value]) => value !== undefined)\n .map(([key]) => key),\n );\n const from = ctx.diagnostics.length;\n const entry = checkEntry(ctx, patch, `providers.${id}`, present);\n // Attributed once over everything this entry raised, so no message site\n // can forget to say which files the operator has to edit.\n const contributors = (options.sources ?? [])\n .filter((source) => source.providers[id] !== undefined)\n .map((source) => source.label);\n if (contributors.length > 0) {\n const where = ` (contributed by ${contributors.join(\", \")})`;\n for (const diagnostic of ctx.diagnostics.slice(from)) diagnostic.message += where;\n }\n if (entry === undefined) continue;\n providers[id] = entry;\n origin[id] = merged.origin[id];\n order.push(id);\n }\n\n return {\n registry: {\n version: 1,\n providers,\n order,\n origin,\n locked: merged.locked.filter((id) => providers[id] !== undefined),\n },\n diagnostics: ctx.diagnostics,\n };\n}\n\n/**\n * Narrow a merged registry to the entries named in `ids`.\n *\n * Registry order is kept (the order of `merged.order`, not of `ids`), so bare\n * model ids still resolve down the same precedence list. `origin` and\n * `locked` are restricted to the picked entries. An id the registry does not\n * hold is ignored here; the caller that wants to warn about it compares `ids`\n * with the result's `order`.\n */\nexport function pickRegistryEntries(\n merged: MergedAIProviderRegistry,\n ids: readonly string[],\n): MergedAIProviderRegistry {\n const wanted: ReadonlySet<string> = new Set(ids);\n const order = merged.order.filter((id) => wanted.has(id) && merged.providers[id] !== undefined);\n const providers: AIProviderRegistry = {};\n const origin: Record<string, AIProviderLayerId> = {};\n for (const id of order) {\n providers[id] = merged.providers[id];\n origin[id] = merged.origin[id];\n }\n return {\n version: 1,\n providers,\n order,\n origin,\n locked: merged.locked.filter((id) => providers[id] !== undefined),\n };\n}\n\n/** Entries of a registry in registry order, as `[id, entry]` pairs. */\nexport function registryEntries(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n): Array<[string, AIProviderEntry]> {\n if (isMergedRegistry(registry)) {\n return registry.order.map((id) => [id, registry.providers[id]] as [string, AIProviderEntry]);\n }\n return Object.entries(registry);\n}\n\nfunction isMergedRegistry(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n): registry is MergedAIProviderRegistry {\n return Array.isArray((registry as MergedAIProviderRegistry).order);\n}\n\n// ── Credential references ──────────────────────────────────────────────────\n\n/** A parsed `credential.ref` (§1.4). */\nexport type AIProviderCredentialRef =\n | { form: \"env\"; name: string }\n | { form: \"cmd\"; command: string }\n | { form: \"platform\"; configId: string }\n | { form: \"keyring\"; service: string; account: string };\n\n/**\n * Parse a `credential.ref`. Returns `undefined` for anything that is not one of\n * the four reference forms — which, in a registry file, means a literal secret.\n */\nexport function parseCredentialRef(ref: string): AIProviderCredentialRef | undefined {\n const match = CREDENTIAL_REF.exec(ref.trim());\n if (!match) return undefined;\n const [, form, rest] = match;\n const body = rest.trim();\n if (body === \"\") return undefined;\n switch (form) {\n case \"env\":\n return ENV_NAME.test(body) ? { form: \"env\", name: body } : undefined;\n case \"cmd\":\n return { form: \"cmd\", command: body };\n case \"platform\":\n return { form: \"platform\", configId: body };\n case \"keyring\": {\n const slash = body.indexOf(\"/\");\n if (slash <= 0 || slash === body.length - 1) return undefined;\n return { form: \"keyring\", service: body.slice(0, slash), account: body.slice(slash + 1) };\n }\n default:\n return undefined;\n }\n}\n\n/** Render a parsed reference back to its `<form>:<body>` string. */\nexport function formatCredentialRef(ref: AIProviderCredentialRef): string {\n switch (ref.form) {\n case \"env\":\n return `env:${ref.name}`;\n case \"cmd\":\n return `cmd:${ref.command}`;\n case \"platform\":\n return `platform:${ref.configId}`;\n case \"keyring\":\n return `keyring:${ref.service}/${ref.account}`;\n }\n}\n\n// ── Model references ───────────────────────────────────────────────────────\n\n/** A model selector resolved against a registry. */\nexport interface ResolvedModelRef {\n /** Entry the model routes to. */\n providerId: string;\n /**\n * Logical model id, after `@role` expansion and before `model_map`. Absent\n * only when a dangling role left the provider without a named model — the\n * driver then uses its own default.\n */\n modelId?: string;\n /** Provider-side id: `model_map[modelId] ?? modelId`. */\n providerModelId?: string;\n /** The role name, when the selector was `@role`. */\n role?: string;\n /** Non-fatal notes: a dangling role, a role pointing at an unknown provider. */\n warnings: string[];\n}\n\n/** Entries a model reference may resolve to: enabled, and not a voice endpoint. */\nfunction selectableEntries(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n): Array<[string, AIProviderLlmEntry]> {\n return registryEntries(registry).filter(\n (pair): pair is [string, AIProviderLlmEntry] =>\n (pair[1].kind === \"llm\" || pair[1].kind === \"embed\") && isEntryEnabled(pair[1]),\n );\n}\n\nfunction resolveAgainstEntry(\n providerId: string,\n entry: AIProviderLlmEntry,\n modelId: string | undefined,\n extra: { role?: string; warnings: string[] },\n): ResolvedModelRef {\n return {\n providerId,\n modelId,\n providerModelId: modelId === undefined ? undefined : (entry.model_map?.[modelId] ?? modelId),\n role: extra.role,\n warnings: extra.warnings,\n };\n}\n\n/**\n * Resolve a model selector against a registry (§1.6, §9.8).\n *\n * Three forms:\n * - `\"<providerId>/<modelId>\"` — explicit. The leading segment is only treated\n * as a provider when the registry actually has that entry, so vendor-scoped\n * ids (`meta-llama/Llama-3.3-70B`, `openai/gpt-oss-120b`) still resolve as\n * bare model ids.\n * - `\"<modelId>\"` — bare; the first entry in registry order that maps the id\n * wins, else the first entry in registry order.\n * - `\"@role\"` — resolved through `roles` (which lives in `skaile.yaml`). A\n * dangling role is **not** fatal: it falls back to registry order and reports\n * a warning.\n *\n * Returns `undefined` when no entry can serve the reference at all (an empty or\n * fully-disabled registry).\n */\nexport function parseModelRef(\n ref: string,\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n roles?: Record<string, string>,\n): ResolvedModelRef | undefined {\n const entries = selectableEntries(registry);\n if (entries.length === 0) return undefined;\n\n const warnings: string[] = [];\n let selector = ref.trim();\n let role: string | undefined;\n\n if (selector.startsWith(\"@\")) {\n role = selector.slice(1);\n const target = roles?.[role];\n if (!target) {\n warnings.push(`role '@${role}' is not defined in roles — falling back to registry order`);\n const [providerId, entry] = entries[0];\n return resolveAgainstEntry(providerId, entry, undefined, { role, warnings });\n }\n selector = target.trim();\n if (selector.startsWith(\"@\")) {\n warnings.push(`role '@${role}' points at another role ('${selector}') — roles do not chain`);\n const [providerId, entry] = entries[0];\n return resolveAgainstEntry(providerId, entry, undefined, { role, warnings });\n }\n }\n\n const slash = selector.indexOf(\"/\");\n if (slash > 0) {\n const head = selector.slice(0, slash);\n const tail = selector.slice(slash + 1);\n const match = entries.find(([id]) => id === head);\n if (match && tail !== \"\") {\n return resolveAgainstEntry(match[0], match[1], tail, { role, warnings });\n }\n if (!match && registryEntries(registry).some(([id]) => id === head)) {\n warnings.push(`provider '${head}' is disabled or not an llm entry — falling back`);\n }\n }\n\n const mapped = entries.find(\n ([, entry]) => entry.model_map?.[selector] !== undefined || entry.capabilities?.[selector],\n );\n const [providerId, entry] = mapped ?? entries[0];\n return resolveAgainstEntry(providerId, entry, selector, { role, warnings });\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { logErr } from './chunk-
|
|
2
|
-
import { flowKindProvider } from './chunk-
|
|
3
|
-
import { knowledgeKindProvider } from './chunk-
|
|
1
|
+
import { logErr } from './chunk-RTQTWQHW.js';
|
|
2
|
+
import { flowKindProvider } from './chunk-JULFGNQN.js';
|
|
3
|
+
import { knowledgeKindProvider } from './chunk-BR2IXOWX.js';
|
|
4
4
|
import { createDefaultRegistry } from './chunk-HGPSZXZP.js';
|
|
5
5
|
|
|
6
6
|
// cli/src/open-registry.ts
|
|
@@ -103,5 +103,5 @@ async function openLibraryManager() {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export { LocalCatalogDisabledError, createFullRegistry, openCatalogSource, openLibrary, openLibraryManager, resolveCatalogSource };
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
106
|
+
//# sourceMappingURL=chunk-NHABMUXY.js.map
|
|
107
|
+
//# sourceMappingURL=chunk-NHABMUXY.js.map
|