diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts index b101170c..1b27bbd4 100644 --- a/client/src/lib/api.ts +++ b/client/src/lib/api.ts @@ -388,6 +388,7 @@ import type { LaneCounts, LaneGitFacts, LaneRuntime, + LaneTool, ModelPricing, NamedLock, PipelineStats, @@ -1569,8 +1570,9 @@ export const api = { if (options?.laneId !== undefined) qs.set("laneId", String(options.laneId)); return request<{ items: DashboardRunHistoryItem[] }>(`/run/history?${qs.toString()}`); }, - /** GET /api/run/binary - whether `claude` was found on PATH. */ - binary: () => request<{ found: boolean; path: string | null }>("/run/binary"), + /** GET /api/run/binary - whether the lane's CLI (`claude` or `codex`) was found on PATH. */ + binary: (tool: LaneTool = "claude") => + request<{ found: boolean; path: string | null }>(`/run/binary?tool=${tool}`), /** GET /api/run/tmux - whether the `tmux` binary was found on PATH. */ tmuxAvailable: () => request<{ available: boolean }>("/run/tmux"), /** GET /api/run/cwds - suggested working directories for the cwd picker. */ @@ -1907,7 +1909,7 @@ export const api = { * location isn't tied to a specific project (e.g. Sagi's mascot lane). * @returns `{ lane, created }` — the lane (newly created or existing) and whether it was created. */ - ensure: (body: { cwd?: string; title?: string; pipeline?: string }) => + ensure: (body: { cwd?: string; title?: string; pipeline?: string; tool?: LaneTool }) => request<{ lane: Lane; created: boolean }>("/lanes/ensure", { method: "POST", body: JSON.stringify(body), @@ -1955,6 +1957,7 @@ export const api = { base?: string; branch?: string; pipeline?: string; + tool?: LaneTool; }) => request<{ lane: Lane }>("/lanes/worktree", { method: "POST", @@ -2589,6 +2592,9 @@ export type EffortLevel = "" | "low" | "medium" | "high" | "xhigh" | "max"; * state on every read, never cached. */ export type RunStatus = "running" | "gone"; +export type CodexSandbox = "read-only" | "workspace-write" | "danger-full-access"; +export type CodexApproval = "on-request" | "never"; + /** Body for POST /api/run - parameters for starting a lane's terminal run. */ export interface RunStartArgs { laneId: number; @@ -2601,6 +2607,12 @@ export interface RunStartArgs { /** Sent as `claude`'s first positional message once the pane boots; omit * to just open the pane and let the user type. */ initialPrompt?: string; + /** Codex only: `-s`. Ignored by a claude lane. */ + sandbox?: CodexSandbox; + /** Codex only: `-a`. Ignored by a claude lane. */ + approval?: CodexApproval; + /** Codex only: `codex resume --last` instead of picking a session id. */ + resumeLast?: boolean; } /** A lane's tmux-backed terminal run — one per lane, id is the tmux session @@ -2620,6 +2632,7 @@ export interface RunHandle { startedAt: string | null; /** Initial prompt preview (first 500 chars), null when not provided. */ promptPreview: string | null; + tool: LaneTool; } /** Response shape of GET /api/run. */ @@ -2650,6 +2663,7 @@ export interface DashboardRunHistoryItem { started_at: string; ended_at: string | null; isLive: boolean; + tool: LaneTool; } /** One suggested working directory for the Run page's cwd picker. */ diff --git a/client/src/lib/types.ts b/client/src/lib/types.ts index 5d5d7b90..c3d86f45 100644 --- a/client/src/lib/types.ts +++ b/client/src/lib/types.ts @@ -2281,12 +2281,17 @@ export interface ProofFeature { mtime: number; } +/** Which CLI drives a lane's pane. Fixed at lane creation and never patched. */ +export type LaneTool = "claude" | "codex"; + export interface Lane { id: number; title: string; cwd: string; branch: string | null; kind: "managed" | "adopted"; + /** The CLI this lane's runs spawn. Immutable once the lane exists. */ + tool: LaneTool; /** For a managed worktree lane, the repo it was provisioned from. Null for * an adopted lane (it IS a source repo, not a worktree of one). */ source_repo: string | null;