import { type RuntimeMode } from "@jam-mcp/launcher"; import type { CredentialDescription, CredentialPort, CredentialSource } from "../ports/credentials.port.js"; import { type HostRunner, type HostState } from "./host-mcp.js"; import { type McpInspection } from "./mcp-config-merger.js"; import { type ProjectBinding } from "./project-bindings.js"; import { type GitRemoteFn } from "./workspace-identity.js"; export type RuntimeState = { configured: boolean; mode?: RuntimeMode; source?: string; version?: string; /** Set when a runtime is configured but cannot currently be resolved. */ error?: string; }; export type CredentialState = { present: boolean; source: CredentialSource; /** Which source supplied each field. Names only - never a value. */ sources?: CredentialDescription["sources"]; baseUrl?: string; email?: string; }; export type ProjectState = { root: string; hasConfig: boolean; configPath?: string; key?: string; /** Set when a config file exists but could not be parsed. */ error?: string; /** What this user has bound this workspace to, if anything. */ binding?: ProjectBinding; }; export type SetupState = { cwd: string; /** Stable id for this workspace - what a personal binding is recorded against. */ workspaceId: string; /** * True when `~/.jam/projects.yaml` exists but could not be read. Recorded * rather than thrown so planning can refuse to rewrite it, instead of * discovering the problem halfway through applying. */ bindingsUnreadable: boolean; runtime: RuntimeState; credentials: CredentialState; project: ProjectState; mcp: McpInspection & { jamEntryIsLegacy: boolean; }; /** * The coding agents on this machine and whether each already knows about * jam. Empty unless probing was asked for: it costs a process launch per * host, which `jam doctor` has no reason to pay. */ hosts: HostState[]; /** * The version the global `jam` executable actually runs, when one answers. * Measured with the hosts (same probe budget); undefined otherwise. This is * what decides whether a repair registers bare `jam` or an npx pin. */ bareLauncher?: string; }; export type DetectOptions = { cwd?: string; /** Injected by tests to isolate ~/.jam. */ home?: string; credentials?: CredentialPort; /** Injected by tests so identity never depends on the checkout under test. */ git?: GitRemoteFn; /** Probe the host CLIs. Only the setup paths need this. */ probeHosts?: boolean; /** Injected by tests so no test ever reaches a real host CLI. */ runHost?: HostRunner; }; /** * Snapshot everything setup needs to decide, without changing any of it. * * Strictly read-only: no file is created, and no config is bootstrapped. That * separation is what makes `setup plan` safe to run speculatively, and what * lets an agent inspect a machine before proposing anything. */ export declare function detectSetupState(options?: DetectOptions): SetupState;