// Fast-forward spawn (#67): one keystroke, every default resolved, no form. // Pure resolution only — the caller (main.ts) owns the fetches and the POST, // and falls back to a seeded draft pane when anything is missing. import type { CreateSessionRequest, Project, SpawnPreset } from "./types.js"; import { sortProjects } from "./projectList.js"; /** What one fast-forward keystroke resolved. Anything absent means "open a * draft pre-filled with the rest instead of spawning". */ export interface FastForwardResolution { project?: Project; command?: string; name?: string; } /** The defaults: most recent project (fresh-first, same ordering the picker * shows), its last command falling back to the first non-custom preset, and * a freshly generated name when the daemon supplied one. */ export function resolveFastForward( projects: Project[], presets: SpawnPreset[], name?: string, ): FastForwardResolution { const project = sortProjects(projects, new Date())[0]; const lastCommand = project?.last_command?.trim(); const command = lastCommand || presets.find((p) => p.command !== "")?.command || undefined; return { project, command, name: name || undefined }; } /** The immediate spawn request — worktree on, new branch named after the * generated session name — or `null` when any default is missing. */ export function buildFastForwardRequest( res: FastForwardResolution, ): CreateSessionRequest | null { const { project, command, name } = res; if (!project || !command?.trim() || !name) return null; return { cwd: project.path, command, metadata: { name }, worktree: { base_repo: project.base_repo ?? project.path, branch: name, create_branch: true, }, }; } /** Seed for the fallback draft pane: whatever did resolve goes into the * form; the rest stays with its own defaults. */ export function fastForwardSeed(res: FastForwardResolution) { return { cwd: res.project?.path ?? "", command: res.command ?? "", name: res.name ?? "", // Left undefined rather than false when nothing resolved: the form // defaults the toggle on, and `false` would stick, so the fallback draft // would disagree with both a normally-opened draft and the TUI's fast path // (#67 review). worktreeEnabled: res.project ? true : undefined, worktreeBranch: res.project && res.name ? res.name : undefined, }; }