import { z } from 'zod'; import { type Runner } from './health.ts'; /** * The workspace + settings families: `~/.cezar/config.json`'s settings slice, both GUI-pref bags * (per-repo and workspace), the per-repo agent knobs, provider auth status, the host model * catalog, the skills-update state, and the "Open in…" targets. * * Node-free by construction (see README rule 1) — `zod` and the sibling contract modules only. */ /** * `GET/PUT /api/v1/workspace/config` — the settings slice of `~/.cezar/config.json` (step 2.7). * * Global knobs only: the registry itself is `GET /api/v1/projects`, and `schemaVersion` (a * migration cursor, not a setting) is deliberately absent. `resources` is the workspace's * host-protection budget — the ONLY effective `maxParallel`/`memoryLimitMb` since Phase 2; * `worktreeRetentionDefault` seeds projects that set none. * * `composerDefaults` and every `resources` key are REQUIRED: `workspaceConfigBody` * (src/server/server.ts:1888) materializes all of them from schema defaults on every answer, * including the degraded path. The hand-written DTO declared `composerDefaults`, * `resources.maxMonitoringSessions` and `resources.monitoringWakeIntervalMinutes` optional, which * was wider than the server has ever been. */ export declare const workspaceConfigResponseSchema: z.ZodObject<{ browseRoot: z.ZodString; projectsDir: z.ZodString; skillsAutoUpdate: z.ZodNullable; effectiveSkillsAutoUpdate: z.ZodBoolean; composerDefaults: z.ZodObject<{ autonomous: z.ZodNullable; worktree: z.ZodNullable; inheritedAutonomous: z.ZodUnion]>; inheritedWorktree: z.ZodBoolean; }, z.core.$strip>; resources: z.ZodObject<{ maxParallel: z.ZodNumber; maxMonitoringSessions: z.ZodNumber; monitoringWakeIntervalMinutes: z.ZodNullable; autoResumeOnUsageLimit: z.ZodBoolean; memoryLimitMb: z.ZodNullable; worktreeRetentionDefault: z.ZodNumber; }, z.core.$strip>; agentDefaults: z.ZodObject<{ runner: z.ZodOptional>; models: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strip>>; }, z.core.$strip>; }, z.core.$strip>; export type WorkspaceConfigResponse = z.infer; /** * `PUT /api/v1/workspace/config` body — partial: absent keys stay untouched. A rejected workspace * root (not writable) 400s with the reason and persists NOTHING, resources included, so callers * may send both in one request only if they want that atomicity. Bounds mirror * `src/workspace/config.ts` exactly, so a value this schema accepts can never be degraded away by * the next load's `.catch`. */ export declare const setWorkspaceConfigInputSchema: z.ZodObject<{ browseRoot: z.ZodOptional; projectsDir: z.ZodOptional; skillsAutoUpdate: z.ZodOptional>; composerDefaults: z.ZodOptional>; worktree: z.ZodOptional>; }, z.core.$strip>>; agentDefaults: z.ZodOptional>>; models: z.ZodOptional>; codex: z.ZodOptional>; opencode: z.ZodOptional>; pi: z.ZodOptional>; }, z.core.$strip>>; }, z.core.$strip>>; resources: z.ZodOptional; maxMonitoringSessions: z.ZodOptional; monitoringWakeIntervalMinutes: z.ZodOptional>; autoResumeOnUsageLimit: z.ZodOptional; memoryLimitMb: z.ZodOptional>; worktreeRetentionDefault: z.ZodOptional; }, z.core.$strip>>; }, z.core.$strip>; export type SetWorkspaceConfigInput = z.infer; /** * `GET/PUT /api/v1/ui-state` — the per-repo GUI prefs in `.ai/cezar/ui-state.json`. * * An OPEN bag on purpose (BACKWARD_COMPATIBILITY.md §3): unknown keys round-trip untouched, so a * newer cockpit's prefs survive an older server and a future pref needs no server change. Hence * `z.looseObject`, not a closed object — the keys below are the ones the server's schema *names*, * never the ones it *permits*. The write side caps the TOP-LEVEL key count at 200 (#429); that cap * is a request-body refinement in `src/server/server.ts` (`capUiStateKeys`, :756) and is not part * of the response shape. * * `notifications` is deliberately NOT here: it moved to `WorkspaceUiState` at step 3.5 and the * per-repo schema (src/server/server.ts:550) has not named it since. The hand-written DTO still * listed it, which made it wider than the route. */ export declare const uiStateSchema: z.ZodObject<{ lastTask: z.ZodOptional; ref: z.ZodString; }, z.core.$strip>>; recentSources: z.ZodOptional; ref: z.ZodString; }, z.core.$strip>>>; lastWorktree: z.ZodOptional; lastAutonomous: z.ZodOptional; lastGenerateFollowups: z.ZodOptional; skillUsage: z.ZodOptional>; runsView: z.ZodOptional>; githubView: z.ZodOptional>; appearance: z.ZodOptional>; density: z.ZodOptional>; width: z.ZodOptional>; }, z.core.$strip>>; promptTemplates: z.ZodOptional>; }, z.core.$strip>>>; dismissedSkillsBanner: z.ZodOptional; }, z.core.$loose>; export type UiState = z.infer; /** * `GET/PUT /api/v1/workspace/ui-state` — cross-project GUI prefs in `~/.cezar/ui-state.json` * (multi-project spec, step 2.7). * * The same open bag as its per-repo twin above, and open for the same reason. The PUT merges * SHALLOWLY at the top level server-side, so a writer must send the whole `sidebar` object (or the * whole `importedSkills` array), never a leaf. */ export declare const workspaceLastLocationSchema: z.ZodObject<{ projectId: z.ZodString; pathname: z.ZodString; search: z.ZodOptional; hash: z.ZodOptional; }, z.core.$strict>; export type WorkspaceLastLocation = z.infer; export declare const workspaceUiStateSchema: z.ZodObject<{ sidebar: z.ZodOptional>; }, z.core.$loose>>; dismissedProviderAuthFailures: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strip>>; appearance: z.ZodOptional>; density: z.ZodOptional>; width: z.ZodOptional>; }, z.core.$strip>>; notifications: z.ZodOptional; }, z.core.$loose>>; taskTable: z.ZodOptional>; }, z.core.$loose>>; lastLocation: z.ZodOptional; hash: z.ZodOptional; }, z.core.$strict>>; importedSkills: z.ZodOptional>; }, z.core.$loose>; export type WorkspaceUiState = z.infer; /** * `PUT /api/v1/workspace/ui-state` body. The response remains an open, tolerant bag so data from * a newer cockpit survives an older server; this write-side schema adds bounded known fields so * the current cockpit cannot grow the user-owned file without limit. */ export declare const setWorkspaceUiStateInputSchema: z.ZodObject<{ appearance: z.ZodOptional>; density: z.ZodOptional>; width: z.ZodOptional>; }, z.core.$strip>>; notifications: z.ZodOptional; }, z.core.$loose>>; lastLocation: z.ZodOptional; hash: z.ZodOptional; }, z.core.$strict>>; sidebar: z.ZodOptional>; }, z.core.$loose>>; dismissedProviderAuthFailures: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strict>>; importedSkills: z.ZodOptional>; taskTable: z.ZodOptional>; }, z.core.$loose>>; }, z.core.$loose>; export type SetWorkspaceUiStateInput = z.infer; /** Per-runner default model preset (Settings → Agents): the composer preselects this model id for * the runner. Absent = auto (the runner decides). Keyed by runner name rather than derived from * `runnerSchema` because the server's own `defaultModels` object (src/config.ts:92) is spelled * the same way — one key per runner, each independently optional. */ export declare const runnerModelsSchema: z.ZodObject<{ claude: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strip>; export type RunnerModels = z.infer; /** `GET /api/v1/config` — every Settings → Agents knob in one read. */ export declare const configResponseSchema: z.ZodObject<{ baseBranch: z.ZodNullable; defaultRunner: z.ZodEnum<{ claude: "claude"; codex: "codex"; opencode: "opencode"; pi: "pi"; }>; systemPrompt: z.ZodNullable; defaultModels: z.ZodObject<{ claude: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strip>; modelsLocked: z.ZodBoolean; maxParallel: z.ZodNumber; memoryLimitMb: z.ZodNullable; worktreeRetention: z.ZodNumber; liveTitleUpdates: z.ZodNullable; reviewGate: z.ZodNullable; }, z.core.$strip>; export type ConfigResponse = z.infer; /** The `PUT /api/v1/config` answer: the same shape GET serves (`configAnswer` builds both). */ export declare const setConfigResponseSchema: z.ZodObject<{ baseBranch: z.ZodNullable; defaultRunner: z.ZodEnum<{ claude: "claude"; codex: "codex"; opencode: "opencode"; pi: "pi"; }>; systemPrompt: z.ZodNullable; defaultModels: z.ZodObject<{ claude: z.ZodOptional; codex: z.ZodOptional; opencode: z.ZodOptional; pi: z.ZodOptional; }, z.core.$strip>; modelsLocked: z.ZodBoolean; maxParallel: z.ZodNumber; memoryLimitMb: z.ZodNullable; worktreeRetention: z.ZodNumber; liveTitleUpdates: z.ZodNullable; reviewGate: z.ZodNullable; }, z.core.$strip>; export type SetConfigResponse = z.infer; /** * `PUT /api/v1/config` body (Settings → Agents; the Repo tab's base-branch picker). * `baseBranch: null` clears the setting back to "follow checked-out branch"; `systemPrompt` and * per-runner `defaultModels` entries clear on `null` (or `''`) too. Merged into the raw * config.json server-side — `defaultModels` merges per runner, so one write never clobbers * another runner's preset. */ export declare const setConfigInputSchema: z.ZodObject<{ baseBranch: z.ZodOptional>; defaultRunner: z.ZodOptional>; systemPrompt: z.ZodOptional>; defaultModels: z.ZodOptional>; codex: z.ZodOptional>; opencode: z.ZodOptional>; pi: z.ZodOptional>; }, z.core.$strip>>; maxParallel: z.ZodOptional; memoryLimitMb: z.ZodOptional>; worktreeRetention: z.ZodOptional>; liveTitleUpdates: z.ZodOptional>; reviewGate: z.ZodOptional>; }, z.core.$strip>; export type SetConfigInput = z.infer; export declare const skillsUpdateStatusSchema: z.ZodEnum<{ available: "available"; checking: "checking"; current: "current"; error: "error"; idle: "idle"; unavailable: "unavailable"; updating: "updating"; }>; export type SkillsUpdateStatus = z.infer; export declare const skillsUpdateScopeStateSchema: z.ZodObject<{ scope: z.ZodEnum<{ global: "global"; project: "project"; }>; status: z.ZodEnum<{ available: "available"; checking: "checking"; current: "current"; error: "error"; idle: "idle"; unavailable: "unavailable"; updating: "updating"; }>; available: z.ZodBoolean; skills: z.ZodArray; checkedAt: z.ZodNullable; updatedAt: z.ZodNullable; reason: z.ZodOptional; }, z.core.$strip>; export type SkillsUpdateScopeState = z.infer; /** `GET /api/v1/workspace/skills-update` (and the check/apply POSTs) — the merged project+global * skills-update state. `autoUpdateEnabled`/`inherited` are re-stamped from the workspace config * on the way out (`skillsUpdateResponse`, src/server/server.ts:1818). */ export declare const skillsUpdateStateSchema: z.ZodObject<{ status: z.ZodEnum<{ available: "available"; checking: "checking"; current: "current"; error: "error"; idle: "idle"; unavailable: "unavailable"; updating: "updating"; }>; available: z.ZodBoolean; autoUpdateEnabled: z.ZodBoolean; inherited: z.ZodBoolean; checkedAt: z.ZodNullable; updatedAt: z.ZodNullable; scopes: z.ZodArray; status: z.ZodEnum<{ available: "available"; checking: "checking"; current: "current"; error: "error"; idle: "idle"; unavailable: "unavailable"; updating: "updating"; }>; available: z.ZodBoolean; skills: z.ZodArray; checkedAt: z.ZodNullable; updatedAt: z.ZodNullable; reason: z.ZodOptional; }, z.core.$strip>>; needsUpgradeNotes: z.ZodBoolean; }, z.core.$strip>; export type SkillsUpdateState = z.infer; /** The agent backends are the providers — one alias, never a second enum. */ export declare const providerIdSchema: z.ZodEnum<{ claude: "claude"; codex: "codex"; opencode: "opencode"; pi: "pi"; }>; export type ProviderId = Runner; /** Coarse host authentication state. Credentials, account identity, and raw CLI output never * cross this boundary. */ export declare const providerConnectionStateSchema: z.ZodEnum<{ connected: "connected"; disconnected: "disconnected"; "not-installed": "not-installed"; unknown: "unknown"; }>; export type ProviderConnectionState = z.infer; /** * One provider row. * * `enabled` is OPTIONAL: `ProviderAuth.status()` (src/core/provider-auth.ts:12) builds rows * without it and only `applyProviderEnablement` stamps it in, so the type the routes answer keeps * the key optional. The hand-written DTO declared it required — narrower than the route. */ export declare const providerStatusSchema: z.ZodObject<{ provider: z.ZodEnum<{ claude: "claude"; codex: "codex"; opencode: "opencode"; pi: "pi"; }>; status: z.ZodEnum<{ connected: "connected"; disconnected: "disconnected"; "not-installed": "not-installed"; unknown: "unknown"; }>; enabled: z.ZodOptional; hint: z.ZodOptional; authFailureId: z.ZodOptional; profileId: z.ZodOptional; }, z.core.$strip>; export type ProviderStatus = z.infer; /** `GET /api/v1/providers/status`, and the answer of the enabled/retry mutators. */ export declare const providerStatusResponseSchema: z.ZodObject<{ providers: z.ZodArray; status: z.ZodEnum<{ connected: "connected"; disconnected: "disconnected"; "not-installed": "not-installed"; unknown: "unknown"; }>; enabled: z.ZodOptional; hint: z.ZodOptional; authFailureId: z.ZodOptional; profileId: z.ZodOptional; }, z.core.$strip>>; }, z.core.$strip>; export type ProviderStatusResponse = z.infer; /** `POST /api/v1/providers/connect` — either a terminal was handed the login command, or the * provider turned out to be connected already. Every other outcome is a 409/500 carrying the * same `command` for the clipboard fallback. */ export declare const providerConnectResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ opened: z.ZodLiteral; command: z.ZodString; }, z.core.$strip>, z.ZodObject<{ opened: z.ZodLiteral; connected: z.ZodLiteral; command: z.ZodString; }, z.core.$strip>], "opened">; export type ProviderConnectResponse = z.infer; /** * The runners whose model list is discovered from the host rather than hard-coded: Codex * through its app-server protocol, OpenCode through its own `models` listing (#794). Claude has * no equivalent local source, so its picker keeps static presets and `GET /api/v1/models` * rejects it. One definition, used by the route's query validator and by the cockpit's picker. */ export declare const modelDiscoveryRunnerSchema: z.ZodEnum<{ codex: "codex"; opencode: "opencode"; }>; export type ModelDiscoveryRunner = z.infer; export declare const MODEL_DISCOVERY_RUNNERS: readonly ModelDiscoveryRunner[]; /** True when `runner` has a host-discovered catalog (and therefore a `/models` answer). */ export declare function runnerDiscoversModels(runner: Runner): runner is ModelDiscoveryRunner; export declare const runnerModelOptionSchema: z.ZodObject<{ id: z.ZodString; label: z.ZodString; description: z.ZodString; }, z.core.$strip>; export type RunnerModelOption = z.infer; /** `GET /api/v1/models?runner=codex|opencode` — the models discovered from that runner's own * host installation, plus how fresh the answer is. Never an error: an unavailable CLI degrades * to `source: 'unavailable'` with a `reason`. Claude has no host-local catalog and is rejected. */ export declare const runnerModelCatalogResponseSchema: z.ZodObject<{ runner: z.ZodEnum<{ claude: "claude"; codex: "codex"; opencode: "opencode"; pi: "pi"; }>; models: z.ZodArray>; source: z.ZodEnum<{ cache: "cache"; live: "live"; unavailable: "unavailable"; }>; stale: z.ZodBoolean; reason: z.ZodOptional; }, z.core.$strip>; export type RunnerModelCatalogResponse = z.infer; /** A local app a worktree can be opened in (#open-in): editor, file manager, or terminal. */ export declare const openTargetSchema: z.ZodObject<{ id: z.ZodString; label: z.ZodString; icon: z.ZodOptional; }, z.core.$strip>; export type OpenTarget = z.infer; /** `GET /api/v1/open-targets` — the detected local apps; empty in hosted mode (CEZ_REMOTE). */ export declare const openTargetsResponseSchema: z.ZodObject<{ targets: z.ZodArray; }, z.core.$strip>>; }, z.core.$strip>; export type OpenTargetsResponse = z.infer; /** * `POST /api/v1/open-in` — open THIS PROJECT'S root in a detected app (Settings → the project * folder row). The path is never sent: it is the scoped project's own registered root, resolved * server-side, so the route has no traversal surface at all. `target` is an * `/api/v1/open-targets` id; unlike the run route there is no `default`/`cli:` handling, because * a repo root is a directory and an agent CLI belongs in a task worktree. */ export declare const openProjectInSchema: z.ZodObject<{ target: z.ZodString; }, z.core.$strip>; export type OpenProjectInRequest = z.infer; /** The 200 for the above — `opened` is a literal because every failure is a 409 with `{ error }`, * so a `false` would be unreachable and would only invite a client to branch on it. */ export declare const openProjectInResponseSchema: z.ZodObject<{ opened: z.ZodLiteral; path: z.ZodString; }, z.core.$strip>; export type OpenProjectInResponse = z.infer;