@gullabs/claude-cli 0.4.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +7 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -156,7 +156,7 @@ function mapUsage(usage) {
|
|
|
156
156
|
function partText(part) {
|
|
157
157
|
if (part.kind !== "text") {
|
|
158
158
|
throw new core.LlmError(
|
|
159
|
-
"claude-cli is text-only; non-text message parts are not supported",
|
|
159
|
+
"claude-cli is text-only; non-text message parts (inline media, file URIs, tool-call, tool-result) are not supported",
|
|
160
160
|
{
|
|
161
161
|
kind: "bad_request",
|
|
162
162
|
retryable: false,
|
|
@@ -234,6 +234,12 @@ function claudeCliAdapter(opts) {
|
|
|
234
234
|
{ kind: "bad_request", retryable: false, provider: "claude-cli" }
|
|
235
235
|
);
|
|
236
236
|
}
|
|
237
|
+
if (req.tools !== void 0 && req.tools.length > 0) {
|
|
238
|
+
throw new core.LlmError(
|
|
239
|
+
"claude-cli does not support LlmRequest.tools; CLI runtimes are out of the function-calling seam.",
|
|
240
|
+
{ kind: "bad_request", retryable: false, provider: "claude-cli" }
|
|
241
|
+
);
|
|
242
|
+
}
|
|
237
243
|
const warnings = [];
|
|
238
244
|
const model = req.model;
|
|
239
245
|
const config = req.config;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runner.ts","../src/adapter.ts","../src/models.ts","../src/provider.ts"],"names":["spawn","LlmError","mkdtemp","join","tmpdir","rm","z","toConfigJsonSchema","zodToStandardSchema","createModelRegistry"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * ClaudeCliRunner — the process-execution seam for @gullabs/claude-cli.\n *\n * Adapters depend on the {@link ClaudeCliRunner} interface only.\n * {@link buildClaudeCliRunner} is the sole factory that touches\n * `node:child_process`; committed tests inject a hand-written fake instead of\n * exercising it, so no real `claude` subprocess is ever spawned in CI.\n *\n * @module\n */\n\nimport { spawn } from 'node:child_process'\n\n/**\n * The result of a single `claude` CLI invocation.\n */\nexport interface ClaudeCliRunResult {\n stdout: string\n stderr: string\n exitCode: number | null\n}\n\n/**\n * Options accepted by {@link ClaudeCliRunner.run}.\n */\nexport interface ClaudeCliRunOptions {\n /** Working directory for the subprocess (the adapter owns tmpdir lifecycle). */\n cwd: string\n /** Kill the subprocess if it has not exited within this many milliseconds. */\n timeoutMs?: number\n /** Kill the subprocess if this signal fires. */\n signal?: AbortSignal\n}\n\n/**\n * The process-execution seam consumed by {@link claudeCliAdapter}.\n *\n * Implementations run the `claude` binary with `args`, write `input` to its\n * stdin (the rendered prompt), and resolve with captured stdout/stderr/exit\n * code. Implementations must never throw for a non-zero exit code — that is\n * the adapter's error-classification job; the one exception is a spawn-time\n * failure (e.g. `ENOENT` when the binary is missing), which should reject.\n */\nexport interface ClaudeCliRunner {\n run(\n args: string[],\n input: string,\n opts: ClaudeCliRunOptions,\n ): Promise<ClaudeCliRunResult>\n}\n\n/**\n * Build the real {@link ClaudeCliRunner}, backed by `node:child_process`.\n *\n * Never exercised by committed tests — only the real dev workflow invokes\n * this factory; tests inject a hand-written fake implementing\n * {@link ClaudeCliRunner} instead.\n *\n * @param claudePath - Path or bare command name for the `claude` binary.\n * Defaults to `'claude'`, resolved via `PATH`.\n */\nexport function buildClaudeCliRunner(claudePath = 'claude'): ClaudeCliRunner {\n return {\n run(args, input, opts) {\n return new Promise((resolve, reject) => {\n if (opts.signal?.aborted === true) {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n reject(err)\n return\n }\n\n // NOTE: the argv itself (including the `--safe-mode` vs `--bare`\n // choice) is owned by the adapter (see adapter.ts) — this runner is\n // a dumb pipe. We repeat the rule here only as a pointer: never pass\n // `--bare`, it disables OAuth/keychain auth.\n const child = spawn(claudePath, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n let settled = false\n // Set once a timeout/abort has begun killing the child. The\n // returned promise is NOT rejected with this until the child's\n // 'close' event actually fires — the caller (the adapter) must\n // never observe settlement while the OS process may still be\n // alive and writing to its scratch cwd.\n let pendingError: Error | undefined\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n let killTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n const cleanupTimers = (): void => {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (killTimeoutHandle !== undefined) clearTimeout(killTimeoutHandle)\n }\n\n const cleanup = (): void => {\n cleanupTimers()\n if (opts.signal !== undefined) {\n opts.signal.removeEventListener('abort', onAbort)\n }\n }\n\n const killChild = (): void => {\n child.kill('SIGTERM')\n killTimeoutHandle = setTimeout(() => {\n child.kill('SIGKILL')\n }, 5_000)\n }\n\n const beginReject = (err: Error): void => {\n if (settled || pendingError !== undefined) return\n pendingError = err\n cleanupTimers()\n killChild()\n }\n\n const onAbort = (): void => {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n beginReject(err)\n }\n\n // The pre-aborted case is handled above, before `spawn` — by this\n // point `opts.signal`, if present, is guaranteed not yet aborted.\n if (opts.signal !== undefined) {\n opts.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n if (opts.timeoutMs !== undefined) {\n timeoutHandle = setTimeout(() => {\n const err = new Error(`claude-cli call exceeded ${opts.timeoutMs}ms timeout`)\n err.name = 'TimeoutError'\n beginReject(err)\n }, opts.timeoutMs)\n }\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8')\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8')\n })\n\n child.once('error', (err) => {\n if (settled) return\n settled = true\n cleanup()\n reject(pendingError ?? err)\n })\n\n child.once('close', (exitCode) => {\n if (settled) return\n settled = true\n cleanup()\n if (pendingError !== undefined) {\n reject(pendingError)\n } else {\n resolve({ stdout, stderr, exitCode })\n }\n })\n\n child.stdin.end(input, 'utf8')\n })\n },\n }\n}\n","/**\n * claudeCliAdapter — @gullabs/claude-cli provider adapter.\n *\n * Pure request⇄response mapping over the locally-authenticated `claude`\n * (Claude Code) CLI, via {@link ClaudeCliRunner}. Never persists, never\n * computes cost, never retries, never reads `process.env`.\n *\n * DEV-ONLY: this adapter requires `ctx.auth = { cliSession: true }` — it\n * shells out to a `claude` binary that owns its own local login/session\n * state. It is never usable in a production/serverless environment because\n * there is no interactive CLI login there by construction.\n *\n * @module\n */\n\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport { LlmError } from '@gullabs/core'\nimport type {\n ProviderAdapter,\n ResolvedRequest,\n AdapterCtx,\n AdapterResult,\n Usage,\n Warning,\n FinishReason,\n JsonValue,\n Message,\n Part,\n} from '@gullabs/core'\nimport { buildClaudeCliRunner } from './runner.js'\nimport type { ClaudeCliRunner, ClaudeCliRunResult } from './runner.js'\n\n// ---------------------------------------------------------------------------\n// Captured CLI envelope shape (see repo notes for the two captured fixtures)\n// ---------------------------------------------------------------------------\n\n/**\n * The `usage` object nested inside the `claude -p --output-format json`\n * result envelope. Only the fields this adapter consumes are typed here;\n * the full object is preserved verbatim in `Usage.raw`.\n */\nexport interface ClaudeCliUsageShape {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n [key: string]: unknown\n}\n\n/**\n * The top-level JSON envelope emitted on stdout by\n * `claude -p ... --output-format json` on completion (success or error).\n */\nexport interface ClaudeCliEnvelope {\n type: string\n subtype?: string\n is_error?: boolean\n result?: string\n stop_reason?: string\n session_id?: string\n total_cost_usd?: number\n num_turns?: number\n usage?: ClaudeCliUsageShape\n [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Tiny in-file semaphore — adapter-internal concurrency control\n// ---------------------------------------------------------------------------\n\nclass Semaphore {\n private available: number\n private readonly queue: Array<() => void> = []\n\n constructor(max: number) {\n this.available = max\n }\n\n async acquire(): Promise<() => void> {\n if (this.available > 0) {\n this.available -= 1\n return () => {\n this.release()\n }\n }\n await new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n this.available -= 1\n return () => {\n this.release()\n }\n }\n\n private release(): void {\n this.available += 1\n const next = this.queue.shift()\n if (next !== undefined) next()\n }\n}\n\n// ---------------------------------------------------------------------------\n// FinishReason mapping\n// ---------------------------------------------------------------------------\n\nfunction mapFinishReason(stopReason: string | undefined): FinishReason | undefined {\n if (stopReason === undefined) return undefined\n switch (stopReason) {\n case 'end_turn':\n return 'stop'\n case 'tool_use':\n // The CLI's own final answer, not a caller-visible tool call — treat\n // as a successful completion for our purposes.\n return 'stop'\n default:\n return 'other'\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage mapping — GROSS convention\n//\n// `totalTokens` is not reported by the claude-cli usage payload — it is\n// derived as `inputTokens + outputTokens` whenever a usage payload was\n// present; left undefined when there was no usage payload at all.\n// ---------------------------------------------------------------------------\n\nfunction mapUsage(usage: ClaudeCliUsageShape | undefined): Usage {\n const inputTokens = usage?.input_tokens ?? 0\n const outputTokens = usage?.output_tokens ?? 0\n const cachedInputTokens = usage?.cache_read_input_tokens\n const totalTokens = usage !== undefined ? inputTokens + outputTokens : undefined\n\n const details: Record<string, number> = {\n input: inputTokens,\n output: outputTokens,\n ...(cachedInputTokens !== undefined ? { cached: cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { total: totalTokens } : {}),\n }\n\n const raw: JsonValue = usage !== undefined ? (usage as unknown as JsonValue) : null\n\n return {\n inputTokens,\n outputTokens,\n details,\n raw,\n ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { totalTokens } : {}),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt serialization\n// ---------------------------------------------------------------------------\n\nfunction partText(part: Part): string {\n if (part.kind !== 'text') {\n throw new LlmError(\n 'claude-cli is text-only; non-text message parts are not supported',\n {\n kind: 'bad_request',\n retryable: false,\n provider: 'claude-cli',\n },\n )\n }\n return part.text\n}\n\nfunction messageText(msg: Message): string {\n return msg.parts.map(partText).join('')\n}\n\n/**\n * Serialize `req.messages` into the single string sent to the CLI over\n * stdin.\n *\n * - Single user message, single text part → the text verbatim.\n * - Otherwise → a role-labelled transcript, blocks separated by a blank line.\n */\nfunction buildPrompt(messages: Message[]): string {\n if (messages.length === 1 && messages[0]?.parts.length === 1) {\n return partText(messages[0].parts[0] as Part)\n }\n\n return messages\n .map((msg) => {\n const label = msg.role === 'assistant' ? 'Assistant' : 'User'\n return `${label}:\\n${messageText(msg)}`\n })\n .join('\\n\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Error classification\n// ---------------------------------------------------------------------------\n\nfunction looksAuthy(text: string): boolean {\n return /login|auth|unauthorized/i.test(text)\n}\n\nfunction looksRateLimited(text: string): boolean {\n return /rate limit|429/i.test(text)\n}\n\nfunction classifyRunFailure(\n envelope: ClaudeCliEnvelope | undefined,\n result: ClaudeCliRunResult,\n): LlmError {\n const combinedText = `${envelope?.subtype ?? ''} ${result.stderr}`\n\n if (looksAuthy(combinedText)) {\n return new LlmError(\n `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (looksRateLimited(combinedText)) {\n return new LlmError(\n `claude CLI reported rate limiting: ${result.stderr.slice(-500)}`,\n {\n kind: 'rate_limited',\n retryable: true,\n provider: 'claude-cli',\n },\n )\n }\n\n if (envelope?.is_error === true) {\n return new LlmError(\n `claude CLI reported an error (subtype: ${envelope.subtype ?? 'unknown'}): ${result.stderr.slice(-500)}`,\n { kind: 'server', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const stderrTail = result.stderr.slice(-500)\n return new LlmError(\n `claude CLI exited with code ${String(result.exitCode)}: ${stderrTail}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n}\n\n// ---------------------------------------------------------------------------\n// Adapter options\n// ---------------------------------------------------------------------------\n\nexport interface ClaudeCliAdapterOptions {\n /** Inject a runner (real or fake). Defaults to `buildClaudeCliRunner()`. */\n runner?: ClaudeCliRunner\n /** Path or bare command name for the `claude` binary. Defaults to `'claude'`. */\n claudePath?: string\n /** Max concurrent CLI invocations. Defaults to `2`. */\n maxConcurrency?: number\n}\n\n// ---------------------------------------------------------------------------\n// claudeCliAdapter factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a dev-only Claude Code CLI provider adapter.\n *\n * Requires `ctx.auth = { cliSession: true }` — see module docs.\n */\nexport function claudeCliAdapter(opts?: ClaudeCliAdapterOptions): ProviderAdapter {\n // Constructed eagerly but never invoked unless `opts.runner` is absent —\n // `buildClaudeCliRunner` only closes over `node:child_process`, it does not\n // spawn anything until `.run()` is called.\n const runner: ClaudeCliRunner = opts?.runner ?? buildClaudeCliRunner(opts?.claudePath)\n\n const semaphore = new Semaphore(opts?.maxConcurrency ?? 2)\n\n return {\n id: 'claude-cli',\n\n async run(req: ResolvedRequest, ctx: AdapterCtx): Promise<AdapterResult> {\n // ------------------------------------------------------------------\n // 1. Auth — CliSessionAuth only.\n // ------------------------------------------------------------------\n const hasCliSession = 'cliSession' in ctx.auth && ctx.auth.cliSession\n if (!hasCliSession) {\n throw new LlmError(\n '@gullabs/claude-cli requires auth: { cliSession: true } — these dev-only providers route through a locally-authenticated `claude` CLI session, not an API key',\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (req.provider !== 'claude-cli') {\n throw new LlmError(\n `@gullabs/claude-cli received a request routed for provider \"${req.provider}\" — this adapter only serves \"claude-cli\"`,\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const warnings: Warning[] = []\n const model = req.model\n const config = req.config\n\n // ------------------------------------------------------------------\n // 2. Prompt serialization (throws bad_request on non-text parts).\n // ------------------------------------------------------------------\n const prompt = buildPrompt(req.messages)\n\n // ------------------------------------------------------------------\n // 3. Invariant argv — adapter-owned, never caller-configurable.\n //\n // We use --safe-mode, NEVER --bare: --bare disables OAuth/keychain\n // auth and would break subscription-based Claude Code auth — the\n // exact mechanism that lets these dev-only providers work with zero\n // API-key configuration at all.\n // ------------------------------------------------------------------\n const args: string[] = [\n '-p',\n '--output-format',\n 'json',\n '--safe-mode',\n '--tools',\n '',\n '--disable-slash-commands',\n '--no-session-persistence',\n ]\n\n args.push('--model', model)\n\n const effort = config.reasoning?.effort\n if (effort !== undefined) {\n // `effort` was already validated against this package's own zod\n // schema at the config layer before the engine called us — forward\n // verbatim, no re-validation, no `any` cast.\n args.push('--effort', String(effort))\n }\n\n if (req.system !== undefined) {\n args.push('--system-prompt', req.system)\n }\n\n if (req.outputJsonSchema !== undefined) {\n args.push('--json-schema', JSON.stringify(req.outputJsonSchema))\n }\n\n // ------------------------------------------------------------------\n // 4. Timeout + scratch dir + runner invocation.\n // ------------------------------------------------------------------\n const timeoutMs = req.attemptTimeoutMs ?? config.timeoutMs\n\n // The runner owns timeout/abort enforcement end-to-end: it only\n // settles (resolve OR reject) once the child process has actually\n // exited (its 'close' event fired). We deliberately do NOT race an\n // independent timer against `runner.run(...)` here — doing so could\n // let this adapter move on (and release the semaphore / rm the\n // scratch dir) while the real OS child process is still alive and\n // possibly still writing into `cwd`. We simply await the runner\n // promise and classify whatever it settles with.\n const cwd = await mkdtemp(join(tmpdir(), 'claude-cli-'))\n const release = await semaphore.acquire()\n let result: ClaudeCliRunResult\n try {\n result = await runner.run(args, prompt, {\n cwd,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}),\n })\n } catch (rawErr) {\n release()\n await rm(cwd, { recursive: true, force: true })\n\n if (rawErr instanceof LlmError) throw rawErr\n\n if (\n typeof rawErr === 'object' &&\n rawErr !== null &&\n 'code' in rawErr &&\n (rawErr as { code?: unknown }).code === 'ENOENT'\n ) {\n throw new LlmError(\n 'claude CLI not found on PATH — install Claude Code and run `claude auth login`',\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (rawErr instanceof Error && rawErr.name === 'AbortError') {\n throw new LlmError(rawErr.message || 'claude-cli call aborted', {\n kind: 'aborted',\n retryable: false,\n provider: 'claude-cli',\n })\n }\n\n if (rawErr instanceof Error && rawErr.name === 'TimeoutError') {\n throw new LlmError(rawErr.message || 'claude-cli call timed out', {\n kind: 'timeout',\n retryable: true,\n provider: 'claude-cli',\n })\n }\n\n throw new LlmError(\n `claude-cli runner failed: ${rawErr instanceof Error ? rawErr.message : String(rawErr)}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli', cause: rawErr },\n )\n }\n release()\n await rm(cwd, { recursive: true, force: true })\n\n // ------------------------------------------------------------------\n // 5. Parse the envelope from stdout.\n // ------------------------------------------------------------------\n let envelope: ClaudeCliEnvelope | undefined\n try {\n envelope = JSON.parse(result.stdout) as ClaudeCliEnvelope\n } catch {\n envelope = undefined\n }\n\n if (\n result.exitCode !== 0 ||\n envelope?.is_error === true ||\n envelope === undefined\n ) {\n throw classifyRunFailure(envelope, result)\n }\n\n // ------------------------------------------------------------------\n // 6. Map result → AdapterResult.\n // ------------------------------------------------------------------\n const text = envelope.result ?? ''\n\n let rawStructured: unknown\n if (req.outputJsonSchema !== undefined) {\n try {\n rawStructured = JSON.parse(text)\n } catch {\n warnings.push({\n type: 'other',\n message: 'claude-cli: failed to parse structured output as JSON',\n })\n }\n }\n\n const usage = mapUsage(envelope.usage)\n const finishReason = mapFinishReason(envelope.stop_reason)\n\n const providerMetadata: Record<string, JsonValue> = {\n ...(envelope.total_cost_usd !== undefined\n ? { totalCostUsd: envelope.total_cost_usd }\n : {}),\n ...(envelope.session_id !== undefined ? { sessionId: envelope.session_id } : {}),\n ...(envelope.subtype !== undefined ? { subtype: envelope.subtype } : {}),\n ...(envelope.num_turns !== undefined ? { numTurns: envelope.num_turns } : {}),\n }\n\n const adapterResult: AdapterResult = {\n model,\n usage,\n warnings,\n ...(text.length > 0 ? { text } : {}),\n ...(rawStructured !== undefined ? { rawStructured } : {}),\n ...(finishReason !== undefined ? { finishReason } : {}),\n ...(Object.keys(providerMetadata).length > 0 ? { providerMetadata } : {}),\n }\n\n return adapterResult\n },\n }\n}\n","/**\n * Model config schemas + registry for @gullabs/claude-cli.\n *\n * DEVIATION FROM CONVENTION: `@gullabs/core`'s `packages/core/src/model-config/`\n * only carries config schemas for production API providers (Gemini/Gemma).\n * This dev-only CLI provider intentionally keeps its own model config schemas\n * and registry local to this package instead — core stays free of any\n * knowledge of the local-CLI dev workflow.\n *\n * @module\n */\n\nimport { z } from 'zod'\nimport type { ModelDescriptor, ModelRegistry } from '@gullabs/core'\nimport {\n createModelRegistry,\n toConfigJsonSchema,\n zodToStandardSchema,\n} from '@gullabs/core'\n\n// ---------------------------------------------------------------------------\n// Model ids\n// ---------------------------------------------------------------------------\n\n/** Every model id `@gullabs/claude-cli` knows how to route. */\nexport type ClaudeCliModelId =\n 'claude-fable-5' | 'claude-opus-4-8' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001'\n\nconst CLAUDE_CLI_MODEL_IDS: readonly ClaudeCliModelId[] = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-sonnet-5',\n 'claude-haiku-4-5-20251001',\n]\n\n/**\n * Reasoning effort levels admitted by the `claude` CLI's `--effort` flag.\n *\n * A strict superset of `@gullabs/core`'s `ReasoningEffort` union (which is\n * `'none' | 'low' | 'medium' | 'high' | 'xhigh'`) — `'max'` is the extra\n * value the CLI supports that core's engine-level type does not know about.\n * Because of this mismatch, `admittedReasoningEfforts` (typed\n * `ReadonlyArray<ReasoningEffort>` in `ModelDescriptor.capabilities`) is\n * intentionally OMITTED below rather than cast — this package's own zod\n * schema is the sole validator for `reasoning.effort`, so the field is\n * advisory-only and safe to skip.\n */\nconst CLAUDE_CLI_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\n\n/**\n * Build the strict per-model config schema for a `claude-cli` model.\n *\n * No `temperature`/`topP`/`topK`/`maxOutputTokens`/`stopSequences` fields —\n * the CLI does not support tuning any of these, and `z.strictObject` rejects\n * any unknown key outright (reject, don't map/clamp).\n */\nfunction buildClaudeCliConfigSchema(modelName: string): z.ZodType {\n return z\n .strictObject({\n reasoning: z\n .strictObject({\n effort: z.enum(CLAUDE_CLI_EFFORTS).meta({\n title: 'Reasoning Effort',\n description: `Reasoning effort forwarded to the claude CLI's --effort flag for ${modelName}.`,\n }),\n })\n .optional()\n .meta({\n title: 'Reasoning',\n description: `Reasoning configuration for ${modelName}.`,\n }),\n timeoutMs: z.number().int().positive().max(1_800_000).optional().meta({\n title: 'Timeout',\n description:\n 'Logical request timeout in milliseconds; forwarded to the CLI runner.',\n }),\n })\n .meta({\n title: `${modelName}Config`,\n description: `Strict claude-cli config for model ${modelName}. Text-only, no sampling knobs, effort-based reasoning.`,\n })\n}\n\nexport const ClaudeFable5ConfigSchema = buildClaudeCliConfigSchema('claude-fable-5')\nexport const ClaudeOpus48ConfigSchema = buildClaudeCliConfigSchema('claude-opus-4-8')\nexport const ClaudeSonnet5ConfigSchema = buildClaudeCliConfigSchema('claude-sonnet-5')\nexport const ClaudeHaiku45ConfigSchema = buildClaudeCliConfigSchema(\n 'claude-haiku-4-5-20251001',\n)\n\nconst CONFIG_SCHEMAS: Record<ClaudeCliModelId, z.ZodType> = {\n 'claude-fable-5': ClaudeFable5ConfigSchema,\n 'claude-opus-4-8': ClaudeOpus48ConfigSchema,\n 'claude-sonnet-5': ClaudeSonnet5ConfigSchema,\n 'claude-haiku-4-5-20251001': ClaudeHaiku45ConfigSchema,\n}\n\n// ---------------------------------------------------------------------------\n// Descriptors + registry\n// ---------------------------------------------------------------------------\n\nexport const claudeCliModelDescriptors: ModelDescriptor[] = CLAUDE_CLI_MODEL_IDS.map(\n (id): ModelDescriptor => {\n const configSchema = CONFIG_SCHEMAS[id]\n return {\n model: id,\n provider: 'claude-cli',\n capabilities: {\n structuredOutput: true,\n nativeStructuredOutput: true,\n reasoningApi: 'level',\n sampling: 'fixed',\n vision: false,\n },\n configSchema,\n configJsonSchema: toConfigJsonSchema(configSchema),\n validateConfig: zodToStandardSchema(configSchema),\n }\n },\n)\n\nexport const claudeCliRegistry: ModelRegistry = createModelRegistry(\n claudeCliModelDescriptors,\n)\n","/**\n * `claudeCliProvider` — {@link ProviderPlugin} factory for @gullabs/claude-cli.\n *\n * Bundles the dev-only Claude CLI adapter with its model descriptors. This\n * provider is unpriced by design (dev-only CLI, $0 API spend) — the returned\n * plugin has no `pricingSource`.\n *\n * @module\n */\n\nimport type { ProviderPlugin } from '@gullabs/core'\n\nimport { claudeCliAdapter } from './adapter.js'\nimport type { ClaudeCliAdapterOptions } from './adapter.js'\nimport { claudeCliModelDescriptors } from './models.js'\n\n/**\n * Create a {@link ProviderPlugin} for the dev-only Claude Code CLI provider.\n *\n * Unpriced by design: the returned plugin omits `pricingSource` entirely.\n *\n * @param opts - Forwarded to {@link claudeCliAdapter}.\n * @returns A plugin bundling the Claude CLI adapter and its model descriptors.\n *\n * @example\n * ```ts\n * import { createClient, composeProviders } from '@gullabs/core'\n * import { claudeCliProvider } from '@gullabs/claude-cli'\n *\n * const client = createClient({\n * ...composeProviders([claudeCliProvider()]),\n * })\n * ```\n */\nexport function claudeCliProvider(opts?: ClaudeCliAdapterOptions): ProviderPlugin {\n return {\n adapter: claudeCliAdapter(opts),\n modelDescriptors: claudeCliModelDescriptors,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/runner.ts","../src/adapter.ts","../src/models.ts","../src/provider.ts"],"names":["spawn","LlmError","mkdtemp","join","tmpdir","rm","z","toConfigJsonSchema","zodToStandardSchema","createModelRegistry"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * ClaudeCliRunner — the process-execution seam for @gullabs/claude-cli.\n *\n * Adapters depend on the {@link ClaudeCliRunner} interface only.\n * {@link buildClaudeCliRunner} is the sole factory that touches\n * `node:child_process`; committed tests inject a hand-written fake instead of\n * exercising it, so no real `claude` subprocess is ever spawned in CI.\n *\n * @module\n */\n\nimport { spawn } from 'node:child_process'\n\n/**\n * The result of a single `claude` CLI invocation.\n */\nexport interface ClaudeCliRunResult {\n stdout: string\n stderr: string\n exitCode: number | null\n}\n\n/**\n * Options accepted by {@link ClaudeCliRunner.run}.\n */\nexport interface ClaudeCliRunOptions {\n /** Working directory for the subprocess (the adapter owns tmpdir lifecycle). */\n cwd: string\n /** Kill the subprocess if it has not exited within this many milliseconds. */\n timeoutMs?: number\n /** Kill the subprocess if this signal fires. */\n signal?: AbortSignal\n}\n\n/**\n * The process-execution seam consumed by {@link claudeCliAdapter}.\n *\n * Implementations run the `claude` binary with `args`, write `input` to its\n * stdin (the rendered prompt), and resolve with captured stdout/stderr/exit\n * code. Implementations must never throw for a non-zero exit code — that is\n * the adapter's error-classification job; the one exception is a spawn-time\n * failure (e.g. `ENOENT` when the binary is missing), which should reject.\n */\nexport interface ClaudeCliRunner {\n run(\n args: string[],\n input: string,\n opts: ClaudeCliRunOptions,\n ): Promise<ClaudeCliRunResult>\n}\n\n/**\n * Build the real {@link ClaudeCliRunner}, backed by `node:child_process`.\n *\n * Never exercised by committed tests — only the real dev workflow invokes\n * this factory; tests inject a hand-written fake implementing\n * {@link ClaudeCliRunner} instead.\n *\n * @param claudePath - Path or bare command name for the `claude` binary.\n * Defaults to `'claude'`, resolved via `PATH`.\n */\nexport function buildClaudeCliRunner(claudePath = 'claude'): ClaudeCliRunner {\n return {\n run(args, input, opts) {\n return new Promise((resolve, reject) => {\n if (opts.signal?.aborted === true) {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n reject(err)\n return\n }\n\n // NOTE: the argv itself (including the `--safe-mode` vs `--bare`\n // choice) is owned by the adapter (see adapter.ts) — this runner is\n // a dumb pipe. We repeat the rule here only as a pointer: never pass\n // `--bare`, it disables OAuth/keychain auth.\n const child = spawn(claudePath, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n let settled = false\n // Set once a timeout/abort has begun killing the child. The\n // returned promise is NOT rejected with this until the child's\n // 'close' event actually fires — the caller (the adapter) must\n // never observe settlement while the OS process may still be\n // alive and writing to its scratch cwd.\n let pendingError: Error | undefined\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n let killTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n const cleanupTimers = (): void => {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (killTimeoutHandle !== undefined) clearTimeout(killTimeoutHandle)\n }\n\n const cleanup = (): void => {\n cleanupTimers()\n if (opts.signal !== undefined) {\n opts.signal.removeEventListener('abort', onAbort)\n }\n }\n\n const killChild = (): void => {\n child.kill('SIGTERM')\n killTimeoutHandle = setTimeout(() => {\n child.kill('SIGKILL')\n }, 5_000)\n }\n\n const beginReject = (err: Error): void => {\n if (settled || pendingError !== undefined) return\n pendingError = err\n cleanupTimers()\n killChild()\n }\n\n const onAbort = (): void => {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n beginReject(err)\n }\n\n // The pre-aborted case is handled above, before `spawn` — by this\n // point `opts.signal`, if present, is guaranteed not yet aborted.\n if (opts.signal !== undefined) {\n opts.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n if (opts.timeoutMs !== undefined) {\n timeoutHandle = setTimeout(() => {\n const err = new Error(`claude-cli call exceeded ${opts.timeoutMs}ms timeout`)\n err.name = 'TimeoutError'\n beginReject(err)\n }, opts.timeoutMs)\n }\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8')\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8')\n })\n\n child.once('error', (err) => {\n if (settled) return\n settled = true\n cleanup()\n reject(pendingError ?? err)\n })\n\n child.once('close', (exitCode) => {\n if (settled) return\n settled = true\n cleanup()\n if (pendingError !== undefined) {\n reject(pendingError)\n } else {\n resolve({ stdout, stderr, exitCode })\n }\n })\n\n child.stdin.end(input, 'utf8')\n })\n },\n }\n}\n","/**\n * claudeCliAdapter — @gullabs/claude-cli provider adapter.\n *\n * Pure request⇄response mapping over the locally-authenticated `claude`\n * (Claude Code) CLI, via {@link ClaudeCliRunner}. Never persists, never\n * computes cost, never retries, never reads `process.env`.\n *\n * DEV-ONLY: this adapter requires `ctx.auth = { cliSession: true }` — it\n * shells out to a `claude` binary that owns its own local login/session\n * state. It is never usable in a production/serverless environment because\n * there is no interactive CLI login there by construction.\n *\n * @module\n */\n\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport { LlmError } from '@gullabs/core'\nimport type {\n ProviderAdapter,\n ResolvedRequest,\n AdapterCtx,\n AdapterResult,\n Usage,\n Warning,\n FinishReason,\n JsonValue,\n Message,\n Part,\n} from '@gullabs/core'\nimport { buildClaudeCliRunner } from './runner.js'\nimport type { ClaudeCliRunner, ClaudeCliRunResult } from './runner.js'\n\n// ---------------------------------------------------------------------------\n// Captured CLI envelope shape (see repo notes for the two captured fixtures)\n// ---------------------------------------------------------------------------\n\n/**\n * The `usage` object nested inside the `claude -p --output-format json`\n * result envelope. Only the fields this adapter consumes are typed here;\n * the full object is preserved verbatim in `Usage.raw`.\n */\nexport interface ClaudeCliUsageShape {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n [key: string]: unknown\n}\n\n/**\n * The top-level JSON envelope emitted on stdout by\n * `claude -p ... --output-format json` on completion (success or error).\n */\nexport interface ClaudeCliEnvelope {\n type: string\n subtype?: string\n is_error?: boolean\n result?: string\n stop_reason?: string\n session_id?: string\n total_cost_usd?: number\n num_turns?: number\n usage?: ClaudeCliUsageShape\n [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Tiny in-file semaphore — adapter-internal concurrency control\n// ---------------------------------------------------------------------------\n\nclass Semaphore {\n private available: number\n private readonly queue: Array<() => void> = []\n\n constructor(max: number) {\n this.available = max\n }\n\n async acquire(): Promise<() => void> {\n if (this.available > 0) {\n this.available -= 1\n return () => {\n this.release()\n }\n }\n await new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n this.available -= 1\n return () => {\n this.release()\n }\n }\n\n private release(): void {\n this.available += 1\n const next = this.queue.shift()\n if (next !== undefined) next()\n }\n}\n\n// ---------------------------------------------------------------------------\n// FinishReason mapping\n// ---------------------------------------------------------------------------\n\nfunction mapFinishReason(stopReason: string | undefined): FinishReason | undefined {\n if (stopReason === undefined) return undefined\n switch (stopReason) {\n case 'end_turn':\n return 'stop'\n case 'tool_use':\n // The CLI's own final answer, not a caller-visible tool call — treat\n // as a successful completion for our purposes.\n return 'stop'\n default:\n return 'other'\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage mapping — GROSS convention\n//\n// `totalTokens` is not reported by the claude-cli usage payload — it is\n// derived as `inputTokens + outputTokens` whenever a usage payload was\n// present; left undefined when there was no usage payload at all.\n// ---------------------------------------------------------------------------\n\nfunction mapUsage(usage: ClaudeCliUsageShape | undefined): Usage {\n const inputTokens = usage?.input_tokens ?? 0\n const outputTokens = usage?.output_tokens ?? 0\n const cachedInputTokens = usage?.cache_read_input_tokens\n const totalTokens = usage !== undefined ? inputTokens + outputTokens : undefined\n\n const details: Record<string, number> = {\n input: inputTokens,\n output: outputTokens,\n ...(cachedInputTokens !== undefined ? { cached: cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { total: totalTokens } : {}),\n }\n\n const raw: JsonValue = usage !== undefined ? (usage as unknown as JsonValue) : null\n\n return {\n inputTokens,\n outputTokens,\n details,\n raw,\n ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { totalTokens } : {}),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt serialization\n// ---------------------------------------------------------------------------\n\nfunction partText(part: Part): string {\n if (part.kind !== 'text') {\n throw new LlmError(\n 'claude-cli is text-only; non-text message parts (inline media, file URIs, tool-call, tool-result) are not supported',\n {\n kind: 'bad_request',\n retryable: false,\n provider: 'claude-cli',\n },\n )\n }\n return part.text\n}\n\nfunction messageText(msg: Message): string {\n return msg.parts.map(partText).join('')\n}\n\n/**\n * Serialize `req.messages` into the single string sent to the CLI over\n * stdin.\n *\n * - Single user message, single text part → the text verbatim.\n * - Otherwise → a role-labelled transcript, blocks separated by a blank line.\n */\nfunction buildPrompt(messages: Message[]): string {\n if (messages.length === 1 && messages[0]?.parts.length === 1) {\n return partText(messages[0].parts[0] as Part)\n }\n\n return messages\n .map((msg) => {\n const label = msg.role === 'assistant' ? 'Assistant' : 'User'\n return `${label}:\\n${messageText(msg)}`\n })\n .join('\\n\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Error classification\n// ---------------------------------------------------------------------------\n\nfunction looksAuthy(text: string): boolean {\n return /login|auth|unauthorized/i.test(text)\n}\n\nfunction looksRateLimited(text: string): boolean {\n return /rate limit|429/i.test(text)\n}\n\nfunction classifyRunFailure(\n envelope: ClaudeCliEnvelope | undefined,\n result: ClaudeCliRunResult,\n): LlmError {\n const combinedText = `${envelope?.subtype ?? ''} ${result.stderr}`\n\n if (looksAuthy(combinedText)) {\n return new LlmError(\n `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (looksRateLimited(combinedText)) {\n return new LlmError(\n `claude CLI reported rate limiting: ${result.stderr.slice(-500)}`,\n {\n kind: 'rate_limited',\n retryable: true,\n provider: 'claude-cli',\n },\n )\n }\n\n if (envelope?.is_error === true) {\n return new LlmError(\n `claude CLI reported an error (subtype: ${envelope.subtype ?? 'unknown'}): ${result.stderr.slice(-500)}`,\n { kind: 'server', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const stderrTail = result.stderr.slice(-500)\n return new LlmError(\n `claude CLI exited with code ${String(result.exitCode)}: ${stderrTail}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n}\n\n// ---------------------------------------------------------------------------\n// Adapter options\n// ---------------------------------------------------------------------------\n\nexport interface ClaudeCliAdapterOptions {\n /** Inject a runner (real or fake). Defaults to `buildClaudeCliRunner()`. */\n runner?: ClaudeCliRunner\n /** Path or bare command name for the `claude` binary. Defaults to `'claude'`. */\n claudePath?: string\n /** Max concurrent CLI invocations. Defaults to `2`. */\n maxConcurrency?: number\n}\n\n// ---------------------------------------------------------------------------\n// claudeCliAdapter factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a dev-only Claude Code CLI provider adapter.\n *\n * Requires `ctx.auth = { cliSession: true }` — see module docs.\n */\nexport function claudeCliAdapter(opts?: ClaudeCliAdapterOptions): ProviderAdapter {\n // Constructed eagerly but never invoked unless `opts.runner` is absent —\n // `buildClaudeCliRunner` only closes over `node:child_process`, it does not\n // spawn anything until `.run()` is called.\n const runner: ClaudeCliRunner = opts?.runner ?? buildClaudeCliRunner(opts?.claudePath)\n\n const semaphore = new Semaphore(opts?.maxConcurrency ?? 2)\n\n return {\n id: 'claude-cli',\n\n async run(req: ResolvedRequest, ctx: AdapterCtx): Promise<AdapterResult> {\n // ------------------------------------------------------------------\n // 1. Auth — CliSessionAuth only.\n // ------------------------------------------------------------------\n const hasCliSession = 'cliSession' in ctx.auth && ctx.auth.cliSession\n if (!hasCliSession) {\n throw new LlmError(\n '@gullabs/claude-cli requires auth: { cliSession: true } — these dev-only providers route through a locally-authenticated `claude` CLI session, not an API key',\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (req.provider !== 'claude-cli') {\n throw new LlmError(\n `@gullabs/claude-cli received a request routed for provider \"${req.provider}\" — this adapter only serves \"claude-cli\"`,\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n if (req.tools !== undefined && req.tools.length > 0) {\n throw new LlmError(\n 'claude-cli does not support LlmRequest.tools; CLI runtimes are out of the function-calling seam.',\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const warnings: Warning[] = []\n const model = req.model\n const config = req.config\n\n // ------------------------------------------------------------------\n // 2. Prompt serialization (throws bad_request on non-text parts).\n // ------------------------------------------------------------------\n const prompt = buildPrompt(req.messages)\n\n // ------------------------------------------------------------------\n // 3. Invariant argv — adapter-owned, never caller-configurable.\n //\n // We use --safe-mode, NEVER --bare: --bare disables OAuth/keychain\n // auth and would break subscription-based Claude Code auth — the\n // exact mechanism that lets these dev-only providers work with zero\n // API-key configuration at all.\n // ------------------------------------------------------------------\n const args: string[] = [\n '-p',\n '--output-format',\n 'json',\n '--safe-mode',\n '--tools',\n '',\n '--disable-slash-commands',\n '--no-session-persistence',\n ]\n\n args.push('--model', model)\n\n const effort = config.reasoning?.effort\n if (effort !== undefined) {\n // `effort` was already validated against this package's own zod\n // schema at the config layer before the engine called us — forward\n // verbatim, no re-validation, no `any` cast.\n args.push('--effort', String(effort))\n }\n\n if (req.system !== undefined) {\n args.push('--system-prompt', req.system)\n }\n\n if (req.outputJsonSchema !== undefined) {\n args.push('--json-schema', JSON.stringify(req.outputJsonSchema))\n }\n\n // ------------------------------------------------------------------\n // 4. Timeout + scratch dir + runner invocation.\n // ------------------------------------------------------------------\n const timeoutMs = req.attemptTimeoutMs ?? config.timeoutMs\n\n // The runner owns timeout/abort enforcement end-to-end: it only\n // settles (resolve OR reject) once the child process has actually\n // exited (its 'close' event fired). We deliberately do NOT race an\n // independent timer against `runner.run(...)` here — doing so could\n // let this adapter move on (and release the semaphore / rm the\n // scratch dir) while the real OS child process is still alive and\n // possibly still writing into `cwd`. We simply await the runner\n // promise and classify whatever it settles with.\n const cwd = await mkdtemp(join(tmpdir(), 'claude-cli-'))\n const release = await semaphore.acquire()\n let result: ClaudeCliRunResult\n try {\n result = await runner.run(args, prompt, {\n cwd,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}),\n })\n } catch (rawErr) {\n release()\n await rm(cwd, { recursive: true, force: true })\n\n if (rawErr instanceof LlmError) throw rawErr\n\n if (\n typeof rawErr === 'object' &&\n rawErr !== null &&\n 'code' in rawErr &&\n (rawErr as { code?: unknown }).code === 'ENOENT'\n ) {\n throw new LlmError(\n 'claude CLI not found on PATH — install Claude Code and run `claude auth login`',\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (rawErr instanceof Error && rawErr.name === 'AbortError') {\n throw new LlmError(rawErr.message || 'claude-cli call aborted', {\n kind: 'aborted',\n retryable: false,\n provider: 'claude-cli',\n })\n }\n\n if (rawErr instanceof Error && rawErr.name === 'TimeoutError') {\n throw new LlmError(rawErr.message || 'claude-cli call timed out', {\n kind: 'timeout',\n retryable: true,\n provider: 'claude-cli',\n })\n }\n\n throw new LlmError(\n `claude-cli runner failed: ${rawErr instanceof Error ? rawErr.message : String(rawErr)}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli', cause: rawErr },\n )\n }\n release()\n await rm(cwd, { recursive: true, force: true })\n\n // ------------------------------------------------------------------\n // 5. Parse the envelope from stdout.\n // ------------------------------------------------------------------\n let envelope: ClaudeCliEnvelope | undefined\n try {\n envelope = JSON.parse(result.stdout) as ClaudeCliEnvelope\n } catch {\n envelope = undefined\n }\n\n if (\n result.exitCode !== 0 ||\n envelope?.is_error === true ||\n envelope === undefined\n ) {\n throw classifyRunFailure(envelope, result)\n }\n\n // ------------------------------------------------------------------\n // 6. Map result → AdapterResult.\n // ------------------------------------------------------------------\n const text = envelope.result ?? ''\n\n let rawStructured: unknown\n if (req.outputJsonSchema !== undefined) {\n try {\n rawStructured = JSON.parse(text)\n } catch {\n warnings.push({\n type: 'other',\n message: 'claude-cli: failed to parse structured output as JSON',\n })\n }\n }\n\n const usage = mapUsage(envelope.usage)\n const finishReason = mapFinishReason(envelope.stop_reason)\n\n const providerMetadata: Record<string, JsonValue> = {\n ...(envelope.total_cost_usd !== undefined\n ? { totalCostUsd: envelope.total_cost_usd }\n : {}),\n ...(envelope.session_id !== undefined ? { sessionId: envelope.session_id } : {}),\n ...(envelope.subtype !== undefined ? { subtype: envelope.subtype } : {}),\n ...(envelope.num_turns !== undefined ? { numTurns: envelope.num_turns } : {}),\n }\n\n const adapterResult: AdapterResult = {\n model,\n usage,\n warnings,\n ...(text.length > 0 ? { text } : {}),\n ...(rawStructured !== undefined ? { rawStructured } : {}),\n ...(finishReason !== undefined ? { finishReason } : {}),\n ...(Object.keys(providerMetadata).length > 0 ? { providerMetadata } : {}),\n }\n\n return adapterResult\n },\n }\n}\n","/**\n * Model config schemas + registry for @gullabs/claude-cli.\n *\n * DEVIATION FROM CONVENTION: `@gullabs/core`'s `packages/core/src/model-config/`\n * only carries config schemas for production API providers (Gemini/Gemma).\n * This dev-only CLI provider intentionally keeps its own model config schemas\n * and registry local to this package instead — core stays free of any\n * knowledge of the local-CLI dev workflow.\n *\n * @module\n */\n\nimport { z } from 'zod'\nimport type { ModelDescriptor, ModelRegistry } from '@gullabs/core'\nimport {\n createModelRegistry,\n toConfigJsonSchema,\n zodToStandardSchema,\n} from '@gullabs/core'\n\n// ---------------------------------------------------------------------------\n// Model ids\n// ---------------------------------------------------------------------------\n\n/** Every model id `@gullabs/claude-cli` knows how to route. */\nexport type ClaudeCliModelId =\n 'claude-fable-5' | 'claude-opus-4-8' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001'\n\nconst CLAUDE_CLI_MODEL_IDS: readonly ClaudeCliModelId[] = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-sonnet-5',\n 'claude-haiku-4-5-20251001',\n]\n\n/**\n * Reasoning effort levels admitted by the `claude` CLI's `--effort` flag.\n *\n * A strict superset of `@gullabs/core`'s `ReasoningEffort` union (which is\n * `'none' | 'low' | 'medium' | 'high' | 'xhigh'`) — `'max'` is the extra\n * value the CLI supports that core's engine-level type does not know about.\n * Because of this mismatch, `admittedReasoningEfforts` (typed\n * `ReadonlyArray<ReasoningEffort>` in `ModelDescriptor.capabilities`) is\n * intentionally OMITTED below rather than cast — this package's own zod\n * schema is the sole validator for `reasoning.effort`, so the field is\n * advisory-only and safe to skip.\n */\nconst CLAUDE_CLI_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\n\n/**\n * Build the strict per-model config schema for a `claude-cli` model.\n *\n * No `temperature`/`topP`/`topK`/`maxOutputTokens`/`stopSequences` fields —\n * the CLI does not support tuning any of these, and `z.strictObject` rejects\n * any unknown key outright (reject, don't map/clamp).\n */\nfunction buildClaudeCliConfigSchema(modelName: string): z.ZodType {\n return z\n .strictObject({\n reasoning: z\n .strictObject({\n effort: z.enum(CLAUDE_CLI_EFFORTS).meta({\n title: 'Reasoning Effort',\n description: `Reasoning effort forwarded to the claude CLI's --effort flag for ${modelName}.`,\n }),\n })\n .optional()\n .meta({\n title: 'Reasoning',\n description: `Reasoning configuration for ${modelName}.`,\n }),\n timeoutMs: z.number().int().positive().max(1_800_000).optional().meta({\n title: 'Timeout',\n description:\n 'Logical request timeout in milliseconds; forwarded to the CLI runner.',\n }),\n })\n .meta({\n title: `${modelName}Config`,\n description: `Strict claude-cli config for model ${modelName}. Text-only, no sampling knobs, effort-based reasoning.`,\n })\n}\n\nexport const ClaudeFable5ConfigSchema = buildClaudeCliConfigSchema('claude-fable-5')\nexport const ClaudeOpus48ConfigSchema = buildClaudeCliConfigSchema('claude-opus-4-8')\nexport const ClaudeSonnet5ConfigSchema = buildClaudeCliConfigSchema('claude-sonnet-5')\nexport const ClaudeHaiku45ConfigSchema = buildClaudeCliConfigSchema(\n 'claude-haiku-4-5-20251001',\n)\n\nconst CONFIG_SCHEMAS: Record<ClaudeCliModelId, z.ZodType> = {\n 'claude-fable-5': ClaudeFable5ConfigSchema,\n 'claude-opus-4-8': ClaudeOpus48ConfigSchema,\n 'claude-sonnet-5': ClaudeSonnet5ConfigSchema,\n 'claude-haiku-4-5-20251001': ClaudeHaiku45ConfigSchema,\n}\n\n// ---------------------------------------------------------------------------\n// Descriptors + registry\n// ---------------------------------------------------------------------------\n\nexport const claudeCliModelDescriptors: ModelDescriptor[] = CLAUDE_CLI_MODEL_IDS.map(\n (id): ModelDescriptor => {\n const configSchema = CONFIG_SCHEMAS[id]\n return {\n model: id,\n provider: 'claude-cli',\n capabilities: {\n structuredOutput: true,\n nativeStructuredOutput: true,\n reasoningApi: 'level',\n sampling: 'fixed',\n vision: false,\n },\n configSchema,\n configJsonSchema: toConfigJsonSchema(configSchema),\n validateConfig: zodToStandardSchema(configSchema),\n }\n },\n)\n\nexport const claudeCliRegistry: ModelRegistry = createModelRegistry(\n claudeCliModelDescriptors,\n)\n","/**\n * `claudeCliProvider` — {@link ProviderPlugin} factory for @gullabs/claude-cli.\n *\n * Bundles the dev-only Claude CLI adapter with its model descriptors. This\n * provider is unpriced by design (dev-only CLI, $0 API spend) — the returned\n * plugin has no `pricingSource`.\n *\n * @module\n */\n\nimport type { ProviderPlugin } from '@gullabs/core'\n\nimport { claudeCliAdapter } from './adapter.js'\nimport type { ClaudeCliAdapterOptions } from './adapter.js'\nimport { claudeCliModelDescriptors } from './models.js'\n\n/**\n * Create a {@link ProviderPlugin} for the dev-only Claude Code CLI provider.\n *\n * Unpriced by design: the returned plugin omits `pricingSource` entirely.\n *\n * @param opts - Forwarded to {@link claudeCliAdapter}.\n * @returns A plugin bundling the Claude CLI adapter and its model descriptors.\n *\n * @example\n * ```ts\n * import { createClient, composeProviders } from '@gullabs/core'\n * import { claudeCliProvider } from '@gullabs/claude-cli'\n *\n * const client = createClient({\n * ...composeProviders([claudeCliProvider()]),\n * })\n * ```\n */\nexport function claudeCliProvider(opts?: ClaudeCliAdapterOptions): ProviderPlugin {\n return {\n adapter: claudeCliAdapter(opts),\n modelDescriptors: claudeCliModelDescriptors,\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -154,7 +154,7 @@ function mapUsage(usage) {
|
|
|
154
154
|
function partText(part) {
|
|
155
155
|
if (part.kind !== "text") {
|
|
156
156
|
throw new LlmError(
|
|
157
|
-
"claude-cli is text-only; non-text message parts are not supported",
|
|
157
|
+
"claude-cli is text-only; non-text message parts (inline media, file URIs, tool-call, tool-result) are not supported",
|
|
158
158
|
{
|
|
159
159
|
kind: "bad_request",
|
|
160
160
|
retryable: false,
|
|
@@ -232,6 +232,12 @@ function claudeCliAdapter(opts) {
|
|
|
232
232
|
{ kind: "bad_request", retryable: false, provider: "claude-cli" }
|
|
233
233
|
);
|
|
234
234
|
}
|
|
235
|
+
if (req.tools !== void 0 && req.tools.length > 0) {
|
|
236
|
+
throw new LlmError(
|
|
237
|
+
"claude-cli does not support LlmRequest.tools; CLI runtimes are out of the function-calling seam.",
|
|
238
|
+
{ kind: "bad_request", retryable: false, provider: "claude-cli" }
|
|
239
|
+
);
|
|
240
|
+
}
|
|
235
241
|
const warnings = [];
|
|
236
242
|
const model = req.model;
|
|
237
243
|
const config = req.config;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runner.ts","../src/adapter.ts","../src/models.ts","../src/provider.ts"],"names":[],"mappings":";;;;;;;;AA6DO,SAAS,oBAAA,CAAqB,aAAa,QAAA,EAA2B;AAC3E,EAAA,OAAO;AAAA,IACL,GAAA,CAAI,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM;AACrB,MAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,QAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,OAAA,KAAY,IAAA,EAAM;AACjC,UAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,yBAAyB,CAAA;AAC/C,UAAA,GAAA,CAAI,IAAA,GAAO,YAAA;AACX,UAAA,MAAA,CAAO,GAAG,CAAA;AACV,UAAA;AAAA,QACF;AAMA,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,UAAA,EAAY,IAAA,EAAM;AAAA,UACpC,KAAK,IAAA,CAAK,GAAA;AAAA,UACV,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,SAC/B,CAAA;AAED,QAAA,IAAI,MAAA,GAAS,EAAA;AACb,QAAA,IAAI,MAAA,GAAS,EAAA;AACb,QAAA,IAAI,OAAA,GAAU,KAAA;AAMd,QAAA,IAAI,YAAA;AACJ,QAAA,IAAI,aAAA;AACJ,QAAA,IAAI,iBAAA;AAEJ,QAAA,MAAM,gBAAgB,MAAY;AAChC,UAAA,IAAI,aAAA,KAAkB,MAAA,EAAW,YAAA,CAAa,aAAa,CAAA;AAC3D,UAAA,IAAI,iBAAA,KAAsB,MAAA,EAAW,YAAA,CAAa,iBAAiB,CAAA;AAAA,QACrE,CAAA;AAEA,QAAA,MAAM,UAAU,MAAY;AAC1B,UAAA,aAAA,EAAc;AACd,UAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,YAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AAAA,UAClD;AAAA,QACF,CAAA;AAEA,QAAA,MAAM,YAAY,MAAY;AAC5B,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,UAAA,iBAAA,GAAoB,WAAW,MAAM;AACnC,YAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UACtB,GAAG,GAAK,CAAA;AAAA,QACV,CAAA;AAEA,QAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAAqB;AACxC,UAAA,IAAI,OAAA,IAAW,iBAAiB,MAAA,EAAW;AAC3C,UAAA,YAAA,GAAe,GAAA;AACf,UAAA,aAAA,EAAc;AACd,UAAA,SAAA,EAAU;AAAA,QACZ,CAAA;AAEA,QAAA,MAAM,UAAU,MAAY;AAC1B,UAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,yBAAyB,CAAA;AAC/C,UAAA,GAAA,CAAI,IAAA,GAAO,YAAA;AACX,UAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QACjB,CAAA;AAIA,QAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,UAAA,IAAA,CAAK,OAAO,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,QAC/D;AAEA,QAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,UAAA,aAAA,GAAgB,WAAW,MAAM;AAC/B,YAAA,MAAM,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAA,CAAK,SAAS,CAAA,UAAA,CAAY,CAAA;AAC5E,YAAA,GAAA,CAAI,IAAA,GAAO,cAAA;AACX,YAAA,WAAA,CAAY,GAAG,CAAA;AAAA,UACjB,CAAA,EAAG,KAAK,SAAS,CAAA;AAAA,QACnB;AAEA,QAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AACzC,UAAA,MAAA,IAAU,KAAA,CAAM,SAAS,MAAM,CAAA;AAAA,QACjC,CAAC,CAAA;AACD,QAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AACzC,UAAA,MAAA,IAAU,KAAA,CAAM,SAAS,MAAM,CAAA;AAAA,QACjC,CAAC,CAAA;AAED,QAAA,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAC,GAAA,KAAQ;AAC3B,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,OAAA,EAAQ;AACR,UAAA,MAAA,CAAO,gBAAgB,GAAG,CAAA;AAAA,QAC5B,CAAC,CAAA;AAED,QAAA,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAC,QAAA,KAAa;AAChC,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,OAAA,EAAQ;AACR,UAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,YAAA,MAAA,CAAO,YAAY,CAAA;AAAA,UACrB,CAAA,MAAO;AACL,YAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,CAAA;AAAA,UACtC;AAAA,QACF,CAAC,CAAA;AAED,QAAA,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA;AAAA,MAC/B,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;AC/FA,IAAM,YAAN,MAAgB;AAAA,EACN,SAAA;AAAA,EACS,QAA2B,EAAC;AAAA,EAE7C,YAAY,GAAA,EAAa;AACvB,IAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AAAA,EACnB;AAAA,EAEA,MAAM,OAAA,GAA+B;AACnC,IAAA,IAAI,IAAA,CAAK,YAAY,CAAA,EAAG;AACtB,MAAA,IAAA,CAAK,SAAA,IAAa,CAAA;AAClB,MAAA,OAAO,MAAM;AACX,QAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,MACf,CAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,IAAA,CAAK,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,IACzB,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,IAAa,CAAA;AAClB,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf,CAAA;AAAA,EACF;AAAA,EAEQ,OAAA,GAAgB;AACtB,IAAA,IAAA,CAAK,SAAA,IAAa,CAAA;AAClB,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC9B,IAAA,IAAI,IAAA,KAAS,QAAW,IAAA,EAAK;AAAA,EAC/B;AACF,CAAA;AAMA,SAAS,gBAAgB,UAAA,EAA0D;AACjF,EAAA,IAAI,UAAA,KAAe,QAAW,OAAO,MAAA;AACrC,EAAA,QAAQ,UAAA;AAAY,IAClB,KAAK,UAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,UAAA;AAGH,MAAA,OAAO,MAAA;AAAA,IACT;AACE,MAAA,OAAO,OAAA;AAAA;AAEb;AAUA,SAAS,SAAS,KAAA,EAA+C;AAC/D,EAAA,MAAM,WAAA,GAAc,OAAO,YAAA,IAAgB,CAAA;AAC3C,EAAA,MAAM,YAAA,GAAe,OAAO,aAAA,IAAiB,CAAA;AAC7C,EAAA,MAAM,oBAAoB,KAAA,EAAO,uBAAA;AACjC,EAAA,MAAM,WAAA,GAAc,KAAA,KAAU,MAAA,GAAY,WAAA,GAAc,YAAA,GAAe,MAAA;AAEvE,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,KAAA,EAAO,WAAA;AAAA,IACP,MAAA,EAAQ,YAAA;AAAA,IACR,GAAI,iBAAA,KAAsB,MAAA,GAAY,EAAE,MAAA,EAAQ,iBAAA,KAAsB,EAAC;AAAA,IACvE,GAAI,WAAA,KAAgB,MAAA,GAAY,EAAE,KAAA,EAAO,WAAA,KAAgB;AAAC,GAC5D;AAEA,EAAA,MAAM,GAAA,GAAiB,KAAA,KAAU,MAAA,GAAa,KAAA,GAAiC,IAAA;AAE/E,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAA;AAAA,IACA,GAAI,iBAAA,KAAsB,MAAA,GAAY,EAAE,iBAAA,KAAsB,EAAC;AAAA,IAC/D,GAAI,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,KAAgB;AAAC,GACrD;AACF;AAMA,SAAS,SAAS,IAAA,EAAoB;AACpC,EAAA,IAAI,IAAA,CAAK,SAAS,MAAA,EAAQ;AACxB,IAAA,MAAM,IAAI,QAAA;AAAA,MACR,mEAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,SAAA,EAAW,KAAA;AAAA,QACX,QAAA,EAAU;AAAA;AACZ,KACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA,CAAK,IAAA;AACd;AAEA,SAAS,YAAY,GAAA,EAAsB;AACzC,EAAA,OAAO,IAAI,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA,CAAE,KAAK,EAAE,CAAA;AACxC;AASA,SAAS,YAAY,QAAA,EAA6B;AAChD,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,IAAK,QAAA,CAAS,CAAC,CAAA,EAAG,KAAA,CAAM,WAAW,CAAA,EAAG;AAC5D,IAAA,OAAO,SAAS,QAAA,CAAS,CAAC,CAAA,CAAE,KAAA,CAAM,CAAC,CAAS,CAAA;AAAA,EAC9C;AAEA,EAAA,OAAO,QAAA,CACJ,GAAA,CAAI,CAAC,GAAA,KAAQ;AACZ,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,IAAA,KAAS,WAAA,GAAc,WAAA,GAAc,MAAA;AACvD,IAAA,OAAO,GAAG,KAAK,CAAA;AAAA,EAAM,WAAA,CAAY,GAAG,CAAC,CAAA,CAAA;AAAA,EACvC,CAAC,CAAA,CACA,IAAA,CAAK,MAAM,CAAA;AAChB;AAMA,SAAS,WAAW,IAAA,EAAuB;AACzC,EAAA,OAAO,0BAAA,CAA2B,KAAK,IAAI,CAAA;AAC7C;AAEA,SAAS,iBAAiB,IAAA,EAAuB;AAC/C,EAAA,OAAO,iBAAA,CAAkB,KAAK,IAAI,CAAA;AACpC;AAEA,SAAS,kBAAA,CACP,UACA,MAAA,EACU;AACV,EAAA,MAAM,eAAe,CAAA,EAAG,QAAA,EAAU,WAAW,EAAE,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,CAAA;AAEhE,EAAA,IAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,CAAA,+CAAA,EAAkD,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,MAC3E,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,KACnE;AAAA,EACF;AAEA,EAAA,IAAI,gBAAA,CAAiB,YAAY,CAAA,EAAG;AAClC,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,CAAA,mCAAA,EAAsC,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,MAC/D;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,SAAA,EAAW,IAAA;AAAA,QACX,QAAA,EAAU;AAAA;AACZ,KACF;AAAA,EACF;AAEA,EAAA,IAAI,QAAA,EAAU,aAAa,IAAA,EAAM;AAC/B,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,CAAA,uCAAA,EAA0C,SAAS,OAAA,IAAW,SAAS,MAAM,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,MACtG,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,KAC7D;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC3C,EAAA,OAAO,IAAI,QAAA;AAAA,IACT,+BAA+B,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,KAAK,UAAU,CAAA,CAAA;AAAA,IACrE,EAAE,IAAA,EAAM,SAAA,EAAW,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,GAC9D;AACF;AAwBO,SAAS,iBAAiB,IAAA,EAAiD;AAIhF,EAAA,MAAM,MAAA,GAA0B,IAAA,EAAM,MAAA,IAAU,oBAAA,CAAqB,MAAM,UAAU,CAAA;AAErF,EAAA,MAAM,SAAA,GAAY,IAAI,SAAA,CAAU,IAAA,EAAM,kBAAkB,CAAC,CAAA;AAEzD,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,YAAA;AAAA,IAEJ,MAAM,GAAA,CAAI,GAAA,EAAsB,GAAA,EAAyC;AAIvE,MAAA,MAAM,aAAA,GAAgB,YAAA,IAAgB,GAAA,CAAI,IAAA,IAAQ,IAAI,IAAA,CAAK,UAAA;AAC3D,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,MAAM,IAAI,QAAA;AAAA,UACR,oKAAA;AAAA,UACA,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,SACnE;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,aAAa,YAAA,EAAc;AACjC,QAAA,MAAM,IAAI,QAAA;AAAA,UACR,CAAA,4DAAA,EAA+D,IAAI,QAAQ,CAAA,8CAAA,CAAA;AAAA,UAC3E,EAAE,IAAA,EAAM,aAAA,EAAe,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,SAClE;AAAA,MACF;AAEA,MAAA,MAAM,WAAsB,EAAC;AAC7B,MAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,MAAA,MAAM,SAAS,GAAA,CAAI,MAAA;AAKnB,MAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AAUvC,MAAA,MAAM,IAAA,GAAiB;AAAA,QACrB,IAAA;AAAA,QACA,iBAAA;AAAA,QACA,MAAA;AAAA,QACA,aAAA;AAAA,QACA,SAAA;AAAA,QACA,EAAA;AAAA,QACA,0BAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,IAAA,CAAK,IAAA,CAAK,WAAW,KAAK,CAAA;AAE1B,MAAA,MAAM,MAAA,GAAS,OAAO,SAAA,EAAW,MAAA;AACjC,MAAA,IAAI,WAAW,MAAA,EAAW;AAIxB,QAAA,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,MACtC;AAEA,MAAA,IAAI,GAAA,CAAI,WAAW,MAAA,EAAW;AAC5B,QAAA,IAAA,CAAK,IAAA,CAAK,iBAAA,EAAmB,GAAA,CAAI,MAAM,CAAA;AAAA,MACzC;AAEA,MAAA,IAAI,GAAA,CAAI,qBAAqB,MAAA,EAAW;AACtC,QAAA,IAAA,CAAK,KAAK,eAAA,EAAiB,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,gBAAgB,CAAC,CAAA;AAAA,MACjE;AAKA,MAAA,MAAM,SAAA,GAAY,GAAA,CAAI,gBAAA,IAAoB,MAAA,CAAO,SAAA;AAUjD,MAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,KAAK,MAAA,EAAO,EAAG,aAAa,CAAC,CAAA;AACvD,MAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,OAAA,EAAQ;AACxC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,MAAA,CAAO,GAAA,CAAI,IAAA,EAAM,MAAA,EAAQ;AAAA,UACtC,GAAA;AAAA,UACA,GAAI,SAAA,KAAc,KAAA,CAAA,GAAY,EAAE,SAAA,KAAc,EAAC;AAAA,UAC/C,GAAI,IAAI,MAAA,KAAW,KAAA,CAAA,GAAY,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAO,GAAI;AAAC,SAC1D,CAAA;AAAA,MACH,SAAS,MAAA,EAAQ;AACf,QAAA,OAAA,EAAQ;AACR,QAAA,MAAM,GAAG,GAAA,EAAK,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAE9C,QAAA,IAAI,MAAA,YAAkB,UAAU,MAAM,MAAA;AAEtC,QAAA,IACE,OAAO,WAAW,QAAA,IAClB,MAAA,KAAW,QACX,MAAA,IAAU,MAAA,IACT,MAAA,CAA8B,IAAA,KAAS,QAAA,EACxC;AACA,UAAA,MAAM,IAAI,QAAA;AAAA,YACR,qFAAA;AAAA,YACA,EAAE,IAAA,EAAM,SAAA,EAAW,SAAA,EAAW,KAAA,EAAO,UAAU,YAAA;AAAa,WAC9D;AAAA,QACF;AAEA,QAAA,IAAI,MAAA,YAAkB,KAAA,IAAS,MAAA,CAAO,IAAA,KAAS,YAAA,EAAc;AAC3D,UAAA,MAAM,IAAI,QAAA,CAAS,MAAA,CAAO,OAAA,IAAW,yBAAA,EAA2B;AAAA,YAC9D,IAAA,EAAM,SAAA;AAAA,YACN,SAAA,EAAW,KAAA;AAAA,YACX,QAAA,EAAU;AAAA,WACX,CAAA;AAAA,QACH;AAEA,QAAA,IAAI,MAAA,YAAkB,KAAA,IAAS,MAAA,CAAO,IAAA,KAAS,cAAA,EAAgB;AAC7D,UAAA,MAAM,IAAI,QAAA,CAAS,MAAA,CAAO,OAAA,IAAW,2BAAA,EAA6B;AAAA,YAChE,IAAA,EAAM,SAAA;AAAA,YACN,SAAA,EAAW,IAAA;AAAA,YACX,QAAA,EAAU;AAAA,WACX,CAAA;AAAA,QACH;AAEA,QAAA,MAAM,IAAI,QAAA;AAAA,UACR,6BAA6B,MAAA,YAAkB,KAAA,GAAQ,OAAO,OAAA,GAAU,MAAA,CAAO,MAAM,CAAC,CAAA,CAAA;AAAA,UACtF,EAAE,MAAM,SAAA,EAAW,SAAA,EAAW,OAAO,QAAA,EAAU,YAAA,EAAc,OAAO,MAAA;AAAO,SAC7E;AAAA,MACF;AACA,MAAA,OAAA,EAAQ;AACR,MAAA,MAAM,GAAG,GAAA,EAAK,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAK9C,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA;AAAA,MACrC,CAAA,CAAA,MAAQ;AACN,QAAA,QAAA,GAAW,MAAA;AAAA,MACb;AAEA,MAAA,IACE,OAAO,QAAA,KAAa,CAAA,IACpB,UAAU,QAAA,KAAa,IAAA,IACvB,aAAa,MAAA,EACb;AACA,QAAA,MAAM,kBAAA,CAAmB,UAAU,MAAM,CAAA;AAAA,MAC3C;AAKA,MAAA,MAAM,IAAA,GAAO,SAAS,MAAA,IAAU,EAAA;AAEhC,MAAA,IAAI,aAAA;AACJ,MAAA,IAAI,GAAA,CAAI,qBAAqB,MAAA,EAAW;AACtC,QAAA,IAAI;AACF,UAAA,aAAA,GAAgB,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,QACjC,CAAA,CAAA,MAAQ;AACN,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,IAAA,EAAM,OAAA;AAAA,YACN,OAAA,EAAS;AAAA,WACV,CAAA;AAAA,QACH;AAAA,MACF;AAEA,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA;AACrC,MAAA,MAAM,YAAA,GAAe,eAAA,CAAgB,QAAA,CAAS,WAAW,CAAA;AAEzD,MAAA,MAAM,gBAAA,GAA8C;AAAA,QAClD,GAAI,SAAS,cAAA,KAAmB,MAAA,GAC5B,EAAE,YAAA,EAAc,QAAA,CAAS,cAAA,EAAe,GACxC,EAAC;AAAA,QACL,GAAI,SAAS,UAAA,KAAe,MAAA,GAAY,EAAE,SAAA,EAAW,QAAA,CAAS,UAAA,EAAW,GAAI,EAAC;AAAA,QAC9E,GAAI,SAAS,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,QAAA,CAAS,OAAA,EAAQ,GAAI,EAAC;AAAA,QACtE,GAAI,SAAS,SAAA,KAAc,MAAA,GAAY,EAAE,QAAA,EAAU,QAAA,CAAS,SAAA,EAAU,GAAI;AAAC,OAC7E;AAEA,MAAA,MAAM,aAAA,GAA+B;AAAA,QACnC,KAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAI,IAAA,CAAK,MAAA,GAAS,IAAI,EAAE,IAAA,KAAS,EAAC;AAAA,QAClC,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB,EAAC;AAAA,QACvD,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB,EAAC;AAAA,QACrD,GAAI,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,SAAS,CAAA,GAAI,EAAE,gBAAA,EAAiB,GAAI;AAAC,OACzE;AAEA,MAAA,OAAO,aAAA;AAAA,IACT;AAAA,GACF;AACF;ACzbA,IAAM,oBAAA,GAAoD;AAAA,EACxD,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAcA,IAAM,qBAAqB,CAAC,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,SAAS,KAAK,CAAA;AASnE,SAAS,2BAA2B,SAAA,EAA8B;AAChE,EAAA,OAAO,EACJ,YAAA,CAAa;AAAA,IACZ,SAAA,EAAW,EACR,YAAA,CAAa;AAAA,MACZ,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,kBAAkB,EAAE,IAAA,CAAK;AAAA,QACtC,KAAA,EAAO,kBAAA;AAAA,QACP,WAAA,EAAa,oEAAoE,SAAS,CAAA,CAAA;AAAA,OAC3F;AAAA,KACF,CAAA,CACA,QAAA,EAAS,CACT,IAAA,CAAK;AAAA,MACJ,KAAA,EAAO,WAAA;AAAA,MACP,WAAA,EAAa,+BAA+B,SAAS,CAAA,CAAA;AAAA,KACtD,CAAA;AAAA,IACH,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI,CAAE,QAAA,EAAS,CAAE,GAAA,CAAI,IAAS,CAAA,CAAE,QAAA,GAAW,IAAA,CAAK;AAAA,MACpE,KAAA,EAAO,SAAA;AAAA,MACP,WAAA,EACE;AAAA,KACH;AAAA,GACF,EACA,IAAA,CAAK;AAAA,IACJ,KAAA,EAAO,GAAG,SAAS,CAAA,MAAA,CAAA;AAAA,IACnB,WAAA,EAAa,sCAAsC,SAAS,CAAA,uDAAA;AAAA,GAC7D,CAAA;AACL;AAEO,IAAM,wBAAA,GAA2B,2BAA2B,gBAAgB;AAC5E,IAAM,wBAAA,GAA2B,2BAA2B,iBAAiB;AAC7E,IAAM,yBAAA,GAA4B,2BAA2B,iBAAiB;AAC9E,IAAM,yBAAA,GAA4B,0BAAA;AAAA,EACvC;AACF;AAEA,IAAM,cAAA,GAAsD;AAAA,EAC1D,gBAAA,EAAkB,wBAAA;AAAA,EAClB,iBAAA,EAAmB,wBAAA;AAAA,EACnB,iBAAA,EAAmB,yBAAA;AAAA,EACnB,2BAAA,EAA6B;AAC/B,CAAA;AAMO,IAAM,4BAA+C,oBAAA,CAAqB,GAAA;AAAA,EAC/E,CAAC,EAAA,KAAwB;AACvB,IAAA,MAAM,YAAA,GAAe,eAAe,EAAE,CAAA;AACtC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,EAAA;AAAA,MACP,QAAA,EAAU,YAAA;AAAA,MACV,YAAA,EAAc;AAAA,QACZ,gBAAA,EAAkB,IAAA;AAAA,QAClB,sBAAA,EAAwB,IAAA;AAAA,QACxB,YAAA,EAAc,OAAA;AAAA,QACd,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACV;AAAA,MACA,YAAA;AAAA,MACA,gBAAA,EAAkB,mBAAmB,YAAY,CAAA;AAAA,MACjD,cAAA,EAAgB,oBAAoB,YAAY;AAAA,KAClD;AAAA,EACF;AACF;AAEO,IAAM,iBAAA,GAAmC,mBAAA;AAAA,EAC9C;AACF;;;ACzFO,SAAS,kBAAkB,IAAA,EAAgD;AAChF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,iBAAiB,IAAI,CAAA;AAAA,IAC9B,gBAAA,EAAkB;AAAA,GACpB;AACF","file":"index.js","sourcesContent":["/**\n * ClaudeCliRunner — the process-execution seam for @gullabs/claude-cli.\n *\n * Adapters depend on the {@link ClaudeCliRunner} interface only.\n * {@link buildClaudeCliRunner} is the sole factory that touches\n * `node:child_process`; committed tests inject a hand-written fake instead of\n * exercising it, so no real `claude` subprocess is ever spawned in CI.\n *\n * @module\n */\n\nimport { spawn } from 'node:child_process'\n\n/**\n * The result of a single `claude` CLI invocation.\n */\nexport interface ClaudeCliRunResult {\n stdout: string\n stderr: string\n exitCode: number | null\n}\n\n/**\n * Options accepted by {@link ClaudeCliRunner.run}.\n */\nexport interface ClaudeCliRunOptions {\n /** Working directory for the subprocess (the adapter owns tmpdir lifecycle). */\n cwd: string\n /** Kill the subprocess if it has not exited within this many milliseconds. */\n timeoutMs?: number\n /** Kill the subprocess if this signal fires. */\n signal?: AbortSignal\n}\n\n/**\n * The process-execution seam consumed by {@link claudeCliAdapter}.\n *\n * Implementations run the `claude` binary with `args`, write `input` to its\n * stdin (the rendered prompt), and resolve with captured stdout/stderr/exit\n * code. Implementations must never throw for a non-zero exit code — that is\n * the adapter's error-classification job; the one exception is a spawn-time\n * failure (e.g. `ENOENT` when the binary is missing), which should reject.\n */\nexport interface ClaudeCliRunner {\n run(\n args: string[],\n input: string,\n opts: ClaudeCliRunOptions,\n ): Promise<ClaudeCliRunResult>\n}\n\n/**\n * Build the real {@link ClaudeCliRunner}, backed by `node:child_process`.\n *\n * Never exercised by committed tests — only the real dev workflow invokes\n * this factory; tests inject a hand-written fake implementing\n * {@link ClaudeCliRunner} instead.\n *\n * @param claudePath - Path or bare command name for the `claude` binary.\n * Defaults to `'claude'`, resolved via `PATH`.\n */\nexport function buildClaudeCliRunner(claudePath = 'claude'): ClaudeCliRunner {\n return {\n run(args, input, opts) {\n return new Promise((resolve, reject) => {\n if (opts.signal?.aborted === true) {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n reject(err)\n return\n }\n\n // NOTE: the argv itself (including the `--safe-mode` vs `--bare`\n // choice) is owned by the adapter (see adapter.ts) — this runner is\n // a dumb pipe. We repeat the rule here only as a pointer: never pass\n // `--bare`, it disables OAuth/keychain auth.\n const child = spawn(claudePath, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n let settled = false\n // Set once a timeout/abort has begun killing the child. The\n // returned promise is NOT rejected with this until the child's\n // 'close' event actually fires — the caller (the adapter) must\n // never observe settlement while the OS process may still be\n // alive and writing to its scratch cwd.\n let pendingError: Error | undefined\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n let killTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n const cleanupTimers = (): void => {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (killTimeoutHandle !== undefined) clearTimeout(killTimeoutHandle)\n }\n\n const cleanup = (): void => {\n cleanupTimers()\n if (opts.signal !== undefined) {\n opts.signal.removeEventListener('abort', onAbort)\n }\n }\n\n const killChild = (): void => {\n child.kill('SIGTERM')\n killTimeoutHandle = setTimeout(() => {\n child.kill('SIGKILL')\n }, 5_000)\n }\n\n const beginReject = (err: Error): void => {\n if (settled || pendingError !== undefined) return\n pendingError = err\n cleanupTimers()\n killChild()\n }\n\n const onAbort = (): void => {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n beginReject(err)\n }\n\n // The pre-aborted case is handled above, before `spawn` — by this\n // point `opts.signal`, if present, is guaranteed not yet aborted.\n if (opts.signal !== undefined) {\n opts.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n if (opts.timeoutMs !== undefined) {\n timeoutHandle = setTimeout(() => {\n const err = new Error(`claude-cli call exceeded ${opts.timeoutMs}ms timeout`)\n err.name = 'TimeoutError'\n beginReject(err)\n }, opts.timeoutMs)\n }\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8')\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8')\n })\n\n child.once('error', (err) => {\n if (settled) return\n settled = true\n cleanup()\n reject(pendingError ?? err)\n })\n\n child.once('close', (exitCode) => {\n if (settled) return\n settled = true\n cleanup()\n if (pendingError !== undefined) {\n reject(pendingError)\n } else {\n resolve({ stdout, stderr, exitCode })\n }\n })\n\n child.stdin.end(input, 'utf8')\n })\n },\n }\n}\n","/**\n * claudeCliAdapter — @gullabs/claude-cli provider adapter.\n *\n * Pure request⇄response mapping over the locally-authenticated `claude`\n * (Claude Code) CLI, via {@link ClaudeCliRunner}. Never persists, never\n * computes cost, never retries, never reads `process.env`.\n *\n * DEV-ONLY: this adapter requires `ctx.auth = { cliSession: true }` — it\n * shells out to a `claude` binary that owns its own local login/session\n * state. It is never usable in a production/serverless environment because\n * there is no interactive CLI login there by construction.\n *\n * @module\n */\n\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport { LlmError } from '@gullabs/core'\nimport type {\n ProviderAdapter,\n ResolvedRequest,\n AdapterCtx,\n AdapterResult,\n Usage,\n Warning,\n FinishReason,\n JsonValue,\n Message,\n Part,\n} from '@gullabs/core'\nimport { buildClaudeCliRunner } from './runner.js'\nimport type { ClaudeCliRunner, ClaudeCliRunResult } from './runner.js'\n\n// ---------------------------------------------------------------------------\n// Captured CLI envelope shape (see repo notes for the two captured fixtures)\n// ---------------------------------------------------------------------------\n\n/**\n * The `usage` object nested inside the `claude -p --output-format json`\n * result envelope. Only the fields this adapter consumes are typed here;\n * the full object is preserved verbatim in `Usage.raw`.\n */\nexport interface ClaudeCliUsageShape {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n [key: string]: unknown\n}\n\n/**\n * The top-level JSON envelope emitted on stdout by\n * `claude -p ... --output-format json` on completion (success or error).\n */\nexport interface ClaudeCliEnvelope {\n type: string\n subtype?: string\n is_error?: boolean\n result?: string\n stop_reason?: string\n session_id?: string\n total_cost_usd?: number\n num_turns?: number\n usage?: ClaudeCliUsageShape\n [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Tiny in-file semaphore — adapter-internal concurrency control\n// ---------------------------------------------------------------------------\n\nclass Semaphore {\n private available: number\n private readonly queue: Array<() => void> = []\n\n constructor(max: number) {\n this.available = max\n }\n\n async acquire(): Promise<() => void> {\n if (this.available > 0) {\n this.available -= 1\n return () => {\n this.release()\n }\n }\n await new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n this.available -= 1\n return () => {\n this.release()\n }\n }\n\n private release(): void {\n this.available += 1\n const next = this.queue.shift()\n if (next !== undefined) next()\n }\n}\n\n// ---------------------------------------------------------------------------\n// FinishReason mapping\n// ---------------------------------------------------------------------------\n\nfunction mapFinishReason(stopReason: string | undefined): FinishReason | undefined {\n if (stopReason === undefined) return undefined\n switch (stopReason) {\n case 'end_turn':\n return 'stop'\n case 'tool_use':\n // The CLI's own final answer, not a caller-visible tool call — treat\n // as a successful completion for our purposes.\n return 'stop'\n default:\n return 'other'\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage mapping — GROSS convention\n//\n// `totalTokens` is not reported by the claude-cli usage payload — it is\n// derived as `inputTokens + outputTokens` whenever a usage payload was\n// present; left undefined when there was no usage payload at all.\n// ---------------------------------------------------------------------------\n\nfunction mapUsage(usage: ClaudeCliUsageShape | undefined): Usage {\n const inputTokens = usage?.input_tokens ?? 0\n const outputTokens = usage?.output_tokens ?? 0\n const cachedInputTokens = usage?.cache_read_input_tokens\n const totalTokens = usage !== undefined ? inputTokens + outputTokens : undefined\n\n const details: Record<string, number> = {\n input: inputTokens,\n output: outputTokens,\n ...(cachedInputTokens !== undefined ? { cached: cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { total: totalTokens } : {}),\n }\n\n const raw: JsonValue = usage !== undefined ? (usage as unknown as JsonValue) : null\n\n return {\n inputTokens,\n outputTokens,\n details,\n raw,\n ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { totalTokens } : {}),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt serialization\n// ---------------------------------------------------------------------------\n\nfunction partText(part: Part): string {\n if (part.kind !== 'text') {\n throw new LlmError(\n 'claude-cli is text-only; non-text message parts are not supported',\n {\n kind: 'bad_request',\n retryable: false,\n provider: 'claude-cli',\n },\n )\n }\n return part.text\n}\n\nfunction messageText(msg: Message): string {\n return msg.parts.map(partText).join('')\n}\n\n/**\n * Serialize `req.messages` into the single string sent to the CLI over\n * stdin.\n *\n * - Single user message, single text part → the text verbatim.\n * - Otherwise → a role-labelled transcript, blocks separated by a blank line.\n */\nfunction buildPrompt(messages: Message[]): string {\n if (messages.length === 1 && messages[0]?.parts.length === 1) {\n return partText(messages[0].parts[0] as Part)\n }\n\n return messages\n .map((msg) => {\n const label = msg.role === 'assistant' ? 'Assistant' : 'User'\n return `${label}:\\n${messageText(msg)}`\n })\n .join('\\n\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Error classification\n// ---------------------------------------------------------------------------\n\nfunction looksAuthy(text: string): boolean {\n return /login|auth|unauthorized/i.test(text)\n}\n\nfunction looksRateLimited(text: string): boolean {\n return /rate limit|429/i.test(text)\n}\n\nfunction classifyRunFailure(\n envelope: ClaudeCliEnvelope | undefined,\n result: ClaudeCliRunResult,\n): LlmError {\n const combinedText = `${envelope?.subtype ?? ''} ${result.stderr}`\n\n if (looksAuthy(combinedText)) {\n return new LlmError(\n `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (looksRateLimited(combinedText)) {\n return new LlmError(\n `claude CLI reported rate limiting: ${result.stderr.slice(-500)}`,\n {\n kind: 'rate_limited',\n retryable: true,\n provider: 'claude-cli',\n },\n )\n }\n\n if (envelope?.is_error === true) {\n return new LlmError(\n `claude CLI reported an error (subtype: ${envelope.subtype ?? 'unknown'}): ${result.stderr.slice(-500)}`,\n { kind: 'server', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const stderrTail = result.stderr.slice(-500)\n return new LlmError(\n `claude CLI exited with code ${String(result.exitCode)}: ${stderrTail}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n}\n\n// ---------------------------------------------------------------------------\n// Adapter options\n// ---------------------------------------------------------------------------\n\nexport interface ClaudeCliAdapterOptions {\n /** Inject a runner (real or fake). Defaults to `buildClaudeCliRunner()`. */\n runner?: ClaudeCliRunner\n /** Path or bare command name for the `claude` binary. Defaults to `'claude'`. */\n claudePath?: string\n /** Max concurrent CLI invocations. Defaults to `2`. */\n maxConcurrency?: number\n}\n\n// ---------------------------------------------------------------------------\n// claudeCliAdapter factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a dev-only Claude Code CLI provider adapter.\n *\n * Requires `ctx.auth = { cliSession: true }` — see module docs.\n */\nexport function claudeCliAdapter(opts?: ClaudeCliAdapterOptions): ProviderAdapter {\n // Constructed eagerly but never invoked unless `opts.runner` is absent —\n // `buildClaudeCliRunner` only closes over `node:child_process`, it does not\n // spawn anything until `.run()` is called.\n const runner: ClaudeCliRunner = opts?.runner ?? buildClaudeCliRunner(opts?.claudePath)\n\n const semaphore = new Semaphore(opts?.maxConcurrency ?? 2)\n\n return {\n id: 'claude-cli',\n\n async run(req: ResolvedRequest, ctx: AdapterCtx): Promise<AdapterResult> {\n // ------------------------------------------------------------------\n // 1. Auth — CliSessionAuth only.\n // ------------------------------------------------------------------\n const hasCliSession = 'cliSession' in ctx.auth && ctx.auth.cliSession\n if (!hasCliSession) {\n throw new LlmError(\n '@gullabs/claude-cli requires auth: { cliSession: true } — these dev-only providers route through a locally-authenticated `claude` CLI session, not an API key',\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (req.provider !== 'claude-cli') {\n throw new LlmError(\n `@gullabs/claude-cli received a request routed for provider \"${req.provider}\" — this adapter only serves \"claude-cli\"`,\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const warnings: Warning[] = []\n const model = req.model\n const config = req.config\n\n // ------------------------------------------------------------------\n // 2. Prompt serialization (throws bad_request on non-text parts).\n // ------------------------------------------------------------------\n const prompt = buildPrompt(req.messages)\n\n // ------------------------------------------------------------------\n // 3. Invariant argv — adapter-owned, never caller-configurable.\n //\n // We use --safe-mode, NEVER --bare: --bare disables OAuth/keychain\n // auth and would break subscription-based Claude Code auth — the\n // exact mechanism that lets these dev-only providers work with zero\n // API-key configuration at all.\n // ------------------------------------------------------------------\n const args: string[] = [\n '-p',\n '--output-format',\n 'json',\n '--safe-mode',\n '--tools',\n '',\n '--disable-slash-commands',\n '--no-session-persistence',\n ]\n\n args.push('--model', model)\n\n const effort = config.reasoning?.effort\n if (effort !== undefined) {\n // `effort` was already validated against this package's own zod\n // schema at the config layer before the engine called us — forward\n // verbatim, no re-validation, no `any` cast.\n args.push('--effort', String(effort))\n }\n\n if (req.system !== undefined) {\n args.push('--system-prompt', req.system)\n }\n\n if (req.outputJsonSchema !== undefined) {\n args.push('--json-schema', JSON.stringify(req.outputJsonSchema))\n }\n\n // ------------------------------------------------------------------\n // 4. Timeout + scratch dir + runner invocation.\n // ------------------------------------------------------------------\n const timeoutMs = req.attemptTimeoutMs ?? config.timeoutMs\n\n // The runner owns timeout/abort enforcement end-to-end: it only\n // settles (resolve OR reject) once the child process has actually\n // exited (its 'close' event fired). We deliberately do NOT race an\n // independent timer against `runner.run(...)` here — doing so could\n // let this adapter move on (and release the semaphore / rm the\n // scratch dir) while the real OS child process is still alive and\n // possibly still writing into `cwd`. We simply await the runner\n // promise and classify whatever it settles with.\n const cwd = await mkdtemp(join(tmpdir(), 'claude-cli-'))\n const release = await semaphore.acquire()\n let result: ClaudeCliRunResult\n try {\n result = await runner.run(args, prompt, {\n cwd,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}),\n })\n } catch (rawErr) {\n release()\n await rm(cwd, { recursive: true, force: true })\n\n if (rawErr instanceof LlmError) throw rawErr\n\n if (\n typeof rawErr === 'object' &&\n rawErr !== null &&\n 'code' in rawErr &&\n (rawErr as { code?: unknown }).code === 'ENOENT'\n ) {\n throw new LlmError(\n 'claude CLI not found on PATH — install Claude Code and run `claude auth login`',\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (rawErr instanceof Error && rawErr.name === 'AbortError') {\n throw new LlmError(rawErr.message || 'claude-cli call aborted', {\n kind: 'aborted',\n retryable: false,\n provider: 'claude-cli',\n })\n }\n\n if (rawErr instanceof Error && rawErr.name === 'TimeoutError') {\n throw new LlmError(rawErr.message || 'claude-cli call timed out', {\n kind: 'timeout',\n retryable: true,\n provider: 'claude-cli',\n })\n }\n\n throw new LlmError(\n `claude-cli runner failed: ${rawErr instanceof Error ? rawErr.message : String(rawErr)}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli', cause: rawErr },\n )\n }\n release()\n await rm(cwd, { recursive: true, force: true })\n\n // ------------------------------------------------------------------\n // 5. Parse the envelope from stdout.\n // ------------------------------------------------------------------\n let envelope: ClaudeCliEnvelope | undefined\n try {\n envelope = JSON.parse(result.stdout) as ClaudeCliEnvelope\n } catch {\n envelope = undefined\n }\n\n if (\n result.exitCode !== 0 ||\n envelope?.is_error === true ||\n envelope === undefined\n ) {\n throw classifyRunFailure(envelope, result)\n }\n\n // ------------------------------------------------------------------\n // 6. Map result → AdapterResult.\n // ------------------------------------------------------------------\n const text = envelope.result ?? ''\n\n let rawStructured: unknown\n if (req.outputJsonSchema !== undefined) {\n try {\n rawStructured = JSON.parse(text)\n } catch {\n warnings.push({\n type: 'other',\n message: 'claude-cli: failed to parse structured output as JSON',\n })\n }\n }\n\n const usage = mapUsage(envelope.usage)\n const finishReason = mapFinishReason(envelope.stop_reason)\n\n const providerMetadata: Record<string, JsonValue> = {\n ...(envelope.total_cost_usd !== undefined\n ? { totalCostUsd: envelope.total_cost_usd }\n : {}),\n ...(envelope.session_id !== undefined ? { sessionId: envelope.session_id } : {}),\n ...(envelope.subtype !== undefined ? { subtype: envelope.subtype } : {}),\n ...(envelope.num_turns !== undefined ? { numTurns: envelope.num_turns } : {}),\n }\n\n const adapterResult: AdapterResult = {\n model,\n usage,\n warnings,\n ...(text.length > 0 ? { text } : {}),\n ...(rawStructured !== undefined ? { rawStructured } : {}),\n ...(finishReason !== undefined ? { finishReason } : {}),\n ...(Object.keys(providerMetadata).length > 0 ? { providerMetadata } : {}),\n }\n\n return adapterResult\n },\n }\n}\n","/**\n * Model config schemas + registry for @gullabs/claude-cli.\n *\n * DEVIATION FROM CONVENTION: `@gullabs/core`'s `packages/core/src/model-config/`\n * only carries config schemas for production API providers (Gemini/Gemma).\n * This dev-only CLI provider intentionally keeps its own model config schemas\n * and registry local to this package instead — core stays free of any\n * knowledge of the local-CLI dev workflow.\n *\n * @module\n */\n\nimport { z } from 'zod'\nimport type { ModelDescriptor, ModelRegistry } from '@gullabs/core'\nimport {\n createModelRegistry,\n toConfigJsonSchema,\n zodToStandardSchema,\n} from '@gullabs/core'\n\n// ---------------------------------------------------------------------------\n// Model ids\n// ---------------------------------------------------------------------------\n\n/** Every model id `@gullabs/claude-cli` knows how to route. */\nexport type ClaudeCliModelId =\n 'claude-fable-5' | 'claude-opus-4-8' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001'\n\nconst CLAUDE_CLI_MODEL_IDS: readonly ClaudeCliModelId[] = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-sonnet-5',\n 'claude-haiku-4-5-20251001',\n]\n\n/**\n * Reasoning effort levels admitted by the `claude` CLI's `--effort` flag.\n *\n * A strict superset of `@gullabs/core`'s `ReasoningEffort` union (which is\n * `'none' | 'low' | 'medium' | 'high' | 'xhigh'`) — `'max'` is the extra\n * value the CLI supports that core's engine-level type does not know about.\n * Because of this mismatch, `admittedReasoningEfforts` (typed\n * `ReadonlyArray<ReasoningEffort>` in `ModelDescriptor.capabilities`) is\n * intentionally OMITTED below rather than cast — this package's own zod\n * schema is the sole validator for `reasoning.effort`, so the field is\n * advisory-only and safe to skip.\n */\nconst CLAUDE_CLI_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\n\n/**\n * Build the strict per-model config schema for a `claude-cli` model.\n *\n * No `temperature`/`topP`/`topK`/`maxOutputTokens`/`stopSequences` fields —\n * the CLI does not support tuning any of these, and `z.strictObject` rejects\n * any unknown key outright (reject, don't map/clamp).\n */\nfunction buildClaudeCliConfigSchema(modelName: string): z.ZodType {\n return z\n .strictObject({\n reasoning: z\n .strictObject({\n effort: z.enum(CLAUDE_CLI_EFFORTS).meta({\n title: 'Reasoning Effort',\n description: `Reasoning effort forwarded to the claude CLI's --effort flag for ${modelName}.`,\n }),\n })\n .optional()\n .meta({\n title: 'Reasoning',\n description: `Reasoning configuration for ${modelName}.`,\n }),\n timeoutMs: z.number().int().positive().max(1_800_000).optional().meta({\n title: 'Timeout',\n description:\n 'Logical request timeout in milliseconds; forwarded to the CLI runner.',\n }),\n })\n .meta({\n title: `${modelName}Config`,\n description: `Strict claude-cli config for model ${modelName}. Text-only, no sampling knobs, effort-based reasoning.`,\n })\n}\n\nexport const ClaudeFable5ConfigSchema = buildClaudeCliConfigSchema('claude-fable-5')\nexport const ClaudeOpus48ConfigSchema = buildClaudeCliConfigSchema('claude-opus-4-8')\nexport const ClaudeSonnet5ConfigSchema = buildClaudeCliConfigSchema('claude-sonnet-5')\nexport const ClaudeHaiku45ConfigSchema = buildClaudeCliConfigSchema(\n 'claude-haiku-4-5-20251001',\n)\n\nconst CONFIG_SCHEMAS: Record<ClaudeCliModelId, z.ZodType> = {\n 'claude-fable-5': ClaudeFable5ConfigSchema,\n 'claude-opus-4-8': ClaudeOpus48ConfigSchema,\n 'claude-sonnet-5': ClaudeSonnet5ConfigSchema,\n 'claude-haiku-4-5-20251001': ClaudeHaiku45ConfigSchema,\n}\n\n// ---------------------------------------------------------------------------\n// Descriptors + registry\n// ---------------------------------------------------------------------------\n\nexport const claudeCliModelDescriptors: ModelDescriptor[] = CLAUDE_CLI_MODEL_IDS.map(\n (id): ModelDescriptor => {\n const configSchema = CONFIG_SCHEMAS[id]\n return {\n model: id,\n provider: 'claude-cli',\n capabilities: {\n structuredOutput: true,\n nativeStructuredOutput: true,\n reasoningApi: 'level',\n sampling: 'fixed',\n vision: false,\n },\n configSchema,\n configJsonSchema: toConfigJsonSchema(configSchema),\n validateConfig: zodToStandardSchema(configSchema),\n }\n },\n)\n\nexport const claudeCliRegistry: ModelRegistry = createModelRegistry(\n claudeCliModelDescriptors,\n)\n","/**\n * `claudeCliProvider` — {@link ProviderPlugin} factory for @gullabs/claude-cli.\n *\n * Bundles the dev-only Claude CLI adapter with its model descriptors. This\n * provider is unpriced by design (dev-only CLI, $0 API spend) — the returned\n * plugin has no `pricingSource`.\n *\n * @module\n */\n\nimport type { ProviderPlugin } from '@gullabs/core'\n\nimport { claudeCliAdapter } from './adapter.js'\nimport type { ClaudeCliAdapterOptions } from './adapter.js'\nimport { claudeCliModelDescriptors } from './models.js'\n\n/**\n * Create a {@link ProviderPlugin} for the dev-only Claude Code CLI provider.\n *\n * Unpriced by design: the returned plugin omits `pricingSource` entirely.\n *\n * @param opts - Forwarded to {@link claudeCliAdapter}.\n * @returns A plugin bundling the Claude CLI adapter and its model descriptors.\n *\n * @example\n * ```ts\n * import { createClient, composeProviders } from '@gullabs/core'\n * import { claudeCliProvider } from '@gullabs/claude-cli'\n *\n * const client = createClient({\n * ...composeProviders([claudeCliProvider()]),\n * })\n * ```\n */\nexport function claudeCliProvider(opts?: ClaudeCliAdapterOptions): ProviderPlugin {\n return {\n adapter: claudeCliAdapter(opts),\n modelDescriptors: claudeCliModelDescriptors,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/runner.ts","../src/adapter.ts","../src/models.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ClaudeCliRunner — the process-execution seam for @gullabs/claude-cli.\n *\n * Adapters depend on the {@link ClaudeCliRunner} interface only.\n * {@link buildClaudeCliRunner} is the sole factory that touches\n * `node:child_process`; committed tests inject a hand-written fake instead of\n * exercising it, so no real `claude` subprocess is ever spawned in CI.\n *\n * @module\n */\n\nimport { spawn } from 'node:child_process'\n\n/**\n * The result of a single `claude` CLI invocation.\n */\nexport interface ClaudeCliRunResult {\n stdout: string\n stderr: string\n exitCode: number | null\n}\n\n/**\n * Options accepted by {@link ClaudeCliRunner.run}.\n */\nexport interface ClaudeCliRunOptions {\n /** Working directory for the subprocess (the adapter owns tmpdir lifecycle). */\n cwd: string\n /** Kill the subprocess if it has not exited within this many milliseconds. */\n timeoutMs?: number\n /** Kill the subprocess if this signal fires. */\n signal?: AbortSignal\n}\n\n/**\n * The process-execution seam consumed by {@link claudeCliAdapter}.\n *\n * Implementations run the `claude` binary with `args`, write `input` to its\n * stdin (the rendered prompt), and resolve with captured stdout/stderr/exit\n * code. Implementations must never throw for a non-zero exit code — that is\n * the adapter's error-classification job; the one exception is a spawn-time\n * failure (e.g. `ENOENT` when the binary is missing), which should reject.\n */\nexport interface ClaudeCliRunner {\n run(\n args: string[],\n input: string,\n opts: ClaudeCliRunOptions,\n ): Promise<ClaudeCliRunResult>\n}\n\n/**\n * Build the real {@link ClaudeCliRunner}, backed by `node:child_process`.\n *\n * Never exercised by committed tests — only the real dev workflow invokes\n * this factory; tests inject a hand-written fake implementing\n * {@link ClaudeCliRunner} instead.\n *\n * @param claudePath - Path or bare command name for the `claude` binary.\n * Defaults to `'claude'`, resolved via `PATH`.\n */\nexport function buildClaudeCliRunner(claudePath = 'claude'): ClaudeCliRunner {\n return {\n run(args, input, opts) {\n return new Promise((resolve, reject) => {\n if (opts.signal?.aborted === true) {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n reject(err)\n return\n }\n\n // NOTE: the argv itself (including the `--safe-mode` vs `--bare`\n // choice) is owned by the adapter (see adapter.ts) — this runner is\n // a dumb pipe. We repeat the rule here only as a pointer: never pass\n // `--bare`, it disables OAuth/keychain auth.\n const child = spawn(claudePath, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n let settled = false\n // Set once a timeout/abort has begun killing the child. The\n // returned promise is NOT rejected with this until the child's\n // 'close' event actually fires — the caller (the adapter) must\n // never observe settlement while the OS process may still be\n // alive and writing to its scratch cwd.\n let pendingError: Error | undefined\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n let killTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n const cleanupTimers = (): void => {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n if (killTimeoutHandle !== undefined) clearTimeout(killTimeoutHandle)\n }\n\n const cleanup = (): void => {\n cleanupTimers()\n if (opts.signal !== undefined) {\n opts.signal.removeEventListener('abort', onAbort)\n }\n }\n\n const killChild = (): void => {\n child.kill('SIGTERM')\n killTimeoutHandle = setTimeout(() => {\n child.kill('SIGKILL')\n }, 5_000)\n }\n\n const beginReject = (err: Error): void => {\n if (settled || pendingError !== undefined) return\n pendingError = err\n cleanupTimers()\n killChild()\n }\n\n const onAbort = (): void => {\n const err = new Error('claude-cli call aborted')\n err.name = 'AbortError'\n beginReject(err)\n }\n\n // The pre-aborted case is handled above, before `spawn` — by this\n // point `opts.signal`, if present, is guaranteed not yet aborted.\n if (opts.signal !== undefined) {\n opts.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n if (opts.timeoutMs !== undefined) {\n timeoutHandle = setTimeout(() => {\n const err = new Error(`claude-cli call exceeded ${opts.timeoutMs}ms timeout`)\n err.name = 'TimeoutError'\n beginReject(err)\n }, opts.timeoutMs)\n }\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8')\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8')\n })\n\n child.once('error', (err) => {\n if (settled) return\n settled = true\n cleanup()\n reject(pendingError ?? err)\n })\n\n child.once('close', (exitCode) => {\n if (settled) return\n settled = true\n cleanup()\n if (pendingError !== undefined) {\n reject(pendingError)\n } else {\n resolve({ stdout, stderr, exitCode })\n }\n })\n\n child.stdin.end(input, 'utf8')\n })\n },\n }\n}\n","/**\n * claudeCliAdapter — @gullabs/claude-cli provider adapter.\n *\n * Pure request⇄response mapping over the locally-authenticated `claude`\n * (Claude Code) CLI, via {@link ClaudeCliRunner}. Never persists, never\n * computes cost, never retries, never reads `process.env`.\n *\n * DEV-ONLY: this adapter requires `ctx.auth = { cliSession: true }` — it\n * shells out to a `claude` binary that owns its own local login/session\n * state. It is never usable in a production/serverless environment because\n * there is no interactive CLI login there by construction.\n *\n * @module\n */\n\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport { LlmError } from '@gullabs/core'\nimport type {\n ProviderAdapter,\n ResolvedRequest,\n AdapterCtx,\n AdapterResult,\n Usage,\n Warning,\n FinishReason,\n JsonValue,\n Message,\n Part,\n} from '@gullabs/core'\nimport { buildClaudeCliRunner } from './runner.js'\nimport type { ClaudeCliRunner, ClaudeCliRunResult } from './runner.js'\n\n// ---------------------------------------------------------------------------\n// Captured CLI envelope shape (see repo notes for the two captured fixtures)\n// ---------------------------------------------------------------------------\n\n/**\n * The `usage` object nested inside the `claude -p --output-format json`\n * result envelope. Only the fields this adapter consumes are typed here;\n * the full object is preserved verbatim in `Usage.raw`.\n */\nexport interface ClaudeCliUsageShape {\n input_tokens: number\n output_tokens: number\n cache_read_input_tokens?: number\n cache_creation_input_tokens?: number\n [key: string]: unknown\n}\n\n/**\n * The top-level JSON envelope emitted on stdout by\n * `claude -p ... --output-format json` on completion (success or error).\n */\nexport interface ClaudeCliEnvelope {\n type: string\n subtype?: string\n is_error?: boolean\n result?: string\n stop_reason?: string\n session_id?: string\n total_cost_usd?: number\n num_turns?: number\n usage?: ClaudeCliUsageShape\n [key: string]: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Tiny in-file semaphore — adapter-internal concurrency control\n// ---------------------------------------------------------------------------\n\nclass Semaphore {\n private available: number\n private readonly queue: Array<() => void> = []\n\n constructor(max: number) {\n this.available = max\n }\n\n async acquire(): Promise<() => void> {\n if (this.available > 0) {\n this.available -= 1\n return () => {\n this.release()\n }\n }\n await new Promise<void>((resolve) => {\n this.queue.push(resolve)\n })\n this.available -= 1\n return () => {\n this.release()\n }\n }\n\n private release(): void {\n this.available += 1\n const next = this.queue.shift()\n if (next !== undefined) next()\n }\n}\n\n// ---------------------------------------------------------------------------\n// FinishReason mapping\n// ---------------------------------------------------------------------------\n\nfunction mapFinishReason(stopReason: string | undefined): FinishReason | undefined {\n if (stopReason === undefined) return undefined\n switch (stopReason) {\n case 'end_turn':\n return 'stop'\n case 'tool_use':\n // The CLI's own final answer, not a caller-visible tool call — treat\n // as a successful completion for our purposes.\n return 'stop'\n default:\n return 'other'\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage mapping — GROSS convention\n//\n// `totalTokens` is not reported by the claude-cli usage payload — it is\n// derived as `inputTokens + outputTokens` whenever a usage payload was\n// present; left undefined when there was no usage payload at all.\n// ---------------------------------------------------------------------------\n\nfunction mapUsage(usage: ClaudeCliUsageShape | undefined): Usage {\n const inputTokens = usage?.input_tokens ?? 0\n const outputTokens = usage?.output_tokens ?? 0\n const cachedInputTokens = usage?.cache_read_input_tokens\n const totalTokens = usage !== undefined ? inputTokens + outputTokens : undefined\n\n const details: Record<string, number> = {\n input: inputTokens,\n output: outputTokens,\n ...(cachedInputTokens !== undefined ? { cached: cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { total: totalTokens } : {}),\n }\n\n const raw: JsonValue = usage !== undefined ? (usage as unknown as JsonValue) : null\n\n return {\n inputTokens,\n outputTokens,\n details,\n raw,\n ...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),\n ...(totalTokens !== undefined ? { totalTokens } : {}),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt serialization\n// ---------------------------------------------------------------------------\n\nfunction partText(part: Part): string {\n if (part.kind !== 'text') {\n throw new LlmError(\n 'claude-cli is text-only; non-text message parts (inline media, file URIs, tool-call, tool-result) are not supported',\n {\n kind: 'bad_request',\n retryable: false,\n provider: 'claude-cli',\n },\n )\n }\n return part.text\n}\n\nfunction messageText(msg: Message): string {\n return msg.parts.map(partText).join('')\n}\n\n/**\n * Serialize `req.messages` into the single string sent to the CLI over\n * stdin.\n *\n * - Single user message, single text part → the text verbatim.\n * - Otherwise → a role-labelled transcript, blocks separated by a blank line.\n */\nfunction buildPrompt(messages: Message[]): string {\n if (messages.length === 1 && messages[0]?.parts.length === 1) {\n return partText(messages[0].parts[0] as Part)\n }\n\n return messages\n .map((msg) => {\n const label = msg.role === 'assistant' ? 'Assistant' : 'User'\n return `${label}:\\n${messageText(msg)}`\n })\n .join('\\n\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Error classification\n// ---------------------------------------------------------------------------\n\nfunction looksAuthy(text: string): boolean {\n return /login|auth|unauthorized/i.test(text)\n}\n\nfunction looksRateLimited(text: string): boolean {\n return /rate limit|429/i.test(text)\n}\n\nfunction classifyRunFailure(\n envelope: ClaudeCliEnvelope | undefined,\n result: ClaudeCliRunResult,\n): LlmError {\n const combinedText = `${envelope?.subtype ?? ''} ${result.stderr}`\n\n if (looksAuthy(combinedText)) {\n return new LlmError(\n `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (looksRateLimited(combinedText)) {\n return new LlmError(\n `claude CLI reported rate limiting: ${result.stderr.slice(-500)}`,\n {\n kind: 'rate_limited',\n retryable: true,\n provider: 'claude-cli',\n },\n )\n }\n\n if (envelope?.is_error === true) {\n return new LlmError(\n `claude CLI reported an error (subtype: ${envelope.subtype ?? 'unknown'}): ${result.stderr.slice(-500)}`,\n { kind: 'server', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const stderrTail = result.stderr.slice(-500)\n return new LlmError(\n `claude CLI exited with code ${String(result.exitCode)}: ${stderrTail}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n}\n\n// ---------------------------------------------------------------------------\n// Adapter options\n// ---------------------------------------------------------------------------\n\nexport interface ClaudeCliAdapterOptions {\n /** Inject a runner (real or fake). Defaults to `buildClaudeCliRunner()`. */\n runner?: ClaudeCliRunner\n /** Path or bare command name for the `claude` binary. Defaults to `'claude'`. */\n claudePath?: string\n /** Max concurrent CLI invocations. Defaults to `2`. */\n maxConcurrency?: number\n}\n\n// ---------------------------------------------------------------------------\n// claudeCliAdapter factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a dev-only Claude Code CLI provider adapter.\n *\n * Requires `ctx.auth = { cliSession: true }` — see module docs.\n */\nexport function claudeCliAdapter(opts?: ClaudeCliAdapterOptions): ProviderAdapter {\n // Constructed eagerly but never invoked unless `opts.runner` is absent —\n // `buildClaudeCliRunner` only closes over `node:child_process`, it does not\n // spawn anything until `.run()` is called.\n const runner: ClaudeCliRunner = opts?.runner ?? buildClaudeCliRunner(opts?.claudePath)\n\n const semaphore = new Semaphore(opts?.maxConcurrency ?? 2)\n\n return {\n id: 'claude-cli',\n\n async run(req: ResolvedRequest, ctx: AdapterCtx): Promise<AdapterResult> {\n // ------------------------------------------------------------------\n // 1. Auth — CliSessionAuth only.\n // ------------------------------------------------------------------\n const hasCliSession = 'cliSession' in ctx.auth && ctx.auth.cliSession\n if (!hasCliSession) {\n throw new LlmError(\n '@gullabs/claude-cli requires auth: { cliSession: true } — these dev-only providers route through a locally-authenticated `claude` CLI session, not an API key',\n { kind: 'invalid_auth', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (req.provider !== 'claude-cli') {\n throw new LlmError(\n `@gullabs/claude-cli received a request routed for provider \"${req.provider}\" — this adapter only serves \"claude-cli\"`,\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n if (req.tools !== undefined && req.tools.length > 0) {\n throw new LlmError(\n 'claude-cli does not support LlmRequest.tools; CLI runtimes are out of the function-calling seam.',\n { kind: 'bad_request', retryable: false, provider: 'claude-cli' },\n )\n }\n\n const warnings: Warning[] = []\n const model = req.model\n const config = req.config\n\n // ------------------------------------------------------------------\n // 2. Prompt serialization (throws bad_request on non-text parts).\n // ------------------------------------------------------------------\n const prompt = buildPrompt(req.messages)\n\n // ------------------------------------------------------------------\n // 3. Invariant argv — adapter-owned, never caller-configurable.\n //\n // We use --safe-mode, NEVER --bare: --bare disables OAuth/keychain\n // auth and would break subscription-based Claude Code auth — the\n // exact mechanism that lets these dev-only providers work with zero\n // API-key configuration at all.\n // ------------------------------------------------------------------\n const args: string[] = [\n '-p',\n '--output-format',\n 'json',\n '--safe-mode',\n '--tools',\n '',\n '--disable-slash-commands',\n '--no-session-persistence',\n ]\n\n args.push('--model', model)\n\n const effort = config.reasoning?.effort\n if (effort !== undefined) {\n // `effort` was already validated against this package's own zod\n // schema at the config layer before the engine called us — forward\n // verbatim, no re-validation, no `any` cast.\n args.push('--effort', String(effort))\n }\n\n if (req.system !== undefined) {\n args.push('--system-prompt', req.system)\n }\n\n if (req.outputJsonSchema !== undefined) {\n args.push('--json-schema', JSON.stringify(req.outputJsonSchema))\n }\n\n // ------------------------------------------------------------------\n // 4. Timeout + scratch dir + runner invocation.\n // ------------------------------------------------------------------\n const timeoutMs = req.attemptTimeoutMs ?? config.timeoutMs\n\n // The runner owns timeout/abort enforcement end-to-end: it only\n // settles (resolve OR reject) once the child process has actually\n // exited (its 'close' event fired). We deliberately do NOT race an\n // independent timer against `runner.run(...)` here — doing so could\n // let this adapter move on (and release the semaphore / rm the\n // scratch dir) while the real OS child process is still alive and\n // possibly still writing into `cwd`. We simply await the runner\n // promise and classify whatever it settles with.\n const cwd = await mkdtemp(join(tmpdir(), 'claude-cli-'))\n const release = await semaphore.acquire()\n let result: ClaudeCliRunResult\n try {\n result = await runner.run(args, prompt, {\n cwd,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}),\n })\n } catch (rawErr) {\n release()\n await rm(cwd, { recursive: true, force: true })\n\n if (rawErr instanceof LlmError) throw rawErr\n\n if (\n typeof rawErr === 'object' &&\n rawErr !== null &&\n 'code' in rawErr &&\n (rawErr as { code?: unknown }).code === 'ENOENT'\n ) {\n throw new LlmError(\n 'claude CLI not found on PATH — install Claude Code and run `claude auth login`',\n { kind: 'unknown', retryable: false, provider: 'claude-cli' },\n )\n }\n\n if (rawErr instanceof Error && rawErr.name === 'AbortError') {\n throw new LlmError(rawErr.message || 'claude-cli call aborted', {\n kind: 'aborted',\n retryable: false,\n provider: 'claude-cli',\n })\n }\n\n if (rawErr instanceof Error && rawErr.name === 'TimeoutError') {\n throw new LlmError(rawErr.message || 'claude-cli call timed out', {\n kind: 'timeout',\n retryable: true,\n provider: 'claude-cli',\n })\n }\n\n throw new LlmError(\n `claude-cli runner failed: ${rawErr instanceof Error ? rawErr.message : String(rawErr)}`,\n { kind: 'unknown', retryable: false, provider: 'claude-cli', cause: rawErr },\n )\n }\n release()\n await rm(cwd, { recursive: true, force: true })\n\n // ------------------------------------------------------------------\n // 5. Parse the envelope from stdout.\n // ------------------------------------------------------------------\n let envelope: ClaudeCliEnvelope | undefined\n try {\n envelope = JSON.parse(result.stdout) as ClaudeCliEnvelope\n } catch {\n envelope = undefined\n }\n\n if (\n result.exitCode !== 0 ||\n envelope?.is_error === true ||\n envelope === undefined\n ) {\n throw classifyRunFailure(envelope, result)\n }\n\n // ------------------------------------------------------------------\n // 6. Map result → AdapterResult.\n // ------------------------------------------------------------------\n const text = envelope.result ?? ''\n\n let rawStructured: unknown\n if (req.outputJsonSchema !== undefined) {\n try {\n rawStructured = JSON.parse(text)\n } catch {\n warnings.push({\n type: 'other',\n message: 'claude-cli: failed to parse structured output as JSON',\n })\n }\n }\n\n const usage = mapUsage(envelope.usage)\n const finishReason = mapFinishReason(envelope.stop_reason)\n\n const providerMetadata: Record<string, JsonValue> = {\n ...(envelope.total_cost_usd !== undefined\n ? { totalCostUsd: envelope.total_cost_usd }\n : {}),\n ...(envelope.session_id !== undefined ? { sessionId: envelope.session_id } : {}),\n ...(envelope.subtype !== undefined ? { subtype: envelope.subtype } : {}),\n ...(envelope.num_turns !== undefined ? { numTurns: envelope.num_turns } : {}),\n }\n\n const adapterResult: AdapterResult = {\n model,\n usage,\n warnings,\n ...(text.length > 0 ? { text } : {}),\n ...(rawStructured !== undefined ? { rawStructured } : {}),\n ...(finishReason !== undefined ? { finishReason } : {}),\n ...(Object.keys(providerMetadata).length > 0 ? { providerMetadata } : {}),\n }\n\n return adapterResult\n },\n }\n}\n","/**\n * Model config schemas + registry for @gullabs/claude-cli.\n *\n * DEVIATION FROM CONVENTION: `@gullabs/core`'s `packages/core/src/model-config/`\n * only carries config schemas for production API providers (Gemini/Gemma).\n * This dev-only CLI provider intentionally keeps its own model config schemas\n * and registry local to this package instead — core stays free of any\n * knowledge of the local-CLI dev workflow.\n *\n * @module\n */\n\nimport { z } from 'zod'\nimport type { ModelDescriptor, ModelRegistry } from '@gullabs/core'\nimport {\n createModelRegistry,\n toConfigJsonSchema,\n zodToStandardSchema,\n} from '@gullabs/core'\n\n// ---------------------------------------------------------------------------\n// Model ids\n// ---------------------------------------------------------------------------\n\n/** Every model id `@gullabs/claude-cli` knows how to route. */\nexport type ClaudeCliModelId =\n 'claude-fable-5' | 'claude-opus-4-8' | 'claude-sonnet-5' | 'claude-haiku-4-5-20251001'\n\nconst CLAUDE_CLI_MODEL_IDS: readonly ClaudeCliModelId[] = [\n 'claude-fable-5',\n 'claude-opus-4-8',\n 'claude-sonnet-5',\n 'claude-haiku-4-5-20251001',\n]\n\n/**\n * Reasoning effort levels admitted by the `claude` CLI's `--effort` flag.\n *\n * A strict superset of `@gullabs/core`'s `ReasoningEffort` union (which is\n * `'none' | 'low' | 'medium' | 'high' | 'xhigh'`) — `'max'` is the extra\n * value the CLI supports that core's engine-level type does not know about.\n * Because of this mismatch, `admittedReasoningEfforts` (typed\n * `ReadonlyArray<ReasoningEffort>` in `ModelDescriptor.capabilities`) is\n * intentionally OMITTED below rather than cast — this package's own zod\n * schema is the sole validator for `reasoning.effort`, so the field is\n * advisory-only and safe to skip.\n */\nconst CLAUDE_CLI_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\n\n/**\n * Build the strict per-model config schema for a `claude-cli` model.\n *\n * No `temperature`/`topP`/`topK`/`maxOutputTokens`/`stopSequences` fields —\n * the CLI does not support tuning any of these, and `z.strictObject` rejects\n * any unknown key outright (reject, don't map/clamp).\n */\nfunction buildClaudeCliConfigSchema(modelName: string): z.ZodType {\n return z\n .strictObject({\n reasoning: z\n .strictObject({\n effort: z.enum(CLAUDE_CLI_EFFORTS).meta({\n title: 'Reasoning Effort',\n description: `Reasoning effort forwarded to the claude CLI's --effort flag for ${modelName}.`,\n }),\n })\n .optional()\n .meta({\n title: 'Reasoning',\n description: `Reasoning configuration for ${modelName}.`,\n }),\n timeoutMs: z.number().int().positive().max(1_800_000).optional().meta({\n title: 'Timeout',\n description:\n 'Logical request timeout in milliseconds; forwarded to the CLI runner.',\n }),\n })\n .meta({\n title: `${modelName}Config`,\n description: `Strict claude-cli config for model ${modelName}. Text-only, no sampling knobs, effort-based reasoning.`,\n })\n}\n\nexport const ClaudeFable5ConfigSchema = buildClaudeCliConfigSchema('claude-fable-5')\nexport const ClaudeOpus48ConfigSchema = buildClaudeCliConfigSchema('claude-opus-4-8')\nexport const ClaudeSonnet5ConfigSchema = buildClaudeCliConfigSchema('claude-sonnet-5')\nexport const ClaudeHaiku45ConfigSchema = buildClaudeCliConfigSchema(\n 'claude-haiku-4-5-20251001',\n)\n\nconst CONFIG_SCHEMAS: Record<ClaudeCliModelId, z.ZodType> = {\n 'claude-fable-5': ClaudeFable5ConfigSchema,\n 'claude-opus-4-8': ClaudeOpus48ConfigSchema,\n 'claude-sonnet-5': ClaudeSonnet5ConfigSchema,\n 'claude-haiku-4-5-20251001': ClaudeHaiku45ConfigSchema,\n}\n\n// ---------------------------------------------------------------------------\n// Descriptors + registry\n// ---------------------------------------------------------------------------\n\nexport const claudeCliModelDescriptors: ModelDescriptor[] = CLAUDE_CLI_MODEL_IDS.map(\n (id): ModelDescriptor => {\n const configSchema = CONFIG_SCHEMAS[id]\n return {\n model: id,\n provider: 'claude-cli',\n capabilities: {\n structuredOutput: true,\n nativeStructuredOutput: true,\n reasoningApi: 'level',\n sampling: 'fixed',\n vision: false,\n },\n configSchema,\n configJsonSchema: toConfigJsonSchema(configSchema),\n validateConfig: zodToStandardSchema(configSchema),\n }\n },\n)\n\nexport const claudeCliRegistry: ModelRegistry = createModelRegistry(\n claudeCliModelDescriptors,\n)\n","/**\n * `claudeCliProvider` — {@link ProviderPlugin} factory for @gullabs/claude-cli.\n *\n * Bundles the dev-only Claude CLI adapter with its model descriptors. This\n * provider is unpriced by design (dev-only CLI, $0 API spend) — the returned\n * plugin has no `pricingSource`.\n *\n * @module\n */\n\nimport type { ProviderPlugin } from '@gullabs/core'\n\nimport { claudeCliAdapter } from './adapter.js'\nimport type { ClaudeCliAdapterOptions } from './adapter.js'\nimport { claudeCliModelDescriptors } from './models.js'\n\n/**\n * Create a {@link ProviderPlugin} for the dev-only Claude Code CLI provider.\n *\n * Unpriced by design: the returned plugin omits `pricingSource` entirely.\n *\n * @param opts - Forwarded to {@link claudeCliAdapter}.\n * @returns A plugin bundling the Claude CLI adapter and its model descriptors.\n *\n * @example\n * ```ts\n * import { createClient, composeProviders } from '@gullabs/core'\n * import { claudeCliProvider } from '@gullabs/claude-cli'\n *\n * const client = createClient({\n * ...composeProviders([claudeCliProvider()]),\n * })\n * ```\n */\nexport function claudeCliProvider(opts?: ClaudeCliAdapterOptions): ProviderPlugin {\n return {\n adapter: claudeCliAdapter(opts),\n modelDescriptors: claudeCliModelDescriptors,\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gullabs/claude-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Dev-only Claude Code CLI provider adapter for any-llm — routes calls through a locally-authenticated `claude` CLI session for $0 API spend during workflow iteration. NOT for production use.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"zod": "^4.4.3",
|
|
27
|
-
"@gullabs/core": "0.
|
|
27
|
+
"@gullabs/core": "0.13.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@gullabs/testing": "0.
|
|
30
|
+
"@gullabs/testing": "0.7.0"
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=20.9.0"
|