@skaile/workspaces 4.16.2 → 4.17.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 +16 -0
- package/dist/{asset-feeds-7SXXHPIF.js → asset-feeds-MQKQDF3R.js} +4 -4
- package/dist/{asset-feeds-7SXXHPIF.js.map → asset-feeds-MQKQDF3R.js.map} +1 -1
- package/dist/asset-manager/index.js +1 -1
- package/dist/bridge/drivers/claude-sdk.js +8 -6
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +5 -3
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +4 -4
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +6 -6
- package/dist/bridge/drivers/goose.js +4 -4
- package/dist/bridge/drivers/omp.js +5 -3
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +4 -4
- package/dist/bridge/drivers/qwen.js +6 -6
- package/dist/bridge/index.js +5 -5
- package/dist/bridge/src/agent-exec.d.ts +34 -0
- package/dist/bridge/src/agent-exec.d.ts.map +1 -0
- package/dist/bridge/src/drivers/_subprocess-cli.d.ts.map +1 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/bridge/src/index.d.ts +2 -0
- package/dist/bridge/src/index.d.ts.map +1 -1
- package/dist/bridge/src/runner-private-env.d.ts +19 -0
- package/dist/bridge/src/runner-private-env.d.ts.map +1 -0
- package/dist/{chunk-MRCGJ4N3.js → chunk-2AQIFJHK.js} +3 -3
- package/dist/{chunk-MRCGJ4N3.js.map → chunk-2AQIFJHK.js.map} +1 -1
- package/dist/{chunk-MGGFO32R.js → chunk-3H4HP733.js} +52 -12
- package/dist/chunk-3H4HP733.js.map +1 -0
- package/dist/{chunk-CJGNYHPG.js → chunk-3VGQLF3N.js} +2 -2
- package/dist/{chunk-CJGNYHPG.js.map → chunk-3VGQLF3N.js.map} +1 -1
- package/dist/{chunk-4SIMGJIU.js → chunk-3W7AOGPY.js} +19 -4
- package/dist/chunk-3W7AOGPY.js.map +1 -0
- package/dist/{chunk-LISGIFKY.js → chunk-4RKCOURU.js} +3 -3
- package/dist/{chunk-LISGIFKY.js.map → chunk-4RKCOURU.js.map} +1 -1
- package/dist/{chunk-RTIFNBX6.js → chunk-6F4TIY7X.js} +4 -4
- package/dist/{chunk-RTIFNBX6.js.map → chunk-6F4TIY7X.js.map} +1 -1
- package/dist/{chunk-OWFWZ2K4.js → chunk-7EAJNEQ5.js} +6 -6
- package/dist/{chunk-OWFWZ2K4.js.map → chunk-7EAJNEQ5.js.map} +1 -1
- package/dist/{chunk-43JBP4QJ.js → chunk-AAZDYM5D.js} +3 -3
- package/dist/{chunk-43JBP4QJ.js.map → chunk-AAZDYM5D.js.map} +1 -1
- package/dist/{chunk-KP2DZHAL.js → chunk-AOFJ2OKW.js} +2 -2
- package/dist/{chunk-KP2DZHAL.js.map → chunk-AOFJ2OKW.js.map} +1 -1
- package/dist/{chunk-GAH4YRCI.js → chunk-BGY4KTU6.js} +13 -3
- package/dist/chunk-BGY4KTU6.js.map +1 -0
- package/dist/{chunk-RPC2C3QL.js → chunk-C3YE4REG.js} +3 -3
- package/dist/{chunk-RPC2C3QL.js.map → chunk-C3YE4REG.js.map} +1 -1
- package/dist/{chunk-TEQDWOBS.js → chunk-D5CRFGDL.js} +4 -4
- package/dist/{chunk-TEQDWOBS.js.map → chunk-D5CRFGDL.js.map} +1 -1
- package/dist/{chunk-LDT6NGSL.js → chunk-JURHZYOY.js} +3 -3
- package/dist/{chunk-LDT6NGSL.js.map → chunk-JURHZYOY.js.map} +1 -1
- package/dist/{chunk-DEZOLXIA.js → chunk-NYDTZ2MK.js} +5 -5
- package/dist/{chunk-DEZOLXIA.js.map → chunk-NYDTZ2MK.js.map} +1 -1
- package/dist/{chunk-2TY2HO6D.js → chunk-RAHLV6QG.js} +6 -6
- package/dist/{chunk-2TY2HO6D.js.map → chunk-RAHLV6QG.js.map} +1 -1
- package/dist/{chunk-B4L3DTPD.js → chunk-WOE4LPGF.js} +3 -3
- package/dist/{chunk-B4L3DTPD.js.map → chunk-WOE4LPGF.js.map} +1 -1
- package/dist/{chunk-NFKLOGA2.js → chunk-XRTOSEF3.js} +2 -2
- package/dist/{chunk-NFKLOGA2.js.map → chunk-XRTOSEF3.js.map} +1 -1
- package/dist/{chunk-J7WFDLV6.js → chunk-YXXEHY7D.js} +5 -5
- package/dist/chunk-YXXEHY7D.js.map +1 -0
- package/dist/{chunk-OH2ULGQX.js → chunk-Z7KDOGKF.js} +6 -6
- package/dist/{chunk-OH2ULGQX.js.map → chunk-Z7KDOGKF.js.map} +1 -1
- package/dist/cli/index.js +36 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/connectors/index.js +6 -6
- package/dist/{ensure-sources-YQTLMWC7.js → ensure-sources-6XKA46PN.js} +4 -4
- package/dist/{ensure-sources-YQTLMWC7.js.map → ensure-sources-6XKA46PN.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +6 -6
- package/dist/factory-assets/connectors/deploy.js +6 -6
- package/dist/factory-assets/connectors/devserver.js +6 -6
- package/dist/factory-assets/connectors/flow/adapter.js +6 -6
- package/dist/factory-assets/connectors/flow/run-flow.js +7 -7
- package/dist/factory-assets/connectors/flow.js +6 -6
- package/dist/factory-assets/connectors/git.js +6 -6
- package/dist/factory-assets/connectors/gmail.js +6 -6
- package/dist/factory-assets/connectors/googledrive.js +6 -6
- package/dist/factory-assets/connectors/local.js +6 -6
- package/dist/factory-assets/connectors/mattermost.js +6 -6
- package/dist/factory-assets/connectors/memory.js +6 -6
- package/dist/factory-assets/connectors/minio.js +6 -6
- package/dist/factory-assets/connectors/postgres.js +6 -6
- package/dist/factory-assets/connectors/s3.js +6 -6
- package/dist/factory-assets/connectors/sharepoint.js +6 -6
- package/dist/factory-assets/connectors/sqlite.js +6 -6
- package/dist/factory-assets/connectors/static-server.js +6 -6
- package/dist/factory-assets/connectors/tunnel.js +6 -6
- package/dist/factory-assets/connectors/webdav.js +6 -6
- package/dist/factory-assets/connectors/xstate-store.js +6 -6
- package/dist/factory-assets/connectors/xstate.js +6 -6
- package/dist/{helpers-FLGUKSJC.js → helpers-6I4SY2S7.js} +4 -4
- package/dist/{helpers-FLGUKSJC.js.map → helpers-6I4SY2S7.js.map} +1 -1
- package/dist/{library-publish-GAGKIYZM.js → library-publish-PPNFBAVH.js} +6 -6
- package/dist/{library-publish-GAGKIYZM.js.map → library-publish-PPNFBAVH.js.map} +1 -1
- package/dist/{open-library-KBKNUPXA.js → open-library-64LO64NE.js} +5 -5
- package/dist/{open-library-KBKNUPXA.js.map → open-library-64LO64NE.js.map} +1 -1
- package/dist/{project-WJCOAMD2.js → project-3UFTV7DL.js} +5 -5
- package/dist/{project-WJCOAMD2.js.map → project-3UFTV7DL.js.map} +1 -1
- package/dist/runner/index.js +9 -9
- package/dist/runner/src/index.d.ts +1 -0
- package/dist/runner/src/index.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts +12 -2
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/ws-auth-token.d.ts +52 -0
- package/dist/runner/src/ws-auth-token.d.ts.map +1 -0
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/bridge.js +5 -5
- package/dist/sdk/index.js +9 -9
- package/dist/sdk/runner.js +9 -9
- package/dist/{setup-Y44FMZ3F.js → setup-JGXLTJ57.js} +10 -10
- package/dist/{setup-Y44FMZ3F.js.map → setup-JGXLTJ57.js.map} +1 -1
- package/dist/{source-4U7OVLVV.js → source-NHEYY7WH.js} +6 -6
- package/dist/{source-4U7OVLVV.js.map → source-NHEYY7WH.js.map} +1 -1
- package/dist/{source-manifest-publish-RUJVFIJG.js → source-manifest-publish-IJLVR3IL.js} +7 -7
- package/dist/{source-manifest-publish-RUJVFIJG.js.map → source-manifest-publish-IJLVR3IL.js.map} +1 -1
- package/dist/tui/index.js +9 -9
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-4SIMGJIU.js.map +0 -1
- package/dist/chunk-GAH4YRCI.js.map +0 -1
- package/dist/chunk-J7WFDLV6.js.map +0 -1
- package/dist/chunk-MGGFO32R.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fsDeadlineMs, withFsDeadline, tryWithFsDeadline } from './chunk-2FBPAR2V.js';
|
|
2
2
|
import { entryTransport, normalizeAnthropicBaseUrl, resolveEntryBaseUrl } from './chunk-GZZPKAV5.js';
|
|
3
|
+
import { isAbsolute, join } from 'path';
|
|
3
4
|
import { createReadStream, createWriteStream } from 'fs';
|
|
4
5
|
import { readdir, stat, rename, unlink } from 'fs/promises';
|
|
5
|
-
import { join } from 'path';
|
|
6
6
|
import { pipeline } from 'stream/promises';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
|
|
@@ -77,6 +77,21 @@ function buildClaudeEndpointEnv(args) {
|
|
|
77
77
|
}
|
|
78
78
|
return env;
|
|
79
79
|
}
|
|
80
|
+
var AGENT_EXEC_ENV = "SKAILE_AGENT_EXEC";
|
|
81
|
+
function resolveAgentExec(env = process.env) {
|
|
82
|
+
const value = env[AGENT_EXEC_ENV]?.trim();
|
|
83
|
+
if (!value) return null;
|
|
84
|
+
if (!isAbsolute(value)) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`${AGENT_EXEC_ENV} must be an absolute path to the agent launch shim, got "${value}"`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
function wrapAgentCommand(command, args, shim) {
|
|
92
|
+
if (!shim) return { command, args: [...args] };
|
|
93
|
+
return { command: shim, args: ["--", command, ...args] };
|
|
94
|
+
}
|
|
80
95
|
var STUB_TEXT = "[image removed: unprocessable image data]";
|
|
81
96
|
var STUB_TEXT_OVERSIZED = "[image removed: image too large]";
|
|
82
97
|
var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
@@ -293,6 +308,6 @@ async function probeResumeTranscript(sessionId, opts) {
|
|
|
293
308
|
}
|
|
294
309
|
}
|
|
295
310
|
|
|
296
|
-
export { ANTHROPIC_DEFAULT_BASE_URL, buildClaudeEndpointEnv, claudeEndpointMode, probeResumeTranscript, resolveClaudeConfigDir, scrubPoisonedTranscript };
|
|
297
|
-
//# sourceMappingURL=chunk-
|
|
298
|
-
//# sourceMappingURL=chunk-
|
|
311
|
+
export { AGENT_EXEC_ENV, ANTHROPIC_DEFAULT_BASE_URL, buildClaudeEndpointEnv, claudeEndpointMode, probeResumeTranscript, resolveAgentExec, resolveClaudeConfigDir, scrubPoisonedTranscript, wrapAgentCommand };
|
|
312
|
+
//# sourceMappingURL=chunk-3W7AOGPY.js.map
|
|
313
|
+
//# sourceMappingURL=chunk-3W7AOGPY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../bridge/src/cloud.ts","../bridge/src/agent-exec.ts","../bridge/src/drivers/scrub-transcript.ts","../bridge/src/drivers/resume-probe.ts"],"names":["join"],"mappings":"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","file":"chunk-3W7AOGPY.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","import { isAbsolute } from \"node:path\";\n\n/**\n * Names the shim that starts agent processes as a separate uid.\n *\n * In the Skaile agent image the runner cannot switch uid itself (it runs with\n * no-new-privs and no `CAP_SETUID`). When the container entrypoint has started\n * the root launcher (`skaile-agent-launchd`), it exports this variable with the\n * absolute path of the runner-side shim (`skaile-agent-exec`). A driver then\n * spawns `<shim> -- <command> <args...>` instead of `<command>`: the shim\n * passes its stdio, cwd, argv and env to the launcher, which runs the command\n * as the agent uid, forwards signals and reports the exit status, so the\n * returned child behaves like a direct one.\n *\n * Unset (every other environment, and the image until the entrypoint wires\n * it): drivers spawn directly, unchanged.\n */\nexport const AGENT_EXEC_ENV = \"SKAILE_AGENT_EXEC\";\n\n/**\n * The shim path from `env`, or `null` when the uid split is off.\n *\n * Throws on a relative path rather than spawning the agent unsplit: only the\n * entrypoint sets this, so a bad value is a broken image, and silently running\n * the agent as the runner's uid would hide exactly what the variable promises.\n */\nexport function resolveAgentExec(\n env: Record<string, string | undefined> = process.env,\n): string | null {\n const value = env[AGENT_EXEC_ENV]?.trim();\n if (!value) return null;\n if (!isAbsolute(value)) {\n throw new Error(\n `${AGENT_EXEC_ENV} must be an absolute path to the agent launch shim, got \"${value}\"`,\n );\n }\n return value;\n}\n\n/**\n * The command line to spawn: `command args` itself, or routed through the\n * shim when one is configured. The `--` stops the shim reading the agent's\n * own arguments as options.\n */\nexport function wrapAgentCommand(\n command: string,\n args: readonly string[],\n shim: string | null,\n): { command: string; args: string[] } {\n if (!shim) return { command, args: [...args] };\n return { command: shim, args: [\"--\", command, ...args] };\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\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(filePath: string): AsyncGenerator<string> {\n const stream = createReadStream(filePath, { encoding: \"utf8\" });\n let pending = \"\";\n try {\n for await (const chunk of stream) {\n pending += chunk as string;\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 } finally {\n stream.destroy();\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 timeoutMs = fsDeadlineMs();\n const result: ScrubTranscriptResult = {\n filePath: null,\n corrected: 0,\n stubbed: 0,\n cacheStripped: 0,\n changed: false,\n };\n\n const filePath = await locateTranscriptPath(configDir, sessionId, timeoutMs);\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(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 tmpPath = `${filePath}.scrub-tmp`;\n try {\n await withFsDeadline(\n `rewrite transcript ${filePath}`,\n async () => {\n const discard: ScrubCounters = { corrected: 0, stubbed: 0, cacheStripped: 0 };\n await pipeline(\n (async function* () {\n let first = true;\n for await (const line of streamLines(filePath)) {\n yield first ? repairLine(line, discard) : `\\n${repairLine(line, discard)}`;\n first = false;\n }\n })(),\n createWriteStream(tmpPath, { encoding: \"utf8\" }),\n );\n await rename(tmpPath, filePath);\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 sibling behind — the next scrub would rewrite\n // it anyway, but a stray `.scrub-tmp` in the SDK's projects dir is noise.\n await tryWithFsDeadline(`unlink ${tmpPath}`, () => unlink(tmpPath), undefined, timeoutMs);\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","/**\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,4 +1,4 @@
|
|
|
1
|
-
import { logErr } from './chunk-
|
|
1
|
+
import { logErr } from './chunk-WOE4LPGF.js';
|
|
2
2
|
import { flowKindProvider } from './chunk-KTCMBEEB.js';
|
|
3
3
|
import { knowledgeKindProvider } from './chunk-UFWADBG6.js';
|
|
4
4
|
import { createDefaultRegistry } from './chunk-HGPSZXZP.js';
|
|
@@ -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-4RKCOURU.js.map
|
|
107
|
+
//# sourceMappingURL=chunk-4RKCOURU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/src/open-registry.ts","../cli/src/open-library.ts"],"names":["source"],"mappings":"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","file":"chunk-LISGIFKY.js","sourcesContent":["/**\n * open-registry.ts — shared helper to create a full AssetKindRegistry.\n *\n * Bootstraps the registry with all built-in providers (9 core + preset)\n * from @skaile/discovery, plus the extension kind providers (flow from\n * @skaile/workspaces/factory-assets/connectors/flow/engine, knowledge from @skaile/library).\n *\n * This is the single registration point for the CLI. All code paths\n * that need a registry (source sync, lib-status, etc.) should use this.\n */\n\nimport type { AssetKindRegistry } from \"@skaile/workspaces/discovery\";\nimport { createDefaultRegistry } from \"@skaile/workspaces/discovery\";\nimport { flowKindProvider } from \"@skaile/workspaces/factory-assets/connectors/flow/engine\";\nimport { knowledgeKindProvider } from \"@skaile/workspaces/library\";\n\n/**\n * Create a fully-configured AssetKindRegistry with all known providers.\n *\n * Registers:\n * - 9 core kinds (skill, agent, connector, mount, mcp-server, contract, prompt, persona, ruleset)\n * - preset (composition entity)\n * - flow (extension, from @skaile/workspaces/factory-assets/connectors/flow/engine)\n * - knowledge (extension, from @skaile/library)\n *\n * @returns An unfrozen registry (auto-freezes on first read)\n */\nexport function createFullRegistry(): AssetKindRegistry {\n const registry = createDefaultRegistry();\n registry.register(flowKindProvider);\n registry.register(knowledgeKindProvider);\n return registry;\n}\n","/**\n * open-library.ts — shared helpers to open the LocalIndex and the configured\n * Catalog source.\n *\n * Lazy-loads the `@skaile/workspaces/library` subpath and returns the\n * LocalIndex instance (backed by `@libsql/client`; runs on Node and Bun).\n * The catalog-source helper reads\n * `~/.skaile/config.yaml` (and project-level overlay if `projectDir` is given)\n * to decide between {@link RemoteCatalogSource} (default — points at\n * `https://skaile.store`) and a {@link LocalCatalogSource} bound to the most\n * recent local library registered via `skaile source add`.\n */\n\nimport { logErr } from \"./helpers.ts\";\nimport { createFullRegistry } from \"./open-registry.ts\";\n\n/** Thrown by {@link openCatalogSource} when `catalog.url` is the `local` sentinel. */\nexport class LocalCatalogDisabledError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LocalCatalogDisabledError\";\n }\n}\n\n/**\n * Open the LocalIndex with the full kind registry. Exits with code 1\n * if the library directory cannot be created.\n *\n * @returns A `LocalIndex` instance ready for use.\n * @docLink cli/dev-guide#open-library\n */\nexport async function openLibrary() {\n try {\n const { LocalIndex } = await import(\"@skaile/workspaces/library\");\n return new LocalIndex({ kindRegistry: createFullRegistry() });\n } catch (err) {\n logErr(`Could not open LocalIndex: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\n/**\n * Resolve the configured **remote** Catalog source for the CLI.\n *\n * Reads `~/.skaile/config.yaml` (plus the optional project-level overlay) and\n * returns a {@link RemoteCatalogSource} pointing at `catalog.url` (default:\n * `https://skaile.store`). The `cache_ttl: 0` config flag flips the source\n * into air-gapped mode: network reads are disabled, only `skaile update`\n * performs refreshes.\n *\n * **Local-mode rejection.** If the resolved config has `catalog.url: local`\n * this helper throws — callers wanting the dispatched local-or-remote source\n * must use {@link resolveCatalogSource}. Remote-only consumers like\n * `skaile update --catalog-only` rely on this strict behaviour.\n *\n * @param opts - Project directory (overlays project config) and explicit overrides.\n * @returns A configured {@link RemoteCatalogSource}.\n * @throws When `catalog.url` is the `local` sentinel.\n * @docLink cli/dev-guide#open-library\n */\nexport async function openCatalogSource(opts?: {\n projectDir?: string;\n baseUrlOverride?: string;\n /** Override the user-config path for tests. */\n userConfigFile?: string;\n}): Promise<\n | import(\"@skaile/workspaces/library\").RemoteCatalogSource\n | import(\"@skaile/workspaces/library\").RestCatalogSource\n> {\n const { resolveConfig, RemoteCatalogSource, RestCatalogSource, isLocalCatalogUrl } = await import(\n \"@skaile/workspaces/library\"\n );\n const cfg = resolveConfig({\n projectDir: opts?.projectDir,\n userConfigFile: opts?.userConfigFile,\n });\n const baseUrl = opts?.baseUrlOverride ?? cfg.catalog.url;\n if (isLocalCatalogUrl(baseUrl)) {\n throw new LocalCatalogDisabledError(\n \"catalog.url is set to 'local' — remote catalog is disabled. \" +\n \"Use `skaile source add <path>` + `skaile source sync` for local sources, \" +\n \"or set `catalog.url: https://skaile.store` in ~/.skaile/config.yaml.\",\n );\n }\n const cacheTtlMs = cfg.catalog.cache_ttl * 1000;\n if (cfg.catalog.framing === \"rest\") {\n return new RestCatalogSource({ baseUrl, cacheTtlMs });\n }\n return new RemoteCatalogSource({ baseUrl, cacheTtlMs });\n}\n\n/**\n * Resolved catalog source plus a close handle for releasing any underlying\n * resources (e.g. the `LocalIndex` SQLite connection in local mode).\n *\n * Callers MUST invoke `close()` when done — typically in a `finally` block.\n * For remote-mode sources `close()` is a no-op, but the contract is uniform\n * so consumers don't have to branch.\n *\n * @docLink cli/dev-guide#open-library\n */\nexport interface ResolvedCatalogSource {\n /** The {@link ICatalogSource} ready for use. */\n source: import(\"@skaile/workspaces/library\").ICatalogSource;\n /** Release any underlying resources (SQLite handle in local mode). */\n close(): void;\n}\n\n/**\n * Resolve the configured Catalog source — local or remote — based on\n * `~/.skaile/config.yaml`.\n *\n * Dispatch:\n * - `catalog.url: local` → opens {@link LocalIndex}, picks the most recently\n * registered local library whose `path` still exists on disk, and returns a\n * {@link LocalCatalogSource} bound to that library. Throws if no usable\n * local library is registered.\n * - any URL → returns {@link RemoteCatalogSource} (same as\n * {@link openCatalogSource}).\n *\n * The returned `close()` releases the underlying `LocalIndex` SQLite handle\n * in local mode (no-op in remote mode). Callers MUST invoke it — typically in\n * a `finally` block — to satisfy `library/CLAUDE.md` § \"Notes for Consumers\".\n *\n * @param opts - Project directory (overlays project config) and explicit overrides.\n * @returns A `ResolvedCatalogSource` carrying the source and a close handle.\n * @throws When `local` is configured but no usable local library is registered.\n * @docLink cli/dev-guide#open-library\n */\nexport async function resolveCatalogSource(opts?: {\n projectDir?: string;\n baseUrlOverride?: string;\n /** Override the user-config path for tests. */\n userConfigFile?: string;\n}): Promise<ResolvedCatalogSource> {\n const {\n resolveConfig,\n RemoteCatalogSource,\n RestCatalogSource,\n LocalCatalogSource,\n isLocalCatalogUrl,\n } = await import(\"@skaile/workspaces/library\");\n const cfg = resolveConfig({\n projectDir: opts?.projectDir,\n userConfigFile: opts?.userConfigFile,\n });\n const baseUrl = opts?.baseUrlOverride ?? cfg.catalog.url;\n\n if (isLocalCatalogUrl(baseUrl)) {\n const fs = await import(\"node:fs\");\n const library = await openLibrary();\n try {\n const sources = await library.listSources();\n type LibraryRow = (typeof sources)[number];\n // Type-narrow: `path` is required for local libraries after the filter.\n const usable = sources\n .filter(\n (s): s is LibraryRow & { path: string } =>\n s.backend === \"local\" && typeof s.path === \"string\" && s.path.length > 0,\n )\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n\n if (usable.length === 0) {\n throw new Error(\n \"catalog.url is set to 'local' but no local library is registered. \" +\n \"Run `skaile source add <path>` first, then `skaile source sync`.\",\n );\n }\n\n // Prefer the most recently added library whose path still exists.\n const present = usable.find((s) => fs.existsSync(s.path));\n if (!present) {\n const head = usable[0];\n throw new Error(\n `catalog.url is set to 'local' but every registered local library has a missing path on disk. ` +\n `Most recent: ${head.path} (library ${head.id}). ` +\n `Re-register with \\`skaile source add <existing-path>\\` or run \\`skaile source list\\` to inspect.`,\n );\n }\n\n const source = new LocalCatalogSource(\n library,\n present.id,\n present.path,\n createFullRegistry(),\n );\n return { source, close: () => library.close() };\n } catch (err) {\n // Release the handle on any failure during dispatch — otherwise the\n // SQLite WAL state leaks for the lifetime of the process.\n library.close();\n throw err;\n }\n }\n\n const cacheTtlMs = cfg.catalog.cache_ttl * 1000;\n const source =\n cfg.catalog.framing === \"rest\"\n ? new RestCatalogSource({ baseUrl, cacheTtlMs })\n : new RemoteCatalogSource({ baseUrl, cacheTtlMs });\n return { source, close: () => {} };\n}\n\n/**\n * Open the LibraryManager bound to the active LocalIndex.\n * Caller owns lifetime — must call `close()` (returned helper closes the\n * underlying LocalIndex).\n *\n * @docLink cli/dev-guide#open-library\n */\nexport async function openLibraryManager(): Promise<{\n manager: import(\"@skaile/workspaces/library\").LibraryManager;\n library: import(\"@skaile/workspaces/library\").LocalIndex;\n close: () => void;\n}> {\n const { LibraryManager } = await import(\"@skaile/workspaces/library\");\n const library = await openLibrary();\n const manager = new LibraryManager(library);\n return { manager, library, close: () => library.close() };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../cli/src/open-registry.ts","../cli/src/open-library.ts"],"names":["source"],"mappings":"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","file":"chunk-4RKCOURU.js","sourcesContent":["/**\n * open-registry.ts — shared helper to create a full AssetKindRegistry.\n *\n * Bootstraps the registry with all built-in providers (9 core + preset)\n * from @skaile/discovery, plus the extension kind providers (flow from\n * @skaile/workspaces/factory-assets/connectors/flow/engine, knowledge from @skaile/library).\n *\n * This is the single registration point for the CLI. All code paths\n * that need a registry (source sync, lib-status, etc.) should use this.\n */\n\nimport type { AssetKindRegistry } from \"@skaile/workspaces/discovery\";\nimport { createDefaultRegistry } from \"@skaile/workspaces/discovery\";\nimport { flowKindProvider } from \"@skaile/workspaces/factory-assets/connectors/flow/engine\";\nimport { knowledgeKindProvider } from \"@skaile/workspaces/library\";\n\n/**\n * Create a fully-configured AssetKindRegistry with all known providers.\n *\n * Registers:\n * - 9 core kinds (skill, agent, connector, mount, mcp-server, contract, prompt, persona, ruleset)\n * - preset (composition entity)\n * - flow (extension, from @skaile/workspaces/factory-assets/connectors/flow/engine)\n * - knowledge (extension, from @skaile/library)\n *\n * @returns An unfrozen registry (auto-freezes on first read)\n */\nexport function createFullRegistry(): AssetKindRegistry {\n const registry = createDefaultRegistry();\n registry.register(flowKindProvider);\n registry.register(knowledgeKindProvider);\n return registry;\n}\n","/**\n * open-library.ts — shared helpers to open the LocalIndex and the configured\n * Catalog source.\n *\n * Lazy-loads the `@skaile/workspaces/library` subpath and returns the\n * LocalIndex instance (backed by `@libsql/client`; runs on Node and Bun).\n * The catalog-source helper reads\n * `~/.skaile/config.yaml` (and project-level overlay if `projectDir` is given)\n * to decide between {@link RemoteCatalogSource} (default — points at\n * `https://skaile.store`) and a {@link LocalCatalogSource} bound to the most\n * recent local library registered via `skaile source add`.\n */\n\nimport { logErr } from \"./helpers.ts\";\nimport { createFullRegistry } from \"./open-registry.ts\";\n\n/** Thrown by {@link openCatalogSource} when `catalog.url` is the `local` sentinel. */\nexport class LocalCatalogDisabledError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LocalCatalogDisabledError\";\n }\n}\n\n/**\n * Open the LocalIndex with the full kind registry. Exits with code 1\n * if the library directory cannot be created.\n *\n * @returns A `LocalIndex` instance ready for use.\n * @docLink cli/dev-guide#open-library\n */\nexport async function openLibrary() {\n try {\n const { LocalIndex } = await import(\"@skaile/workspaces/library\");\n return new LocalIndex({ kindRegistry: createFullRegistry() });\n } catch (err) {\n logErr(`Could not open LocalIndex: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\n/**\n * Resolve the configured **remote** Catalog source for the CLI.\n *\n * Reads `~/.skaile/config.yaml` (plus the optional project-level overlay) and\n * returns a {@link RemoteCatalogSource} pointing at `catalog.url` (default:\n * `https://skaile.store`). The `cache_ttl: 0` config flag flips the source\n * into air-gapped mode: network reads are disabled, only `skaile update`\n * performs refreshes.\n *\n * **Local-mode rejection.** If the resolved config has `catalog.url: local`\n * this helper throws — callers wanting the dispatched local-or-remote source\n * must use {@link resolveCatalogSource}. Remote-only consumers like\n * `skaile update --catalog-only` rely on this strict behaviour.\n *\n * @param opts - Project directory (overlays project config) and explicit overrides.\n * @returns A configured {@link RemoteCatalogSource}.\n * @throws When `catalog.url` is the `local` sentinel.\n * @docLink cli/dev-guide#open-library\n */\nexport async function openCatalogSource(opts?: {\n projectDir?: string;\n baseUrlOverride?: string;\n /** Override the user-config path for tests. */\n userConfigFile?: string;\n}): Promise<\n | import(\"@skaile/workspaces/library\").RemoteCatalogSource\n | import(\"@skaile/workspaces/library\").RestCatalogSource\n> {\n const { resolveConfig, RemoteCatalogSource, RestCatalogSource, isLocalCatalogUrl } = await import(\n \"@skaile/workspaces/library\"\n );\n const cfg = resolveConfig({\n projectDir: opts?.projectDir,\n userConfigFile: opts?.userConfigFile,\n });\n const baseUrl = opts?.baseUrlOverride ?? cfg.catalog.url;\n if (isLocalCatalogUrl(baseUrl)) {\n throw new LocalCatalogDisabledError(\n \"catalog.url is set to 'local' — remote catalog is disabled. \" +\n \"Use `skaile source add <path>` + `skaile source sync` for local sources, \" +\n \"or set `catalog.url: https://skaile.store` in ~/.skaile/config.yaml.\",\n );\n }\n const cacheTtlMs = cfg.catalog.cache_ttl * 1000;\n if (cfg.catalog.framing === \"rest\") {\n return new RestCatalogSource({ baseUrl, cacheTtlMs });\n }\n return new RemoteCatalogSource({ baseUrl, cacheTtlMs });\n}\n\n/**\n * Resolved catalog source plus a close handle for releasing any underlying\n * resources (e.g. the `LocalIndex` SQLite connection in local mode).\n *\n * Callers MUST invoke `close()` when done — typically in a `finally` block.\n * For remote-mode sources `close()` is a no-op, but the contract is uniform\n * so consumers don't have to branch.\n *\n * @docLink cli/dev-guide#open-library\n */\nexport interface ResolvedCatalogSource {\n /** The {@link ICatalogSource} ready for use. */\n source: import(\"@skaile/workspaces/library\").ICatalogSource;\n /** Release any underlying resources (SQLite handle in local mode). */\n close(): void;\n}\n\n/**\n * Resolve the configured Catalog source — local or remote — based on\n * `~/.skaile/config.yaml`.\n *\n * Dispatch:\n * - `catalog.url: local` → opens {@link LocalIndex}, picks the most recently\n * registered local library whose `path` still exists on disk, and returns a\n * {@link LocalCatalogSource} bound to that library. Throws if no usable\n * local library is registered.\n * - any URL → returns {@link RemoteCatalogSource} (same as\n * {@link openCatalogSource}).\n *\n * The returned `close()` releases the underlying `LocalIndex` SQLite handle\n * in local mode (no-op in remote mode). Callers MUST invoke it — typically in\n * a `finally` block — to satisfy `library/CLAUDE.md` § \"Notes for Consumers\".\n *\n * @param opts - Project directory (overlays project config) and explicit overrides.\n * @returns A `ResolvedCatalogSource` carrying the source and a close handle.\n * @throws When `local` is configured but no usable local library is registered.\n * @docLink cli/dev-guide#open-library\n */\nexport async function resolveCatalogSource(opts?: {\n projectDir?: string;\n baseUrlOverride?: string;\n /** Override the user-config path for tests. */\n userConfigFile?: string;\n}): Promise<ResolvedCatalogSource> {\n const {\n resolveConfig,\n RemoteCatalogSource,\n RestCatalogSource,\n LocalCatalogSource,\n isLocalCatalogUrl,\n } = await import(\"@skaile/workspaces/library\");\n const cfg = resolveConfig({\n projectDir: opts?.projectDir,\n userConfigFile: opts?.userConfigFile,\n });\n const baseUrl = opts?.baseUrlOverride ?? cfg.catalog.url;\n\n if (isLocalCatalogUrl(baseUrl)) {\n const fs = await import(\"node:fs\");\n const library = await openLibrary();\n try {\n const sources = await library.listSources();\n type LibraryRow = (typeof sources)[number];\n // Type-narrow: `path` is required for local libraries after the filter.\n const usable = sources\n .filter(\n (s): s is LibraryRow & { path: string } =>\n s.backend === \"local\" && typeof s.path === \"string\" && s.path.length > 0,\n )\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n\n if (usable.length === 0) {\n throw new Error(\n \"catalog.url is set to 'local' but no local library is registered. \" +\n \"Run `skaile source add <path>` first, then `skaile source sync`.\",\n );\n }\n\n // Prefer the most recently added library whose path still exists.\n const present = usable.find((s) => fs.existsSync(s.path));\n if (!present) {\n const head = usable[0];\n throw new Error(\n `catalog.url is set to 'local' but every registered local library has a missing path on disk. ` +\n `Most recent: ${head.path} (library ${head.id}). ` +\n `Re-register with \\`skaile source add <existing-path>\\` or run \\`skaile source list\\` to inspect.`,\n );\n }\n\n const source = new LocalCatalogSource(\n library,\n present.id,\n present.path,\n createFullRegistry(),\n );\n return { source, close: () => library.close() };\n } catch (err) {\n // Release the handle on any failure during dispatch — otherwise the\n // SQLite WAL state leaks for the lifetime of the process.\n library.close();\n throw err;\n }\n }\n\n const cacheTtlMs = cfg.catalog.cache_ttl * 1000;\n const source =\n cfg.catalog.framing === \"rest\"\n ? new RestCatalogSource({ baseUrl, cacheTtlMs })\n : new RemoteCatalogSource({ baseUrl, cacheTtlMs });\n return { source, close: () => {} };\n}\n\n/**\n * Open the LibraryManager bound to the active LocalIndex.\n * Caller owns lifetime — must call `close()` (returned helper closes the\n * underlying LocalIndex).\n *\n * @docLink cli/dev-guide#open-library\n */\nexport async function openLibraryManager(): Promise<{\n manager: import(\"@skaile/workspaces/library\").LibraryManager;\n library: import(\"@skaile/workspaces/library\").LocalIndex;\n close: () => void;\n}> {\n const { LibraryManager } = await import(\"@skaile/workspaces/library\");\n const library = await openLibrary();\n const manager = new LibraryManager(library);\n return { manager, library, close: () => library.close() };\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { logErr, logWarn, S, logOk, logInfo } from './chunk-
|
|
2
|
-
import { catalogLayer, getProviderPreset, expandPreset, listProviderPresets, presetBaseUrl, probeProviderEntry } from './chunk-
|
|
1
|
+
import { logErr, logWarn, S, logOk, logInfo } from './chunk-WOE4LPGF.js';
|
|
2
|
+
import { catalogLayer, getProviderPreset, expandPreset, listProviderPresets, presetBaseUrl, probeProviderEntry } from './chunk-3VGQLF3N.js';
|
|
3
3
|
import { loadProviderRegistry, saveProviderRegistryFile, workspaceProviderRegistryPath, userProviderRegistryPath } from './chunk-UWU572Q6.js';
|
|
4
4
|
import { resolveCredential } from './chunk-DPLIN2RA.js';
|
|
5
5
|
import { validateMergedRegistry, mergeRegistries, isSafeProviderId, parseCredentialRef, validateRegistry, resolveEntryBaseUrl, AI_PROVIDER_SURFACES, entryTransport, isEntryEnabled, AI_PROVIDER_LAYERS } from './chunk-GZZPKAV5.js';
|
|
@@ -496,5 +496,5 @@ function makeProvidersCommand() {
|
|
|
496
496
|
}
|
|
497
497
|
|
|
498
498
|
export { ProviderRegistryWriteError, addProviderEntry, credentialEnvVarName, loadRegistryView, makeProvidersCommand };
|
|
499
|
-
//# sourceMappingURL=chunk-
|
|
500
|
-
//# sourceMappingURL=chunk-
|
|
499
|
+
//# sourceMappingURL=chunk-6F4TIY7X.js.map
|
|
500
|
+
//# sourceMappingURL=chunk-6F4TIY7X.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/src/commands/providers.ts"],"names":[],"mappings":"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","file":"chunk-RTIFNBX6.js","sourcesContent":["/**\n * `skaile providers` — manage the AI provider registry.\n *\n * Endpoints are defined once, in `~/.skaile/providers.yml`, optionally\n * overridden per project in `<workspace>/.skaile/providers.yml` (gitignored by\n * `skaile init`). Every subcommand writes exactly one of those two files and\n * validates the result before it lands — a literal secret never reaches disk.\n *\n * @see PROVIDER-CONFIG-PLAN.md §1, §2.5\n */\n\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n catalogLayer,\n expandPreset,\n getProviderPreset,\n listProviderPresets,\n presetBaseUrl,\n probeProviderEntry,\n} from \"@skaile/workspaces/bridge\";\nimport {\n AI_PROVIDER_LAYERS,\n AI_PROVIDER_SURFACES,\n type AIProviderDiagnostic,\n type AIProviderEntry,\n type AIProviderLayerId,\n type AIProviderLlmEntry,\n type AIProviderRegistryDocument,\n type AIProviderSurface,\n entryTransport,\n isEntryEnabled,\n isSafeProviderId,\n loadProviderRegistry,\n type MergedAIProviderRegistry,\n mergeRegistries,\n parseCredentialRef,\n type ProviderRegistryFile,\n resolveCredential,\n resolveEntryBaseUrl,\n saveProviderRegistryFile,\n userProviderRegistryPath,\n validateMergedRegistry,\n validateRegistry,\n workspaceProviderRegistryPath,\n} from \"@skaile/workspaces/core\";\nimport { Command } from \"commander\";\nimport { logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\n\n/** Preset id that means \"no preset — I will supply the three literals\". */\nconst CUSTOM_PRESET = \"custom\";\n\n/** Which of the two registry files a command reads or writes. */\nexport interface ScopeOptions {\n projectDir?: string;\n workspace?: boolean;\n}\n\n/** The file a mutating subcommand writes: the workspace layer or the user one. */\nfunction targetFile(opts: ScopeOptions): { layer: \"user\" | \"workspace\"; path: string } {\n if (opts.workspace) {\n return { layer: \"workspace\", path: workspaceProviderRegistryPath(resolveProjectDir(opts)) };\n }\n return { layer: \"user\", path: userProviderRegistryPath() };\n}\n\n/** Project directory a subcommand operates on — `--project-dir` or the cwd. */\nfunction resolveProjectDir(opts: ScopeOptions): string {\n return opts.projectDir ? path.resolve(opts.projectDir) : process.cwd();\n}\n\n/** Both file layers plus the catalog, merged — what every reader sees. */\nexport interface RegistryView {\n merged: MergedAIProviderRegistry;\n files: ProviderRegistryFile[];\n diagnostics: AIProviderDiagnostic[];\n}\n\n/**\n * Load both file layers and merge them with the catalog layer the configured\n * `preset:` keys pull in, then gate the result. Read once, merged twice — the\n * catalog layer can only be built after the configured entries are known,\n * and it is built from the **pre-gate** merge: an entry that leaves `kind` or\n * its transport `params` to the preset fails the first gate by design.\n *\n * The gate is on the merged view, not per file: a workspace entry that sets\n * one field of an entry the user file defines is an override (§1.5), so it is\n * only here that an entry can be judged complete.\n */\nexport function loadRegistryView(opts: ScopeOptions): RegistryView {\n const loaded = loadProviderRegistry({ projectDir: resolveProjectDir(opts) });\n const fileLayers = loaded.files.map((file) => ({\n layer: file.layer as AIProviderLayerId,\n providers: file.document.providers,\n }));\n const catalog = catalogLayer(loaded.patches);\n const { registry, diagnostics } = validateMergedRegistry(\n mergeRegistries([...fileLayers, catalog]),\n {\n sources: [\n ...loaded.files.map((file) => ({ label: file.path, providers: file.document.providers })),\n ],\n },\n );\n return {\n merged: registry,\n files: loaded.files,\n // `loaded.diagnostics` already carries the merge notes for the file layers\n // alone; this second merge adds the catalog, so its notes replace them.\n diagnostics: [...loaded.files.flatMap((file) => file.diagnostics), ...diagnostics],\n };\n}\n\n/** Print diagnostics; returns how many were errors. */\nfunction reportDiagnostics(diagnostics: AIProviderDiagnostic[]): number {\n let errors = 0;\n for (const diagnostic of diagnostics) {\n const where = diagnostic.path ? `${diagnostic.path}: ` : \"\";\n if (diagnostic.severity === \"error\") {\n errors++;\n logErr(`${where}${diagnostic.message}`);\n } else {\n logWarn(`${where}${diagnostic.message}`);\n }\n }\n return errors;\n}\n\n/** Highest layer that pins an entry with `locked: true`. */\nfunction lockOwner(id: string, files: ProviderRegistryFile[]): AIProviderLayerId | undefined {\n let owner: AIProviderLayerId | undefined;\n for (const file of files) {\n if (file.document.providers[id]?.locked) {\n const layer = file.layer as AIProviderLayerId;\n if (!owner || AI_PROVIDER_LAYERS.indexOf(layer) > AI_PROVIDER_LAYERS.indexOf(owner)) {\n owner = layer;\n }\n }\n }\n return owner;\n}\n\n/**\n * The message for an edit a lock forbids, or `undefined` when it is allowed.\n * The merge ignores a lower layer silently; the CLI must not, or the operator\n * would watch an accepted edit have no effect.\n *\n * `set <id> locked <value>` stays legal at the locking layer itself —\n * otherwise a lock could never be lifted without hand-editing the file.\n */\nfunction lockConflict(\n id: string,\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n key?: string,\n): string | undefined {\n const owner = lockOwner(id, files);\n if (!owner) return undefined;\n const ownerRank = AI_PROVIDER_LAYERS.indexOf(owner);\n const targetRank = AI_PROVIDER_LAYERS.indexOf(target.layer);\n if (ownerRank === targetRank && key === \"locked\") return undefined;\n if (ownerRank < targetRank) return undefined;\n return (\n `'${id}' is locked by the ${owner} layer and cannot be changed from ${target.layer}.\\n` +\n (ownerRank === targetRank\n ? ` Unlock it first: skaile providers set ${id} locked false`\n : ` A higher layer owns this entry — change it there.`)\n );\n}\n\n/** Refuse loudly when a locked entry would be edited. */\nfunction exitIfLocked(\n id: string,\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n key?: string,\n): void {\n const message = lockConflict(id, target, files, key);\n if (!message) return;\n logErr(message);\n process.exit(1);\n}\n\n/** Read the target file, or an empty document when it does not exist yet. */\nfunction readTargetDocument(\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n): AIProviderRegistryDocument {\n const file = files.find((f) => f.path === target.path);\n return file?.document ?? { version: 1, providers: {} };\n}\n\n/**\n * Validate the file that is about to be written; exits non-zero on errors.\n *\n * Validated as the layer it is, so `set` may leave a one-field override in the\n * workspace file (§1.5). Completeness is the merged registry's business, and\n * `loadRegistryView` reports it on the next read.\n */\nfunction validateOrExit(\n document: AIProviderRegistryDocument,\n target: { layer: \"user\" | \"workspace\"; path: string },\n): void {\n const { diagnostics } = validateRegistry(\n { version: 1, providers: document.providers },\n { source: target.path, layer: target.layer },\n );\n if (reportDiagnostics(diagnostics) > 0) process.exit(1);\n}\n\n// ── list ───────────────────────────────────────────────────────────────────\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction credentialSummary(entry: AIProviderEntry): string {\n const credential = entry.credential;\n if (!credential || credential.kind === \"none\") return \"none\";\n return credential.ref ? `${credential.kind} ${credential.ref}` : credential.kind;\n}\n\nfunction printPresets(): void {\n const presets = listProviderPresets();\n console.log();\n console.log(` ${S.heading(\"Catalog presets\")}`);\n const idWidth = Math.max(...presets.map((x) => x.id.length)) + 2;\n const surfaceWidth = Math.max(...AI_PROVIDER_SURFACES.map((s) => s.length)) + 2;\n const header = `${pad(\"preset\", idWidth)}${pad(\"kind\", 7)}${pad(\"surface\", surfaceWidth)}${pad(\"transport\", 14)}default base URL`;\n console.log(` ${S.dim(header)}`);\n for (const preset of presets) {\n const row =\n pad(preset.id, idWidth) +\n pad(preset.kind, 7) +\n pad(preset.surface ?? \"—\", surfaceWidth) +\n pad(\n preset.kind === \"llm\" || preset.kind === \"embed\" ? (preset.transport ?? \"direct\") : \"—\",\n 14,\n ) +\n (presetBaseUrl(preset) ?? \"—\");\n console.log(` ${row}`);\n }\n}\n\nfunction printConfigured(view: RegistryView): void {\n const ids = view.merged.order;\n console.log();\n console.log(` ${S.heading(\"Configured providers\")}`);\n if (ids.length === 0) {\n console.log(\n ` ${S.dim(\"none — add one with\")} ${S.cmd(\"skaile providers add --preset <preset>\")}`,\n );\n console.log();\n return;\n }\n const idWidth = Math.max(...ids.map((id) => id.length)) + 2;\n const header = `${pad(\"id\", idWidth)}${pad(\"layer\", 11)}${pad(\"surface\", 26)}${pad(\"transport\", 14)}endpoint`;\n console.log(` ${S.dim(header)}`);\n for (const id of ids) {\n const entry = view.merged.providers[id];\n const surface = (entry as AIProviderLlmEntry).surface ?? \"—\";\n const transport = entryTransport(entry) ?? \"—\";\n const url = resolveEntryBaseUrl(entry) ?? S.dim(\"(unresolved)\");\n const flags = [\n isEntryEnabled(entry) ? \"\" : S.warn(\"disabled\"),\n entry.locked ? S.warn(\"locked\") : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n console.log(\n ` ${pad(id, idWidth)}${pad(view.merged.origin[id], 11)}${pad(surface, 26)}${pad(transport, 14)}${url} ${flags}`.trimEnd(),\n );\n console.log(` ${S.dim(`${pad(\"\", idWidth)}${credentialSummary(entry)}`)}`);\n }\n console.log();\n}\n\n// ── add ────────────────────────────────────────────────────────────────────\n\ninterface AddOptions extends ScopeOptions {\n preset?: string;\n credential?: string;\n baseUrl?: string;\n surface?: string;\n label?: string;\n kind?: string;\n param: string[];\n force?: boolean;\n}\n\nfunction parseParams(pairs: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf(\"=\");\n if (eq <= 0) {\n logErr(`--param expects <key>=<value> (got '${pair}')`);\n process.exit(1);\n }\n out[pair.slice(0, eq)] = pair.slice(eq + 1);\n }\n return out;\n}\n\n/** Ask for the three literals a custom endpoint needs. Nothing else. */\nasync function promptCustomEntry(\n id: string,\n opts: AddOptions,\n): Promise<{ surface: AIProviderSurface; baseUrl: string; credentialRef: string }> {\n const interactive = process.stdin.isTTY === true;\n let surface = opts.surface as AIProviderSurface | undefined;\n let baseUrl = opts.baseUrl;\n let credentialRef = opts.credential;\n\n if (!interactive && (!surface || !baseUrl || !credentialRef)) {\n logErr(\n \"--preset custom needs --surface, --base-url and --credential when there is no terminal to prompt on\",\n );\n process.exit(1);\n }\n\n if (!surface) {\n const answer = await p.select({\n message: \"Wire surface:\",\n options: AI_PROVIDER_SURFACES.map((value) => ({ value, label: value })),\n initialValue: \"openai-completions\" as AIProviderSurface,\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n surface = answer as AIProviderSurface;\n }\n if (!baseUrl) {\n const answer = await p.text({\n message: \"Base URL:\",\n placeholder: \"https://api.example.com/v1\",\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n baseUrl = answer as string;\n }\n if (!credentialRef) {\n const answer = await p.text({\n message: \"Credential reference (env:NAME, cmd:<shell>, platform:<id>, keyring:<svc>/<acct>):\",\n initialValue: `env:${id.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_API_KEY`,\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n credentialRef = answer as string;\n }\n return { surface, baseUrl, credentialRef };\n}\n\n/** A rejected registry write. The message is already CLI-ready. */\nexport class ProviderRegistryWriteError extends Error {}\n\n/** What {@link addProviderEntry} writes. */\nexport interface AddProviderEntryInput extends ScopeOptions {\n /** Registry entry id — `[a-z0-9][a-z0-9_-]*`. */\n id: string;\n /** Catalog preset to expand. Mutually exclusive with `entry`. */\n presetId?: string;\n /** A fully-built entry (the `--preset custom` path, which needs prompts). */\n entry?: AIProviderEntry;\n /** `env:NAME` / `cmd:…` / `platform:…` / `keyring:…` — never a literal. */\n credentialRef?: string;\n baseUrl?: string;\n surface?: AIProviderSurface;\n label?: string;\n params?: Record<string, string>;\n /** Overwrite an entry that already exists in the target file. */\n force?: boolean;\n}\n\n/** Result of {@link addProviderEntry}. */\nexport interface AddedProviderEntry {\n id: string;\n layer: \"user\" | \"workspace\";\n path: string;\n entry: AIProviderEntry;\n /** True when an existing entry in the target file was overwritten. */\n replaced: boolean;\n}\n\n/**\n * Write one entry into a registry file — the single write path behind\n * `skaile providers add` and the `skaile setup` wizard.\n *\n * Throws {@link ProviderRegistryWriteError} instead of exiting, so a wizard\n * can report the failure in its own idiom. Every rejection a caller can\n * provoke (bad id, unknown preset, missing transport parameter, locked entry,\n * a literal secret) lands here, and the document is validated before it is\n * written — a secret cannot reach disk through this function.\n */\nexport function addProviderEntry(input: AddProviderEntryInput): AddedProviderEntry {\n const { id } = input;\n if (!isSafeProviderId(id)) {\n throw new ProviderRegistryWriteError(\n `'${id}' is not a valid entry id — use [a-z0-9][a-z0-9_-]*`,\n );\n }\n if (input.credentialRef && !parseCredentialRef(input.credentialRef)) {\n throw new ProviderRegistryWriteError(\n \"the credential must be a reference, not a secret: \" +\n \"env:NAME, cmd:<shell>, platform:<configId> or keyring:<service>/<account>\",\n );\n }\n\n const view = loadRegistryView(input);\n const target = targetFile(input);\n const locked = lockConflict(id, target, view.files);\n if (locked) throw new ProviderRegistryWriteError(locked);\n\n const document = readTargetDocument(target, view.files);\n const replaced = document.providers[id] !== undefined;\n if (replaced && !input.force) {\n throw new ProviderRegistryWriteError(\n `'${id}' already exists in ${target.path} — pass --force to overwrite it.`,\n );\n }\n\n let entry: AIProviderEntry;\n if (input.entry) {\n entry = input.entry;\n } else {\n const preset = input.presetId ? getProviderPreset(input.presetId) : undefined;\n if (!preset) {\n throw new ProviderRegistryWriteError(\n `Unknown preset '${input.presetId}'. Run \\`skaile providers list\\` to see the catalog, ` +\n \"or use `--preset custom`.\",\n );\n }\n entry = expandPreset(preset, {\n credentialRef: input.credentialRef,\n baseUrl: input.baseUrl,\n surface: input.surface,\n label: input.label,\n params: input.params,\n });\n const missing = (preset.required_params ?? []).filter(\n (key) => !(key in ((entry as AIProviderLlmEntry).params ?? {})),\n );\n if (missing.length > 0) {\n throw new ProviderRegistryWriteError(\n `Preset '${preset.id}' needs ${missing.map((m) => `--param ${m}=<value>`).join(\" \")}`,\n );\n }\n }\n\n const next: AIProviderRegistryDocument = {\n version: 1,\n providers: { ...document.providers, [id]: entry },\n };\n const { diagnostics } = validateRegistry(\n { version: 1, providers: next.providers },\n { source: target.path },\n );\n const errors = diagnostics.filter((d) => d.severity === \"error\");\n if (errors.length > 0) {\n throw new ProviderRegistryWriteError(\n errors.map((d) => (d.path ? `${d.path}: ${d.message}` : d.message)).join(\"\\n\"),\n );\n }\n saveProviderRegistryFile(target.path, next);\n\n return { id, layer: target.layer, path: target.path, entry, replaced };\n}\n\n/** The env var an `env:` credential reference points at, if it is one. */\nexport function credentialEnvVarName(entry: AIProviderEntry): string | undefined {\n const ref = entry.credential?.ref;\n return ref?.startsWith(\"env:\") ? ref.slice(4) : undefined;\n}\n\n/** Build the `--preset custom` entry from the three literals the user gave. */\nfunction customEntry(\n answers: { surface: AIProviderSurface; baseUrl: string; credentialRef: string },\n opts: AddOptions,\n): AIProviderEntry {\n const kind = (opts.kind ?? \"llm\") as AIProviderEntry[\"kind\"];\n // Anthropic- and Google-shaped surfaces read a dedicated API-key header;\n // everything else is a bearer token. `set <id> credential.kind …` adjusts.\n const credentialKind =\n kind === \"stt\" ||\n kind === \"tts\" ||\n answers.surface === \"anthropic-messages\" ||\n answers.surface === \"google-generative-ai\" ||\n answers.surface === \"azure-openai-responses\"\n ? \"api_key_header\"\n : \"bearer\";\n if (kind === \"stt\" || kind === \"tts\") {\n return {\n kind,\n ...(opts.label ? { label: opts.label } : {}),\n base_url: answers.baseUrl,\n credential: { kind: credentialKind, ref: answers.credentialRef },\n };\n }\n return {\n kind,\n ...(opts.label ? { label: opts.label } : {}),\n surface: answers.surface,\n base_url: answers.baseUrl,\n credential: { kind: credentialKind, ref: answers.credentialRef },\n } as AIProviderLlmEntry;\n}\n\nasync function runAdd(idArg: string | undefined, opts: AddOptions): Promise<void> {\n const presetId = opts.preset;\n if (!presetId) {\n logErr(\n `--preset is required. Run ${S.cmd(\"skaile providers list\")} for the catalog, ` +\n `or use ${S.cmd(\"--preset custom\")}.`,\n );\n process.exit(1);\n }\n const id = idArg ?? presetId;\n if (id === CUSTOM_PRESET && !idArg) {\n logErr(\"--preset custom needs an entry id: skaile providers add <id> --preset custom\");\n process.exit(1);\n }\n\n const entry =\n presetId === CUSTOM_PRESET ? customEntry(await promptCustomEntry(id, opts), opts) : undefined;\n\n let added: AddedProviderEntry;\n try {\n added = addProviderEntry({\n id,\n ...(entry ? { entry } : { presetId }),\n credentialRef: opts.credential,\n baseUrl: opts.baseUrl,\n surface: opts.surface as AIProviderSurface | undefined,\n label: opts.label,\n params: parseParams(opts.param),\n projectDir: opts.projectDir,\n workspace: opts.workspace,\n force: opts.force,\n });\n } catch (error) {\n logErr(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n logOk(`Added ${S.bold(id)} (${presetId}) to the ${added.layer} registry`);\n console.log(S.dim(` → ${added.path}`));\n const name = credentialEnvVarName(added.entry);\n if (name) {\n console.log(\n ` ${S.dim(\"The secret itself never goes in this file — export it:\")} ${S.cmd(`export ${name}=…`)}`,\n );\n }\n console.log(` ${S.dim(\"Verify with:\")} ${S.cmd(`skaile providers test ${id}`)}`);\n}\n\n// ── set / rm ───────────────────────────────────────────────────────────────\n\n/** Coerce a CLI string into the type the schema expects at `key`. */\nfunction coerceValue(key: string, value: string): unknown {\n const leaf = key.split(\".\").pop() ?? key;\n if (leaf === \"enabled\" || leaf === \"locked\" || leaf === \"tools\" || leaf === \"images\") {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n logErr(`'${key}' takes true or false (got '${value}')`);\n process.exit(1);\n }\n if (leaf === \"context_window\" || leaf === \"thinking_max\") {\n const parsed = Number(value);\n if (!Number.isFinite(parsed)) {\n logErr(`'${key}' takes a number (got '${value}')`);\n process.exit(1);\n }\n return parsed;\n }\n return value;\n}\n\n/** Write `value` at a dotted path, creating intermediate maps. */\nfunction setDotted(entry: Record<string, unknown>, key: string, value: unknown): void {\n const segments = key.split(\".\");\n let cursor = entry;\n for (const segment of segments.slice(0, -1)) {\n const next = cursor[segment];\n if (typeof next !== \"object\" || next === null || Array.isArray(next)) {\n cursor[segment] = {};\n }\n cursor = cursor[segment] as Record<string, unknown>;\n }\n cursor[segments[segments.length - 1]] = value;\n}\n\nfunction runSet(id: string, key: string, value: string, opts: ScopeOptions): void {\n const view = loadRegistryView(opts);\n const target = targetFile(opts);\n exitIfLocked(id, target, view.files, key);\n\n const document = readTargetDocument(target, view.files);\n const existing = document.providers[id];\n const inherited = view.merged.providers[id];\n if (!existing && !inherited) {\n logErr(\n `No provider '${id}'. Add it with ${S.cmd(`skaile providers add ${id} --preset <preset>`)}`,\n );\n process.exit(1);\n }\n\n // Writing a field into a layer that has no entry yet leaves a one-field\n // override: the layers below keep supplying the rest (§1.5), so copying\n // their `kind` down here would pin a value this layer does not own.\n const base = (existing ? structuredClone(existing) : {}) as unknown as Record<string, unknown>;\n setDotted(base, key, coerceValue(key, value));\n\n const next: AIProviderRegistryDocument = {\n version: 1,\n providers: { ...document.providers, [id]: base as unknown as AIProviderEntry },\n };\n validateOrExit(next, target);\n saveProviderRegistryFile(target.path, next);\n\n logOk(`Set ${S.bold(`${id}.${key}`)} = ${value} in the ${target.layer} registry`);\n console.log(S.dim(` → ${target.path}`));\n}\n\nfunction runRemove(id: string, opts: ScopeOptions): void {\n const view = loadRegistryView(opts);\n const target = targetFile(opts);\n exitIfLocked(id, target, view.files);\n\n const document = readTargetDocument(target, view.files);\n if (!document.providers[id]) {\n logErr(`No provider '${id}' in ${target.path}`);\n process.exit(1);\n }\n const providers = { ...document.providers };\n delete providers[id];\n saveProviderRegistryFile(target.path, { version: 1, providers });\n\n logOk(`Removed ${S.bold(id)} from the ${target.layer} registry`);\n console.log(S.dim(` → ${target.path}`));\n if (\n view.merged.providers[id] &&\n view.files.some((f) => f.path !== target.path && f.document.providers[id])\n ) {\n logInfo(`'${id}' is still defined in another layer — run 'skaile providers list' to see it.`);\n }\n}\n\n// ── test ───────────────────────────────────────────────────────────────────\n\nasync function runTest(id: string, opts: ScopeOptions): Promise<void> {\n const view = loadRegistryView(opts);\n const entry = view.merged.providers[id];\n if (!entry) {\n logErr(`No provider '${id}'. Run ${S.cmd(\"skaile providers list\")} to see what is configured.`);\n process.exit(1);\n }\n\n const credential = resolveCredential(entry);\n console.log();\n console.log(` ${S.heading(id)} ${S.dim(`(${view.merged.origin[id]} layer)`)}`);\n console.log(` ${S.label(\"endpoint \")} ${resolveEntryBaseUrl(entry) ?? S.dim(\"(unresolved)\")}`);\n console.log(\n ` ${S.label(\"credential\")} ${credentialSummary(entry)} ${\n credential.error\n ? S.err(`— ${credential.error}`)\n : S.dim(`— resolved from ${credential.source}`)\n }`,\n );\n\n if (credential.error) {\n console.log();\n logErr(`${id} is not usable yet: ${credential.error}`);\n process.exit(1);\n }\n\n const result = await probeProviderEntry(entry, { secret: credential.value });\n if (result.url) console.log(` ${S.label(\"probe \")} GET ${result.url}`);\n console.log();\n if (result.ok) {\n logOk(`${id}: ${result.detail}${result.status ? ` (HTTP ${result.status})` : \"\"}`);\n return;\n }\n if (!result.probed) {\n logWarn(`${id}: ${result.detail}`);\n return;\n }\n logErr(`${id}: ${result.detail}`);\n process.exit(1);\n}\n\n// ── command ────────────────────────────────────────────────────────────────\n\n/**\n * Create the `skaile providers` command group.\n *\n * `list` shows the catalog and what is configured; `add` writes an entry from\n * a preset (or from three literals with `--preset custom`); `set` and `rm`\n * edit one layer; `test` sends one read-only request and reports what came\n * back, never the credential.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n */\nexport function makeProvidersCommand(): Command {\n const cmd = new Command(\"providers\").description(\n \"Manage AI provider endpoints (~/.skaile/providers.yml)\",\n );\n\n cmd\n .command(\"list\")\n .description(\"List catalog presets and configured providers\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .option(\"--json\", \"Machine-readable output\")\n .action((opts) => {\n const view = loadRegistryView(opts);\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n presets: listProviderPresets().map((preset) => ({\n id: preset.id,\n kind: preset.kind,\n surface: preset.surface,\n transport: preset.transport ?? (preset.surface ? \"direct\" : undefined),\n base_url: presetBaseUrl(preset),\n credential: preset.credential,\n required_params: preset.required_params,\n })),\n providers: view.merged.order.map((id) => ({\n id,\n layer: view.merged.origin[id],\n entry: view.merged.providers[id],\n base_url: resolveEntryBaseUrl(view.merged.providers[id]),\n })),\n },\n null,\n 2,\n ),\n );\n return;\n }\n reportDiagnostics(view.diagnostics);\n printPresets();\n printConfigured(view);\n });\n\n cmd\n .command(\"add [id]\")\n .description(\"Add a provider from a catalog preset (id defaults to the preset name)\")\n .requiredOption(\"--preset <preset>\", `Catalog preset, or '${CUSTOM_PRESET}'`)\n .option(\"--credential <ref>\", \"Credential reference (env:NAME, cmd:…, platform:…, keyring:…)\")\n .option(\"--base-url <url>\", \"Override the preset endpoint\")\n .option(\"--surface <surface>\", `Wire surface (${AI_PROVIDER_SURFACES.join(\", \")})`)\n .option(\"--kind <kind>\", \"Entry kind for --preset custom (llm, embed, stt, tts)\", \"llm\")\n .option(\"--label <text>\", \"Display label\")\n .option(\n \"--param <key=value>\",\n \"Transport parameter (repeatable): region, project, location, resource, deployment, api_version\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"--workspace\", \"Write <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .option(\"--force\", \"Overwrite an existing entry in the target file\")\n .action((id: string | undefined, opts: AddOptions) => runAdd(id, opts));\n\n cmd\n .command(\"set <id> <key> <value>\")\n .description(\n \"Set one field (base_url, enabled, credential.ref, headers.<name>, model_map.<id>…)\",\n )\n .option(\"--workspace\", \"Write <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, key: string, value: string, opts: ScopeOptions) =>\n runSet(id, key, value, opts),\n );\n\n cmd\n .command(\"rm <id>\")\n .description(\"Remove a provider from one layer\")\n .option(\"--workspace\", \"Edit <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, opts: ScopeOptions) => runRemove(id, opts));\n\n cmd\n .command(\"test <id>\")\n .description(\"Send one read-only request to a provider and report the result\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, opts: ScopeOptions) => runTest(id, opts));\n\n return cmd;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../cli/src/commands/providers.ts"],"names":[],"mappings":"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","file":"chunk-6F4TIY7X.js","sourcesContent":["/**\n * `skaile providers` — manage the AI provider registry.\n *\n * Endpoints are defined once, in `~/.skaile/providers.yml`, optionally\n * overridden per project in `<workspace>/.skaile/providers.yml` (gitignored by\n * `skaile init`). Every subcommand writes exactly one of those two files and\n * validates the result before it lands — a literal secret never reaches disk.\n *\n * @see PROVIDER-CONFIG-PLAN.md §1, §2.5\n */\n\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n catalogLayer,\n expandPreset,\n getProviderPreset,\n listProviderPresets,\n presetBaseUrl,\n probeProviderEntry,\n} from \"@skaile/workspaces/bridge\";\nimport {\n AI_PROVIDER_LAYERS,\n AI_PROVIDER_SURFACES,\n type AIProviderDiagnostic,\n type AIProviderEntry,\n type AIProviderLayerId,\n type AIProviderLlmEntry,\n type AIProviderRegistryDocument,\n type AIProviderSurface,\n entryTransport,\n isEntryEnabled,\n isSafeProviderId,\n loadProviderRegistry,\n type MergedAIProviderRegistry,\n mergeRegistries,\n parseCredentialRef,\n type ProviderRegistryFile,\n resolveCredential,\n resolveEntryBaseUrl,\n saveProviderRegistryFile,\n userProviderRegistryPath,\n validateMergedRegistry,\n validateRegistry,\n workspaceProviderRegistryPath,\n} from \"@skaile/workspaces/core\";\nimport { Command } from \"commander\";\nimport { logErr, logInfo, logOk, logWarn, S } from \"../helpers.ts\";\n\n/** Preset id that means \"no preset — I will supply the three literals\". */\nconst CUSTOM_PRESET = \"custom\";\n\n/** Which of the two registry files a command reads or writes. */\nexport interface ScopeOptions {\n projectDir?: string;\n workspace?: boolean;\n}\n\n/** The file a mutating subcommand writes: the workspace layer or the user one. */\nfunction targetFile(opts: ScopeOptions): { layer: \"user\" | \"workspace\"; path: string } {\n if (opts.workspace) {\n return { layer: \"workspace\", path: workspaceProviderRegistryPath(resolveProjectDir(opts)) };\n }\n return { layer: \"user\", path: userProviderRegistryPath() };\n}\n\n/** Project directory a subcommand operates on — `--project-dir` or the cwd. */\nfunction resolveProjectDir(opts: ScopeOptions): string {\n return opts.projectDir ? path.resolve(opts.projectDir) : process.cwd();\n}\n\n/** Both file layers plus the catalog, merged — what every reader sees. */\nexport interface RegistryView {\n merged: MergedAIProviderRegistry;\n files: ProviderRegistryFile[];\n diagnostics: AIProviderDiagnostic[];\n}\n\n/**\n * Load both file layers and merge them with the catalog layer the configured\n * `preset:` keys pull in, then gate the result. Read once, merged twice — the\n * catalog layer can only be built after the configured entries are known,\n * and it is built from the **pre-gate** merge: an entry that leaves `kind` or\n * its transport `params` to the preset fails the first gate by design.\n *\n * The gate is on the merged view, not per file: a workspace entry that sets\n * one field of an entry the user file defines is an override (§1.5), so it is\n * only here that an entry can be judged complete.\n */\nexport function loadRegistryView(opts: ScopeOptions): RegistryView {\n const loaded = loadProviderRegistry({ projectDir: resolveProjectDir(opts) });\n const fileLayers = loaded.files.map((file) => ({\n layer: file.layer as AIProviderLayerId,\n providers: file.document.providers,\n }));\n const catalog = catalogLayer(loaded.patches);\n const { registry, diagnostics } = validateMergedRegistry(\n mergeRegistries([...fileLayers, catalog]),\n {\n sources: [\n ...loaded.files.map((file) => ({ label: file.path, providers: file.document.providers })),\n ],\n },\n );\n return {\n merged: registry,\n files: loaded.files,\n // `loaded.diagnostics` already carries the merge notes for the file layers\n // alone; this second merge adds the catalog, so its notes replace them.\n diagnostics: [...loaded.files.flatMap((file) => file.diagnostics), ...diagnostics],\n };\n}\n\n/** Print diagnostics; returns how many were errors. */\nfunction reportDiagnostics(diagnostics: AIProviderDiagnostic[]): number {\n let errors = 0;\n for (const diagnostic of diagnostics) {\n const where = diagnostic.path ? `${diagnostic.path}: ` : \"\";\n if (diagnostic.severity === \"error\") {\n errors++;\n logErr(`${where}${diagnostic.message}`);\n } else {\n logWarn(`${where}${diagnostic.message}`);\n }\n }\n return errors;\n}\n\n/** Highest layer that pins an entry with `locked: true`. */\nfunction lockOwner(id: string, files: ProviderRegistryFile[]): AIProviderLayerId | undefined {\n let owner: AIProviderLayerId | undefined;\n for (const file of files) {\n if (file.document.providers[id]?.locked) {\n const layer = file.layer as AIProviderLayerId;\n if (!owner || AI_PROVIDER_LAYERS.indexOf(layer) > AI_PROVIDER_LAYERS.indexOf(owner)) {\n owner = layer;\n }\n }\n }\n return owner;\n}\n\n/**\n * The message for an edit a lock forbids, or `undefined` when it is allowed.\n * The merge ignores a lower layer silently; the CLI must not, or the operator\n * would watch an accepted edit have no effect.\n *\n * `set <id> locked <value>` stays legal at the locking layer itself —\n * otherwise a lock could never be lifted without hand-editing the file.\n */\nfunction lockConflict(\n id: string,\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n key?: string,\n): string | undefined {\n const owner = lockOwner(id, files);\n if (!owner) return undefined;\n const ownerRank = AI_PROVIDER_LAYERS.indexOf(owner);\n const targetRank = AI_PROVIDER_LAYERS.indexOf(target.layer);\n if (ownerRank === targetRank && key === \"locked\") return undefined;\n if (ownerRank < targetRank) return undefined;\n return (\n `'${id}' is locked by the ${owner} layer and cannot be changed from ${target.layer}.\\n` +\n (ownerRank === targetRank\n ? ` Unlock it first: skaile providers set ${id} locked false`\n : ` A higher layer owns this entry — change it there.`)\n );\n}\n\n/** Refuse loudly when a locked entry would be edited. */\nfunction exitIfLocked(\n id: string,\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n key?: string,\n): void {\n const message = lockConflict(id, target, files, key);\n if (!message) return;\n logErr(message);\n process.exit(1);\n}\n\n/** Read the target file, or an empty document when it does not exist yet. */\nfunction readTargetDocument(\n target: { layer: \"user\" | \"workspace\"; path: string },\n files: ProviderRegistryFile[],\n): AIProviderRegistryDocument {\n const file = files.find((f) => f.path === target.path);\n return file?.document ?? { version: 1, providers: {} };\n}\n\n/**\n * Validate the file that is about to be written; exits non-zero on errors.\n *\n * Validated as the layer it is, so `set` may leave a one-field override in the\n * workspace file (§1.5). Completeness is the merged registry's business, and\n * `loadRegistryView` reports it on the next read.\n */\nfunction validateOrExit(\n document: AIProviderRegistryDocument,\n target: { layer: \"user\" | \"workspace\"; path: string },\n): void {\n const { diagnostics } = validateRegistry(\n { version: 1, providers: document.providers },\n { source: target.path, layer: target.layer },\n );\n if (reportDiagnostics(diagnostics) > 0) process.exit(1);\n}\n\n// ── list ───────────────────────────────────────────────────────────────────\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction credentialSummary(entry: AIProviderEntry): string {\n const credential = entry.credential;\n if (!credential || credential.kind === \"none\") return \"none\";\n return credential.ref ? `${credential.kind} ${credential.ref}` : credential.kind;\n}\n\nfunction printPresets(): void {\n const presets = listProviderPresets();\n console.log();\n console.log(` ${S.heading(\"Catalog presets\")}`);\n const idWidth = Math.max(...presets.map((x) => x.id.length)) + 2;\n const surfaceWidth = Math.max(...AI_PROVIDER_SURFACES.map((s) => s.length)) + 2;\n const header = `${pad(\"preset\", idWidth)}${pad(\"kind\", 7)}${pad(\"surface\", surfaceWidth)}${pad(\"transport\", 14)}default base URL`;\n console.log(` ${S.dim(header)}`);\n for (const preset of presets) {\n const row =\n pad(preset.id, idWidth) +\n pad(preset.kind, 7) +\n pad(preset.surface ?? \"—\", surfaceWidth) +\n pad(\n preset.kind === \"llm\" || preset.kind === \"embed\" ? (preset.transport ?? \"direct\") : \"—\",\n 14,\n ) +\n (presetBaseUrl(preset) ?? \"—\");\n console.log(` ${row}`);\n }\n}\n\nfunction printConfigured(view: RegistryView): void {\n const ids = view.merged.order;\n console.log();\n console.log(` ${S.heading(\"Configured providers\")}`);\n if (ids.length === 0) {\n console.log(\n ` ${S.dim(\"none — add one with\")} ${S.cmd(\"skaile providers add --preset <preset>\")}`,\n );\n console.log();\n return;\n }\n const idWidth = Math.max(...ids.map((id) => id.length)) + 2;\n const header = `${pad(\"id\", idWidth)}${pad(\"layer\", 11)}${pad(\"surface\", 26)}${pad(\"transport\", 14)}endpoint`;\n console.log(` ${S.dim(header)}`);\n for (const id of ids) {\n const entry = view.merged.providers[id];\n const surface = (entry as AIProviderLlmEntry).surface ?? \"—\";\n const transport = entryTransport(entry) ?? \"—\";\n const url = resolveEntryBaseUrl(entry) ?? S.dim(\"(unresolved)\");\n const flags = [\n isEntryEnabled(entry) ? \"\" : S.warn(\"disabled\"),\n entry.locked ? S.warn(\"locked\") : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n console.log(\n ` ${pad(id, idWidth)}${pad(view.merged.origin[id], 11)}${pad(surface, 26)}${pad(transport, 14)}${url} ${flags}`.trimEnd(),\n );\n console.log(` ${S.dim(`${pad(\"\", idWidth)}${credentialSummary(entry)}`)}`);\n }\n console.log();\n}\n\n// ── add ────────────────────────────────────────────────────────────────────\n\ninterface AddOptions extends ScopeOptions {\n preset?: string;\n credential?: string;\n baseUrl?: string;\n surface?: string;\n label?: string;\n kind?: string;\n param: string[];\n force?: boolean;\n}\n\nfunction parseParams(pairs: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf(\"=\");\n if (eq <= 0) {\n logErr(`--param expects <key>=<value> (got '${pair}')`);\n process.exit(1);\n }\n out[pair.slice(0, eq)] = pair.slice(eq + 1);\n }\n return out;\n}\n\n/** Ask for the three literals a custom endpoint needs. Nothing else. */\nasync function promptCustomEntry(\n id: string,\n opts: AddOptions,\n): Promise<{ surface: AIProviderSurface; baseUrl: string; credentialRef: string }> {\n const interactive = process.stdin.isTTY === true;\n let surface = opts.surface as AIProviderSurface | undefined;\n let baseUrl = opts.baseUrl;\n let credentialRef = opts.credential;\n\n if (!interactive && (!surface || !baseUrl || !credentialRef)) {\n logErr(\n \"--preset custom needs --surface, --base-url and --credential when there is no terminal to prompt on\",\n );\n process.exit(1);\n }\n\n if (!surface) {\n const answer = await p.select({\n message: \"Wire surface:\",\n options: AI_PROVIDER_SURFACES.map((value) => ({ value, label: value })),\n initialValue: \"openai-completions\" as AIProviderSurface,\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n surface = answer as AIProviderSurface;\n }\n if (!baseUrl) {\n const answer = await p.text({\n message: \"Base URL:\",\n placeholder: \"https://api.example.com/v1\",\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n baseUrl = answer as string;\n }\n if (!credentialRef) {\n const answer = await p.text({\n message: \"Credential reference (env:NAME, cmd:<shell>, platform:<id>, keyring:<svc>/<acct>):\",\n initialValue: `env:${id.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_API_KEY`,\n });\n if (p.isCancel(answer)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n credentialRef = answer as string;\n }\n return { surface, baseUrl, credentialRef };\n}\n\n/** A rejected registry write. The message is already CLI-ready. */\nexport class ProviderRegistryWriteError extends Error {}\n\n/** What {@link addProviderEntry} writes. */\nexport interface AddProviderEntryInput extends ScopeOptions {\n /** Registry entry id — `[a-z0-9][a-z0-9_-]*`. */\n id: string;\n /** Catalog preset to expand. Mutually exclusive with `entry`. */\n presetId?: string;\n /** A fully-built entry (the `--preset custom` path, which needs prompts). */\n entry?: AIProviderEntry;\n /** `env:NAME` / `cmd:…` / `platform:…` / `keyring:…` — never a literal. */\n credentialRef?: string;\n baseUrl?: string;\n surface?: AIProviderSurface;\n label?: string;\n params?: Record<string, string>;\n /** Overwrite an entry that already exists in the target file. */\n force?: boolean;\n}\n\n/** Result of {@link addProviderEntry}. */\nexport interface AddedProviderEntry {\n id: string;\n layer: \"user\" | \"workspace\";\n path: string;\n entry: AIProviderEntry;\n /** True when an existing entry in the target file was overwritten. */\n replaced: boolean;\n}\n\n/**\n * Write one entry into a registry file — the single write path behind\n * `skaile providers add` and the `skaile setup` wizard.\n *\n * Throws {@link ProviderRegistryWriteError} instead of exiting, so a wizard\n * can report the failure in its own idiom. Every rejection a caller can\n * provoke (bad id, unknown preset, missing transport parameter, locked entry,\n * a literal secret) lands here, and the document is validated before it is\n * written — a secret cannot reach disk through this function.\n */\nexport function addProviderEntry(input: AddProviderEntryInput): AddedProviderEntry {\n const { id } = input;\n if (!isSafeProviderId(id)) {\n throw new ProviderRegistryWriteError(\n `'${id}' is not a valid entry id — use [a-z0-9][a-z0-9_-]*`,\n );\n }\n if (input.credentialRef && !parseCredentialRef(input.credentialRef)) {\n throw new ProviderRegistryWriteError(\n \"the credential must be a reference, not a secret: \" +\n \"env:NAME, cmd:<shell>, platform:<configId> or keyring:<service>/<account>\",\n );\n }\n\n const view = loadRegistryView(input);\n const target = targetFile(input);\n const locked = lockConflict(id, target, view.files);\n if (locked) throw new ProviderRegistryWriteError(locked);\n\n const document = readTargetDocument(target, view.files);\n const replaced = document.providers[id] !== undefined;\n if (replaced && !input.force) {\n throw new ProviderRegistryWriteError(\n `'${id}' already exists in ${target.path} — pass --force to overwrite it.`,\n );\n }\n\n let entry: AIProviderEntry;\n if (input.entry) {\n entry = input.entry;\n } else {\n const preset = input.presetId ? getProviderPreset(input.presetId) : undefined;\n if (!preset) {\n throw new ProviderRegistryWriteError(\n `Unknown preset '${input.presetId}'. Run \\`skaile providers list\\` to see the catalog, ` +\n \"or use `--preset custom`.\",\n );\n }\n entry = expandPreset(preset, {\n credentialRef: input.credentialRef,\n baseUrl: input.baseUrl,\n surface: input.surface,\n label: input.label,\n params: input.params,\n });\n const missing = (preset.required_params ?? []).filter(\n (key) => !(key in ((entry as AIProviderLlmEntry).params ?? {})),\n );\n if (missing.length > 0) {\n throw new ProviderRegistryWriteError(\n `Preset '${preset.id}' needs ${missing.map((m) => `--param ${m}=<value>`).join(\" \")}`,\n );\n }\n }\n\n const next: AIProviderRegistryDocument = {\n version: 1,\n providers: { ...document.providers, [id]: entry },\n };\n const { diagnostics } = validateRegistry(\n { version: 1, providers: next.providers },\n { source: target.path },\n );\n const errors = diagnostics.filter((d) => d.severity === \"error\");\n if (errors.length > 0) {\n throw new ProviderRegistryWriteError(\n errors.map((d) => (d.path ? `${d.path}: ${d.message}` : d.message)).join(\"\\n\"),\n );\n }\n saveProviderRegistryFile(target.path, next);\n\n return { id, layer: target.layer, path: target.path, entry, replaced };\n}\n\n/** The env var an `env:` credential reference points at, if it is one. */\nexport function credentialEnvVarName(entry: AIProviderEntry): string | undefined {\n const ref = entry.credential?.ref;\n return ref?.startsWith(\"env:\") ? ref.slice(4) : undefined;\n}\n\n/** Build the `--preset custom` entry from the three literals the user gave. */\nfunction customEntry(\n answers: { surface: AIProviderSurface; baseUrl: string; credentialRef: string },\n opts: AddOptions,\n): AIProviderEntry {\n const kind = (opts.kind ?? \"llm\") as AIProviderEntry[\"kind\"];\n // Anthropic- and Google-shaped surfaces read a dedicated API-key header;\n // everything else is a bearer token. `set <id> credential.kind …` adjusts.\n const credentialKind =\n kind === \"stt\" ||\n kind === \"tts\" ||\n answers.surface === \"anthropic-messages\" ||\n answers.surface === \"google-generative-ai\" ||\n answers.surface === \"azure-openai-responses\"\n ? \"api_key_header\"\n : \"bearer\";\n if (kind === \"stt\" || kind === \"tts\") {\n return {\n kind,\n ...(opts.label ? { label: opts.label } : {}),\n base_url: answers.baseUrl,\n credential: { kind: credentialKind, ref: answers.credentialRef },\n };\n }\n return {\n kind,\n ...(opts.label ? { label: opts.label } : {}),\n surface: answers.surface,\n base_url: answers.baseUrl,\n credential: { kind: credentialKind, ref: answers.credentialRef },\n } as AIProviderLlmEntry;\n}\n\nasync function runAdd(idArg: string | undefined, opts: AddOptions): Promise<void> {\n const presetId = opts.preset;\n if (!presetId) {\n logErr(\n `--preset is required. Run ${S.cmd(\"skaile providers list\")} for the catalog, ` +\n `or use ${S.cmd(\"--preset custom\")}.`,\n );\n process.exit(1);\n }\n const id = idArg ?? presetId;\n if (id === CUSTOM_PRESET && !idArg) {\n logErr(\"--preset custom needs an entry id: skaile providers add <id> --preset custom\");\n process.exit(1);\n }\n\n const entry =\n presetId === CUSTOM_PRESET ? customEntry(await promptCustomEntry(id, opts), opts) : undefined;\n\n let added: AddedProviderEntry;\n try {\n added = addProviderEntry({\n id,\n ...(entry ? { entry } : { presetId }),\n credentialRef: opts.credential,\n baseUrl: opts.baseUrl,\n surface: opts.surface as AIProviderSurface | undefined,\n label: opts.label,\n params: parseParams(opts.param),\n projectDir: opts.projectDir,\n workspace: opts.workspace,\n force: opts.force,\n });\n } catch (error) {\n logErr(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n logOk(`Added ${S.bold(id)} (${presetId}) to the ${added.layer} registry`);\n console.log(S.dim(` → ${added.path}`));\n const name = credentialEnvVarName(added.entry);\n if (name) {\n console.log(\n ` ${S.dim(\"The secret itself never goes in this file — export it:\")} ${S.cmd(`export ${name}=…`)}`,\n );\n }\n console.log(` ${S.dim(\"Verify with:\")} ${S.cmd(`skaile providers test ${id}`)}`);\n}\n\n// ── set / rm ───────────────────────────────────────────────────────────────\n\n/** Coerce a CLI string into the type the schema expects at `key`. */\nfunction coerceValue(key: string, value: string): unknown {\n const leaf = key.split(\".\").pop() ?? key;\n if (leaf === \"enabled\" || leaf === \"locked\" || leaf === \"tools\" || leaf === \"images\") {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n logErr(`'${key}' takes true or false (got '${value}')`);\n process.exit(1);\n }\n if (leaf === \"context_window\" || leaf === \"thinking_max\") {\n const parsed = Number(value);\n if (!Number.isFinite(parsed)) {\n logErr(`'${key}' takes a number (got '${value}')`);\n process.exit(1);\n }\n return parsed;\n }\n return value;\n}\n\n/** Write `value` at a dotted path, creating intermediate maps. */\nfunction setDotted(entry: Record<string, unknown>, key: string, value: unknown): void {\n const segments = key.split(\".\");\n let cursor = entry;\n for (const segment of segments.slice(0, -1)) {\n const next = cursor[segment];\n if (typeof next !== \"object\" || next === null || Array.isArray(next)) {\n cursor[segment] = {};\n }\n cursor = cursor[segment] as Record<string, unknown>;\n }\n cursor[segments[segments.length - 1]] = value;\n}\n\nfunction runSet(id: string, key: string, value: string, opts: ScopeOptions): void {\n const view = loadRegistryView(opts);\n const target = targetFile(opts);\n exitIfLocked(id, target, view.files, key);\n\n const document = readTargetDocument(target, view.files);\n const existing = document.providers[id];\n const inherited = view.merged.providers[id];\n if (!existing && !inherited) {\n logErr(\n `No provider '${id}'. Add it with ${S.cmd(`skaile providers add ${id} --preset <preset>`)}`,\n );\n process.exit(1);\n }\n\n // Writing a field into a layer that has no entry yet leaves a one-field\n // override: the layers below keep supplying the rest (§1.5), so copying\n // their `kind` down here would pin a value this layer does not own.\n const base = (existing ? structuredClone(existing) : {}) as unknown as Record<string, unknown>;\n setDotted(base, key, coerceValue(key, value));\n\n const next: AIProviderRegistryDocument = {\n version: 1,\n providers: { ...document.providers, [id]: base as unknown as AIProviderEntry },\n };\n validateOrExit(next, target);\n saveProviderRegistryFile(target.path, next);\n\n logOk(`Set ${S.bold(`${id}.${key}`)} = ${value} in the ${target.layer} registry`);\n console.log(S.dim(` → ${target.path}`));\n}\n\nfunction runRemove(id: string, opts: ScopeOptions): void {\n const view = loadRegistryView(opts);\n const target = targetFile(opts);\n exitIfLocked(id, target, view.files);\n\n const document = readTargetDocument(target, view.files);\n if (!document.providers[id]) {\n logErr(`No provider '${id}' in ${target.path}`);\n process.exit(1);\n }\n const providers = { ...document.providers };\n delete providers[id];\n saveProviderRegistryFile(target.path, { version: 1, providers });\n\n logOk(`Removed ${S.bold(id)} from the ${target.layer} registry`);\n console.log(S.dim(` → ${target.path}`));\n if (\n view.merged.providers[id] &&\n view.files.some((f) => f.path !== target.path && f.document.providers[id])\n ) {\n logInfo(`'${id}' is still defined in another layer — run 'skaile providers list' to see it.`);\n }\n}\n\n// ── test ───────────────────────────────────────────────────────────────────\n\nasync function runTest(id: string, opts: ScopeOptions): Promise<void> {\n const view = loadRegistryView(opts);\n const entry = view.merged.providers[id];\n if (!entry) {\n logErr(`No provider '${id}'. Run ${S.cmd(\"skaile providers list\")} to see what is configured.`);\n process.exit(1);\n }\n\n const credential = resolveCredential(entry);\n console.log();\n console.log(` ${S.heading(id)} ${S.dim(`(${view.merged.origin[id]} layer)`)}`);\n console.log(` ${S.label(\"endpoint \")} ${resolveEntryBaseUrl(entry) ?? S.dim(\"(unresolved)\")}`);\n console.log(\n ` ${S.label(\"credential\")} ${credentialSummary(entry)} ${\n credential.error\n ? S.err(`— ${credential.error}`)\n : S.dim(`— resolved from ${credential.source}`)\n }`,\n );\n\n if (credential.error) {\n console.log();\n logErr(`${id} is not usable yet: ${credential.error}`);\n process.exit(1);\n }\n\n const result = await probeProviderEntry(entry, { secret: credential.value });\n if (result.url) console.log(` ${S.label(\"probe \")} GET ${result.url}`);\n console.log();\n if (result.ok) {\n logOk(`${id}: ${result.detail}${result.status ? ` (HTTP ${result.status})` : \"\"}`);\n return;\n }\n if (!result.probed) {\n logWarn(`${id}: ${result.detail}`);\n return;\n }\n logErr(`${id}: ${result.detail}`);\n process.exit(1);\n}\n\n// ── command ────────────────────────────────────────────────────────────────\n\n/**\n * Create the `skaile providers` command group.\n *\n * `list` shows the catalog and what is configured; `add` writes an entry from\n * a preset (or from three literals with `--preset custom`); `set` and `rm`\n * edit one layer; `test` sends one read-only request and reports what came\n * back, never the credential.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n */\nexport function makeProvidersCommand(): Command {\n const cmd = new Command(\"providers\").description(\n \"Manage AI provider endpoints (~/.skaile/providers.yml)\",\n );\n\n cmd\n .command(\"list\")\n .description(\"List catalog presets and configured providers\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .option(\"--json\", \"Machine-readable output\")\n .action((opts) => {\n const view = loadRegistryView(opts);\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n presets: listProviderPresets().map((preset) => ({\n id: preset.id,\n kind: preset.kind,\n surface: preset.surface,\n transport: preset.transport ?? (preset.surface ? \"direct\" : undefined),\n base_url: presetBaseUrl(preset),\n credential: preset.credential,\n required_params: preset.required_params,\n })),\n providers: view.merged.order.map((id) => ({\n id,\n layer: view.merged.origin[id],\n entry: view.merged.providers[id],\n base_url: resolveEntryBaseUrl(view.merged.providers[id]),\n })),\n },\n null,\n 2,\n ),\n );\n return;\n }\n reportDiagnostics(view.diagnostics);\n printPresets();\n printConfigured(view);\n });\n\n cmd\n .command(\"add [id]\")\n .description(\"Add a provider from a catalog preset (id defaults to the preset name)\")\n .requiredOption(\"--preset <preset>\", `Catalog preset, or '${CUSTOM_PRESET}'`)\n .option(\"--credential <ref>\", \"Credential reference (env:NAME, cmd:…, platform:…, keyring:…)\")\n .option(\"--base-url <url>\", \"Override the preset endpoint\")\n .option(\"--surface <surface>\", `Wire surface (${AI_PROVIDER_SURFACES.join(\", \")})`)\n .option(\"--kind <kind>\", \"Entry kind for --preset custom (llm, embed, stt, tts)\", \"llm\")\n .option(\"--label <text>\", \"Display label\")\n .option(\n \"--param <key=value>\",\n \"Transport parameter (repeatable): region, project, location, resource, deployment, api_version\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"--workspace\", \"Write <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .option(\"--force\", \"Overwrite an existing entry in the target file\")\n .action((id: string | undefined, opts: AddOptions) => runAdd(id, opts));\n\n cmd\n .command(\"set <id> <key> <value>\")\n .description(\n \"Set one field (base_url, enabled, credential.ref, headers.<name>, model_map.<id>…)\",\n )\n .option(\"--workspace\", \"Write <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, key: string, value: string, opts: ScopeOptions) =>\n runSet(id, key, value, opts),\n );\n\n cmd\n .command(\"rm <id>\")\n .description(\"Remove a provider from one layer\")\n .option(\"--workspace\", \"Edit <workspace>/.skaile/providers.yml instead of the user file\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, opts: ScopeOptions) => runRemove(id, opts));\n\n cmd\n .command(\"test <id>\")\n .description(\"Send one read-only request to a provider and report the result\")\n .option(\"--project-dir <path>\", \"Project directory\")\n .action((id: string, opts: ScopeOptions) => runTest(id, opts));\n\n return cmd;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { logErr, logOk, colorRef, logInfo, S, logWarn, formatSoftDepHint } from './chunk-
|
|
2
|
-
import { AssetManager } from './chunk-
|
|
1
|
+
import { logErr, logOk, colorRef, logInfo, S, logWarn, formatSoftDepHint } from './chunk-WOE4LPGF.js';
|
|
2
|
+
import { AssetManager } from './chunk-AOFJ2OKW.js';
|
|
3
3
|
import { readLock } from './chunk-UWU572Q6.js';
|
|
4
4
|
import { SUPPORTED_DRIVER_TARGETS } from './chunk-MENCWIHW.js';
|
|
5
5
|
import { parseAssetRef } from './chunk-GEEW6SY2.js';
|
|
@@ -82,7 +82,7 @@ async function runRefInstall(ref, opts) {
|
|
|
82
82
|
const spinner2 = p.spinner();
|
|
83
83
|
spinner2.start(`Installing ${ref}`);
|
|
84
84
|
try {
|
|
85
|
-
const { openCatalogSource, openLibrary } = await import('./open-library-
|
|
85
|
+
const { openCatalogSource, openLibrary } = await import('./open-library-64LO64NE.js');
|
|
86
86
|
const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });
|
|
87
87
|
if (!supportsInstallManifest(catalog)) {
|
|
88
88
|
throw new Error(
|
|
@@ -124,7 +124,7 @@ async function runYamlInstall(opts) {
|
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
126
|
try {
|
|
127
|
-
const { ensureSourcesCloned } = await import('./ensure-sources-
|
|
127
|
+
const { ensureSourcesCloned } = await import('./ensure-sources-6XKA46PN.js');
|
|
128
128
|
const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
|
|
129
129
|
if (hydrate.cloned.length > 0) {
|
|
130
130
|
logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
|
|
@@ -290,5 +290,5 @@ function makeCleanCommand() {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
export { makeCheckCommand, makeCleanCommand, makeInstallCommand, reportInstalledSoftDeps, runPointerOnlyInstall, supportsInstallManifest };
|
|
293
|
-
//# sourceMappingURL=chunk-
|
|
294
|
-
//# sourceMappingURL=chunk-
|
|
293
|
+
//# sourceMappingURL=chunk-7EAJNEQ5.js.map
|
|
294
|
+
//# sourceMappingURL=chunk-7EAJNEQ5.js.map
|