import type { HarnessModelSpec } from "@claudexor/core"; import { harnessBinaryIdentity, harnessBinaryIdentityOnPath, runCapture } from "@claudexor/core"; import type { HarnessModel } from "@claudexor/schema"; type Env = Record; /** * The manifest declaration of what `models()` proves — kept beside the * producer so the two halves cannot drift apart (INV-104, codex precedent). * `model_inventory_routes` is OMITTED on purpose: the picker answers on every * route (logged out included), so the producer serves unscoped queries too. */ export declare const CLAUDE_MODEL_INVENTORY: { readonly model_inventory_absence: "advisory"; }; /** Exactly what the probe spawns. NEVER `--model`: the picker echoes it back * as a fabricated row with an invented effort ladder. */ export declare const CLAUDE_MODEL_PROBE_ARGS: readonly string[]; export declare const CLAUDE_MODEL_PROBE_TIMEOUT_MS = 10000; export declare const CLAUDE_MODEL_PROBE_TTL_MS: number; export declare const CLAUDE_MODEL_PROBE_FAILURE_TTL_MS = 60000; /** The one stdin frame: the initialize handshake interactive runs also open with. */ export declare function claudeInitializeFrame(): string; export interface ClaudeInitializePickerRow { value: string; displayName: string | null; resolvedModel: string | null; } export interface ClaudeInitializeAnswer { models: ClaudeInitializePickerRow[]; } /** * Pure parse of the probe's stdout: the line whose `control_response` answers * OUR request id with `subtype: "success"` and a `models` array. Hook frames * (`system/hook_started`, …) may precede it, so the frame is selected by id, * never by position. Anything else — no such frame, an error subtype, a * non-array picker — is a probe failure (`null`), never "no models". * `description`, effort fields and `supportsFastMode` are deliberately not * read (no per-model effort harvesting in v1; no regex over model prose). */ export declare function parseClaudeInitialize(stdout: string, requestId: string): ClaudeInitializeAnswer | null; /** * The rows every consumer sees, in this order and deduplicated by exact id: * 1. each picker selector verbatim (`origin: "live"`, `resolved_model` = what * the vendor says it resolves to; the alias→resolution link stays on the * alias row); * 2. each resolution not already a row of its own (`origin: "live"`) — a * vendor-endorsed exact id a dropdown can pin (owner Q7: no free text); * 3. every frozen `CLAUDE_KNOWN_MODELS` id not already present * (`origin: "hint"`) — the presence floor, which is ALL of the answer when * the probe failed. `context_window: null` always (the only sources would * be the `[1m]` suffix or description prose); `routes: null` (the answer * already reflects the route it ran under). */ export declare function claudeModelRows(answer: ClaudeInitializeAnswer | null): HarnessModel[]; export type ClaudeModelProbeScope = { kind: "profile"; key: string; configDir: string; } | { kind: "credential"; key: string; envKey: "ANTHROPIC_API_KEY" | "CLAUDE_CODE_OAUTH_TOKEN"; secretRef: string | null; } | { kind: "binary"; key: "binary"; }; /** * Which store the probe reads. A `config_dir_login` profile is probed under * its OWN config dir; an `api_key` / `oauth_token` profile with its OWN * credential in the env var its runs use; no profile (the unscoped listing) * gets the credential-free binary probe. The scope key is the account half of * the cache key; it never carries secret bytes (a config dir path or a profile * id, not a token). */ export declare function claudeModelProbeScope(spec?: HarnessModelSpec): ClaudeModelProbeScope; /** * The env PATCH the probe child spawns under (applied by `runCapture` over the * normalized host env; `null` deletes). Provider secrets are scrubbed on every * scope; the profile scope re-adds nothing (the keychain bridge IS the * credential transport), the credential scope re-adds exactly the profile's * own variable, and both credential-free scopes point HOME/config at the * scratch dir. Every model-override key present anywhere in the effective env * is deleted explicitly so the answer describes the binary, not this host. */ export declare function claudeModelProbeEnv(scope: ClaudeModelProbeScope, base: Env | undefined, scratchDir: string, secret?: string | null): Env; /** Injection seams (tests only; production callers pass the adapter's secret resolver). */ export interface ClaudeModelProbeDeps { runCapture?: typeof runCapture; binaryIdentity?: typeof harnessBinaryIdentity; binaryIdentityOnPath?: typeof harnessBinaryIdentityOnPath; /** The profile's credential for a credential scope (never logged, never keyed). */ resolveProfileSecret?: (ref: string) => string | null; nowMs?: () => number; } /** Drop every cached answer and forget in-flight probes (tests). A login or * logout changes the account half of a profile scope, and nothing calls this * on that path today: such a profile can serve its previous rows for up to * the hour-long TTL, and `fresh: true` on the query is the bypass. */ export declare function clearClaudeModelProbeCache(): void; /** * The adapter's `models()`: TOTAL and never empty. Any failure — the binary * missing, a spawn error, a timeout/signal, an unparseable answer, an env * derivation error (bad profile locator, keychain bridge) — yields the hint * rows alone, so presence never shrinks below the manifest and a listing can * never make a caller believe the account has no models. */ export declare function probeClaudeModels(spec?: HarnessModelSpec, deps?: ClaudeModelProbeDeps): Promise; export {}; //# sourceMappingURL=model-probe.d.ts.map