import { type ServerActionRegistration } from "../actions/sync/public.js"; import type { EnvKeyProvider } from "../harnesses/inference/resolve.js"; import { type AuthWire } from "./init-auth.js"; /** The wired preset line plus its escape-hatch comment. The lead-in stays honest about how the preset got here: detection cites the found dependency, a chosen one says "Selected". `hoisted` binds the preset to a module-scope `const auth` instead of writing the config key inline — what the agent-loop arm needs, where the resolver this module exports has to reach the SAME instance the wire composed. The hand-written seam ("write my own") is not a call, so it takes the same road the anonymous composition does: `authOwnSeamLines`, through the one `auth:` door. */ export declare function authConfigLines(auth: Exclude, hoisted?: boolean): string; /** * The "write my own" seam: the smallest identity object that actually BOOTS and * opens the MCP door — a fixed dev subject for `principal`, and a pass-through * `oauth` that hands the door back whatever subject it is given (the two-seam * shape tests/theme-seam.test.ts drives a real MCP client through). Everything * else on the `auth` object is optional. * * Written through the SAME one door `anonymousPrincipalLines` uses — it is that * block plus the `oauth` half — so a host that later adds `facts`, `memberships` * or `actAs` adds a member here rather than learning a second config shape. * * A fixed subject means every caller is the SAME person, so the marker rides in * the file itself and not in a summary line nobody re-reads. */ export declare function authOwnSeamLines(typescript: boolean, hoisted?: boolean): string; /** The anonymous-composition identity block (no auth preset wired), written through the ONE DOOR `auth:` takes by hand — the same key a preset fills, so the host who later adds `facts`, `memberships` or the door's `oauth` adds a member to this object instead of learning a second config shape. The subject matches the demo principal both existing-agents quickstarts set in their chat routes — the wire route MUST resolve the same subject as the host's agent loop, or every app/approval created in chat is invisible to the embeds, which call this route directly (0.4.1 E2E cert blocker B4: a `() => null` wire against a demo-user chat route rendered an infinite skeleton). Replaced wholesale when an auth preset is wired. */ export declare function anonymousPrincipalLines(typescript: boolean): string; /** The provider key init found in the host's environment at scaffold time. * Env keys are CREDENTIALS and composition SELECTS the model, so a stray * ANTHROPIC_API_KEY no longer picks one by itself — the explicit line has to * exist in the config. Init detected the key, so init writes that line; a * host that "just worked" off an ambient key keeps working. */ export interface ScaffoldModel { provider: EnvKeyProvider; /** The variable the key came from — named in the line's comment so the reader knows what still supplies it. */ envVar: string; } /** The Next.js wire route: a THIN handler over the composition module. A route module may export only route handlers, so `createVendo` cannot live here — and everything that needs the SAME instance (the host's own agent loop, the origin-root discovery route) imports the one module instead of composing a second wire that shares none of the first one's state. */ export declare function routeSource(composition: string): string; /** * The Next composition module (`lib/vendo.ts`, or `src/lib/vendo.ts`) — the one * file that calls `createVendo`, exporting the instance the thin route, the * origin-root discovery route and the host's own agent loop all import. * * On the MCP arm `auth` is non-null by construction: the door mints its own * principals through the preset's oauth half and composition throws without * one, so `planMcp` blocks before it ever reaches this function (10-mcp §3). */ export declare function compositionModuleSource(options: { serverActions: boolean; auth: AuthWire | null; /** The provider key init found, written as the explicit `models` selection. */ models?: ScaffoldModel | null; /** The MCP door (10-mcp), and whether first-party service auth is wired off the environment with it (local posture only). */ mcp?: { serviceAuth: boolean; }; /** The agent-loop arm (`--use-case agent-loop`), where the host's own loop needs the caller: this module exports the resolver too. Off on every other arm — the file is shared, and an export nothing imports is noise. */ agentLoop?: boolean; }): string; /** Where a Next host's composition lives: `lib/vendo.ts`, under `src/` exactly when the app directory is (`appDirectory`'s own rule, so the two can never land on different bases). */ export declare function compositionModulePath(root: string): Promise; /** How a file in `fromDir` imports the composition module. */ export declare function compositionSpecifier(root: string, fromDir: string): Promise; /** * The server actions the runtime will actually dispatch: the host's current * `"use server"` surface, minus whatever a judgment or a human override * disabled. `vendo init` and `vendo doctor` MUST resolve the same set — a split * here is a nag on one side (register a tool nothing will ever call) or a false * green on the other. Failure degrades to none: sync reports extraction * problems loudly, and execution fails closed on a missing registration anyway. */ export declare function requiredServerActions(root: string): Promise; /** * Host tools this run extracted and then left off WITHOUT being asked to, each * with the layer that turned it off. The run that wrote them has to name them, * or the developer meets the hole later, as an assistant that cannot answer and * will not say why. Whatever the merge decided is what this reports. * * A tool the human disabled in overrides.json is left out: that decision is * theirs and already written down, so repeating it back on every run is the nag * the receipt has always refused to be. */ export declare function disabledTools(root: string): Promise; /** * How a route composes its server-action map. Init raises the wiring paste and * doctor raises E-WIRE-009 on exactly ONE of these — `"unwired"` — so the two * share the answer instead of each pattern-matching their own way. The scope is * load-bearing: an `import { serverActions } …` line with nothing inside * `createVendo({ … })` is NOT wiring (the tools still fail closed), and it is * the likeliest real state, because it is where a half-applied paste lands. */ export type ServerActionsWiring = "wired" | "unwired" | "unknown"; export declare function serverActionsWiring(source: string): ServerActionsWiring; /** Is this a THIN route over the composition module — the shape init writes, where `createVendo` lives in `lib/vendo` because a Next.js route module may export only handlers? The composition, not the route, is the file to grade for server-action wiring; without this a thin route reads as an unrecognized composition and doctor goes quiet on a host that is wired. `./vendo` stays matched: it is what earlier MCP installs wrote next to the route. */ export declare function importsSplitComposition(source: string): boolean; /** Does this route source the GENERATED map? A route that composes its own (a local object, an aliased import) is a shape init leaves alone, so neither init nor doctor may create or grade `vendo-actions.ts` for it. */ export declare function importsGeneratedMap(source: string): boolean; /** A registration in the map's own key form. */ export declare function registrationKey(registration: ServerActionRegistration): string; /** Registrations an existing map does not carry. A map is compared by the keys it registers, never byte-for-byte: it is the developer's file from creation on, so their formatting, their comments, and their own extra entries are all legitimate — only an ABSENT key means a tool that fails closed. */ export declare function missingRegistrations(map: string, registrations: readonly ServerActionRegistration[]): ServerActionRegistration[]; /** * The generated server-action registration map (04-actions §1, ENG-248): the * wiring file imports each detected `"use server"` action module and passes * the map into `createVendo({ serverActions })`. Deterministic content — * sorted registrations, stable aliases — so re-init stays idempotent. */ export declare function serverActionsModuleSource(root: string, wiringDir: string, registrations: ServerActionRegistration[]): string; /** The runtime-neutral composition (`--framework custom`): plain Request → * Response with env passed per call, so ONE generated module serves any * Web-standard host — Cloudflare Workers, Bun, Deno, Hono, Lambda adapters. * Construction is lazy (first request): the safe shape everywhere and the * only legal one at Workers module scope. With a Vendo Cloud key the four * infrastructure seams wire the Cloud adapters explicitly per the adapter * rule (reference shape: the vendo-on-Workers field integration, * 2026-07-21). */ export declare function customServerSource(typescript: boolean, auth?: AuthWire | null): string; export declare function expressServerSource(typescript: boolean, auth?: AuthWire | null): string; /** The port the host's own dev server listens on, read off its `dev` script: `-p`/`--port` in either spelling, or a leading `PORT=`. 3000 is the answer when the script says nothing — a placeholder naming a port the host does not serve on is worse than no placeholder, because it looks answered. */ export declare function devScriptPort(script: string | undefined): number; export declare function devPort(root: string): Promise; /** Where the host answers in dev: the value the dev-URL question prefills, and the illustrative line `.env.example` carries. One spelling for both. */ export declare const devBaseUrl: (port: number) => string; export declare const baseUrlLine: (port: number) => string; export declare const vendoEnvExample: (port: number) => string;