import { type DevCredential } from "../harnesses/inference/resolve.js"; import { type CloudDoctorResult } from "./cloud/client.js"; import type { SelectOption } from "./pretty.js"; import { type Output, type TelemetryOptions } from "./shared.js"; /** * ENG-339 (install-dx design §6) — cloud in init. Detect VENDO_API_KEY when * present and check its shape locally (key problems surface on the first real * service call), one calm line when absent, and — when a starter model key * would actually help the ladder — offer `vendo login` inline: the auth.md * user-claimed ceremony approves a code in the browser and lands the minted * VENDO_API_KEY in .env.local, so the dev never pastes a key. */ /** Upsert one NAME=value line in .env.local without clobbering other lines. Exported for init's --cloud-key flag, which lands a supplied key exactly where the mint below would, and for the bring-your-own-key paste. Every caller follows the write with `ensureEnvLocalIgnored` — a secret just landed on disk. */ export declare function upsertEnvLocal(root: string, name: string, value: string): Promise; /** The single answer to "we just wrote a secret to disk". A secret in an unignored, UNTRACKED file is a one-line fix, so it gets made and reported instead of turned into homework. The tracked case is the one branch that must not be silently "fixed" — .gitignore does nothing for a file already in the index — so it keeps its warning, verbatim, and so does the case where git cannot answer at all. Never blocks the write: the key is already minted and unrecoverable, so the dev needs to know, not to be stopped. Returns the line added, or null when nothing was written. */ export declare function ensureEnvLocalIgnored(root: string, output: Output): Promise; /** Which variable a pasted provider key belongs in, read off the key's own prefix. null means "cannot tell" — ask, never guess: a key in the wrong variable fails at the first turn as a provider mismatch, not a bad key. */ export declare function providerKeyVar(key: string): string | null; /** The auth.md protocol file on Vendo Cloud (Agent Install DX, Layer 2). */ export declare const AUTH_MD_URL = "https://vendo.run/auth.md"; /** The agent-path key pointer: when an agent-driven init needs a Cloud key and none exists, this block is the whole story — the CLI command that runs the user-claimed ceremony, its discovery URL, and both fallbacks (paste a key with --cloud-key; stay keyless with --byo). Three lines, not the full device-flow walkthrough: `vendo login` narrates its own ceremony step by step, and the upsell used to open a keyless init before the user learned what init did (self-serve audit F8). Deterministic lines an agent parses; exported so init's tail and the tests share one source. */ export declare function agentKeyPointerLines(): string[]; export interface CloudStepOptions { root: string; output: Output; yes: boolean; /** --byo: the explicit "no Cloud" answer — skip the offer AND the agent pointer (bring-your-own stays first-class, no nudging past it). */ byo?: boolean; /** TTY seam for the decline path (tests pin both sides). */ isTty?: boolean; /** What the model ladder resolved — decides whether a starter key helps. */ credential: DevCredential; env?: Record; apiUrl?: string; /** Fetch seam for the default ceremony (tests script the console with it). */ fetchImpl?: typeof fetch; /** How models run, answered up front instead of asked (--cloud-key ⇒ "cloud", --byo ⇒ "byo"). */ models?: ModelsAnswer; /** Seams (tests). */ confirm?: (question: string, defaultYes?: boolean) => Promise; /** The models question as a select — Cloud first and recommended, BYO one keystroke away, "decide later" the graceful exit. Absent (plain terminals, tests) keeps today's confirm. */ select?: (question: string, options: SelectOption[]) => Promise; /** The masked prompt behind "bring my own key". */ askSecret?: (question: string, hint?: string) => Promise; /** The pretty renderer is driving: the ceremony drops its machine-readable receipt, which is noise under a rail. Every machine-consumed path keeps it — see DeviceLoginOptions.pretty. */ pretty?: boolean; cloudProbe?: (options: { env?: Record; }) => Promise; /** The whole ceremony in one seam (default: runDeviceLogin). */ deviceLogin?: () => Promise; sleep?: (ms: number) => Promise; /** Injectable telemetry deps (matches init/doctor). */ telemetry?: TelemetryOptions; } export interface CloudStepResult { keyPresent: boolean; keyValid: boolean; wroteEnvLocal: boolean; /** The provider variable a bring-your-own-key paste landed in this run — re-merged by the caller exactly like a minted VENDO_API_KEY, so THIS run's model passes already benefit from the key just pasted. */ wroteKeyVar?: string; } /** The four answers to "how do you want to run models?". */ export type ModelsAnswer = "cloud" | "vendo-key" | "byo" | "later"; /** init's cloud step (design §6). Never changes init's exit code. Tracked as `command_run` command "cloud-init" (TELEMETRY.md): ok is "the step ended in a non-error outcome" — a valid key, a clean skip/decline, or a minted starter key; failures name their step. Telemetry never changes the step's behavior: the tracker is fully guarded and a thrown error still rethrows. */ export declare function runCloudStep(options: CloudStepOptions): Promise;