/** * The first real `LlmRunner` in peaks-loop: it binds a caller to the * Anthropic Messages API shape at `/v1/messages`, * which is the same endpoint the running session is already using. * * Why this exists: `peaks audit goal` is the entry gate for every * peaks-* workflow, and until this file landed the CLI could only answer * with a fixed `scaffold-only` envelope — a gate that gated nothing. * * No SDK and no new runtime dependency: Node 18+ global `fetch` covers it. * Every transport concern (auth scheme, timeout, text extraction) lives * here so the CLI layer never speaks HTTP itself, and so tests can inject * a fake transport instead of reaching the network. */ import type { LlmRunner } from '../audit/audit-goal-service.js'; /** * The subset of `Response` this client touches. Declared narrowly so tests * can inject a plain object and stay off the network. */ export interface LlmHttpResponse { readonly ok: boolean; readonly status: number; json(): Promise; text(): Promise; } export interface LlmFetchInit { readonly method: string; readonly headers: Record; readonly body: string; readonly signal: AbortSignal; } export type FetchLike = (url: string, init: LlmFetchInit) => Promise; /** Which header carries the credential. */ export type AnthropicAuthScheme = 'bearer' | 'x-api-key'; export interface AnthropicConfig { readonly baseUrl: string; readonly authToken: string; readonly authScheme: AnthropicAuthScheme; readonly model: string; } /** * Thrown when the environment cannot name a usable LLM. `code` distinguishes * an absent credential from an absent model so the CLI can name the env var * to set instead of degrading into a scaffold. */ export declare class LlmBindingError extends Error { readonly code: 'LLM_CREDENTIAL_MISSING' | 'LLM_MODEL_MISSING'; /** * The environment variables that were absent, verbatim. * * `message` also names them, but `fail()` runs every envelope message * through `redactSensitiveErrorMessage`, whose catch-all pattern matches * the words `token` / `api_key` and would strip them out of this very * message. Callers must surface `missingEnv` on a channel the redactor * does not touch (envelope `data` / `nextActions`) so the operator is told * exactly what to set. */ readonly missingEnv: readonly string[]; constructor(code: 'LLM_CREDENTIAL_MISSING' | 'LLM_MODEL_MISSING', message: string, missingEnv: readonly string[]); } /** Thrown when a bound LLM could not be reached, answered non-2xx, or answered without text. */ export declare class LlmRequestError extends Error { readonly code: "LLM_REQUEST_FAILED"; constructor(message: string); } /** * Resolve the session's LLM from the environment. * * Precedence: * - credential: `ANTHROPIC_AUTH_TOKEN` first (it is what a Claude-Code * session exports for a gateway), else `ANTHROPIC_API_KEY`. * - auth header: `Authorization: Bearer` for `ANTHROPIC_AUTH_TOKEN`, * `x-api-key` for `ANTHROPIC_API_KEY` — each matches its own convention. * - model: `ANTHROPIC_MODEL`, else `CLAUDE_CODE_SUBAGENT_MODEL`. * - base URL: `ANTHROPIC_BASE_URL`, else the public Anthropic endpoint. * Expected WITHOUT a trailing `/v1` — this function appends `/v1/messages`. * * Throws `LlmBindingError` rather than defaulting: a gate that quietly * falls back is the bug this file was written to remove. */ export declare function resolveAnthropicConfig(env?: NodeJS.ProcessEnv): AnthropicConfig; export interface AnthropicRunnerOptions { /** Injected transport. Tests pass a fake so no test performs a network call. */ readonly fetchImpl?: FetchLike; readonly timeoutMs?: number; } export declare function createAnthropicRunner(config: AnthropicConfig, options?: AnthropicRunnerOptions): LlmRunner;