craig-cli 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +47 -46
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await
|
|
4
|
-
`)};var
|
|
5
|
-
`).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if(
|
|
2
|
+
var Ad=Object.defineProperty;var ir=(e,t)=>{for(var r in t)Ad(e,r,{get:t[r],enumerable:!0})};import X from"node:path";function Z(e){let t=X.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:X.join(t,"index.json"),reposDir:X.join(t,"repos"),workspacesDir:X.join(t,"workspaces"),sessionsDir:X.join(t,"sessions"),runtimeDir:X.join(t,"runtime"),uiStateFile:X.join(t,"runtime","ui-state.json"),tasksDir:X.join(t,"tasks"),jobsDir:X.join(t,"jobs"),logsDir:X.join(t,"logs"),errorLogFile:X.join(t,"logs","errors.log"),artifactsDir:X.join(t,"artifacts"),worktreesDir:X.join(t,"worktrees"),configFile:X.join(t,"config.json")}}import{readFile as Od}from"node:fs/promises";import{randomUUID as Ed}from"node:crypto";import{open as xd,readFile as Sw,rename as Dd,rm as $d}from"node:fs/promises";import mn from"node:path";async function q(e,t){let r=mn.dirname(e),n=mn.join(r,`.${mn.basename(e)}.${process.pid}.${Date.now()}.${Ed()}.tmp`),s=await xd(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await Dd(n,e)}catch(o){throw await s.close().catch(()=>{}),await $d(n,{force:!0}).catch(()=>{}),o}}async function it(e){try{let t=await Od(e.uiStateFile,"utf8"),r=JSON.parse(t);return Md(r,e.uiStateFile)}catch(t){if(Nd(t))return null;throw t}}async function Ee(e,t){await q(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function lr(){return{version:1,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null,selectedPtyTabId:null,inputMode:"control",focusedRegion:"tasks",activeTab:"agent",inspectorSection:"task",inspectionMode:"files",openInspectionKind:null,selectedFileTreePath:null,selectedFilePath:null,selectedDiffPath:null,collapsedFileTreePaths:[],selectedActionId:"commit",updatedAt:new Date().toISOString()}}function Md(e,t){if(typeof e!="object"||e===null||e.version!==1||!(e.selectedRepoId===null||typeof e.selectedRepoId=="string")||!(e.selectedWorkspaceId===null||typeof e.selectedWorkspaceId=="string")||!(e.selectedTaskId===null||typeof e.selectedTaskId=="string")||!(e.selectedPtyTabId===void 0||e.selectedPtyTabId===null||typeof e.selectedPtyTabId=="string")||!ot(e,"inputMode")||!ot(e,"focusedRegion")||!ot(e,"activeTab")||!ot(e,"inspectorSection")||!ot(e,"inspectionMode")||!ar(e,"openInspectionKind")||!ar(e,"selectedFileTreePath")||!ar(e,"selectedFilePath")||!ar(e,"selectedDiffPath")||!Ld(e,"collapsedFileTreePaths")||!ot(e,"selectedActionId")||typeof e.updatedAt!="string")throw new Error(`Craig UI state at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}function ot(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function ar(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Ld(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function Nd(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var fn={};ir(fn,{RUNNER_IDS:()=>O,assertEnabled:()=>Go,buildCommand:()=>Yo,getConfiguredProfile:()=>cr,getDefault:()=>Ko,getDisplayName:()=>zo,getEnabled:()=>dr,getProfile:()=>at,isRunnerType:()=>ur,parse:()=>Ho,setRunnerEnabled:()=>Jo,setRunnerPath:()=>Qo});var O=["codex","cursor","claude"];var Vo={codex:{id:"codex",displayName:"Codex",executable:"codex",defaultAgentTitle:"Codex"},cursor:{id:"cursor",displayName:"Cursor",executable:"cursor-agent",defaultAgentTitle:"Cursor"},claude:{id:"claude",displayName:"Claude",executable:"claude",defaultAgentTitle:"Claude"}};var at=e=>Vo[e];var cr=(e,t={})=>{let r=at(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var dr=(e={})=>O.filter(t=>e.runners?.[t]?.enabled!==!1);var Ko=(e={})=>{let t=dr(e);if(t.length===0)throw new Error("No runners are enabled. Enable at least one runner in .craig/config.json.");return t.includes("codex")?"codex":t[0]};var Go=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var ur=e=>O.includes(e);var Ho=e=>{if(!e||e.length===0)return"codex";if(!ur(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${O.join(", ")}.`);return e};var zo=e=>at(e).displayName;var Yo=(e,t,r={})=>{let n=[cr(e,r).executable];return t&&t.length>0&&n.push(t),n};var Jo=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var Qo=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};var gn={};ir(gn,{PREVIEW_FEATURE_IDS:()=>de,isEnabled:()=>Xo,setEnabled:()=>Zo});var de=["incrementalCenterPane","agentActivityIndicators"];function Xo(e,t){return e.previews?.[t]===!0}function Zo(e,t,r){return{...e,previews:{...e.previews,[t]:r}}}import{mkdir as jd,readFile as Fd,writeFile as _d}from"node:fs/promises";import Wd from"node:path";var qd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",ei=async e=>{try{return await Fd(e,"utf8")}catch(t){if(qd(t))return null;throw t}},ti=async(e,t)=>{await jd(Wd.dirname(e),{recursive:!0}),await _d(e,t,"utf8")};var pr=(e,t)=>{if(typeof e!="object"||e===null)throw new Error(`Craig config at ${t} is invalid. Expected a JSON object.`);let r=e;if(r.runners!==void 0){if(typeof r.runners!="object"||r.runners===null||Array.isArray(r.runners))throw new Error(`Craig config at ${t} is invalid. "runners" must be an object.`);for(let[n,s]of Object.entries(r.runners)){if(!O.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${O.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" must be an object.`);let o=s;if(o.enabled!==void 0&&typeof o.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${n}.enabled" must be a boolean.`);if(o.path!==void 0&&(typeof o.path!="string"||o.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${n}.path" must be a non-empty string.`)}}if(r.checks!==void 0&&(typeof r.checks!="object"||r.checks===null||!Array.isArray(r.checks.commands)||!r.checks.commands.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(r.open!==void 0&&(typeof r.open!="object"||r.open===null||!Array.isArray(r.open.command)||!r.open.command.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}if(r.previews!==void 0){if(typeof r.previews!="object"||r.previews===null||Array.isArray(r.previews))throw new Error(`Craig config at ${t} is invalid. "previews" must be an object.`);for(let[n,s]of Object.entries(r.previews)){if(!de.includes(n))throw new Error(`Craig config at ${t} is invalid. "previews.${n}" is not supported. Expected one of: ${de.join(", ")}.`);if(typeof s!="boolean")throw new Error(`Craig config at ${t} is invalid. "previews.${n}" must be a boolean.`)}}return r};var hn=async(e,t={readConfigFile:ei})=>{let r=await t.readConfigFile(e.configFile);if(!r)return{};if(r.trimStart()[0]!=="{")throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`);let n;try{n=JSON.parse(r)}catch{throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`)}return pr(n,e.configFile)};var wn=async(e,t,r={writeConfigFile:ti})=>{pr(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var kn={};ir(kn,{checkForUpdate:()=>ri,getCurrent:()=>mr});var mr=()=>{try{return"0.10.1"}catch{return"unknown"}};var Ud="https://registry.npmjs.org/craig-cli/latest",Bd=3600*1e3,Vd={value:null},Kd=(e,t)=>{let r=c=>c.split(".").map(Number),[n=0,s=0,o=0]=r(e),[i=0,a=0,l=0]=r(t);return n!==i?n>i:s!==a?s>a:o>l},ri=async(e={fetch:globalThis.fetch,getCurrent:mr,cache:Vd})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<Bd)return e.cache.value.result;let n=null;try{let o=await e.fetch(Ud,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&Kd(n,t)};return e.cache.value={result:s,cachedAt:r},s};var f={load:hn,save:wn,previews:gn,runners:fn,version:kn};var ni={CLI_USAGE:2,INPUT_REQUIRED:2,WORKSPACE_CONTEXT_NOT_FOUND:3,WORKSPACE_CONTEXT_INVALID:4,WORKSPACE_NOT_FOUND:3,WORKSPACE_RECORD_INVALID:2,TASK_CONTEXT_NOT_FOUND:3,TASK_CONTEXT_AMBIGUOUS:4,TASK_CONTEXT_CONFLICT:4,TASK_NOT_FOUND:3,TASK_RECORD_INVALID:2,REPO_NOT_FOUND:3,REPO_RECORD_INVALID:2,PR_REPOSITORY_MISMATCH:4,PR_BRANCH_MISMATCH:4,EXTERNAL_DEPENDENCY_FAILED:5,OPERATION_TIMEOUT:6,PARTIAL_RESULT:7,INTERNAL_ERROR:1},R=class extends Error{code;exitCode;retryable;details;constructor(t,r,n){super(r,n.cause===void 0?void 0:{cause:n.cause}),this.name="CraigError",this.code=t,this.exitCode=ni[t],this.retryable=n.retryable??!1,this.details=n.details??{}}};function Tn(e){return e instanceof R?e:new R("INTERNAL_ERROR",e instanceof Error?e.message:"Unknown Craig error",{cause:e})}import{appendFile as Gd,mkdir as Hd,readFile as zd}from"node:fs/promises";import Yd from"node:path";var si=80,yn=async(e,t)=>{await Hd(Yd.dirname(e.errorLogFile),{recursive:!0}),await Gd(e.errorLogFile,Jd(t),"utf8")},oi=async(e,t)=>{try{await yn(e,t)}catch{}},Rn=async(e,t=si)=>{try{let n=(await zd(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
5
|
+
`).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if(Qd(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},ii=async(e,t=si)=>Rn(e,t);function Jd(e){let r=[`[${new Date().toISOString()}] ${e.context}`,`message: ${e.message}`];return e.details&&e.details.trim().length>0&&(r.push("details:"),r.push(...e.details.trimEnd().split(`
|
|
6
6
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
7
7
|
`)}
|
|
8
8
|
|
|
9
|
-
`}function
|
|
10
|
-
`)}function
|
|
9
|
+
`}function Qd(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var lt={appendErrorLog:yn,appendErrorLogBestEffort:oi,readErrorLog:Rn,readRecentErrorLines:ii};function ui(e){let{commandTokens:t,options:r,help:n}=Zd(e);if(n)return ai({kind:"help"},r);if(t.length===0)return{mode:"interactive",options:r};let[s,o,...i]=t,a;switch(`${s??""}:${o??""}`){case"context:show":bn(i,"context show"),a={kind:"showContext"};break;case"repo:add":a={kind:"addRepo",path:ci(i,"Repo path")};break;case"repo:list":bn(i,"repo list"),a={kind:"listRepos"};break;case"repo:remove":a={kind:"removeRepo",repoId:ne(i,"Repo id")};break;case"workspace:add":a={kind:"addWorkspace",path:ci(i,"Workspace path")};break;case"workspace:list":a=eu(i);break;case"workspace:archive":a={kind:"archiveWorkspace",workspaceId:ne(i,"Workspace id")};break;case"workspace:restore":a={kind:"restoreWorkspace",workspaceId:ne(i,"Workspace id")};break;case"workspace:remove":a={kind:"removeWorkspace",workspaceId:ne(i,"Workspace id")};break;case"task:new":a=ru(i);break;case"task:list":a=tu(i);break;case"task:current":bn(i,"task current"),a={kind:"currentTask"};break;case"task:show":a=i.length===0?{kind:"showCurrentTask"}:{kind:"showTask",taskId:ne(i,"Task id")};break;case"task:pr":a=nu(i);break;case"task:attach":a={kind:"attachTask",taskId:ne(i,"Task id")};break;case"task:logs":a={kind:"streamTaskLogs",taskId:ne(i,"Task id")};break;case"task:diff":a={kind:"showTaskDiff",taskId:ne(i,"Task id")};break;case"task:focus":a={kind:"focusTask",taskId:ne(i,"Task id")};break;case"task:open":a={kind:"openTask",taskId:ne(i,"Task id")};break;case"task:check":a={kind:"runChecks",taskId:ne(i,"Task id")};break;case"task:commit":a={kind:"commitTask",taskId:ne(i,"Task id")};break;case"link:add":a={kind:"addTaskLink",taskId:di(i,0,"Task id"),repoId:di(i,1,"Repo id")},mi(i,2,"link add");break;case"link:list":a={kind:"listTaskLinks",taskId:ne(i,"Task id")};break;default:if(t.length===1&&(s==="help"||s==="--help"||s==="-h")){a={kind:"help"};break}throw M(`Unsupported command: ${t.join(" ")}`)}return ai(a,r)}function pi(e){let t=e[0]==="--"?e.slice(1):e,r=!0;for(let n of t){if(n==="--"){r=!1;continue}if(r&&n==="--json")return!0}return!1}function Xd(e){return{addWorkspace:"workspace.add",addRepo:"repo.add",listRepos:"repo.list",removeRepo:"repo.remove",listWorkspaces:"workspace.list",archiveWorkspace:"workspace.archive",restoreWorkspace:"workspace.restore",removeWorkspace:"workspace.remove",createTask:"task.new",listTasks:"task.list",currentTask:"task.current",showTask:"task.show",showCurrentTask:"task.show",showTaskPr:"task.pr.show",discoverTaskPr:"task.pr.discover",linkTaskPr:"task.pr.link",refreshTaskPr:"task.pr.refresh",unlinkTaskPr:"task.pr.unlink",attachTask:"task.attach",addTaskLink:"link.add",listTaskLinks:"link.list",refreshInteractiveState:"interactive.refresh",showSelectedTask:"task.show",streamTaskLogs:"task.logs",streamSelectedTaskLogs:"task.logs",showTaskDiff:"task.diff",showSelectedTaskDiff:"task.diff",focusTask:"task.focus",focusSelectedTask:"task.focus",openTask:"task.open",openSelectedTask:"task.open",runChecks:"task.check",runSelectedTaskChecks:"task.check",commitTask:"task.commit",commitSelectedTask:"task.commit",showContext:"context.show",help:"help",exit:"exit"}[e.kind]}function Pn(){return["Craig commands:"," craig [--workspace-root <path>] [--task <id>] [--json] [--no-input] <command>"," craig context show Show resolved workspace, task, and agent-tab context"," craig repo add <path> Register a repo in the current Craig workspace"," craig workspace add <path> Register a repo or parent-directory workspace"," craig repo list List registered repos"," craig repo remove <id> Remove a registered repo"," craig workspace list [--archived] List workspaces"," craig workspace archive <id> Archive a workspace"," craig workspace restore <id> Restore an archived workspace"," craig workspace remove <id> Remove an archived workspace"," craig task new --repo <repo-id> [--runner codex|cursor|claude] <prompt>"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude] <prompt>"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task current Show the task resolved from flags, environment, or cwd"," craig task show [<id>] Show task details; omit id to use resolved context"," craig task pr show [<id>] [--repo <repo-id>]"," craig task pr discover [<id>] [--repo <repo-id>]"," craig task pr link [<id>] --pr <url|number> [--repo <repo-id>]"," craig task pr refresh [<id>] [--repo <repo-id>]"," craig task pr unlink [<id>] --pr <url|number> [--repo <repo-id>]"," craig task logs <id> Stream Craig-managed logs for a task"," craig task diff <id> Show the current worktree diff for a task"," craig task attach <id> Attach to a live task session"," craig task focus <id> Focus the tmux pane for a task"," craig task open <id> Open the task worktree or print its path"," craig task check <id> Run configured checks for a task"," craig task commit <id> Commit all task worktree changes"," craig link add <task-id> <repo-id> Add a linked repo to a task"," craig link list <task-id> List linked repos for a task"].join(`
|
|
10
|
+
`)}function Zd(e){let t=[...e];t[0]==="--"&&t.shift();let r=[],n={json:!1,noInput:!1},s=new Set,o=!1,i=!0;for(let a=0;a<t.length;a+=1){let l=t[a];if(l==="--"){i=!1,r.push(l);continue}if(!i||!li(l)){r.push(l);continue}if(s.has(l))throw M(`Global option ${l} may only be provided once.`);if(s.add(l),l==="--json"){n.json=!0;continue}if(l==="--no-input"){n.noInput=!0;continue}if(l==="--help"||l==="-h"){o=!0;continue}let c=t[a+1];if(c===void 0||c==="--"||li(c))throw M(`Global option ${l} requires a value.`);a+=1,l==="--workspace-root"?n.workspaceRoot=ie(c,"Workspace root"):n.taskId=ie(c,"Task id")}return{commandTokens:r,options:n,help:o}}function eu(e){if(e.length===0)return{kind:"listWorkspaces",archived:!1};if(e.length===1&&e[0]==="--archived")return{kind:"listWorkspaces",archived:!0};throw M(`Unsupported command: workspace list ${e.join(" ")}`)}function tu(e){if(e.length===0)return{kind:"listTasks"};if(e.length===2&&e[0]==="--repo")return{kind:"listTasks",repoId:ie(e[1],"Repo id")};throw M(`Unsupported command: task list ${e.join(" ")}`)}function ru(e){let t,r,n,s=[],o=!0;for(let a=0;a<e.length;a+=1){let l=e[a];if(l==="--"){o=!1;continue}if(!o||!["--repo","--workspace","--runner"].includes(l)){if(o&&l.startsWith("--"))throw M(`Unsupported task new option: ${l}`);s.push(l);continue}let c=e[a+1];if(c===void 0||c==="--")throw M(`Task option ${l} requires a value.`);if(a+=1,l==="--repo"){if(t!==void 0)throw M("Task option --repo may only be provided once.");t=ie(c,"Repo id")}else if(l==="--workspace"){if(r!==void 0)throw M("Task option --workspace may only be provided once.");r=ie(c,"Workspace id")}else{if(n!==void 0)throw M("Task option --runner may only be provided once.");try{n=f.runners.parse(c)}catch(d){throw M(d instanceof Error?d.message:"Unsupported runner.")}}}if(!t&&!r)throw M("Task creation requires '--repo <repo-id>' or '--workspace <workspace-id>'.");if(t&&r)throw M("Task creation accepts either '--repo' or '--workspace', not both.");let i=ie(s.join(" "),"Task prompt");return{kind:"createTask",...t?{repoId:t}:{},...r?{workspaceId:r}:{},...n?{runner:n}:{},prompt:i}}function nu(e){let[t,...r]=e;if(!["show","discover","link","refresh","unlink"].includes(t??""))throw M(`Unsupported command: task pr ${e.join(" ")}`);let n,s,o;for(let a=0;a<r.length;a+=1){let l=r[a];if(l!=="--repo"&&l!=="--pr"){if(l.startsWith("--"))throw M(`Unsupported task pr ${t} option: ${l}`);if(n!==void 0)throw M(`task pr ${t} accepts at most one task id.`);n=ie(l,"Task id");continue}let c=r[a+1];if(c===void 0||c==="--")throw M(`Task PR option ${l} requires a value.`);if(a+=1,l==="--repo"){if(s!==void 0)throw M("Task PR option --repo may only be provided once.");s=ie(c,"Repo id")}else{if(o!==void 0)throw M("Task PR option --pr may only be provided once.");o=ie(c,"Pull request selector")}}if((t==="link"||t==="unlink")&&o===void 0)throw M(`task pr ${t} requires --pr <url|number>.`);if(t!=="link"&&t!=="unlink"&&o!==void 0)throw M(`task pr ${t} does not accept --pr.`);let i={...n?{taskId:n}:{},...s?{repoId:s}:{}};switch(t){case"show":return{kind:"showTaskPr",...i};case"discover":return{kind:"discoverTaskPr",...i};case"link":return{kind:"linkTaskPr",...i,pullRequest:o};case"refresh":return{kind:"refreshTaskPr",...i};case"unlink":return{kind:"unlinkTaskPr",...i,pullRequest:o};default:throw M(`Unsupported command: task pr ${e.join(" ")}`)}}function ai(e,t){return{mode:"command",command:e,commandName:Xd(e),options:t}}function li(e){return["--json","--no-input","--workspace-root","--task","--help","-h"].includes(e)}function bn(e,t){mi(e,0,t)}function mi(e,t,r){if(e.length!==t)throw M(`Command ${r} received an unexpected number of arguments.`)}function ne(e,t){if(e.length!==1)throw M(`${t} is required and must be provided once.`);return ie(e[0],t)}function ci(e,t){return ie(e.join(" "),t)}function di(e,t,r){return ie(e[t]??"",r)}function ie(e,t){let r=e.trim();if(r.length===0)throw M(`${t} cannot be empty.`);return r}function M(e){return new R("CLI_USAGE",`${e}
|
|
11
11
|
|
|
12
|
-
${sn()}`,{})}var V=(e,t)=>{let r=on(e);if(!yd(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},on=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:an(t.runner),repoId:typeof t.repoId=="string"?t.repoId:"legacy_repo",workspaceId:typeof t.workspaceId=="string"?t.workspaceId:"legacy_workspace",sessionId:typeof t.sessionId=="string"||t.sessionId===null?t.sessionId:null,selectedPtyTabId:typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null?t.selectedPtyTabId:null,linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(r=>typeof r=="string"):[],ptyTabs:Sd(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:bd(t.repoTargets),runnerSession:t.runnerSession??Rd(t),checks:Dd(t),lastCommit:t.lastCommit??null,prs:$d(t),artifacts:Ld(t),cleanup:Fd(t)}},Rd=e=>{if(typeof e.title!="string")return null;let t=an(e.runner);return{command:f.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},yd=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.id=="string"&&typeof t.title=="string"&&typeof t.slug=="string"&&(t.type==="repo"||t.type==="project")&&typeof t.status=="string"&&f.runners.isRunnerType(t.runner??"")&&typeof t.repoId=="string"&&typeof t.workspaceId=="string"&&(typeof t.sessionId=="string"||t.sessionId===null)&&(typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null)&&Array.isArray(t.linkedRepoIds)&&t.linkedRepoIds.every(r=>typeof r=="string")&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&typeof t.branch=="string"&&No(t.ptyTabs)&&(t.bundlePath===void 0||t.bundlePath===null||typeof t.bundlePath=="string")&&(t.selectedRepoTargetId===void 0||t.selectedRepoTargetId===null||typeof t.selectedRepoTargetId=="string")&&(t.repoTargets===void 0||Pd(t.repoTargets))&&Cd(t.runnerSession)&&vd(t.prompt)&&Lo(t.checks)&&Fo(t.lastCommit)&&Ad(t.prs)&&xd(t.artifacts)&&Wo(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},bd=e=>{if(Array.isArray(e))return e.filter(Mo)},Pd=e=>Array.isArray(e)&&e.every(Mo),Mo=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.repoId=="string"&&typeof t.branch=="string"&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&(t.status==="ready"||t.status==="unavailable"||t.status==="merged"||t.status==="closed")&&(typeof t.failureReason=="string"||t.failureReason===null)&&Lo(t.checks)&&Fo(t.lastCommit)&&jo(t.pullRequest)&&Wo(t.cleanup)},Sd=e=>{if(No(e.ptyTabs))return e.ptyTabs;if(typeof e.id!="string"||typeof e.title!="string")return[];let t=typeof e.updatedAt=="string"?e.updatedAt:new Date().toISOString();return Id(e.id,e.title,t,an(e.runner))},Id=(e,t,r,n)=>{let s=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:f.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},an=e=>e&&f.runners.isRunnerType(e)?e:"codex",No=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.id=="string"&&(t.kind==="agent"||t.kind==="terminal")&&typeof t.title=="string"&&Array.isArray(t.command)&&t.command.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"),Cd=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),vd=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Lo=e=>typeof e=="object"&&e!==null&&typeof e.source=="object"&&e.source!==null&&e.source.type==="repo_config"&&typeof e.source.path=="string"&&(typeof e.lastRunAt=="string"||e.lastRunAt===null)&&(e.status==="not_run"||e.status==="running"||e.status==="passed"||e.status==="failed")&&Array.isArray(e.commands)&&e.commands.every(t=>typeof t=="string")&&Array.isArray(e.results)&&e.results.every(t=>typeof t=="object"&&t!==null&&typeof t.command=="string"&&typeof t.startedAt=="string"&&typeof t.finishedAt=="string"&&typeof t.exitCode=="number"),Fo=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",jo=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Ed(e.requiredChecks),Ed=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.name=="string"&&(t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown")&&(typeof t.conclusion=="string"||t.conclusion===null)),Ad=e=>Array.isArray(e)&&e.every(jo),xd=e=>typeof e=="object"&&e!==null&&(typeof e.logPath=="string"||e.logPath===null)&&(typeof e.checkSummaryPath=="string"||e.checkSummaryPath===null)&&(typeof e.prDraftPath=="string"||e.prDraftPath===null)&&(typeof e.prStatusPath=="string"||e.prStatusPath===null),Wo=e=>typeof e=="object"&&e!==null&&(typeof e.paneClosedAt=="string"||e.paneClosedAt===null)&&(typeof e.worktreeRemovedAt=="string"||e.worktreeRemovedAt===null)&&typeof e.preservedWorktree=="boolean"&&(typeof e.warning=="string"||e.warning===null),Dd=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},$d=e=>{if(Array.isArray(e.prs))return e.prs.map(Od);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:_o(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Uo(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Od=e=>{let t=e??{};return{provider:"github",owner:t.owner??null,repo:t.repo??null,number:typeof t.number=="number"?t.number:null,url:t.url??null,title:t.title??null,status:_o(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Md(t.reviewDecision),requiredChecks:Uo(t.requiredChecks),comments:Nd(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},_o=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Md=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Nd=e=>Array.isArray(e)?e.flatMap(t=>{if(typeof t!="object"||t===null)return[];let r=t;return typeof r.body!="string"||!r.body.trim()?[]:[{author:typeof r.author=="string"?r.author:null,body:r.body,createdAt:typeof r.createdAt=="string"?r.createdAt:null,url:typeof r.url=="string"?r.url:null}]}):[],Uo=e=>Array.isArray(e)?e.map(t=>({...t,status:t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown"?t.status:"unknown",conclusion:t.conclusion??null})):[],Ld=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Fd=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as uu}from"node:fs/promises";import{readFile as jd,readdir as Wd,rm as _d}from"node:fs/promises";import qo from"node:path";var ln=(e,t)=>qo.join(e.workspacesDir,`${t}.json`),Ud=e=>{if(typeof e!="object"||e===null)return e;let t=e,r=t.repoId??t.primaryRepoId;return{...t,kind:t.kind??"repo",name:t.name??r??t.id,rootPath:t.rootPath??"",primaryRepoId:t.primaryRepoId??r??"",repoId:t.kind==="project"?t.repoId:r,discoveredRepoIds:Array.isArray(t.discoveredRepoIds)?t.discoveredRepoIds.filter(n=>typeof n=="string"):t.kind==="project"?[]:r?[r]:[],linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(n=>typeof n=="string"):[]}},Bo=(e,t)=>{let r=Ud(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},je=async(e,t)=>{let r=ln(e,t);try{let n=await jd(r,"utf8");return Bo(JSON.parse(n),r)}catch(n){throw qd(n)?new S("WORKSPACE_NOT_FOUND",`Craig workspace "${t}" was not found.`,{details:{workspaceId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig workspace record at ")?new S("WORKSPACE_RECORD_INVALID",n instanceof Error?n.message:`Craig workspace "${t}" is invalid.`,{details:{workspaceId:t},cause:n}):n}},We=async(e,t)=>{await U(ln(e,t.id),{...t,updatedAt:new Date().toISOString()})},ie=async e=>{let t=await Wd(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>je(e,qo.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Vo=async(e,t)=>{await _d(ln(e,t),{force:!0})},qd=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Bd,readdir as Vd,rm as Kd}from"node:fs/promises";import Ko from"node:path";var cn=(e,t)=>Ko.join(e.reposDir,`${t}.json`),Go=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},ce=async(e,t)=>{let r=cn(e,t);try{let n=await Bd(r,"utf8");return Go(JSON.parse(n),r)}catch(n){throw Gd(n)?new S("REPO_NOT_FOUND",`Craig repo "${t}" was not found.`,{details:{repoId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig repo record at ")?new S("REPO_RECORD_INVALID",n instanceof Error?n.message:`Craig repo "${t}" is invalid.`,{details:{repoId:t},cause:n}):n}},dn=async(e,t)=>{await U(cn(e,t.id),{...t,updatedAt:new Date().toISOString()})},Rt=async e=>{let t=await Vd(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>ce(e,Ko.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Ho=async(e,t)=>{await Kd(cn(e,t),{force:!0})},Gd=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Hd}from"node:fs/promises";var zd=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},rt=(e,t,r)=>{if(!zd(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},te=async e=>{let t=await Hd(e.indexFile,"utf8");return rt(JSON.parse(t),e.workspaceRoot,e.indexFile)},ye=async(e,t)=>{await U(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as Zd,stat as eu}from"node:fs/promises";import st from"node:path";import{realpath as Qo}from"node:fs/promises";import nr from"node:path";import{execFile as Yd}from"node:child_process";import{promisify as Qd}from"node:util";var zo=Qd(Yd);async function I(e,t,r={}){try{let n=await zo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Yo(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function x(e,t,r={}){try{let n=await zo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Yo(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Yo(e){return e instanceof Error}var un=async e=>{try{let r=(await I("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Qo(r).catch(()=>nr.resolve(r)),Qo(e).catch(()=>nr.resolve(e))]);return n===s}catch{return!1}},pn=async e=>{let t=await x("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await I("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"},Jo=async e=>{let t=await x("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd:e}),r=t.stdout.trim();if(t.exitCode!==0||r.length===0)return null;let n=nr.resolve(e,r);return nr.dirname(n)};import{mkdir as ge,readFile as Jd}from"node:fs/promises";var Xd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",nt=async e=>{let t=ee(e);await ge(t.craigDir,{recursive:!0}),await Promise.all([ge(t.reposDir,{recursive:!0}),ge(t.workspacesDir,{recursive:!0}),ge(t.sessionsDir,{recursive:!0}),ge(t.runtimeDir,{recursive:!0}),ge(t.tasksDir,{recursive:!0}),ge(t.jobsDir,{recursive:!0}),ge(t.logsDir,{recursive:!0}),ge(t.artifactsDir,{recursive:!0}),ge(t.worktreesDir,{recursive:!0})]);try{let s=await Jd(t.indexFile,"utf8"),o=JSON.parse(s);return rt(o,e,t.indexFile)}catch(s){if(!Xd(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await U(t.indexFile,n),n};var Xo=(e,t,r)=>{let n=new Date().toISOString();return{id:tu(e,st.basename(t)),name:st.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Zo=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},tu=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",n=`repo_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`repo_${r}_${s}`,s+=1;return n},ru=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},ei=async(e,t)=>{let r=await te(e);await ye(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},nu=async(e,t)=>{let r=await Zd(t,{withFileTypes:!0}),n=await Rt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=st.join(t,o.name);if(!await un(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await pn(i);s.push(a?Zo(a,l):Xo([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},su=async(e,t)=>{let r=await pn(t),n=await Rt(e),s=n.find(u=>u.rootPath===t)??null,o=s?Zo(s,r):Xo(n,t,r),i=`workspace_${o.id}`,l=(await ie(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await dn(e,o),l||await We(e,d),await ei(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},ou=async(e,t)=>{let r=await nu(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await ie(e),s=ru(n,st.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:st.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>dn(e,c))),await We(e,l),await ei(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},yt=async(e,t)=>{await nt(e.workspaceRoot);let r=st.resolve(e.workspaceRoot,t);if(!(await eu(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await un(r)?su(e,r):ou(e,r)};var mn=async(e,t,r={listWorkspaceRecords:ie,ensureCraigState:nt})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var fn=async(e,t,r={readWorkspace:je,writeWorkspace:We})=>{let s={...await r.readWorkspace(e,t),status:"archived",archivedAt:new Date().toISOString()};return await r.writeWorkspace(e,s),{kind:"archiveWorkspace",workspaceId:s.id,status:s.status,branch:s.branch}};var gn=async(e,t)=>{let n={...await je(e,t),status:"active",archivedAt:null};await We(e,n);let s=n.kind==="project"?n.discoveredRepoIds?.[0]??null:n.primaryRepoId;return{kind:"restoreWorkspace",workspaceId:n.id,status:n.status,branch:n.branch,primaryRepoId:s}};var _e=async(e,t,r={deleteWorkspace:Vo,readCraigIndex:te,writeCraigIndex:ye})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var hn=async(e,t,r)=>{let n=await je(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await _e(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};import{readFile as iu,realpath as ni,stat as au}from"node:fs/promises";import sr from"node:path";async function kn(e){let t=await oi(e.cwd,"Current working directory");if(e.explicitWorkspaceRoot!==void 0)return ti(e.explicitWorkspaceRoot,"explicit",t,e.allowUninitializedCwd??!1);if(e.environmentWorkspaceRoot!==void 0)return ti(e.environmentWorkspaceRoot,"environment",t,e.allowUninitializedCwd??!1);let r=await ri(t);if(r)return{workspaceRoot:r,source:"ancestor",initialized:!0};let n=await Jo(t);if(n){let s=await ri(n);if(s)return{workspaceRoot:s,source:"git_common_dir",initialized:!0}}if(e.allowUninitializedCwd)return{workspaceRoot:t,source:"cwd",initialized:!1};throw new S("WORKSPACE_CONTEXT_NOT_FOUND",`No Craig workspace was found from ${t}. Use --workspace-root <path> or run Craig inside an initialized workspace.`,{details:{cwd:t}})}async function ti(e,t,r,n){let s=t==="explicit"?"Workspace root":"CRAIG_WORKSPACE_ROOT",o=await oi(sr.resolve(r,e),s),i=await si(o);if(i)return{workspaceRoot:i,source:t,initialized:!0};if(n)return{workspaceRoot:o,source:t,initialized:!1};throw new S("WORKSPACE_CONTEXT_NOT_FOUND",`${s} ${o} is not an initialized Craig workspace.`,{details:{workspaceRoot:o,source:t}})}async function ri(e){let t=e;for(;;){let r=await si(t);if(r)return r;let n=sr.dirname(t);if(n===t)return null;t=n}}async function si(e){let t=ee(e);try{let r=await iu(t.indexFile,"utf8"),n=JSON.parse(r),s=typeof n=="object"&&n!==null&&"workspaceRoot"in n&&typeof n.workspaceRoot=="string"?n.workspaceRoot:e,o=rt(n,s,t.indexFile);if(await ni(o.workspaceRoot).catch(()=>sr.resolve(o.workspaceRoot))!==e)throw new Error(`Craig index at ${t.indexFile} belongs to ${o.workspaceRoot}, not ${e}. Remove or repair the file before rerunning Craig.`);return o.workspaceRoot}catch(r){if(lu(r))return null;throw r instanceof S?r:new S("WORKSPACE_CONTEXT_INVALID",r instanceof Error?r.message:`Craig workspace at ${e} is invalid.`,{details:{workspaceRoot:e},cause:r})}}async function oi(e,t){let r=sr.resolve(e);try{if(!(await au(r)).isDirectory())throw new S("WORKSPACE_CONTEXT_INVALID",`${t} ${r} is not a directory.`,{details:{path:r}});return await ni(r)}catch(n){throw n instanceof S?n:new S("WORKSPACE_CONTEXT_NOT_FOUND",`${t} ${r} does not exist or cannot be read.`,{details:{path:r},cause:n})}}function lu(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var wn={};Yt(wn,{addRepo:()=>ii,listRegisteredRepos:()=>ai,removeRepo:()=>li});import cu from"node:path";import{stat as du}from"node:fs/promises";var ii=async(e,t)=>{let r=cu.resolve(e.workspaceRoot,t);if(!(await du(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await yt(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var ai=async(e,t={listRepos:Rt,ensureCraigState:nt})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var li=async(e,t,r)=>{let n=await ce(e,t),o=(await ie(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>_e(e,c.id))),await Ho(e,t);let l=await te(e);return await ye(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var H={addWorkspace:yt,listWorkspaces:mn,archiveWorkspace:fn,restoreWorkspace:gn,removeWorkspace:hn,removeWorkspaceRecord:_e,resolveContext:kn,repos:wn};var re=async(e,t)=>{let r=await uu(Rn(e,t),"utf8");return JSON.parse(r)},ae=async(e,t)=>{let r=await re(e,t);return V(r,Rn(e,t))},P=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await U(Rn(e,t.id),r)},Tn=async(e,t)=>{let r=await te(e);r.taskIds.includes(t)||await ye(e,{...r,taskIds:[...r.taskIds,t]})},Rn=(e,t)=>`${e.tasksDir}/${t}.json`;var $=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ve=e=>e.status==="merged"||e.status==="closed",ot=(e,t)=>{let r=e.prs.findIndex(s=>s.number!==null&&s.number===t.number),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},bt=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return ir(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},ir=e=>e.mergeable&&!pu(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),pu=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",yn=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),Pt=(e,t)=>{let r=e.isDraft??!1,n=mu(e.state,r);return{provider:"github",owner:t?.owner??null,repo:t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:n,draft:r,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:fu(e.reviewDecision??null),requiredChecks:St(e.statusCheckRollup),comments:e.comments===void 0?t?.comments??[]:wu(e.comments),createdAt:e.createdAt??t?.createdAt??null,updatedAt:e.updatedAt??t?.updatedAt??null,mergedAt:e.mergedAt??t?.mergedAt??null,lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}},mu=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,fu=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,St=e=>{let t=e.map(n=>gu(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||hu(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},gu=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=t.name??t.context,n=t.state??t.status??t.conclusion;return r?{name:r,status:di(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:ku(t)}:null},hu=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):or(e)&&!or(t)?!0:!or(e)&&or(t)?!1:ci(t.status)>=ci(e.status),or=e=>e.conclusion?.toUpperCase()==="CANCELLED",ci=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},ku=e=>{let t=e.completedAt??e.startedAt??e.createdAt??null;if(!t)return null;let r=new Date(t).getTime();return Number.isFinite(r)?r:null},wu=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Tu).filter(r=>r!==null).slice(-4):[]},Tu=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=Ru(t.bodyText??t.body??"");return r?{author:typeof t.author=="string"?t.author:t.author?.login??null,body:r,createdAt:t.createdAt??null,url:t.url??null}:null},Ru=e=>e.replace(/\s+/g," ").trim(),di=(e,t)=>{let r=e?.toUpperCase()??null,n=t?.toUpperCase()??null;return n==="SKIPPED"||r==="SKIPPED"?"skipped":r==="SUCCESS"||n==="SUCCESS"||n==="NEUTRAL"?"success":r==="PENDING"||r==="EXPECTED"||r==="IN_PROGRESS"||r==="QUEUED"||r==="REQUESTED"||r==="WAITING"?"pending":r==="FAILURE"||r==="FAILED"||r==="ERROR"||r==="TIMED_OUT"||r==="CANCELLED"||r==="ACTION_REQUIRED"||r==="STARTUP_FAILURE"||n==="FAILURE"||n==="FAILED"||n==="ERROR"||n==="TIMED_OUT"||n==="CANCELLED"||n==="ACTION_REQUIRED"||n==="STARTUP_FAILURE"?"failed":r==="COMPLETED"&&n===null?"unknown":r==="COMPLETED"&&n!==null?di(n,n):"unknown"};var he=class extends Error{constructor(t){super(t),this.name="GitHubRateLimitError"}};import{access as yu}from"node:fs/promises";import ui from"node:path";var v=async(e,t,r={readRawTask:re,validateTaskRecord:V})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Cu(n)?new S("TASK_NOT_FOUND",`Craig task "${t}" was not found.`,{details:{taskId:t}}):vu(n)?new S("TASK_RECORD_INVALID",n instanceof Error?n.message:`Craig task "${t}" is invalid.`,{details:{taskId:t},cause:n}):n}},K=async e=>{if(!await bn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},it=(e,t)=>t.artifacts.logPath?ui.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:ui.join(e.workspaceRoot,t.artifacts.logPath):null,It=async(e,t)=>{let r=await bn(t.worktreePath),n=it(e,t),s=n?await bn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:bu(t),lastCommitSummary:Pu(t),prSummary:Su(t),cleanupSummary:Iu(t)}},bn=async e=>{try{return await yu(e),!0}catch{return!1}},bu=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},Pu=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Su=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
12
|
+
${Pn()}`,{})}var ae=(e,t)=>{let r=Sn(e);if(!ou(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Sn=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:In(t.runner),repoId:typeof t.repoId=="string"?t.repoId:"legacy_repo",workspaceId:typeof t.workspaceId=="string"?t.workspaceId:"legacy_workspace",sessionId:typeof t.sessionId=="string"||t.sessionId===null?t.sessionId:null,selectedPtyTabId:typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null?t.selectedPtyTabId:null,linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(r=>typeof r=="string"):[],ptyTabs:lu(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:iu(t.repoTargets),runnerSession:t.runnerSession??su(t),checks:gu(t),lastCommit:t.lastCommit??null,prs:hu(t),artifacts:yu(t),cleanup:Ru(t)}},su=e=>{if(typeof e.title!="string")return null;let t=In(e.runner);return{command:f.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},ou=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.id=="string"&&typeof t.title=="string"&&typeof t.slug=="string"&&(t.type==="repo"||t.type==="project")&&typeof t.status=="string"&&f.runners.isRunnerType(t.runner??"")&&typeof t.repoId=="string"&&typeof t.workspaceId=="string"&&(typeof t.sessionId=="string"||t.sessionId===null)&&(typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null)&&Array.isArray(t.linkedRepoIds)&&t.linkedRepoIds.every(r=>typeof r=="string")&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&typeof t.branch=="string"&&gi(t.ptyTabs)&&(t.bundlePath===void 0||t.bundlePath===null||typeof t.bundlePath=="string")&&(t.selectedRepoTargetId===void 0||t.selectedRepoTargetId===null||typeof t.selectedRepoTargetId=="string")&&(t.repoTargets===void 0||au(t.repoTargets))&&du(t.runnerSession)&&uu(t.prompt)&&hi(t.checks)&&wi(t.lastCommit)&&mu(t.prs)&&fu(t.artifacts)&&Ti(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},iu=e=>{if(Array.isArray(e))return e.filter(fi)},au=e=>Array.isArray(e)&&e.every(fi),fi=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.repoId=="string"&&typeof t.branch=="string"&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&(t.status==="ready"||t.status==="unavailable"||t.status==="merged"||t.status==="closed")&&(typeof t.failureReason=="string"||t.failureReason===null)&&hi(t.checks)&&wi(t.lastCommit)&&ki(t.pullRequest)&&Ti(t.cleanup)},lu=e=>{if(gi(e.ptyTabs))return e.ptyTabs;if(typeof e.id!="string"||typeof e.title!="string")return[];let t=typeof e.updatedAt=="string"?e.updatedAt:new Date().toISOString();return cu(e.id,e.title,t,In(e.runner))},cu=(e,t,r,n)=>{let s=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:f.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},In=e=>e&&f.runners.isRunnerType(e)?e:"codex",gi=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.id=="string"&&(t.kind==="agent"||t.kind==="terminal")&&typeof t.title=="string"&&Array.isArray(t.command)&&t.command.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"),du=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),uu=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",hi=e=>typeof e=="object"&&e!==null&&typeof e.source=="object"&&e.source!==null&&e.source.type==="repo_config"&&typeof e.source.path=="string"&&(typeof e.lastRunAt=="string"||e.lastRunAt===null)&&(e.status==="not_run"||e.status==="running"||e.status==="passed"||e.status==="failed")&&Array.isArray(e.commands)&&e.commands.every(t=>typeof t=="string")&&Array.isArray(e.results)&&e.results.every(t=>typeof t=="object"&&t!==null&&typeof t.command=="string"&&typeof t.startedAt=="string"&&typeof t.finishedAt=="string"&&typeof t.exitCode=="number"),wi=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",ki=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&pu(e.requiredChecks),pu=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.name=="string"&&(t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown")&&(typeof t.conclusion=="string"||t.conclusion===null)),mu=e=>Array.isArray(e)&&e.every(ki),fu=e=>typeof e=="object"&&e!==null&&(typeof e.logPath=="string"||e.logPath===null)&&(typeof e.checkSummaryPath=="string"||e.checkSummaryPath===null)&&(typeof e.prDraftPath=="string"||e.prDraftPath===null)&&(typeof e.prStatusPath=="string"||e.prStatusPath===null),Ti=e=>typeof e=="object"&&e!==null&&(typeof e.paneClosedAt=="string"||e.paneClosedAt===null)&&(typeof e.worktreeRemovedAt=="string"||e.worktreeRemovedAt===null)&&typeof e.preservedWorktree=="boolean"&&(typeof e.warning=="string"||e.warning===null),gu=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},hu=e=>{if(Array.isArray(e.prs))return e.prs.map(wu);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:yi(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Ri(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},wu=e=>{let t=e??{};return{provider:"github",owner:t.owner??null,repo:t.repo??null,number:typeof t.number=="number"?t.number:null,url:t.url??null,title:t.title??null,status:yi(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:ku(t.reviewDecision),requiredChecks:Ri(t.requiredChecks),comments:Tu(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},yi=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,ku=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Tu=e=>Array.isArray(e)?e.flatMap(t=>{if(typeof t!="object"||t===null)return[];let r=t;return typeof r.body!="string"||!r.body.trim()?[]:[{author:typeof r.author=="string"?r.author:null,body:r.body,createdAt:typeof r.createdAt=="string"?r.createdAt:null,url:typeof r.url=="string"?r.url:null}]}):[],Ri=e=>Array.isArray(e)?e.map(t=>({...t,status:t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown"?t.status:"unknown",conclusion:t.conclusion??null})):[],yu=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Ru=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as op}from"node:fs/promises";import{readFile as bu,readdir as Pu,rm as Su}from"node:fs/promises";import bi from"node:path";var Cn=(e,t)=>bi.join(e.workspacesDir,`${t}.json`),Iu=e=>{if(typeof e!="object"||e===null)return e;let t=e,r=t.repoId??t.primaryRepoId;return{...t,kind:t.kind??"repo",name:t.name??r??t.id,rootPath:t.rootPath??"",primaryRepoId:t.primaryRepoId??r??"",repoId:t.kind==="project"?t.repoId:r,discoveredRepoIds:Array.isArray(t.discoveredRepoIds)?t.discoveredRepoIds.filter(n=>typeof n=="string"):t.kind==="project"?[]:r?[r]:[],linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(n=>typeof n=="string"):[]}},Pi=(e,t)=>{let r=Iu(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Ve=async(e,t)=>{let r=Cn(e,t);try{let n=await bu(r,"utf8");return Pi(JSON.parse(n),r)}catch(n){throw Cu(n)?new R("WORKSPACE_NOT_FOUND",`Craig workspace "${t}" was not found.`,{details:{workspaceId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig workspace record at ")?new R("WORKSPACE_RECORD_INVALID",n instanceof Error?n.message:`Craig workspace "${t}" is invalid.`,{details:{workspaceId:t},cause:n}):n}},Ke=async(e,t)=>{await q(Cn(e,t.id),{...t,updatedAt:new Date().toISOString()})},se=async e=>{let t=await Pu(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Ve(e,bi.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Si=async(e,t)=>{await Su(Cn(e,t),{force:!0})},Cu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as vu,readdir as Au,rm as Eu}from"node:fs/promises";import Ii from"node:path";var vn=(e,t)=>Ii.join(e.reposDir,`${t}.json`),Ci=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},le=async(e,t)=>{let r=vn(e,t);try{let n=await vu(r,"utf8");return Ci(JSON.parse(n),r)}catch(n){throw xu(n)?new R("REPO_NOT_FOUND",`Craig repo "${t}" was not found.`,{details:{repoId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig repo record at ")?new R("REPO_RECORD_INVALID",n instanceof Error?n.message:`Craig repo "${t}" is invalid.`,{details:{repoId:t},cause:n}):n}},An=async(e,t)=>{await q(vn(e,t.id),{...t,updatedAt:new Date().toISOString()})},Et=async e=>{let t=await Au(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>le(e,Ii.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},vi=async(e,t)=>{await Eu(vn(e,t),{force:!0})},xu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Du}from"node:fs/promises";var $u=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},ct=(e,t,r)=>{if(!$u(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},ee=async e=>{let t=await Du(e.indexFile,"utf8");return ct(JSON.parse(t),e.workspaceRoot,e.indexFile)},ye=async(e,t)=>{await q(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as ju,stat as Fu}from"node:fs/promises";import ut from"node:path";import{realpath as xi}from"node:fs/promises";import fr from"node:path";import{execFile as Ou}from"node:child_process";import{promisify as Mu}from"node:util";var Ai=Mu(Ou);async function S(e,t,r={}){try{let n=await Ai(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Ei(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function D(e,t,r={}){try{let n=await Ai(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Ei(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Ei(e){return e instanceof Error}var En=async e=>{try{let r=(await S("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([xi(r).catch(()=>fr.resolve(r)),xi(e).catch(()=>fr.resolve(e))]);return n===s}catch{return!1}},xn=async e=>{let t=await D("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await D("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await S("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"},Di=async e=>{let t=await D("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd:e}),r=t.stdout.trim();if(t.exitCode!==0||r.length===0)return null;let n=fr.resolve(e,r);return fr.dirname(n)};import{mkdir as fe,readFile as Lu}from"node:fs/promises";var Nu=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",dt=async e=>{let t=Z(e);await fe(t.craigDir,{recursive:!0}),await Promise.all([fe(t.reposDir,{recursive:!0}),fe(t.workspacesDir,{recursive:!0}),fe(t.sessionsDir,{recursive:!0}),fe(t.runtimeDir,{recursive:!0}),fe(t.tasksDir,{recursive:!0}),fe(t.jobsDir,{recursive:!0}),fe(t.logsDir,{recursive:!0}),fe(t.artifactsDir,{recursive:!0}),fe(t.worktreesDir,{recursive:!0})]);try{let s=await Lu(t.indexFile,"utf8"),o=JSON.parse(s);return ct(o,e,t.indexFile)}catch(s){if(!Nu(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await q(t.indexFile,n),n};var $i=(e,t,r)=>{let n=new Date().toISOString();return{id:_u(e,ut.basename(t)),name:ut.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Oi=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},_u=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",n=`repo_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`repo_${r}_${s}`,s+=1;return n},Wu=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},Mi=async(e,t)=>{let r=await ee(e);await ye(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},qu=async(e,t)=>{let r=await ju(t,{withFileTypes:!0}),n=await Et(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=ut.join(t,o.name);if(!await En(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await xn(i);s.push(a?Oi(a,l):$i([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},Uu=async(e,t)=>{let r=await xn(t),n=await Et(e),s=n.find(u=>u.rootPath===t)??null,o=s?Oi(s,r):$i(n,t,r),i=`workspace_${o.id}`,l=(await se(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await An(e,o),l||await Ke(e,d),await Mi(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},Bu=async(e,t)=>{let r=await qu(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await se(e),s=Wu(n,ut.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:ut.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>An(e,c))),await Ke(e,l),await Mi(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},xt=async(e,t)=>{await dt(e.workspaceRoot);let r=ut.resolve(e.workspaceRoot,t);if(!(await Fu(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await En(r)?Uu(e,r):Bu(e,r)};var Dn=async(e,t,r={listWorkspaceRecords:se,ensureCraigState:dt})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var $n=async(e,t,r={readWorkspace:Ve,writeWorkspace:Ke})=>{let s={...await r.readWorkspace(e,t),status:"archived",archivedAt:new Date().toISOString()};return await r.writeWorkspace(e,s),{kind:"archiveWorkspace",workspaceId:s.id,status:s.status,branch:s.branch}};var On=async(e,t)=>{let n={...await Ve(e,t),status:"active",archivedAt:null};await Ke(e,n);let s=n.kind==="project"?n.discoveredRepoIds?.[0]??null:n.primaryRepoId;return{kind:"restoreWorkspace",workspaceId:n.id,status:n.status,branch:n.branch,primaryRepoId:s}};var Ge=async(e,t,r={deleteWorkspace:Si,readCraigIndex:ee,writeCraigIndex:ye})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Mn=async(e,t,r)=>{let n=await Ve(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await Ge(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};import{readFile as Vu,realpath as ji,stat as Ku}from"node:fs/promises";import gr from"node:path";async function Ln(e){let t=await _i(e.cwd,"Current working directory");if(e.explicitWorkspaceRoot!==void 0)return Li(e.explicitWorkspaceRoot,"explicit",t,e.allowUninitializedCwd??!1);if(e.environmentWorkspaceRoot!==void 0)return Li(e.environmentWorkspaceRoot,"environment",t,e.allowUninitializedCwd??!1);let r=await Ni(t);if(r)return{workspaceRoot:r,source:"ancestor",initialized:!0};let n=await Di(t);if(n){let s=await Ni(n);if(s)return{workspaceRoot:s,source:"git_common_dir",initialized:!0}}if(e.allowUninitializedCwd)return{workspaceRoot:t,source:"cwd",initialized:!1};throw new R("WORKSPACE_CONTEXT_NOT_FOUND",`No Craig workspace was found from ${t}. Use --workspace-root <path> or run Craig inside an initialized workspace.`,{details:{cwd:t}})}async function Li(e,t,r,n){let s=t==="explicit"?"Workspace root":"CRAIG_WORKSPACE_ROOT",o=await _i(gr.resolve(r,e),s),i=await Fi(o);if(i)return{workspaceRoot:i,source:t,initialized:!0};if(n)return{workspaceRoot:o,source:t,initialized:!1};throw new R("WORKSPACE_CONTEXT_NOT_FOUND",`${s} ${o} is not an initialized Craig workspace.`,{details:{workspaceRoot:o,source:t}})}async function Ni(e){let t=e;for(;;){let r=await Fi(t);if(r)return r;let n=gr.dirname(t);if(n===t)return null;t=n}}async function Fi(e){let t=Z(e);try{let r=await Vu(t.indexFile,"utf8"),n=JSON.parse(r),s=typeof n=="object"&&n!==null&&"workspaceRoot"in n&&typeof n.workspaceRoot=="string"?n.workspaceRoot:e,o=ct(n,s,t.indexFile);if(await ji(o.workspaceRoot).catch(()=>gr.resolve(o.workspaceRoot))!==e)throw new Error(`Craig index at ${t.indexFile} belongs to ${o.workspaceRoot}, not ${e}. Remove or repair the file before rerunning Craig.`);return o.workspaceRoot}catch(r){if(Gu(r))return null;throw r instanceof R?r:new R("WORKSPACE_CONTEXT_INVALID",r instanceof Error?r.message:`Craig workspace at ${e} is invalid.`,{details:{workspaceRoot:e},cause:r})}}async function _i(e,t){let r=gr.resolve(e);try{if(!(await Ku(r)).isDirectory())throw new R("WORKSPACE_CONTEXT_INVALID",`${t} ${r} is not a directory.`,{details:{path:r}});return await ji(r)}catch(n){throw n instanceof R?n:new R("WORKSPACE_CONTEXT_NOT_FOUND",`${t} ${r} does not exist or cannot be read.`,{details:{path:r},cause:n})}}function Gu(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Nn={};ir(Nn,{addRepo:()=>Wi,listRegisteredRepos:()=>qi,removeRepo:()=>Ui});import Hu from"node:path";import{stat as zu}from"node:fs/promises";var Wi=async(e,t)=>{let r=Hu.resolve(e.workspaceRoot,t);if(!(await zu(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await xt(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var qi=async(e,t={listRepos:Et,ensureCraigState:dt})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ui=async(e,t,r)=>{let n=await le(e,t),o=(await se(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Ge(e,c.id))),await vi(e,t);let l=await ee(e);return await ye(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var G={addWorkspace:xt,listWorkspaces:Dn,archiveWorkspace:$n,restoreWorkspace:On,removeWorkspace:Mn,removeWorkspaceRecord:Ge,resolveContext:Ln,repos:Nn};import{mkdir as Bi,readFile as Yu,rm as wr,stat as Ju,writeFile as Qu}from"node:fs/promises";import hr from"node:path";var Xu=25,Zu=3e4,ep=5e3;async function xe(e,t,r){let n=hr.join(e.runtimeDir,"task-locks"),s=hr.join(n,`${t}.lock`);await Bi(n,{recursive:!0});let o=Date.now();for(;;)try{await Bi(s);try{await Qu(hr.join(s,"owner.json"),JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()}),"utf8")}catch(i){throw await wr(s,{recursive:!0,force:!0}),i}break}catch(i){if(!np(i))throw i;if(await tp(s))continue;if(Date.now()-o>=Zu)throw new R("OPERATION_TIMEOUT",`Timed out waiting to update task ${t}.`,{retryable:!0,details:{taskId:t}});await sp(Xu)}try{return await r()}finally{await wr(s,{recursive:!0,force:!0})}}async function tp(e){let t=await Yu(hr.join(e,"owner.json"),"utf8").then(n=>JSON.parse(n)).catch(()=>null);if(t&&typeof t.pid=="number")return rp(t.pid)?!1:(await wr(e,{recursive:!0,force:!0}),!0);let r=await Ju(e).catch(()=>null);return!r||Date.now()-r.mtimeMs<ep?!1:(await wr(e,{recursive:!0,force:!0}),!0)}function rp(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="EPERM"}}var np=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="EEXIST",sp=e=>new Promise(t=>setTimeout(t,e));var Re=async(e,t)=>{let r=await op(kr(e,t),"utf8");return JSON.parse(r)},Dt=async(e,t)=>{let r=await Re(e,t);return ae(r,kr(e,t))},be=async(e,t)=>{let r=Vi(t);await q(kr(e,t.id),r)},E=async(e,t,r)=>xe(e,t,async()=>{let n=await Dt(e,t),s=await r(n);if(s.id!==t)throw new Error(`Task mutation cannot change task id ${t} to ${s.id}.`);let o=Vi(s);return await q(kr(e,t),o),o}),jn=async(e,t)=>{let r=await ee(e);r.taskIds.includes(t)||await ye(e,{...r,taskIds:[...r.taskIds,t]})},kr=(e,t)=>`${e.tasksDir}/${t}.json`,Vi=e=>({...e,updatedAt:new Date().toISOString()});var A=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,De=e=>e.status==="merged"||e.status==="closed",Pe=(e,t)=>{let r=e.prs.findIndex(s=>pt(s,t)),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},pt=(e,t)=>e.number===null||t.number===null||e.number!==t.number?!1:!e.owner||!e.repo||!t.owner||!t.repo?!0:e.owner.toLowerCase()===t.owner.toLowerCase()&&e.repo.toLowerCase()===t.repo.toLowerCase(),He=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return yr(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},yr=e=>e.mergeable&&!ip(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),ip=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Fn=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),Se=(e,t,r)=>{let n=e.isDraft??!1,s=ap(e.state,n);return{provider:"github",owner:r?.owner??t?.owner??null,repo:r?.name??t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:s,draft:n,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:lp(e.reviewDecision??null),requiredChecks:_n(e.statusCheckRollup),comments:e.comments===void 0?t?.comments??[]:pp(e.comments),createdAt:e.createdAt??t?.createdAt??null,updatedAt:e.updatedAt??t?.updatedAt??null,mergedAt:e.mergedAt??t?.mergedAt??null,lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}},ap=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,lp=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,_n=e=>{let t=e.map(n=>cp(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||dp(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},cp=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=t.name??t.context,n=t.state??t.status??t.conclusion;return r?{name:r,status:Gi(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:up(t)}:null},dp=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Tr(e)&&!Tr(t)?!0:!Tr(e)&&Tr(t)?!1:Ki(t.status)>=Ki(e.status),Tr=e=>e.conclusion?.toUpperCase()==="CANCELLED",Ki=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},up=e=>{let t=e.completedAt??e.startedAt??e.createdAt??null;if(!t)return null;let r=new Date(t).getTime();return Number.isFinite(r)?r:null},pp=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(mp).filter(r=>r!==null).slice(-4):[]},mp=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=fp(t.bodyText??t.body??"");return r?{author:typeof t.author=="string"?t.author:t.author?.login??null,body:r,createdAt:t.createdAt??null,url:t.url??null}:null},fp=e=>e.replace(/\s+/g," ").trim(),Gi=(e,t)=>{let r=e?.toUpperCase()??null,n=t?.toUpperCase()??null;return n==="SKIPPED"||r==="SKIPPED"?"skipped":r==="SUCCESS"||n==="SUCCESS"||n==="NEUTRAL"?"success":r==="PENDING"||r==="EXPECTED"||r==="IN_PROGRESS"||r==="QUEUED"||r==="REQUESTED"||r==="WAITING"?"pending":r==="FAILURE"||r==="FAILED"||r==="ERROR"||r==="TIMED_OUT"||r==="CANCELLED"||r==="ACTION_REQUIRED"||r==="STARTUP_FAILURE"||n==="FAILURE"||n==="FAILED"||n==="ERROR"||n==="TIMED_OUT"||n==="CANCELLED"||n==="ACTION_REQUIRED"||n==="STARTUP_FAILURE"?"failed":r==="COMPLETED"&&n===null?"unknown":r==="COMPLETED"&&n!==null?Gi(n,n):"unknown"};var ge=class extends Error{constructor(t){super(t),this.name="GitHubRateLimitError"}};import{access as gp}from"node:fs/promises";import Hi from"node:path";var I=async(e,t,r={readRawTask:Re,validateTaskRecord:ae})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw yp(n)?new R("TASK_NOT_FOUND",`Craig task "${t}" was not found.`,{details:{taskId:t}}):Rp(n)?new R("TASK_RECORD_INVALID",n instanceof Error?n.message:`Craig task "${t}" is invalid.`,{details:{taskId:t},cause:n}):n}},K=async e=>{if(!await Wn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},mt=(e,t)=>t.artifacts.logPath?Hi.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Hi.join(e.workspaceRoot,t.artifacts.logPath):null,$t=async(e,t)=>{let r=await Wn(t.worktreePath),n=mt(e,t),s=n?await Wn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:hp(t),lastCommitSummary:wp(t),prSummary:kp(t),cleanupSummary:Tp(t)}},Wn=async e=>{try{return await gp(e),!0}catch{return!1}},hp=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},wp=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",kp=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
13
13
|
${o.join(`
|
|
14
|
-
`)}`}let t
|
|
15
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},
|
|
14
|
+
`)}`}let t=A(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},Tp=e=>e.status!=="merged"?"not merged":e.cleanup.warning?`warning: ${e.cleanup.warning}`:e.cleanup.preservedWorktree?"preserved worktree":e.cleanup.worktreeRemovedAt?`worktree removed at ${e.cleanup.worktreeRemovedAt}`:"cleanup pending",yp=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Rp=e=>e instanceof SyntaxError||e instanceof Error&&e.message.startsWith("Craig task record at ");var zi=async(e,t)=>{let r=await D("git",["show-ref","--verify","--quiet",`refs/heads/${t}`],{cwd:e});if(r.exitCode===0)return!0;if(r.exitCode===1)return!1;throw new Error(r.stderr.trim()||r.stdout.trim()||"Unable to check git branch state.")},qn=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await D("git",["show-ref","--verify","--quiet",`refs/heads/${s}`],{cwd:e})).exitCode!==0)throw new Error(`Base branch '${s}' does not exist locally.`);let i=await bp(e,s);await S("git",["worktree","add","-b",t,r,i],{cwd:e})},bp=async(e,t)=>(await D("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await D("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await D("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,Rr=async e=>{let t=await D("git",["status","--short"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"Unable to inspect git status.");return t.stdout.trim().length>0},Yi=async e=>{await S("git",["add","-A"],{cwd:e})},Ji=async(e,t)=>{await S("git",["commit","-m",t],{cwd:e})},Qi=async e=>{let t=await S("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",n=""]=t.stdout.trim().split(`
|
|
15
|
+
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},Xi=async e=>{let t=await D("git",["branch","--show-current"],{cwd:e});if(t.exitCode!==0)return null;let r=t.stdout.trim();return r.length>0?r:null};var Zi=async(e,t)=>{await S("git",["worktree","remove","--force",t],{cwd:e})};var Un=async e=>ft(e,e.repoRoot),ft=async(e,t)=>{let r=await ee(e),n=ea(new Date),s=ta(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await zi(t,i))return o;s+=1}},Ot=async e=>{let t=await ee(e),r=ea(new Date),n=ta(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},ea=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},ta=(e,t)=>{let r=e.filter(n=>n.startsWith(`task_${t}_`)).map(n=>Number.parseInt(n.slice(-2),10)).filter(n=>Number.isInteger(n));return r.length===0?1:Math.max(...r)+1};var Mt=async(e,t,r={readRawTask:Re,validateTaskRecord:ae})=>{let n=await ee(e),s=[],o=[];await Promise.all(n.taskIds.map(async l=>{try{let c=await r.readRawTask(e,l);s.push(r.validateTaskRecord(c,`${e.tasksDir}/${l}.json`))}catch(c){if(Pp(c)){o.push(l);return}throw c}}));let a=(t?.includeClosed?s:s.filter(l=>l.status!=="closed")).filter(l=>!(t?.workspaceId&&l.workspaceId!==t.workspaceId||t?.repoId&&l.repoId!==t.repoId&&!(l.repoTargets??[]).some(c=>c.repoId===t.repoId)));return a.sort((l,c)=>l.id.localeCompare(c.id)),o.sort(),{kind:"listTasks",tasks:a,missingTaskIds:o,repoId:t?.repoId??null}},Pp=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var ra=["merge_ready","pr_open","checked","review","running","draft"],Bn=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),Vn=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(Sp)[0]?.id??null,Sp=(e,t)=>{let r=na(e.status),n=na(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},na=e=>{let t=ra.indexOf(e);return t>=0?t:ra.length};import sa from"node:path";var ze=(e,t)=>t?sa.isAbsolute(t)?t:sa.join(e.repoRoot,t):null;import{mkdir as Lt,rm as Ip,writeFile as br}from"node:fs/promises";import $ from"node:path";var ia=["AGENTS","md"].join("."),gt=async(e,t,r,n={})=>{let s=await le(e,t),[o,i]=await Promise.all([xp(e,s.id),ft(e,s.rootPath)]),a=n.sessionId??null,l=`craig/${i}`,c=$.join(e.worktreesDir,s.id,i),d=$.join(e.logsDir,`${i}.log`),u=$.join(e.artifactsDir,i);await Promise.all([Lt($.dirname(c),{recursive:!0}),Lt(u,{recursive:!0}),br(d,"","utf8")]);let m=Cp(e,{taskId:i,repoId:s.id,workspaceId:o.id,sessionId:a,repoRoot:s.rootPath,prompt:r,runner:n.runner??"codex",config:n.config??{},branch:l,worktreePath:c});return await be(e,m),await jn(e,i),await qn(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:m}},Nt=async(e,t,r,n={})=>{let s=(await se(e)).find(v=>v.id===t&&v.status==="active");if(!s)throw new Error(`Workspace ${t} does not exist or is archived.`);if(s.kind!=="project"){if(!s.primaryRepoId)throw new Error(`Workspace ${t} is not task-capable.`);let v=await gt(e,s.primaryRepoId,r,n);return{...v,bundlePath:v.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await Ot(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,u=$.join(e.craigDir,"task-bundles",i),m=$.join(e.logsDir,`${i}.log`),g=$.join(e.artifactsDir,i);await Lt(u,{recursive:!0}),await Lt(g,{recursive:!0}),await br(m,"","utf8");let y=await Promise.all(o.map(v=>le(e,v))),w=Ap(y),b=await Promise.all(y.map(v=>vp(e,v,i,d,$.join(u,w.get(v.id))))),V=b.find(v=>v.status==="ready")??b[0];if(!b.some(v=>v.status==="ready"))throw await Ip(u,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${b.map(v=>`${v.repoId}: ${v.failureReason??"unknown error"}`).join("; ")}`);await br($.join(u,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:b.map(v=>({repoId:v.repoId,repoName:y.find(ke=>ke.id===v.repoId)?.name??v.repoId,path:$.relative(u,v.worktreePath),status:v.status,worktreePath:v.worktreePath,failureReason:v.failureReason}))},null,2),"utf8"),await br($.join(u,ia),Ep({taskId:i,workspaceId:t,prompt:r,repos:y,repoTargets:b,bundlePath:u}),"utf8");let H=jt(i,r,a,l,n.config??{}),re={id:i,title:r,slug:aa(r),type:"project",status:"draft",runner:l,repoId:V.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:H[0]?.id??null,linkedRepoIds:o.filter(v=>v!==V.repoId),repoRoot:u,worktreePath:u,branch:d,bundlePath:u,selectedRepoTargetId:V.repoId,repoTargets:b,ptyTabs:H,runnerSession:{command:f.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:V.checks,lastCommit:null,prs:[],artifacts:{logPath:$.relative(e.workspaceRoot,m),checkSummaryPath:$.relative(e.workspaceRoot,$.join(g,"check-summary.json")),prDraftPath:null,prStatusPath:$.relative(e.workspaceRoot,$.join(g,"pr-status.json"))},cleanup:Pr(),lastFailureReason:b.every(v=>v.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await be(e,re),await jn(e,i),{repoId:V.repoId,repoRoot:u,sessionId:c,workspaceId:s.id,task:re,bundlePath:u,repoTargets:b}},jt=(e,t,r,n="codex",s={})=>{let o=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:f.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Cp=(e,t)=>{let r=new Date().toISOString(),n=jt(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:aa(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:n[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:n,runnerSession:{command:f.runners.buildCommand(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{...Kn($.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:$.relative(e.workspaceRoot,$.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:$.relative(e.workspaceRoot,$.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:$.relative(e.workspaceRoot,$.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:Pr(),lastFailureReason:null,createdAt:r,updatedAt:r}},vp=async(e,t,r,n,s)=>{await Lt($.dirname(s),{recursive:!0});try{return await qn(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Kn($.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:oa(),cleanup:Pr()}}catch(o){return{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"unavailable",failureReason:o instanceof Error?o.message:"Failed to create worktree.",checks:Kn($.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:oa(),cleanup:Pr()}}},Ap=e=>{let t=new Set(["manifest.json",ia]),r=new Map;for(let n of e){let s=t.has(n.name)?`${n.name}-repo`:n.name,o=s,i=2;for(;t.has(o);)o=`${s}-${i}`,i+=1;t.add(o),r.set(n.id,o)}return r},Ep=e=>{let t=new Map(e.repos.map(n=>[n.id,n.name])),r=e.repoTargets.map(n=>{let s=t.get(n.repoId)??n.repoId,o=$.relative(e.bundlePath,n.worktreePath),i=n.status==="ready"?"ready":`unavailable: ${n.failureReason??"unknown error"}`;return`- \`${o}/\` - ${s} (${n.repoId}, ${i})`}).join(`
|
|
16
16
|
`);return["# Craig Project Task Bundle","","This directory is a Craig project task bundle. Repo work must happen inside the child repo worktrees listed below.","","Run repo Git commands from a repo worktree directory, not from the bundle root. Use `manifest.json` as the machine-readable source of truth for this bundle.","",`Task: \`${e.taskId}\``,`Workspace: \`${e.workspaceId}\``,`Prompt: ${e.prompt}`,"","## Repo Worktrees","",r,""].join(`
|
|
17
|
-
`)},vn=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Pi=()=>({provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}),cr=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),Lu=async(e,t)=>{let n=(await ie(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},Ii=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import Li from"node:path";import{readFile as Fu,rm as iR}from"node:fs/promises";import ju from"node:path";var Ee=async(e,t)=>{let r=await Fu(En(e,t),"utf8"),n=JSON.parse(r);return Wu(n,En(e,t))},qe=async(e,t)=>{await U(En(e,t.id),{...t,updatedAt:new Date().toISOString()})};var En=(e,t)=>ju.join(e.sessionsDir,`${t}.json`);function Wu(e,t){let r=qu(e);if(typeof r!="object"||r===null||typeof r.id!="string"||typeof r.taskId!="string"||typeof r.repoId!="string"||typeof r.workspaceId!="string"||r.substrate!=="tmux"||typeof r.sessionName!="string"||typeof r.paneId!="string"||!(r.windowTarget===null||typeof r.windowTarget=="string")||typeof r.worktreePath!="string"||!(r.logPath===null||typeof r.logPath=="string")||!Array.isArray(r.command)||!r.command.every(n=>typeof n=="string")||!["starting","running","exited","failed"].includes(r.status)||!(r.startedAt===null||typeof r.startedAt=="string")||!(r.exitedAt===null||typeof r.exitedAt=="string")||!(r.exitCode===null||typeof r.exitCode=="number")||!(r.lastAttachedAt===null||typeof r.lastAttachedAt=="string")||!Uu(r.attach)||!_u(r.snapshot)||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig session record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function _u(e){return e===null||typeof e=="object"&&e!==null&&typeof e.paneId=="string"&&(typeof e.windowTarget=="string"||e.windowTarget===null)&&typeof e.alive=="boolean"&&typeof e.capturedAt=="string"}function Uu(e){return typeof e=="object"&&e!==null&&e.detachChord==="ctrl+]"&&(e.lastSize===null||typeof e.lastSize=="object"&&e.lastSize!==null&&typeof e.lastSize.columns=="number"&&typeof e.lastSize.rows=="number")}function qu(e){let t=typeof e=="object"&&e!==null?e:{};return{id:t.id??"",taskId:t.taskId??"",repoId:t.repoId??"",workspaceId:t.workspaceId??"",substrate:t.substrate??"tmux",sessionName:t.sessionName??"",paneId:t.paneId??"",windowTarget:typeof t.windowTarget=="string"?t.windowTarget:null,worktreePath:t.worktreePath??"",logPath:typeof t.logPath=="string"?t.logPath:null,command:Array.isArray(t.command)?t.command.filter(r=>typeof r=="string"):[],status:t.status??"starting",startedAt:typeof t.startedAt=="string"?t.startedAt:null,exitedAt:typeof t.exitedAt=="string"?t.exitedAt:null,exitCode:typeof t.exitCode=="number"?t.exitCode:null,lastAttachedAt:typeof t.lastAttachedAt=="string"?t.lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:typeof t.attach=="object"&&t.attach!==null&&t.attach.lastSize&&typeof t.attach.lastSize.columns=="number"&&typeof t.attach.lastSize.rows=="number"?t.attach.lastSize:null},snapshot:t.snapshot&&typeof t.snapshot=="object"?{paneId:typeof t.snapshot.paneId=="string"?t.snapshot.paneId:t.paneId??"",windowTarget:typeof t.snapshot.windowTarget=="string"?t.snapshot.windowTarget:null,alive:!!t.snapshot.alive,capturedAt:typeof t.snapshot.capturedAt=="string"?t.snapshot.capturedAt:new Date().toISOString()}:null,createdAt:t.createdAt??"",updatedAt:t.updatedAt??""}}import{spawn as Bu}from"node:child_process";import{createHash as Vu}from"node:crypto";import Ku from"node:path";function dr(e){return`'${e.replace(/'/g,"'\\''")}'`}var Gu="craig",Ci=async(e,t,r)=>{let n=An(e,t),s=zu(),o=await I("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Qu(o.stdout);return await Hu(e,n),i};var Hu=async(e,t)=>{let r=[["set-option","-t",t,"status","off"],["set-option","-t",t,"detach-on-destroy","off"],["set-window-option","-t",t,"pane-border-status","off"],["set-window-option","-t",t,"aggressive-resize","on"]];for(let n of r)await I("tmux",n,{cwd:e})},vi=async(e,t,r)=>{await I("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},Ei=async(e,t,r)=>{await I("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var Ai=async(e,t,r)=>{await I("tmux",["pipe-pane","-o","-t",e,`cat >> ${dr(t)}`],{cwd:r})},ur=async(e,t,r,n)=>{let s=n??Di(e);if(r?await I("tmux",["select-window","-t",r],{cwd:e}):await I("tmux",["select-window","-t",t],{cwd:e}),await I("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await I("tmux",["switch-client","-t",s],{cwd:e});return}await Xu(e,["attach-session","-t",s])};var xi=async(e,t)=>{await I("tmux",["kill-session","-t",t],{cwd:e})};var Di=e=>{let r=Ku.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Vu("sha1").update(e).digest("hex").slice(0,8);return`${Gu}-${r}-${n}`},An=(e,t)=>`${Di(e)}-${t.toLowerCase()}`,zu=()=>{let e=Yu();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Yu=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Qu=e=>{let t=Ju(e);if(t.length<3)throw new Error("tmux did not return the expected session, window, and pane targets for the Craig task session.");return{sessionName:t[0],windowTarget:t[1],paneId:t[2]}},Ju=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Xu=async(e,t)=>{await new Promise((r,n)=>{let s=Bu("tmux",t,{cwd:e,stdio:"inherit"});s.on("error",n),s.on("exit",o=>{if(o===0){r();return}n(new Error(`tmux ${t.join(" ")} failed with exit code ${o??"unknown"}.`))})})};import{accessSync as Zu,constants as ep}from"node:fs";import{homedir as $i}from"node:os";import Ae from"node:path";var tp=[Ae.join($i(),".local","bin"),Ae.join($i(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function Mi(e=process.env){return rp([...(e.PATH??"").split(Ae.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:tp])}function Be(e=process.env){return{...e,PATH:Mi(e).join(Ae.delimiter)}}function xn(e,t={}){if(e.includes(Ae.sep)){let r=Ae.isAbsolute(e)?e:Ae.resolve(t.cwd??process.cwd(),e);return Oi(r)?r:null}for(let r of Mi(t.env)){let n=Ae.join(r,e);if(Oi(n))return n}return null}function Ve(e,t={}){let r=xn(e,t);if(r)return r;throw new Error(`Command not found: ${e}. Install it or add its directory to PATH. Craig also checks ~/.local/bin, /opt/homebrew/bin, and /usr/local/bin.`)}function Oi(e){try{return Zu(e,ep.X_OK),!0}catch{return!1}}function rp(e){return[...new Set(e)]}var Dt={async create(e,t){let r=await Ci(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Ai(r.paneId,t.logPath,t.repoRoot);let n=await Ni({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||An(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await qe(e,s),s},async attach(e,t,r){let n=await Dt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await ur(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await qe(e,s),s},async resize(e,t,r,n){await vi(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await qe(e,s),s},async write(){throw new Error("Direct session writes are owned by the terminal bridge.")},async read(){throw new Error("Direct session reads are owned by the terminal bridge.")},async terminate(e,t,r){let n={...t,status:"failed",exitedAt:new Date().toISOString(),snapshot:{...t.snapshot??{paneId:t.paneId,windowTarget:t.windowTarget,alive:!1,capturedAt:new Date().toISOString()},alive:!1,capturedAt:new Date().toISOString()},command:t.command};return await qe(e,n),n},async snapshot(e,t){return np(e,t)}},Dn={async prepare(e,t){let n=e.runnerSession.command[0],s=Be();Ve(n,{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ve(r[0],{cwd:e.worktreePath,env:Be()});await Ei(t.session.paneId,[n,...r.slice(1)].map(s=>dr(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},np=async(e,t)=>{let r=await x("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return Ni({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},Ni=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var $n=async(e,t,r,n={})=>{let s=r.trim(),o=await f.load(e),i=n.runner??f.runners.getDefault(o);if(f.runners.assertEnabled(i,o),t.trim().length===0)throw new Error(n.workspaceId?"Workspace id cannot be empty.":"Repo id cannot be empty.");if(s.length===0)throw new Error("Task prompt cannot be empty.");let a=n.workspaceId?await At(e,n.workspaceId,s,{runner:i,config:o}):await lt(e,t,s,{runner:i,config:o}),l=a.task,c=f.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?Li.resolve(e.workspaceRoot,l.artifacts.logPath):Li.join(e.logsDir,`${l.id}.log`);try{await Dn.prepare(l,{repoRoot:a.repoRoot});let m=await Dt.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await Dn.launch(l,{repoRoot:a.repoRoot,session:m});let T=new Date().toISOString();m={...m,status:"running",startedAt:T,command:c};let R={...l,status:"running",runner:i,sessionId:m.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:m.command,pid:null,startedAt:T,lastKnownState:"running",exitCode:null,exitedAt:null}};return await P(e,R),await qe(e,m),{kind:"createTask",taskId:R.id,repoId:R.repoId,workspaceId:R.workspaceId,sessionId:m.id,status:R.status,branch:R.branch,worktreePath:R.worktreePath,runner:R.runner}}catch(m){let T={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:m instanceof Error?m.message:"Unknown Craig error"};throw await P(e,T),m}};import{mkdir as lp}from"node:fs/promises";import cp from"node:path";var ct=async e=>{let t=await x("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Fi=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await I("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},pr=async(e,t)=>{let r=await I("gh",_i(e),{cwd:t});return JSON.parse(r.stdout)},dt=async(e,t)=>{let r=await x("gh",_i(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},ji=async(e,t,r)=>{if(r.length===0)return[];let n=ip(r),s;try{s=await I("gh",["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`])}catch(a){throw sp(a)?new he(a instanceof Error?a.message:String(a)):a}let i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=ap(c);return{id:a.id,found:d!==null,view:d}})},Wi=async e=>{let t=await x("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:op(t.stdout.trim())},sp=e=>{let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("rate limit")||t.includes("secondary rate limit")||t.includes("abuse detection")||t.includes("api rate limit exceeded")||t.includes("you have exceeded")},_i=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],op=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},ip=e=>`
|
|
17
|
+
`)},Kn=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),oa=()=>({provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}),Pr=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),xp=async(e,t)=>{let n=(await se(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},aa=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import ka from"node:path";import{readFile as Dp,rm as uR}from"node:fs/promises";import $p from"node:path";var $e=async(e,t)=>{let r=await Dp(Gn(e,t),"utf8"),n=JSON.parse(r);return Op(n,Gn(e,t))},Ye=async(e,t)=>{await q(Gn(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Gn=(e,t)=>$p.join(e.sessionsDir,`${t}.json`);function Op(e,t){let r=Np(e);if(typeof r!="object"||r===null||typeof r.id!="string"||typeof r.taskId!="string"||typeof r.repoId!="string"||typeof r.workspaceId!="string"||r.substrate!=="tmux"||typeof r.sessionName!="string"||typeof r.paneId!="string"||!(r.windowTarget===null||typeof r.windowTarget=="string")||typeof r.worktreePath!="string"||!(r.logPath===null||typeof r.logPath=="string")||!Array.isArray(r.command)||!r.command.every(n=>typeof n=="string")||!["starting","running","exited","failed"].includes(r.status)||!(r.startedAt===null||typeof r.startedAt=="string")||!(r.exitedAt===null||typeof r.exitedAt=="string")||!(r.exitCode===null||typeof r.exitCode=="number")||!(r.lastAttachedAt===null||typeof r.lastAttachedAt=="string")||!Lp(r.attach)||!Mp(r.snapshot)||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig session record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function Mp(e){return e===null||typeof e=="object"&&e!==null&&typeof e.paneId=="string"&&(typeof e.windowTarget=="string"||e.windowTarget===null)&&typeof e.alive=="boolean"&&typeof e.capturedAt=="string"}function Lp(e){return typeof e=="object"&&e!==null&&e.detachChord==="ctrl+]"&&(e.lastSize===null||typeof e.lastSize=="object"&&e.lastSize!==null&&typeof e.lastSize.columns=="number"&&typeof e.lastSize.rows=="number")}function Np(e){let t=typeof e=="object"&&e!==null?e:{};return{id:t.id??"",taskId:t.taskId??"",repoId:t.repoId??"",workspaceId:t.workspaceId??"",substrate:t.substrate??"tmux",sessionName:t.sessionName??"",paneId:t.paneId??"",windowTarget:typeof t.windowTarget=="string"?t.windowTarget:null,worktreePath:t.worktreePath??"",logPath:typeof t.logPath=="string"?t.logPath:null,command:Array.isArray(t.command)?t.command.filter(r=>typeof r=="string"):[],status:t.status??"starting",startedAt:typeof t.startedAt=="string"?t.startedAt:null,exitedAt:typeof t.exitedAt=="string"?t.exitedAt:null,exitCode:typeof t.exitCode=="number"?t.exitCode:null,lastAttachedAt:typeof t.lastAttachedAt=="string"?t.lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:typeof t.attach=="object"&&t.attach!==null&&t.attach.lastSize&&typeof t.attach.lastSize.columns=="number"&&typeof t.attach.lastSize.rows=="number"?t.attach.lastSize:null},snapshot:t.snapshot&&typeof t.snapshot=="object"?{paneId:typeof t.snapshot.paneId=="string"?t.snapshot.paneId:t.paneId??"",windowTarget:typeof t.snapshot.windowTarget=="string"?t.snapshot.windowTarget:null,alive:!!t.snapshot.alive,capturedAt:typeof t.snapshot.capturedAt=="string"?t.snapshot.capturedAt:new Date().toISOString()}:null,createdAt:t.createdAt??"",updatedAt:t.updatedAt??""}}import{spawn as jp}from"node:child_process";import{createHash as Fp}from"node:crypto";import _p from"node:path";function Sr(e){return`'${e.replace(/'/g,"'\\''")}'`}var Wp="craig",la=async(e,t,r)=>{let n=Hn(e,t),s=Up(),o=await S("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Vp(o.stdout);return await qp(e,n),i};var qp=async(e,t)=>{let r=[["set-option","-t",t,"status","off"],["set-option","-t",t,"detach-on-destroy","off"],["set-window-option","-t",t,"pane-border-status","off"],["set-window-option","-t",t,"aggressive-resize","on"]];for(let n of r)await S("tmux",n,{cwd:e})},ca=async(e,t,r)=>{await S("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},da=async(e,t,r)=>{await S("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var ua=async(e,t,r)=>{await S("tmux",["pipe-pane","-o","-t",e,`cat >> ${Sr(t)}`],{cwd:r})},Ir=async(e,t,r,n)=>{let s=n??ma(e);if(r?await S("tmux",["select-window","-t",r],{cwd:e}):await S("tmux",["select-window","-t",t],{cwd:e}),await S("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await S("tmux",["switch-client","-t",s],{cwd:e});return}await Gp(e,["attach-session","-t",s])};var pa=async(e,t)=>{await S("tmux",["kill-session","-t",t],{cwd:e})};var ma=e=>{let r=_p.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Fp("sha1").update(e).digest("hex").slice(0,8);return`${Wp}-${r}-${n}`},Hn=(e,t)=>`${ma(e)}-${t.toLowerCase()}`,Up=()=>{let e=Bp();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Bp=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Vp=e=>{let t=Kp(e);if(t.length<3)throw new Error("tmux did not return the expected session, window, and pane targets for the Craig task session.");return{sessionName:t[0],windowTarget:t[1],paneId:t[2]}},Kp=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Gp=async(e,t)=>{await new Promise((r,n)=>{let s=jp("tmux",t,{cwd:e,stdio:"inherit"});s.on("error",n),s.on("exit",o=>{if(o===0){r();return}n(new Error(`tmux ${t.join(" ")} failed with exit code ${o??"unknown"}.`))})})};import{accessSync as Hp,constants as zp}from"node:fs";import{homedir as fa}from"node:os";import Oe from"node:path";var Yp=[Oe.join(fa(),".local","bin"),Oe.join(fa(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ha(e=process.env){return Jp([...(e.PATH??"").split(Oe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Yp])}function Je(e=process.env){return{...e,PATH:ha(e).join(Oe.delimiter)}}function zn(e,t={}){if(e.includes(Oe.sep)){let r=Oe.isAbsolute(e)?e:Oe.resolve(t.cwd??process.cwd(),e);return ga(r)?r:null}for(let r of ha(t.env)){let n=Oe.join(r,e);if(ga(n))return n}return null}function Qe(e,t={}){let r=zn(e,t);if(r)return r;throw new Error(`Command not found: ${e}. Install it or add its directory to PATH. Craig also checks ~/.local/bin, /opt/homebrew/bin, and /usr/local/bin.`)}function ga(e){try{return Hp(e,zp.X_OK),!0}catch{return!1}}function Jp(e){return[...new Set(e)]}var Ft={async create(e,t){let r=await la(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await ua(r.paneId,t.logPath,t.repoRoot);let n=await wa({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||Hn(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ye(e,s),s},async attach(e,t,r){let n=await Ft.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Ir(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ye(e,s),s},async resize(e,t,r,n){await ca(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ye(e,s),s},async write(){throw new Error("Direct session writes are owned by the terminal bridge.")},async read(){throw new Error("Direct session reads are owned by the terminal bridge.")},async terminate(e,t,r){let n={...t,status:"failed",exitedAt:new Date().toISOString(),snapshot:{...t.snapshot??{paneId:t.paneId,windowTarget:t.windowTarget,alive:!1,capturedAt:new Date().toISOString()},alive:!1,capturedAt:new Date().toISOString()},command:t.command};return await Ye(e,n),n},async snapshot(e,t){return Qp(e,t)}},Yn={async prepare(e,t){let n=e.runnerSession.command[0],s=Je();Qe(n,{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Qe(r[0],{cwd:e.worktreePath,env:Je()});await da(t.session.paneId,[n,...r.slice(1)].map(s=>Sr(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},Qp=async(e,t)=>{let r=await D("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return wa({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},wa=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Jn=async(e,t,r,n={})=>{let s=r.trim(),o=await f.load(e),i=n.runner??f.runners.getDefault(o);if(f.runners.assertEnabled(i,o),t.trim().length===0)throw new Error(n.workspaceId?"Workspace id cannot be empty.":"Repo id cannot be empty.");if(s.length===0)throw new Error("Task prompt cannot be empty.");let a=n.workspaceId?await Nt(e,n.workspaceId,s,{runner:i,config:o}):await gt(e,t,s,{runner:i,config:o}),l=a.task,c=f.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?ka.resolve(e.workspaceRoot,l.artifacts.logPath):ka.join(e.logsDir,`${l.id}.log`);try{await Yn.prepare(l,{repoRoot:a.repoRoot});let m=await Ft.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await Yn.launch(l,{repoRoot:a.repoRoot,session:m});let g=new Date().toISOString();m={...m,status:"running",startedAt:g,command:c};let y=await E(e,l.id,w=>({...w,status:"running",runner:i,sessionId:m.id,selectedPtyTabId:w.selectedPtyTabId,runnerSession:{command:m.command,pid:null,startedAt:g,lastKnownState:"running",exitCode:null,exitedAt:null}}));return await Ye(e,m),{kind:"createTask",taskId:y.id,repoId:y.repoId,workspaceId:y.workspaceId,sessionId:m.id,status:y.status,branch:y.branch,worktreePath:y.worktreePath,runner:y.runner}}catch(m){throw await E(e,l.id,g=>({...g,sessionId:null,status:"draft",runnerSession:{...g.runnerSession,lastKnownState:"failed"},lastFailureReason:m instanceof Error?m.message:"Unknown Craig error"})),m}};import{mkdir as nm}from"node:fs/promises";import sm from"node:path";var Me=async e=>{let t=await D("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Ta=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await S("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},ht=async(e,t)=>{let r=await S("gh",Qn(e),{cwd:t});return JSON.parse(r.stdout)},wt=async(e,t)=>{let r=await D("gh",Qn(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},ya=async(e,t)=>{let r=await D("gh",Qn(e),{cwd:t});if(r.exitCode===0)return JSON.parse(r.stdout);let n=r.stderr.trim()||r.stdout.trim();if(Zp(n))return null;throw new Error(n||`GitHub CLI failed while discovering a pull request for ${e}.`)},Ra=async(e,t,r)=>{if(r.length===0)return[];let n=tm(r),s;try{s=await S("gh",["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`])}catch(a){throw Xp(a)?new ge(a instanceof Error?a.message:String(a)):a}let i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=rm(c);return{id:a.id,found:d!==null,view:d}})},Cr=async e=>{let t=await D("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:em(t.stdout.trim())},Le=e=>{let t=e.trim().match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/([1-9]\d*)(?:[/?#].*)?$/);return!t?.[1]||!t[2]||!t[3]?null:{owner:t[1],name:t[2],number:Number(t[3])}},Xp=e=>{let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("rate limit")||t.includes("secondary rate limit")||t.includes("abuse detection")||t.includes("api rate limit exceeded")||t.includes("you have exceeded")},Zp=e=>{let t=e.toLowerCase();return t.includes("no pull requests found")||t.includes("could not resolve to a pullrequest")},Qn=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],em=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},tm=e=>`
|
|
18
18
|
query CraigPullRequestBatch($owner: String!, $name: String!) {
|
|
19
19
|
repository(owner: $owner, name: $name) {
|
|
20
20
|
${e.map((r,n)=>{let s=`item${n}`;return r.mode==="number"?`${s}: pullRequest(number: ${Number(r.selector)}) { ...PrFields }`:`${s}: pullRequests(headRefName: ${JSON.stringify(r.selector)}, states: OPEN, first: 1, orderBy: { field: UPDATED_AT, direction: DESC }) { nodes { ...PrFields } }`}).join(`
|
|
@@ -68,56 +68,57 @@ fragment PrFields on PullRequest {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
`,
|
|
71
|
+
`,rm=e=>{if(!e||typeof e!="object")return null;let t="nodes"in e?e.nodes?.[0]??null:e;if(!t||typeof t!="object")return null;let r=t,n=r.statusCheckRollup?.contexts?.nodes??[];return{number:r.number,url:r.url,baseRefName:r.baseRefName,headRefName:r.headRefName,headRefOid:r.headRefOid??null,state:r.state,isDraft:r.isDraft??!1,title:r.title??null,createdAt:r.createdAt??null,updatedAt:r.updatedAt??null,mergedAt:r.mergedAt??null,mergeable:r.mergeable,mergeStateStatus:r.mergeStateStatus,reviewDecision:r.reviewDecision??null,statusCheckRollup:n,comments:r.comments?.nodes??[]}};var Xe=async(e,t)=>{let r=ze(e,t.artifacts.prStatusPath);r&&(await nm(sm.dirname(r),{recursive:!0}),await q(r,{taskId:t.id,prs:t.prs}))},_t=async(e,t,r={writeTask:be,writePrStatusArtifact:Xe})=>{await r.writeTask(e,t);try{await r.writePrStatusArtifact(e,t)}catch(n){throw new R("PARTIAL_RESULT",`Task ${t.id} was updated, but its PR status artifact could not be written.`,{retryable:!0,details:{taskId:t.id},cause:n})}return t},Wt=async(e,t,r,n,s={readRawTask:Re,validateTaskRecord:ae,writeTask:be,writePrStatusArtifact:Xe,withTaskLock:xe})=>s.withTaskLock(e,t.id,async()=>{let o=await s.readRawTask(e,t.id),i=s.validateTaskRecord(o,`${e.tasksDir}/${t.id}.json`),a=i.prs.find(m=>n?.number!==null&&m.number===n?.number)??n,l=Se(r,a),c=Pe(i,l),d=i.status==="closed"?i.status:He(c.prs),u={...c,status:d};return _t(e,u,s)}),qt=async(e,t)=>{let r=A(t),n=r?.number?String(r.number):t.branch,s=await ht(n,t.worktreePath);return Wt(e,t,s,r)},Ut=async(e,t)=>{for(let r of await Xn(t)){let n=await wt(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await Wt(e,t,n,null)}}return{discovered:!1,task:t}},Xn=async e=>{let t=await Xi(e.worktreePath).catch(()=>null);return[...new Set([t,e.branch].filter(r=>!!r))]};async function Bt(e,t,r,n){return xe(e,t,async()=>{let s=await I(e,t);if(!s.repoTargets?.find(g=>g.repoId===r))throw new Error(`Project task ${t} has no repo target ${r}.`);let i=Le(n.url),a=s.prs.find(g=>i?pt(g,{owner:i.owner,repo:i.name,number:n.number}):g.number===n.number)??null,l=Se(n,a,i??void 0),c=om(n),d=Pe(s,l),u={...d,repoTargets:(d.repoTargets??[]).map(g=>g.repoId===r?{...g,pullRequest:c}:g)},m={...u,status:u.status==="closed"?u.status:Zn(u)};return _t(e,m)})}function om(e){let t=Le(e.url);return{provider:"github",owner:t?.owner??null,repo:t?.name??null,number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:im(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:am(e.reviewDecision??null),requiredChecks:_n(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}}function Zn(e){let t=(e.repoTargets??[]).filter(n=>n.status==="ready"),r=t.map(n=>n.pullRequest).filter(n=>n.number!==null);return r.length===0?"checked":r.every(n=>n.status==="merged")?"merged":r.length===t.length&&r.every(n=>n.mergeable&&n.reviewDecision!=="REVIEW_REQUIRED"&&n.reviewDecision!=="CHANGES_REQUESTED"&&n.mergeStateStatus!=="REVIEW_REQUIRED"&&n.requiredChecks.length>0&&n.requiredChecks.every(s=>s.status==="success"||s.status==="skipped"))?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"}var im=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,am=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var kt=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let o=await ht(n,r.worktreePath);return await Bt(e,t.id,r.repoId,o),"synced"}let s=await wt(n,r.worktreePath);return s?(await Bt(e,t.id,r.repoId,s),"discovered"):"not_found"};var Vt=async(e,t)=>{let r=await I(e,t),n=A(r);return n?.number?(await Me(r.worktreePath),De(n)?(await Ut(e,r)).task:qt(e,r)):r},ts=async(e,t)=>{let r=await I(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Tt(e,t),I(e,t);let n=A(r);if(await K(r),await Me(r.worktreePath),!n?.number||De(n)){let o=await Ut(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return o.task}return await qt(e,r)},Tt=async(e,t)=>{let r=await I(e,t),n=(r.repoTargets??[]).filter(o=>o.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let o of n){await Me(o.worktreePath);let i=o.pullRequest.number?await kt(e,r,o):await kt(e,r,o).catch(()=>"not_found");s[i==="not_found"?"notFound":i]++}return s},rs=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=es(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let d of s.repoTargets.filter(u=>u.status==="ready")){let u={id:`${s.id}:${d.repoId}`,task:s,targetRepoId:d.repoId,worktreePath:d.worktreePath,selector:d.pullRequest.number?String(d.pullRequest.number):d.branch,mode:d.pullRequest.number?"number":"head",fallbackSelectors:[]};await ba(n,u).catch(async()=>{try{let m=d.pullRequest.number?await kt(e,s,d):await kt(e,s,d).catch(()=>"not_found");vr(o,m,d.pullRequest.number??null,d.pullRequest.url??null)}catch{}})}continue}let i=A(s),a=i?.number&&!De(i),l=a?[]:await Xn(s),c={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):l[0]??s.branch,mode:a?"number":"head",fallbackSelectors:a?[]:l.slice(1)};await ba(n,c).catch(async()=>{try{let{disposition:d,task:u}=await Ar(e,s.id),m=A(u);vr(o,d,m?.number??null,m?.url??null)}catch{}})}for(let s of n.values())try{await Me(s.worktreePath);let o=await Ra(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=es(r,a.task),d=i.get(a.id)?.view??await lm(s.worktreePath,a);if(!d){vr(l,"not_found",null,null);continue}if(a.targetRepoId)await Bt(e,a.task.id,a.targetRepoId,d);else{let u=await Re(e,a.task.id),m=ae(u,`${e.tasksDir}/${a.task.id}.json`);await Wt(e,m,d,a.mode==="number"?A(m):null)}vr(l,a.mode==="number"?"synced":"discovered",d.number,d.url)}}catch(o){if(o instanceof ge)throw o}return t.map(s=>es(r,s))},Ar=async(e,t)=>{let r=await I(e,t);await K(r),await Me(r.worktreePath);let n=A(r);if(n?.number&&!De(n))return{disposition:"synced",task:await qt(e,r)};let s=await Ut(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},lm=async(e,t)=>{if(t.mode!=="head")return null;for(let r of t.fallbackSelectors){let n=await wt(r,e);if(n)return n}return null},ba=async(e,t)=>{let r=await Cr(t.worktreePath);if(!r)throw new Error("GitHub repository remote could not be parsed.");let n=`${r.owner}/${r.name}`,s=e.get(n);if(s){s.items.push(t);return}e.set(n,{worktreePath:t.worktreePath,repository:r,items:[t]})},es=(e,t)=>{let r=e.get(t.id);if(r)return r;let n={taskId:t.id,synced:0,discovered:0,notFound:0,hadPr:t.type==="project"?!!t.repoTargets?.some(s=>s.pullRequest.number):!!A(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},vr=(e,t,r,n)=>{if(t==="synced"){e.synced+=1;return}if(t==="discovered"){e.discovered+=1,e.firstDiscoveredPrNumber??=r,e.firstDiscoveredPrUrl??=n;return}e.notFound+=1};var ns=async(e,t)=>{let r=await I(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Tt(e,t),r=await I(e,t)):r.prs.some(o=>o.number)&&(r=await Vt(e,t))}catch{}let n=await $t(e,r),s=r.sessionId?await $e(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var ss=async(e,t)=>{let r=await I(e,t);if(await K(r),(await S("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await cm(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},cm=async e=>{let t=[],r=await S("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await dm(e);for(let s of n){let o=await D("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
|
|
72
72
|
|
|
73
|
-
`)},
|
|
74
|
-
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Rp}from"node:child_process";import{access as yp}from"node:fs/promises";var Wn=async(e,t)=>{let r=await v(e,t),n=it(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await yp(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},_n=async e=>{await new Promise((t,r)=>{let n=!1,s=Rp("tail",["-n","+1","-f",e],{stdio:"inherit"}),o=()=>{n=!0,s.kill("SIGINT")};process.on("SIGINT",o),s.on("error",a=>{i(),r(a)}),s.on("exit",(a,l)=>{if(i(),n||l==="SIGINT"){t();return}if(a===0){t();return}r(new Error(`tail -n +1 -f ${e} failed with exit code ${a??"unknown"}.`))});function i(){process.off("SIGINT",o)}})};import{mkdir as bp}from"node:fs/promises";import Pp from"node:path";var Un=async(e,t)=>{let r=await v(e,t);if(await K(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await ar(r.worktreePath)&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);let s=(await f.load(e)).checks?.commands??[];if(s.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);r.checks.status="running",r.checks.commands=[...s],r.checks.results=[],await P(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await x("sh",["-lc",i],{cwd:r.worktreePath}),c=new Date().toISOString(),d=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:c,exitCode:d}),d!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=c,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await Ki(e,r),await P(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}return r.checks.results=o,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await Ki(e,r),await P(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Ki=async(e,t)=>{let r=Ue(e,t.artifacts.checkSummaryPath);r&&(await bp(Pp.dirname(r),{recursive:!0}),await U(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var qn=async(e,t)=>{let r=await v(e,t);await K(r);let n=await ar(r.worktreePath);if(r.status==="running"&&n&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!n)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let s=r.prompt.value.trim();await mi(r.worktreePath),await fi(r.worktreePath,s);let o=await gi(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await P(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Sp}from"node:fs/promises";var Bn=async(e,t)=>{let r=await v(e,t),n=await Ip(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await P(e,s),s},Ip=async e=>{try{return await Sp(e),!0}catch{return!1}};var Vn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await Ee(e,t.sessionId);await xi(e.repoRoot,s.sessionName),t.cleanup.paneClosedAt=new Date().toISOString()}}catch(s){n.push(s instanceof Error?s.message:"Failed to close tmux session.")}if(t.cleanup.preservedWorktree=r.preserveWorktree,!r.preserveWorktree)try{await ki(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(s){n.push(s instanceof Error?s.message:"Failed to remove worktree.")}t.cleanup.warning=n.length>0?n.join(" "):null,await P(e,t)};var Kn=async(e,t,r)=>{let[n,s]=await Promise.all([v(e,t),ce(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await P(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Gn=async(e,t)=>{let r=await v(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>ce(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Hn=async(e,t)=>{let r=await v(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([ce(e,r.repoId),Ee(e,r.sessionId)]),o=await Dt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var zn=async(e,t)=>{let r=await v(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await Ee(e,r.sessionId).catch(s=>{throw Cp(s)?new Error(`Task ${r.id} does not have a Craig session.`):s});if(!n.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await ur(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Cp=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as vp}from"node:child_process";var Yn=async(e,t)=>{let r=await v(e,t);await K(r);let s=(await f.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await Ep(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Ep=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=vp(s,o,{cwd:t,stdio:"inherit"});i.on("error",n),i.on("exit",a=>{if(a===0){r();return}n(new Error(`${e.join(" ")} failed with exit code ${a??"unknown"}.`))})})};var Qn=async(e,t,r)=>{let n=await ae(e,t);await P(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},Jn=async(e,t,r)=>{let n=await ae(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await P(e,s),s},Xn=async(e,t)=>{let r=await ae(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await P(e,s),s};import{realpath as Hi}from"node:fs/promises";import Lt from"node:path";async function es(e,t){if(t.explicitTaskId!==void 0){let l=await Gi(e,t.explicitTaskId,"explicit");return Zn(l,"explicit",t.environmentAgentTabId)}if(t.environmentTaskId!==void 0){let l=await Gi(e,t.environmentTaskId,"environment");return Zn(l,"environment",t.environmentAgentTabId)}let r=await Hi(t.cwd).catch(()=>Lt.resolve(t.cwd)),n=await vt(e,{includeClosed:!0}),o=(await Promise.all(n.tasks.map(async l=>({task:l,matches:await xp(l,r)})))).filter(l=>l.matches).map(l=>l.task),i=[...new Map(o.map(l=>[l.id,l])).values()];if(i.length>1)throw new S("TASK_CONTEXT_AMBIGUOUS",`Multiple Craig tasks match ${r}: ${i.map(l=>l.id).join(", ")}. Use --task <id>.`,{details:{cwd:r,taskIds:i.map(l=>l.id)}});let a=i[0];if(a)return Zn(a,"cwd",t.environmentAgentTabId);if(t.environmentAgentTabId!==void 0)throw new S("TASK_CONTEXT_CONFLICT",`CRAIG_AGENT_TAB_ID is set to ${t.environmentAgentTabId}, but no task context could be resolved.`,{details:{agentTabId:t.environmentAgentTabId}});if(t.required)throw new S("TASK_CONTEXT_NOT_FOUND",`No Craig task was found from ${r}. Use --task <id> or run the command inside a task worktree.`,{details:{cwd:r}});return null}async function Gi(e,t,r){try{return await v(e,t)}catch(n){throw!(n instanceof S)||n.code!=="TASK_NOT_FOUND"?n:new S("TASK_CONTEXT_NOT_FOUND",`Craig task "${t}" from ${r==="explicit"?"--task":"CRAIG_TASK_ID"} was not found.`,{details:{taskId:t,source:r},cause:n})}}function Zn(e,t,r){let n=r??null;if(n!==null){let s=e.ptyTabs.find(o=>o.id===n);if(!s||s.kind!=="agent")throw new S("TASK_CONTEXT_CONFLICT",`Agent tab ${n} does not belong to Craig task ${e.id}.`,{details:{taskId:e.id,agentTabId:n}})}return{task:e,source:t,agentTabId:n}}function Ap(e){return[e.worktreePath,...e.bundlePath?[e.bundlePath]:[],...(e.repoTargets??[]).map(t=>t.worktreePath)]}async function xp(e,t){return(await Promise.all(Ap(e).map(n=>Hi(n).catch(()=>Lt.resolve(n))))).some(n=>Dp(n,t))}function Dp(e,t){let r=Lt.relative(Lt.resolve(e),t);return r===""||!r.startsWith("..")&&!Lt.isAbsolute(r)}var ts=async(e,t,r="merge",n)=>{let s=await v(e,t),o=n??$(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Fi(s.worktreePath,o,r)};var E={listTasks:vt,getTask:v,provisionTask:lt,provisionProjectTask:At,createTask:$n,showTask:Fn,showTaskDiff:jn,prepareTaskLogs:Wn,streamTaskLogs:_n,runChecks:Un,commitTask:qn,closeTask:Bn,cleanupTask:Vn,addTaskLink:Kn,listTaskLinks:Gn,sortTasksForDisplay:In,resolveSelectedTaskId:Cn,allocateTaskId:Sn,allocateTaskIdForRepo:at,allocateProjectTaskId:Ct,createDefaultTaskPtyTabs:xt,assertTaskWorktreeExists:K,resolveTaskLogPath:it,buildTaskInspection:It,resolveArtifactPath:Ue,attachTask:Hn,focusTask:zn,openTask:Yn,markRunnerFailed:Qn,recordStartupFailure:Jn,markTaskStarted:Xn,resolveContext:es,prs:{refresh:Nt,refreshChecks:Nn,discoverOrRefresh:fr,discoverOrRefreshAll:pt,discoverOrRefreshMany:Ln,merge:ts,getPrimaryPr:$,isPrTerminal:ve,isMergeReady:ir,deriveTaskStatus:bt,upsertPr:ot,normalizePr:Pt,summarizeRequiredChecks:yn,writePrStatusArtifact:Ke}};async function Yi(e,t){switch(e.kind){case"addWorkspace":{let r=await H.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await rs(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await H.repos.addRepo(t.paths,e.path);return await rs(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return H.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Ze({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await ie(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await H.repos.removeRepo(t.paths,e.repoId,{listTasks:E.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Ce({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Ce({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return H.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await H.archiveWorkspace(t.paths,e.workspaceId);return await $p(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await H.restoreWorkspace(t.paths,e.workspaceId);return await rs(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return H.removeWorkspace(t.paths,e.workspaceId,{listTasks:E.listTasks});case"createTask":return E.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?E.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):E.listTasks(t.paths);case"currentTask":{let r=zi(t);return{kind:"currentTask",task:r.task,context:{source:r.source,agentTabId:r.agentTabId}}}case"attachTask":return E.attachTask(t.paths,e.taskId);case"addTaskLink":return E.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return E.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return E.showTask(t.paths,e.taskId);case"showCurrentTask":return E.showTask(t.paths,zi(t).task.id);case"showSelectedTask":return E.showTask(t.paths,Ge(t,"show"));case"streamTaskLogs":return E.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return E.prepareTaskLogs(t.paths,Ge(t,"logs"));case"showTaskDiff":return E.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return E.showTaskDiff(t.paths,Ge(t,"diff"));case"focusTask":return E.focusTask(t.paths,e.taskId);case"focusSelectedTask":return E.focusTask(t.paths,Ge(t,"focus"));case"openTask":return E.openTask(t.paths,e.taskId);case"openSelectedTask":return E.openTask(t.paths,Ge(t,"open"));case"runChecks":return E.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return E.runChecks(t.paths,Ge(t,"check"));case"commitTask":return E.commitTask(t.paths,e.taskId);case"commitSelectedTask":return E.commitTask(t.paths,Ge(t,"commit"));case"showContext":{let r=Mp(t);return{kind:"showContext",workspace:{root:r.workspaceRoot,source:r.source,initialized:r.initialized},task:t.taskContext?{id:t.taskContext.task.id,source:t.taskContext.source,agentTabId:t.taskContext.agentTabId}:null}}case"help":return{kind:"help",text:sn()};case"exit":return{kind:"exit"};default:return Op(e)}}async function rs(e,t,r){let n=await Ze({uiStateFile:e.uiStateFile})??Jt();await Ce({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function $p(e,t){let r=await Ze({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Ce({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Op(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ge(e,t){if(e.selectedTaskId)return e.selectedTaskId;throw new Error(`No task selected. Create a task with 'task new --repo <repo-id> <prompt>' or use '${t} <id>'.`)}function zi(e){if(e.taskContext)return e.taskContext;throw new Error("Command requires resolved task context.")}function Mp(e){if(e.workspaceContext)return e.workspaceContext;throw new Error("Command requires resolved workspace context.")}function Qi(e){switch(e.kind){case"createWorkspace":return[`${e.created?"Registered":"Updated"} ${e.workspace.kind??"repo"} workspace ${e.workspace.id}`,`Path: ${e.workspace.rootPath??""}`,`Repos: ${e.repos.map(t=>t.id).join(", ")}`].join(`
|
|
73
|
+
`)},dm=async e=>(await S("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
74
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as um}from"node:child_process";import{access as pm}from"node:fs/promises";var os=async(e,t)=>{let r=await I(e,t),n=mt(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await pm(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},is=async e=>{await new Promise((t,r)=>{let n=!1,s=um("tail",["-n","+1","-f",e],{stdio:"inherit"}),o=()=>{n=!0,s.kill("SIGINT")};process.on("SIGINT",o),s.on("error",a=>{i(),r(a)}),s.on("exit",(a,l)=>{if(i(),n||l==="SIGINT"){t();return}if(a===0){t();return}r(new Error(`tail -n +1 -f ${e} failed with exit code ${a??"unknown"}.`))});function i(){process.off("SIGINT",o)}})};import{mkdir as mm}from"node:fs/promises";import fm from"node:path";var as=async(e,t)=>{let r=await I(e,t);if(await K(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await Rr(r.worktreePath)&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);let s=(await f.load(e)).checks?.commands??[];if(s.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);await E(e,r.id,a=>({...a,status:a.status==="running"?r.status:a.status,checks:{...a.checks,status:"running",commands:[...s],results:[]}}));let o=[];for(let a of s){let l=new Date().toISOString(),c=await D("sh",["-lc",a],{cwd:r.worktreePath}),d=new Date().toISOString(),u=c.exitCode??1;if(o.push({command:a,startedAt:l,finishedAt:d,exitCode:u}),u!==0){let m=c.stderr.trim()||c.stdout.trim()||`Check command failed: ${a}`,g=await E(e,r.id,y=>({...y,status:"review",checks:{...y.checks,results:o,status:"failed",lastRunAt:d},lastFailureReason:m}));return await Pa(e,g),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}}let i=await E(e,r.id,a=>({...a,status:a.status==="review"||a.status==="checked"?"checked":a.status,checks:{...a.checks,results:o,status:"passed",lastRunAt:new Date().toISOString()},lastFailureReason:null}));return await Pa(e,i),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Pa=async(e,t)=>{let r=ze(e,t.artifacts.checkSummaryPath);r&&(await mm(fm.dirname(r),{recursive:!0}),await q(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var ls=async(e,t)=>{let r=await I(e,t);await K(r);let n=await Rr(r.worktreePath);if(r.status==="running"&&n&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!n)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let s=r.prompt.value.trim();await Yi(r.worktreePath),await Ji(r.worktreePath,s);let o=await Qi(r.worktreePath),i=new Date().toISOString(),a=await E(e,r.id,l=>({...l,status:l.status==="running"?r.status:l.status,lastCommit:{sha:o.sha,message:o.message,committedAt:i},lastFailureReason:null}));return{kind:"commitTask",taskId:r.id,status:a.status,commitSha:o.sha,message:o.message}};import{access as gm}from"node:fs/promises";var cs=async(e,t)=>{let r=await I(e,t),n=await hm(r.worktreePath);return E(e,t,s=>({...s,status:"closed",cleanup:{...s.cleanup,preservedWorktree:n&&s.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null}))},hm=async e=>{try{return await gm(e),!0}catch{return!1}};var ds=async(e,t,r)=>{let n=[],s=null,o=null;try{if(t.sessionId){let i=await $e(e,t.sessionId);await pa(e.repoRoot,i.sessionName),s=new Date().toISOString()}}catch(i){n.push(i instanceof Error?i.message:"Failed to close tmux session.")}if(!r.preserveWorktree)try{await Zi(e.repoRoot,t.worktreePath),o=new Date().toISOString()}catch(i){n.push(i instanceof Error?i.message:"Failed to remove worktree.")}await E(e,t.id,i=>({...i,cleanup:{...i.cleanup,paneClosedAt:s??i.cleanup.paneClosedAt,worktreeRemovedAt:o??i.cleanup.worktreeRemovedAt,preservedWorktree:r.preserveWorktree,warning:n.length>0?n.join(" "):null}}))};var us=async(e,t,r)=>{let n=await le(e,r),s=await E(e,t,o=>{if(o.repoId===n.id)throw new Error(`Repo ${n.id} is already the primary repo for task ${o.id}.`);return{...o,linkedRepoIds:o.linkedRepoIds.includes(n.id)?o.linkedRepoIds:[...o.linkedRepoIds,n.id]}});return{kind:"addTaskLink",taskId:s.id,repoId:n.id,linkedRepoIds:s.linkedRepoIds}},ps=async(e,t)=>{let r=await I(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>le(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var ms=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([le(e,r.repoId),$e(e,r.sessionId)]),o=await Ft.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var fs=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await $e(e,r.sessionId).catch(s=>{throw wm(s)?new Error(`Task ${r.id} does not have a Craig session.`):s});if(!n.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await Ir(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},wm=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as km}from"node:child_process";var gs=async(e,t)=>{let r=await I(e,t);await K(r);let s=(await f.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await Tm(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Tm=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=km(s,o,{cwd:t,stdio:"inherit"});i.on("error",n),i.on("exit",a=>{if(a===0){r();return}n(new Error(`${e.join(" ")} failed with exit code ${a??"unknown"}.`))})})};var hs=async(e,t,r)=>{await E(e,t,n=>({...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r}))},ws=async(e,t,r)=>E(e,t,n=>({...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})),ks=async(e,t)=>E(e,t,r=>{let n=r.ptyTabs.find(s=>s.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);return{...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}}});import{realpath as Ia}from"node:fs/promises";import Kt from"node:path";async function ys(e,t){if(t.explicitTaskId!==void 0){let l=await Sa(e,t.explicitTaskId,"explicit");return Ts(l,"explicit",t.environmentAgentTabId)}if(t.environmentTaskId!==void 0){let l=await Sa(e,t.environmentTaskId,"environment");return Ts(l,"environment",t.environmentAgentTabId)}let r=await Ia(t.cwd).catch(()=>Kt.resolve(t.cwd)),n=await Mt(e,{includeClosed:!0}),o=(await Promise.all(n.tasks.map(async l=>({task:l,matches:await Rm(l,r)})))).filter(l=>l.matches).map(l=>l.task),i=[...new Map(o.map(l=>[l.id,l])).values()];if(i.length>1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Multiple Craig tasks match ${r}: ${i.map(l=>l.id).join(", ")}. Use --task <id>.`,{details:{cwd:r,taskIds:i.map(l=>l.id)}});let a=i[0];if(a)return Ts(a,"cwd",t.environmentAgentTabId);if(t.environmentAgentTabId!==void 0)throw new R("TASK_CONTEXT_CONFLICT",`CRAIG_AGENT_TAB_ID is set to ${t.environmentAgentTabId}, but no task context could be resolved.`,{details:{agentTabId:t.environmentAgentTabId}});if(t.required)throw new R("TASK_CONTEXT_NOT_FOUND",`No Craig task was found from ${r}. Use --task <id> or run the command inside a task worktree.`,{details:{cwd:r}});return null}async function Sa(e,t,r){try{return await I(e,t)}catch(n){throw!(n instanceof R)||n.code!=="TASK_NOT_FOUND"?n:new R("TASK_CONTEXT_NOT_FOUND",`Craig task "${t}" from ${r==="explicit"?"--task":"CRAIG_TASK_ID"} was not found.`,{details:{taskId:t,source:r},cause:n})}}function Ts(e,t,r){let n=r??null;if(n!==null){let s=e.ptyTabs.find(o=>o.id===n);if(!s||s.kind!=="agent")throw new R("TASK_CONTEXT_CONFLICT",`Agent tab ${n} does not belong to Craig task ${e.id}.`,{details:{taskId:e.id,agentTabId:n}})}return{task:e,source:t,agentTabId:n}}function ym(e){return[e.worktreePath,...e.bundlePath?[e.bundlePath]:[],...(e.repoTargets??[]).map(t=>t.worktreePath)]}async function Rm(e,t){return(await Promise.all(ym(e).map(n=>Ia(n).catch(()=>Kt.resolve(n))))).some(n=>bm(n,t))}function bm(e,t){let r=Kt.relative(Kt.resolve(e),t);return r===""||!r.startsWith("..")&&!Kt.isAbsolute(r)}var Rs=async(e,t,r="merge",n)=>{let s=await I(e,t),o=n??A(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Ta(s.worktreePath,o,r)};var Gt={readTask:I,writeTask:be,withTaskLock:xe,ensureGhAuthenticated:Me,fetchPrView:ht,discoverPrView:ya,getGitHubRepositoryLocator:Cr,writePrStatusArtifact:Xe};async function Ps(e,t,r,n=Gt){let s=await n.readTask(e,t),o=await Sm(s,r,n);return Ne(s,o,"showTaskPr","shown",[])}async function Ss(e,t,r,n=Gt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await Es(s,r,null,n);await xs(o,n);let i=await xr(`discover a pull request for ${o.branch}`,()=>n.discoverPrView(o.branch,o.worktreePath));if(!i)return Ne(s,o,"discoverTaskPr","not_found",[]);Ds(i,o);let a=Dr(s,o,i.number),l=await $s(e,s,o,i,n);return Ne(l,o,"discoverTaskPr",a?"synced":"discovered",[])})}async function Is(e,t,r,n,s=Gt){let o=As(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await Es(i,n,o.repository,s);va(o.repository,a),await xs(a,s);let l=await xr(`fetch pull request ${r}`,()=>s.fetchPrView(r,a.worktreePath));Im(l,o),Ds(l,a);let c=Dr(i,a,l.number),d=Os(i,a),u=d&&!pt(d,{owner:a.repository.owner,repo:a.repository.name,number:l.number})&&d.status!=="closed"&&d.status!=="merged"?[`Pull request #${l.number} becomes active; #${d.number} remains in task history.`]:[],m=await $s(e,i,a,l,s);return Ne(m,a,"linkTaskPr",c?"unchanged":"linked",u)})}async function Pm(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);let i=e.prs.find(a=>a.number===r.number)??A(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Er(i,e.worktreePath,e.repoId,n),projectTarget:null}}if(t){let i=e.repoTargets?.find(c=>c.repoId===t);if(!i)throw yt(e,t);let a=Ca(i.pullRequest),l=e.prs.find(c=>c.number===r.number&&(!c.headBranch||c.headBranch===i.branch)&&(!a||!!(c.owner&&c.repo&&he({owner:c.owner,name:c.repo},a))))??i.pullRequest;return{repoId:t,branch:i.branch,worktreePath:i.worktreePath,repository:await Er(l,i.worktreePath,t,n),projectTarget:i}}if(!r.repository)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for a numeric pull request selector.`,{details:{taskId:e.id,pullRequestNumber:r.number}});let s=r.repository,o=[];for(let i of e.repoTargets??[]){let a=i.pullRequest.owner&&i.pullRequest.repo&&he({owner:i.pullRequest.owner,name:i.pullRequest.repo},s),l=e.prs.some(c=>c.number===r.number&&c.owner&&c.repo&&he({owner:c.owner,name:c.repo},s)&&(!c.headBranch||c.headBranch===i.branch));(a||l)&&o.push({repoId:i.repoId,branch:i.branch,worktreePath:i.worktreePath,repository:s,projectTarget:i})}if(o.length!==1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.repository.owner}/${r.repository.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.repository.owner,repo:r.repository.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Cs(e,t,r,n=Gt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await Es(s,r,null,n),i=Os(s,o);if(!i?.number)return Ne(s,o,"refreshTaskPr","not_found",[]);await xs(o,n);let a=await xr(`refresh pull request #${i.number}`,()=>n.fetchPrView(String(i.number),o.worktreePath));Ds(a,o);let l=await $s(e,s,o,a,n);return Ne(l,o,"refreshTaskPr","synced",[])})}async function vs(e,t,r,n,s=Gt){let o=As(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await Pm(i,n,o,s);if(va(o.repository,a),!Dr(i,a,o.number))return Ne(i,a,"unlinkTaskPr","unchanged",[]);let c=Cm(i,a,o.number),d=await Ea(e,c,s);return Ne(d,a,"unlinkTaskPr","unlinked",[])})}function As(e){let t=e.trim(),r=Le(t);if(r)return{number:r.number,repository:r};if(/^[1-9]\d*$/.test(t))return{number:Number(t),repository:null};throw new R("CLI_USAGE",`Invalid pull request selector "${e}". Use a GitHub pull request URL or positive number.`,{details:{selector:e}})}async function Es(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);return bs(e.repoId,e.branch,e.worktreePath,null,n)}let s=e.repoTargets??[];if(t){let i=s.find(a=>a.repoId===t);if(!i)throw yt(e,t);return bs(i.repoId,i.branch,i.worktreePath,i,n)}if(!r)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:s.map(i=>i.repoId)}});let o=[];for(let i of s){let a=await bs(i.repoId,i.branch,i.worktreePath,i,n).catch(l=>{if(l instanceof R&&l.code==="EXTERNAL_DEPENDENCY_FAILED"&&l.message.includes("does not have a supported GitHub origin remote"))return null;throw l});a&&he(a.repository,r)&&o.push(a)}if(o.length!==1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.owner}/${r.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.owner,repo:r.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Sm(e,t,r){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);let s=A(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Er(s,e.worktreePath,e.repoId,r),projectTarget:null}}if(!t)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:(e.repoTargets??[]).map(s=>s.repoId)}});let n=e.repoTargets?.find(s=>s.repoId===t);if(!n)throw yt(e,t);return{repoId:t,branch:n.branch,worktreePath:n.worktreePath,repository:await Er(n.pullRequest,n.worktreePath,t,r),projectTarget:n}}async function Er(e,t,r,n){let s=Ca(e);return s||(await n.getGitHubRepositoryLocator(t).catch(()=>null)??{owner:"",name:r})}function Ca(e){return e?.owner&&e.repo?{owner:e.owner,name:e.repo}:e?.url?Le(e.url):null}async function bs(e,t,r,n,s){let o=await s.getGitHubRepositoryLocator(r);if(!o)throw new R("EXTERNAL_DEPENDENCY_FAILED",`Repo ${e} does not have a supported GitHub origin remote.`,{details:{repoId:e,worktreePath:r}});return{repoId:e,branch:t,worktreePath:r,repository:o,projectTarget:n}}async function xs(e,t){await xr("verify GitHub CLI authentication",()=>t.ensureGhAuthenticated(e.worktreePath))}async function xr(e,t){try{return await t()}catch(r){throw r instanceof R?r:new R("EXTERNAL_DEPENDENCY_FAILED",`Failed to ${e}: ${r instanceof Error?r.message:String(r)}`,{retryable:!0,cause:r})}}function va(e,t){if(e&&!he(e,t.repository))throw Aa(e,t)}function Im(e,t){let r=Le(e.url);if(!r||r.number!==t.number)throw new R("TASK_CONTEXT_CONFLICT",`GitHub returned ${e.url} for pull request selector #${t.number}.`,{details:{selectorNumber:t.number,returnedUrl:e.url}});if(t.repository&&!he(t.repository,r))throw new R("PR_REPOSITORY_MISMATCH",`GitHub returned a pull request from ${r.owner}/${r.name}, not ${t.repository.owner}/${t.repository.name}.`,{details:{selectorRepository:t.repository,returnedRepository:r}})}function Ds(e,t){let r=Le(e.url);if(!r||!he(r,t.repository))throw Aa(r,t);if(e.headRefName!==t.branch)throw new R("PR_BRANCH_MISMATCH",`Pull request #${e.number} uses head branch ${e.headRefName}, not task branch ${t.branch}.`,{details:{repoId:t.repoId,pullRequestNumber:e.number,expectedBranch:t.branch,actualBranch:e.headRefName}})}function Aa(e,t){return new R("PR_REPOSITORY_MISMATCH",`Pull request repository ${e?`${e.owner}/${e.name}`:"is invalid"} does not match task repo ${t.repository.owner}/${t.repository.name}.`,{details:{repoId:t.repoId,expectedOwner:t.repository.owner,expectedRepo:t.repository.name,actualOwner:e?.owner??null,actualRepo:e?.name??null}})}function yt(e,t){return new R("TASK_CONTEXT_CONFLICT",`Repo ${t} is not a target of task ${e.id}.`,{details:{taskId:e.id,repoId:t}})}function he(e,t){return e.owner.toLowerCase()===t.owner.toLowerCase()&&e.name.toLowerCase()===t.name.toLowerCase()}async function $s(e,t,r,n,s){let o=Dr(t,r,n.number),i=Se(n,o,r.repository),a=Pe(t,i);return r.projectTarget&&(a={...a,repoTargets:(a.repoTargets??[]).map(l=>l.repoId===r.repoId?{...l,pullRequest:$a(i)}:l)}),Ea(e,a,s)}function Cm(e,t,r){let n=e.prs.filter(o=>!Da(o,t,r)),s={...e,prs:n};if(t.projectTarget?.pullRequest.number===r){let o=xa(n.filter(i=>i.owner&&i.repo&&he({owner:i.owner,name:i.repo},t.repository)));s={...s,repoTargets:(s.repoTargets??[]).map(i=>i.repoId===t.repoId?{...i,pullRequest:o?$a(o):Am(t.repository)}:i)}}return s}async function Ea(e,t,r){let n=t.status==="closed"?t.status:t.type==="project"?Zn(t):He(t.prs),s={...t,status:n};return _t(e,s,r)}function Dr(e,t,r){return Ms(e,t).find(n=>Da(n,t,r))??null}function Os(e,t){if(!t.projectTarget)return A(e);let r=Ms(e,t);return xa(r)}function xa(e){return[...e].reverse().find(t=>t.status!=="merged"&&t.status!=="closed")??e[e.length-1]??null}function Ms(e,t){if(!t.projectTarget)return e.prs;let r=e.prs.filter(o=>o.owner&&o.repo&&he({owner:o.owner,name:o.repo},t.repository)),n=e.repoTargets?.find(o=>o.repoId===t.repoId),s=n?.pullRequest.number?vm(n.pullRequest,t.repository):null;return s&&!r.some(o=>pt(o,s))?[...r,s]:r}function Da(e,t,r){return e.number!==r?!1:!e.owner||!e.repo||he({owner:e.owner,name:e.repo},t.repository)}function Ne(e,t,r,n,s){let o=Ms(e,t);return{kind:r,taskId:e.id,repoId:t.repoId,disposition:n,pullRequests:o,primaryPullRequest:Os(e,t),warnings:s}}function $a(e){return{provider:"github",owner:e.owner,repo:e.repo,number:e.number,url:e.url,baseBranch:e.baseBranch,headBranch:e.headBranch,status:e.status==="draft"?"open":e.status,draft:e.draft,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function vm(e,t){return{provider:"github",owner:e.owner??t.owner,repo:e.repo??t.name,number:e.number,url:e.url,title:null,status:e.draft?"draft":e.status,draft:e.draft??!1,baseBranch:e.baseBranch,headBranch:e.headBranch,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function Am(e){return{provider:"github",owner:e.owner,repo:e.name,number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}}var C={listTasks:Mt,getTask:I,provisionTask:gt,provisionProjectTask:Nt,createTask:Jn,showTask:ns,showTaskDiff:ss,prepareTaskLogs:os,streamTaskLogs:is,runChecks:as,commitTask:ls,closeTask:cs,cleanupTask:ds,addTaskLink:us,listTaskLinks:ps,sortTasksForDisplay:Bn,resolveSelectedTaskId:Vn,allocateTaskId:Un,allocateTaskIdForRepo:ft,allocateProjectTaskId:Ot,createDefaultTaskPtyTabs:jt,assertTaskWorktreeExists:K,resolveTaskLogPath:mt,buildTaskInspection:$t,resolveArtifactPath:ze,attachTask:ms,focusTask:fs,openTask:gs,markRunnerFailed:hs,recordStartupFailure:ws,markTaskStarted:ks,resolveContext:ys,prs:{refresh:Vt,refreshChecks:ts,discoverOrRefresh:Ar,discoverOrRefreshAll:Tt,discoverOrRefreshMany:rs,show:Ps,discover:Ss,link:Is,refreshAssociation:Cs,unlink:vs,merge:Rs,getPrimaryPr:A,isPrTerminal:De,isMergeReady:yr,deriveTaskStatus:He,upsertPr:Pe,normalizePr:Se,summarizeRequiredChecks:Fn,writePrStatusArtifact:Xe}};async function Oa(e,t){switch(e.kind){case"addWorkspace":{let r=await G.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await Ls(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await G.repos.addRepo(t.paths,e.path);return await Ls(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return G.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await it({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await se(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await G.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return G.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await G.archiveWorkspace(t.paths,e.workspaceId);return await Em(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await G.restoreWorkspace(t.paths,e.workspaceId);return await Ls(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return G.removeWorkspace(t.paths,e.workspaceId,{listTasks:C.listTasks});case"createTask":return C.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?C.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):C.listTasks(t.paths);case"currentTask":{let r=Ns(t);return{kind:"currentTask",task:r.task,context:{source:r.source,agentTabId:r.agentTabId}}}case"attachTask":return C.attachTask(t.paths,e.taskId);case"addTaskLink":return C.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return C.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return C.showTask(t.paths,e.taskId);case"showCurrentTask":return C.showTask(t.paths,Ns(t).task.id);case"showTaskPr":return C.prs.show(t.paths,Ht(e.taskId,t),e.repoId);case"discoverTaskPr":return C.prs.discover(t.paths,Ht(e.taskId,t),e.repoId);case"linkTaskPr":return C.prs.link(t.paths,Ht(e.taskId,t),e.pullRequest,e.repoId);case"refreshTaskPr":return C.prs.refreshAssociation(t.paths,Ht(e.taskId,t),e.repoId);case"unlinkTaskPr":return C.prs.unlink(t.paths,Ht(e.taskId,t),e.pullRequest,e.repoId);case"showSelectedTask":return C.showTask(t.paths,Ze(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,Ze(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,Ze(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,Ze(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,Ze(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,Ze(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,Ze(t,"commit"));case"showContext":{let r=Dm(t);return{kind:"showContext",workspace:{root:r.workspaceRoot,source:r.source,initialized:r.initialized},task:t.taskContext?{id:t.taskContext.task.id,source:t.taskContext.source,agentTabId:t.taskContext.agentTabId}:null}}case"help":return{kind:"help",text:Pn()};case"exit":return{kind:"exit"};default:return xm(e)}}async function Ls(e,t,r){let n=await it({uiStateFile:e.uiStateFile})??lr();await Ee({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Em(e,t){let r=await it({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Ee({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function xm(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ze(e,t){if(e.selectedTaskId)return e.selectedTaskId;throw new Error(`No task selected. Create a task with 'task new --repo <repo-id> <prompt>' or use '${t} <id>'.`)}function Ns(e){if(e.taskContext)return e.taskContext;throw new Error("Command requires resolved task context.")}function Ht(e,t){return e??Ns(t).task.id}function Dm(e){if(e.workspaceContext)return e.workspaceContext;throw new Error("Command requires resolved workspace context.")}function Ma(e){switch(e.kind){case"createWorkspace":return[`${e.created?"Registered":"Updated"} ${e.workspace.kind??"repo"} workspace ${e.workspace.id}`,`Path: ${e.workspace.rootPath??""}`,`Repos: ${e.repos.map(t=>t.id).join(", ")}`].join(`
|
|
75
75
|
`);case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
|
|
76
76
|
`);case"listRepos":return e.repos.length===0?"No repos registered yet. Use 'craig repo add <path>'.":["ID NAME BRANCH PATH",...e.repos.map(t=>`${t.id} ${t.name} ${t.defaultBranch} ${t.rootPath}`)].join(`
|
|
77
77
|
`);case"removeRepo":return`Removed repo ${e.repoId} (${e.rootPath})`;case"listWorkspaces":return e.workspaces.length===0?e.archivedOnly?"No archived workspaces.":"No active workspaces yet. Register one with 'craig workspace add <path>'.":["ID KIND STATUS REPOS PATH",...e.workspaces.map(t=>`${t.id} ${t.kind??"repo"} ${t.status} ${(t.discoveredRepoIds??[t.primaryRepoId]).join(",")} ${t.rootPath??""}`)].join(`
|
|
78
78
|
`);case"archiveWorkspace":return`Archived workspace ${e.workspaceId} on branch ${e.branch}`;case"restoreWorkspace":return`Restored workspace ${e.workspaceId} on branch ${e.branch}`;case"removeWorkspace":return`Removed workspace ${e.workspaceId} (${e.rootPath})`;case"createTask":return[`Created task ${e.taskId}`,`Repo: ${e.repoId}`,`Workspace: ${e.workspaceId}`,`Session: ${e.sessionId}`,`Status: ${e.status}`,`Branch: ${e.branch}`,`Worktree: ${e.worktreePath}`,`Runner: ${e.runner}`].join(`
|
|
79
79
|
`);case"attachTask":return`Attached to task ${e.taskId} via session ${e.sessionId}`;case"addTaskLink":return`Linked repo ${e.repoId} to task ${e.taskId}: ${e.linkedRepoIds.join(", ")}`;case"listTaskLinks":return e.repos.length===0?`Task ${e.taskId} has no linked repos.`:["ID NAME BRANCH PATH",...e.repos.map(t=>`${t.id} ${t.name} ${t.defaultBranch} ${t.rootPath}`)].join(`
|
|
80
|
-
`);case"help":return e.text;case"exit":return"";case"listTasks":return e.tasks.length===0?`No Craig tasks yet. Use 'task new --repo <repo-id> <prompt>' to create one.${e.missingTaskIds.length>0?` (${e.missingTaskIds.length} referenced task file(s) missing from .craig/tasks)`:""}`:["ID REPO STATUS CHECKS PR TITLE",...e.tasks.map(t=>`${t.id} ${t.repoId} ${t.status} ${
|
|
81
|
-
`);case"showTask":return[`${e.task.id}: ${e.task.title}`,`Status: ${e.task.status}`,`Runner: ${e.task.runner}`,`Repo: ${e.task.repoId}`,`Workspace: ${e.task.workspaceId}`,`Branch: ${e.task.branch}`,`Worktree: ${e.task.worktreePath}`,`Session: ${e.task.sessionId??"<missing>"}`,`tmux: ${e.session?.paneId??"<missing>"}`,`Linked repos: ${e.task.linkedRepoIds.length>0?e.task.linkedRepoIds.join(", "):"none"}`,`Prompt: ${e.task.prompt.source} ${JSON.stringify(e.task.prompt.value)}`,`Runner command: ${e.inspection.runnerCommandText||"<none>"}`,`Runner state: ${e.task.runnerSession.lastKnownState}`,`Started: ${e.task.runnerSession.startedAt??"not started"}`,`Exited: ${e.task.runnerSession.exitedAt??"still running"}`,`Checks: ${e.inspection.checksSummary}`,`Last commit: ${e.inspection.lastCommitSummary}`,`PR: ${e.inspection.prSummary}`,`Cleanup: ${e.inspection.cleanupSummary}`,...
|
|
80
|
+
`);case"help":return e.text;case"exit":return"";case"listTasks":return e.tasks.length===0?`No Craig tasks yet. Use 'task new --repo <repo-id> <prompt>' to create one.${e.missingTaskIds.length>0?` (${e.missingTaskIds.length} referenced task file(s) missing from .craig/tasks)`:""}`:["ID REPO STATUS CHECKS PR TITLE",...e.tasks.map(t=>`${t.id} ${t.repoId} ${t.status} ${Lm(t)} ${Nm(t)} ${t.title}`)].join(`
|
|
81
|
+
`);case"showTask":return[`${e.task.id}: ${e.task.title}`,`Status: ${e.task.status}`,`Runner: ${e.task.runner}`,`Repo: ${e.task.repoId}`,`Workspace: ${e.task.workspaceId}`,`Branch: ${e.task.branch}`,`Worktree: ${e.task.worktreePath}`,`Session: ${e.task.sessionId??"<missing>"}`,`tmux: ${e.session?.paneId??"<missing>"}`,`Linked repos: ${e.task.linkedRepoIds.length>0?e.task.linkedRepoIds.join(", "):"none"}`,`Prompt: ${e.task.prompt.source} ${JSON.stringify(e.task.prompt.value)}`,`Runner command: ${e.inspection.runnerCommandText||"<none>"}`,`Runner state: ${e.task.runnerSession.lastKnownState}`,`Started: ${e.task.runnerSession.startedAt??"not started"}`,`Exited: ${e.task.runnerSession.exitedAt??"still running"}`,`Checks: ${e.inspection.checksSummary}`,`Last commit: ${e.inspection.lastCommitSummary}`,`PR: ${e.inspection.prSummary}`,`Cleanup: ${e.inspection.cleanupSummary}`,...Om(e)].join(`
|
|
82
82
|
`);case"currentTask":return[`${e.task.id}: ${e.task.title}`,`Workspace: ${e.task.workspaceId}`,`Repo: ${e.task.repoId}`,`Worktree: ${e.task.worktreePath}`,`Context source: ${e.context.source}`,`Agent tab: ${e.context.agentTabId??"none"}`].join(`
|
|
83
|
-
`);case"showContext":return[`Workspace: ${e.workspace.root}`,`Workspace source: ${e.workspace.source}`,`Initialized: ${e.workspace.initialized?"yes":"no"}`,`Task: ${e.task?.id??"none"}`,`Task source: ${e.task?.source??"none"}`,`Agent tab: ${e.task?.agentTabId??"none"}`].join(`
|
|
83
|
+
`);case"showTaskPr":case"discoverTaskPr":case"linkTaskPr":case"refreshTaskPr":case"unlinkTaskPr":return $m(e);case"showContext":return[`Workspace: ${e.workspace.root}`,`Workspace source: ${e.workspace.source}`,`Initialized: ${e.workspace.initialized?"yes":"no"}`,`Task: ${e.task?.id??"none"}`,`Task source: ${e.task?.source??"none"}`,`Agent tab: ${e.task?.agentTabId??"none"}`].join(`
|
|
84
84
|
`);case"streamTaskLogs":return`Streaming logs for ${e.taskId} from ${e.logPath}`;case"showTaskDiff":return e.isEmpty?`Task ${e.taskId} has no uncommitted diff.`:e.diffText;case"focusTask":return`Focused task ${e.taskId} on ${e.tmuxTarget}`;case"openTask":return e.launched?`Opened task ${e.taskId} at ${e.worktreePath}`:e.worktreePath;case"runChecks":return`Checks ${e.status} for ${e.taskId}: ${e.commands.join(", ")}`;case"commitTask":return[`Committed task ${e.taskId}`,`Status: ${e.status}`,`Commit: ${e.commitSha}`,`Message: ${e.message}`].join(`
|
|
85
|
-
`);default:return
|
|
86
|
-
`),
|
|
87
|
-
`),
|
|
88
|
-
`).
|
|
89
|
-
`)
|
|
90
|
-
`)
|
|
91
|
-
|
|
92
|
-
${
|
|
93
|
-
${a.stdout.trimEnd()}`)}if(o.includes("
|
|
85
|
+
`);default:return Mm(e)}}function $m(e){let t=`${e.taskId} (${e.repoId}): ${e.disposition}`,r=e.pullRequests.length===0?["No pull requests associated."]:["PR STATUS HEAD URL",...e.pullRequests.map(n=>`#${n.number??"-"} ${n.status??"unknown"} ${n.headBranch??"-"} ${n.url??"-"}`)];return[t,...r,...e.warnings.map(n=>`Warning: ${n}`)].join(`
|
|
86
|
+
`)}function Om(e){let t=[];return e.inspection.worktreeExists||e.task.status==="merged"&&!e.task.cleanup.preservedWorktree&&e.task.cleanup.worktreeRemovedAt||t.push(`Warning: worktree is missing at ${e.task.worktreePath}`),e.task.cleanup.warning&&!(e.task.status==="merged"&&!e.task.cleanup.worktreeRemovedAt)&&t.push(`Cleanup warning: ${e.task.cleanup.warning}`),e.task.artifacts.logPath&&!e.inspection.logExists&&t.push(`Warning: log file is missing at ${e.task.artifacts.logPath}`),e.inspection.recentFailureReason&&t.push(`Last failure: ${e.inspection.recentFailureReason}`),t}function Mm(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Lm(e){return e.checks.status}function Nm(e){if(e.type==="project"&&e.repoTargets?.length){let r=e.repoTargets.filter(s=>s.pullRequest.number);if(r.length===0)return"-";let n=r.reduce((s,o)=>{let i=o.pullRequest.status??"unknown";return s[i]=(s[i]??0)+1,s},{});return Object.entries(n).map(([s,o])=>`${o} ${s}`).join(", ")}let t=e.prs[0];return t?.number?`#${t.number}:${t.status??"unknown"}`:"-"}function La(e,t){let{data:r,warnings:n}=jm(t);return JSON.stringify({schemaVersion:1,command:e,ok:!0,data:r,warnings:n})}function jm(e){if("warnings"in e&&Array.isArray(e.warnings)){let{warnings:t,...r}=e;return{data:r,warnings:t}}return{data:e,warnings:[]}}function Na(e,t){let r={schemaVersion:1,command:e,ok:!1,error:{code:t.code,message:t.message,retryable:t.retryable,details:t.details}};return JSON.stringify(r)}async function js(e){let t=await G.resolveContext({cwd:e.cwd,...e.explicitWorkspaceRoot!==void 0?{explicitWorkspaceRoot:e.explicitWorkspaceRoot}:{},...e.environmentWorkspaceRoot!==void 0?{environmentWorkspaceRoot:e.environmentWorkspaceRoot}:{},...e.allowUninitializedWorkspace!==void 0?{allowUninitializedCwd:e.allowUninitializedWorkspace}:{}}),r=Z(t.workspaceRoot),n=e.resolveTask===!0||e.requireTask===!0||e.explicitTaskId!==void 0||e.environmentTaskId!==void 0||e.environmentAgentTabId!==void 0;if(n&&!t.initialized)throw new R("TASK_CONTEXT_NOT_FOUND",`Task context cannot be resolved because ${t.workspaceRoot} is not an initialized Craig workspace.`,{details:{workspaceRoot:t.workspaceRoot}});let s=n&&t.initialized?await C.resolveContext(r,{cwd:e.cwd,...e.explicitTaskId!==void 0?{explicitTaskId:e.explicitTaskId}:{},...e.environmentTaskId!==void 0?{environmentTaskId:e.environmentTaskId}:{},...e.environmentAgentTabId!==void 0?{environmentAgentTabId:e.environmentAgentTabId}:{},...e.requireTask!==void 0?{required:e.requireTask}:{}}):null;return{paths:r,workspace:t,task:s}}async function ja(e){let t="cli",r=pi(e.argv);try{let n=ui(e.argv);if(r=n.options.json,n.mode==="interactive"){if(n.options.noInput||n.options.json||Bm(e.env)||!e.isInputTty||!e.isOutputTty)throw new R("INPUT_REQUIRED","Interactive Craig requires a TTY. Provide a command instead of starting the terminal application.",{});let c=await js({cwd:e.cwd,...n.options.workspaceRoot!==void 0?{explicitWorkspaceRoot:n.options.workspaceRoot}:{},...e.env.CRAIG_WORKSPACE_ROOT!==void 0?{environmentWorkspaceRoot:e.env.CRAIG_WORKSPACE_ROOT}:{},allowUninitializedWorkspace:!0});return e.runInteractive(c.workspace.workspaceRoot)}if(!n.command||!n.commandName)throw new R("CLI_USAGE","Command mode requires a command.",{});t=n.commandName,Wm(n.command,n.options.taskId);let s=_m(n.command);qm(n.command,n.options.taskId,s);let o=s!=="none",i=await js({cwd:e.cwd,...n.options.workspaceRoot!==void 0?{explicitWorkspaceRoot:n.options.workspaceRoot}:{},...e.env.CRAIG_WORKSPACE_ROOT!==void 0?{environmentWorkspaceRoot:e.env.CRAIG_WORKSPACE_ROOT}:{},...o&&n.options.taskId!==void 0?{explicitTaskId:n.options.taskId}:{},...o&&e.env.CRAIG_TASK_ID!==void 0?{environmentTaskId:e.env.CRAIG_TASK_ID}:{},...o&&e.env.CRAIG_AGENT_TAB_ID!==void 0?{environmentAgentTabId:e.env.CRAIG_AGENT_TAB_ID}:{},allowUninitializedWorkspace:Fm(n.command),resolveTask:s!=="none",requireTask:s==="required"}),a=await Oa(n.command,{paths:i.paths,workspaceContext:i.workspace,taskContext:i.task}),l=r?La(t,a):Ma(a);return l.length>0&&e.writeStdout(`${l}
|
|
87
|
+
`),0}catch(n){let s=Tn(n),o=r?Na(t,s):s.message;return e.writeStderr(`${o}
|
|
88
|
+
`),s.exitCode}}function Fm(e){return["addWorkspace","addRepo","listRepos","listWorkspaces","help"].includes(e.kind)}function _m(e){return e.kind==="showContext"?"optional":e.kind==="currentTask"||e.kind==="showCurrentTask"?"required":Um(e)?e.taskId?"none":"required":"none"}function Wm(e,t){let r=Fa(e);if(!(r===void 0||t===void 0||t===r))throw new R("CLI_USAGE",`Task ${r} conflicts with --task ${t}. Provide only one task target.`,{details:{positionalTaskId:r,globalTaskId:t}})}function qm(e,t,r){if(!(t===void 0||r!=="none"||Fa(e)===t))throw new R("CLI_USAGE",`--task is not supported by ${e.kind}. Use it with context show, task current, or task show without an id.`,{details:{commandKind:e.kind,globalTaskId:t}})}function Fa(e){switch(e.kind){case"showTask":case"attachTask":case"listTaskLinks":case"streamTaskLogs":case"showTaskDiff":case"focusTask":case"openTask":case"runChecks":case"commitTask":return e.taskId;case"showTaskPr":case"discoverTaskPr":case"linkTaskPr":case"refreshTaskPr":case"unlinkTaskPr":return e.taskId;case"addTaskLink":return e.taskId;default:return}}function Um(e){return["showTaskPr","discoverTaskPr","linkTaskPr","refreshTaskPr","unlinkTaskPr"].includes(e.kind)}function Bm(e){let t=e.CI?.trim().toLowerCase();return t!==void 0&&t!==""&&t!=="0"&&t!=="false"}import{createRequire as pw}from"node:module";import{readFile as Vm,stat as Km}from"node:fs/promises";import Fs from"node:path";var Gm=200*1024,Hm=500*1024,$r="100000";async function Wa(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return zm(e,t,r);try{let n=je(r.selectedFilePath??null,t.filePaths),s=je(r.selectedDiffPath??null,t.diffPaths),o=s?await zt(e.worktreePath):null,[i,a]=await Promise.all([Mr(e.worktreePath,n),s?_s(e.worktreePath,s,t.diffRows,o):Promise.resolve(z("No diff selected","No local changes found.","empty"))]),l=s?{[s]:a}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:l,selectedFile:i,selectedDiff:a,error:null}}catch(n){let s=n instanceof Error?n.message:"Unable to inspect task worktree.";return{...t,error:s}}}async function zm(e,t,r){let n=je(r.selectedFilePath??null,t.filePaths),s=je(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([Ua(e,n),(async()=>{if(!s)return z("No diff selected","No local changes found.","empty");let l=Or(e,s),c=l?await zt(l.target.worktreePath).catch(()=>null):null;return Ba(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function qa(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return Ym(e,t);try{await K(e);let r=await zt(e.worktreePath),[n,s]=await Promise.all([Va(e.worktreePath),Ka(e.worktreePath,r)]),o=[...new Set(s.map(u=>u.path))],i=je(t.selectedFilePath??null,n),a=je(t.selectedDiffPath??null,o),[l,c]=await Promise.all([Mr(e.worktreePath,i),a?_s(e.worktreePath,a,s,r):Promise.resolve(z("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:za(n),filePaths:n,diffRows:s,diffPaths:o,diffContents:d,selectedFilePath:i,selectedDiffPath:a,selectedFile:l,selectedDiff:c,error:null}}catch(r){let n=r instanceof Error?r.message:"Unable to inspect task worktree.";return{taskId:e.id,fileRows:[],filePaths:[],diffRows:[],diffPaths:[],diffContents:{},selectedFilePath:null,selectedDiffPath:null,selectedFile:z("Files unavailable",n,"error"),selectedDiff:z("Diff unavailable",n,"error"),error:n}}}async function Ym(e,t){let r=(e.repoTargets??[]).filter(m=>m.status==="ready"),n=await Promise.all(r.map(async m=>{let g=await zt(m.worktreePath).catch(()=>null),[y,w]=await Promise.all([Va(m.worktreePath).catch(()=>[]),Ka(m.worktreePath,g).catch(()=>[])]);return{target:m,baseRef:g,targetFiles:y,targetDiffRows:w}})),s=[],o=[];for(let{target:m,targetFiles:g,targetDiffRows:y}of n)s.push(...g.map(w=>`${m.repoId}/${w}`)),o.push(...y.map(w=>({...w,path:`${m.repoId}/${w.path}`})));let i=[...new Set(o.map(m=>m.path))].sort(),a=je(t.selectedFilePath??null,s),l=je(t.selectedDiffPath??null,i),[c,d]=await Promise.all([Ua(e,a),(async()=>{if(!l)return z("No diff selected","No local changes found.","empty");let m=Or(e,l),g=m?n.find(y=>y.target.repoId===m.target.repoId):null;return Ba(e,l,o,g?.baseRef??null)})()]),u=l?{[l]:d}:{};return{taskId:e.id,fileRows:za(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:u,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function Ua(e,t){let r=Or(e,t);if(!r)return z("No file selected","No Git-visible files found.","empty");let n=await Mr(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function Ba(e,t,r,n=null){let s=Or(e,t);return s?{...await _s(s.target.worktreePath,s.relativePath,r.filter(i=>i.path.startsWith(`${s.target.repoId}/`)).map(i=>({...i,path:i.path.slice(s.target.repoId.length+1)})),n),path:t,title:t}:z(t,"Repo target is unavailable.","error",t)}function Or(e,t){if(!t)return null;let[r,...n]=t.split("/"),s=n.join("/"),o=(e.repoTargets??[]).find(i=>i.repoId===r&&i.status==="ready")??null;return!o||s.length===0?null:{target:o,relativePath:s}}async function Va(e){let t=await S("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Ya(t.stdout)}async function Ka(e,t){let[r,n,s,o]=await Promise.all([Jm(e,t),_a(e,"staged"),_a(e,"unstaged"),Qm(e)]);return[...r,...n,...s,...o]}async function Jm(e,t){if(!t)return[];let[r,n]=await Promise.all([S("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),S("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=Ga(r.stdout),o=Ha(n.stdout);return s.map(i=>{let a=o.get(i.path)??{additions:null,deletions:null};return{group:"branch",path:i.path,status:i.status,additions:a.additions,deletions:a.deletions}}).sort((i,a)=>i.path.localeCompare(a.path))}async function _a(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([S("git",[...r,"--name-status"],{cwd:e}),S("git",[...r,"--numstat"],{cwd:e})]),o=Ga(n.stdout),i=Ha(s.stdout);return o.map(a=>{let l=i.get(a.path)??{additions:null,deletions:null};return{group:t,path:a.path,status:a.status,additions:l.additions,deletions:l.deletions}}).sort((a,l)=>a.path.localeCompare(l.path))}async function Qm(e){let t=await S("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Ya(t.stdout);return await Promise.all(r.map(async s=>{let o=await Mr(e,s),i=o.status==="ready"?Xm(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function Ga(e){return e.split(`
|
|
89
|
+
`).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...n]=t.split(" ");return{status:r,path:n.at(-1)??""}}).filter(t=>t.path.length>0)}function Ha(e){let t=new Map;for(let r of e.split(`
|
|
90
|
+
`)){let n=r.trim();if(!n)continue;let[s="-",o="-",...i]=n.split(" "),a=i.join(" ");a&&t.set(a,{additions:s==="-"?null:Number(s),deletions:o==="-"?null:Number(o)})}return t}async function zt(e){return(await D("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await D("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function Mr(e,t){if(!t)return z("No file selected","No Git-visible files found.","empty");let r=Zm(e,t);try{let n=await Km(r);if(n.size>Gm)return z(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Vm(r);return ef(s)?z(t,"Binary file preview is not available in Craig.","binary",t,s.byteLength):{path:t,status:"ready",title:t,lines:s.toString("utf8").split(`
|
|
91
|
+
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return z(t,s,"missing",t,null)}}async function _s(e,t,r,n=null){if(!t)return z("No diff selected","No local changes found.","empty");let s=[],o=r.filter(a=>a.path===t).map(a=>a.group);if(o.includes("branch")){let a=n??await zt(e);if(a){let l=await S("git",["diff","--stat","--patch",`--unified=${$r}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
92
|
+
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await S("git",["diff","--cached","--stat","--patch",`--unified=${$r}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
93
|
+
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await S("git",["diff","--stat","--patch",`--unified=${$r}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
|
|
94
|
+
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await D("git",["diff","--no-index","--stat","--patch",`--unified=${$r}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
|
|
94
95
|
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
95
96
|
|
|
96
|
-
`);return i.length>
|
|
97
|
-
`):["No diff for this file."],byteLength:i.length}}function
|
|
98
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function
|
|
99
|
-
`}function
|
|
100
|
-
`)}function
|
|
101
|
-
`)}function
|
|
102
|
-
`),center:
|
|
103
|
-
`)}function
|
|
97
|
+
`);return i.length>Hm?z(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?z(t,"Binary diff preview is not available in Craig.","binary",t,i.length):{path:t,status:i.length>0?"ready":"empty",title:t,lines:i.length>0?i.split(`
|
|
98
|
+
`):["No diff for this file."],byteLength:i.length}}function za(e){let t=[],r=new Set;for(let n of e){let s=n.split("/");for(let o=0;o<s.length-1;o+=1){let i=s.slice(0,o+1).join("/");r.has(i)||(r.add(i),t.push({kind:"directory",path:i,depth:o,label:s[o]??i}))}t.push({kind:"file",path:n,depth:s.length-1,label:s.at(-1)??n})}return t}function je(e,t){return e&&t.includes(e)?e:t[0]??null}function Xm(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Ya(e){return[...new Set(e.split(`
|
|
99
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Zm(e,t){let r=Fs.resolve(e,t),n=Fs.resolve(e);if(r!==n&&!r.startsWith(`${n}${Fs.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function ef(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function z(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var tf=["tasks","center","inspector","actions"],Ja=["agent","terminal"],Qa=[],x="inspection",zS=[...Ja,...Qa],Ws=["commit","push","refresh-checks","close-task"],Xa=["refresh-checks","close-task"],Za=["task","checks","pr","setup-run","actions","next-action"],qs=["files","review"];function el(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=lf(e?.openInspectionKind)??r,s=f.runners.getEnabled(t);return{inputMode:df(e?.inputMode),focusedRegion:of(e?.focusedRegion),selectedRepoId:Ie(e?.selectedRepoId),selectedWorkspaceId:Ie(e?.selectedWorkspaceId),selectedTaskId:Ie(e?.selectedTaskId),selectedPtyTabId:Ie(e?.selectedPtyTabId),selectedLeftItemId:hf(Ie(e?.selectedTaskId)),activeTab:r?x:Ie(e?.activeTab)??"agent",preferredPtyTabKind:cf(e?.preferredPtyTabKind),inspectorSection:Yt(e?.inspectorSection,Za,"task"),inspectionMode:af(e?.inspectionMode,r==="diff"?"review":"files"),openInspectionKind:n,selectedFileTreePath:Ie(e?.selectedFileTreePath),selectedFilePath:Ie(e?.selectedFilePath),selectedDiffPath:Ie(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:Yt(e?.selectedActionId,Ws,"commit"),selectedProjectTargetId:null,selectedRunner:uf(e?.selectedRunner,s,f.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:rf(),centerZoomed:!1}}function rf(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function tl(e,t){return{...e??lr(),selectedRepoId:t.selectedRepoId,selectedWorkspaceId:t.selectedWorkspaceId,selectedTaskId:t.selectedTaskId,selectedPtyTabId:t.selectedPtyTabId,inputMode:t.inputMode,focusedRegion:t.focusedRegion,activeTab:t.activeTab,preferredPtyTabKind:t.preferredPtyTabKind,inspectorSection:t.inspectorSection,inspectionMode:t.inspectionMode,openInspectionKind:t.openInspectionKind,selectedFileTreePath:t.selectedFileTreePath,selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath,collapsedFileTreePaths:t.collapsedFileTreePaths,selectedActionId:t.selectedActionId,selectedRunner:t.selectedRunner}}function Jt(e,t,r={}){let n=gf(e,t),s=Bs(n),o=(s?.kind==="workspace"?t.workspaces?.find(d=>d.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(d=>d.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(d=>d.id===s.id)??null:s?.kind==="task"?t.repos.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(d=>d.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(d.id))??null:null)??(o?.kind!=="project"?t.repos.find(d=>d.id===o?.primaryRepoId)??null:null)??t.repos.find(d=>d.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(d=>d.workspaceId===o.id):a?t.tasks.filter(d=>d.repoId===a):[],c=(s?.kind==="task"?l.find(d=>d.id===s.id)??null:null)??l.find(d=>d.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:c?.id??null,...pf(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:sf(e,t,c?.id??null),...mf(e,t,c?.id??null),selectedDiffPath:nf(e,t,c?.id??null),inspectorSection:Yt(e.inspectorSection,Za,"task")}}function Ce(e,t){return{...e,terminal:t}}function rl(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function nl(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function ue(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
100
|
+
`}function sl(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Us(e){return il(e)||Rt(e)!==null}function ol(e){return Qa.includes(e)}function il(e){return Ja.includes(e)}function al(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[x]:[]]}function nf(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function sf(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function Yt(e,t,r){return t.includes(e??"")?e:r}function of(e){return e==="tabs"?"center":Yt(e,tf,"tasks")}function af(e,t){return e==="checks"||e==="actions"||e==="diff"||e==="review"?"review":Yt(e,qs,t)}function lf(e){return e==="file"||e==="diff"?e:null}function cf(e){return e==="terminal"?"terminal":"agent"}function df(e){return e==="terminal"?"terminal":"control"}function uf(e,t=[...O],r="codex"){return e&&f.runners.isRunnerType(e)&&t.includes(e)?e:r}function Lr(e,t=O){let r=t.length>0?t:O,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function Rt(e){let t=O.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function pf(e,t,r){if(!e)return{activeTab:t===x?t:"agent",selectedPtyTabId:null};let n=e.ptyTabs.find(a=>a.id===r)??null,s=e.selectedPtyTabId?e.ptyTabs.find(a=>a.id===e.selectedPtyTabId)??null:null,o=e.ptyTabs.find(a=>a.id===t)??null;if(o)return{activeTab:o.id,selectedPtyTabId:o.id};if(il(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??x,selectedPtyTabId:l?.id??null}}if(t===x)return{activeTab:x,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??x,selectedPtyTabId:i?.id??null}}function mf(e,t,r){if(!t.inspection||t.inspection.taskId!==r)return{selectedFileTreePath:e.selectedFileTreePath,collapsedFileTreePaths:e.collapsedFileTreePaths};let n=e.selectedFileTreePath??t.inspection.selectedFilePath,s=e.selectedFileTreePath===null&&e.collapsedFileTreePaths.length===0?ff(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function ff(e,t){let r=new Set;if(t){let n=t.split("/");for(let s=1;s<n.length;s+=1)r.add(n.slice(0,s).join("/"))}return e.filter(n=>n.kind==="directory"&&!n.path.includes("/")&&!r.has(n.path)).map(n=>n.path).sort((n,s)=>n.localeCompare(s))}function gf(e,t){let r=et(t);return e.selectedLeftItemId&&r.includes(e.selectedLeftItemId)?e.selectedLeftItemId:e.selectedWorkspaceId&&r.includes(`workspace:${e.selectedWorkspaceId}`)?`workspace:${e.selectedWorkspaceId}`:e.selectedTaskId&&r.includes(`task:${e.selectedTaskId}`)?`task:${e.selectedTaskId}`:e.selectedRepoId&&r.includes(`repo:${e.selectedRepoId}`)?`repo:${e.selectedRepoId}`:r[0]??null}function et(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let n of e.tasks.filter(s=>s.workspaceId===r.id))t.push(`task:${n.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let n of e.tasks.filter(s=>s.repoId===r.id))t.push(`task:${n.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}function Bs(e){return e?e.startsWith("workspace:")?{kind:"workspace",id:e.slice(10)}:e.startsWith("repo:")?{kind:"repo",id:e.slice(5)}:e.startsWith("task:")?{kind:"task",id:e.slice(5)}:null:null}function Ie(e){return typeof e=="string"?e:null}function hf(e){return e?`task:${e}`:null}function Qt(e){return typeof e=="string"&&e.startsWith("task:")}function Nr(e){return typeof e=="string"&&e.startsWith("new-task:")}function jr(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function ll(e){return typeof e=="string"&&e.startsWith("workspace:")}function Vs(e){return Nr(e)?e.slice(9):null}function Ks(e){return jr(e)?e.slice(19):null}async function bt(e,t,r){let n=Z(e),[s,o]=await Promise.all([G.repos.listRegisteredRepos(n),G.listWorkspaces(n,{archived:!1})]),i=await C.listTasks(n),a=Gs(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await qa(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function Gs(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function cl(e,t){return Jt(e,t)}import ro from"node:path";import nI from"picocolors";var wf=[" \u2584\u2588\u2588\u2588\u2588\u2584 \u2588\u2588\u2580\u2588\u2588\u2588 \u2584\u2584\u2584 \u2588\u2588\u2593 \u2584\u2588\u2588\u2588\u2588"," \u2592\u2588\u2588\u2580 \u2580\u2588 \u2593\u2588\u2588 \u2592 \u2588\u2588\u2592\u2592\u2588\u2588\u2588\u2588\u2584 \u2593\u2588\u2588\u2592 \u2588\u2588\u2592 \u2580\u2588\u2592"," \u2592\u2593\u2588 \u2584 \u2593\u2588\u2588 \u2591\u2584\u2588 \u2592\u2592\u2588\u2588 \u2580\u2588\u2584 \u2592\u2588\u2588\u2592\u2592\u2588\u2588\u2591\u2584\u2584\u2584\u2591"," \u2592\u2593\u2593\u2584 \u2584\u2588\u2588\u2592\u2592\u2588\u2588\u2580\u2580\u2588\u2584 \u2591\u2588\u2588\u2584\u2584\u2584\u2584\u2588\u2588 \u2591\u2588\u2588\u2591\u2591\u2593\u2588 \u2588\u2588\u2593"," \u2592 \u2593\u2588\u2588\u2588\u2580 \u2591\u2591\u2588\u2588\u2593 \u2592\u2588\u2588\u2592 \u2593\u2588 \u2593\u2588\u2588\u2592\u2591\u2588\u2588\u2591\u2591\u2592\u2593\u2588\u2588\u2588\u2580\u2592"," \u2591 \u2591\u2592 \u2592 \u2591\u2591 \u2592\u2593 \u2591\u2592\u2593\u2591 \u2592\u2592 \u2593\u2592\u2588\u2591\u2591\u2593 \u2591\u2592 \u2592"," \u2591 \u2592 \u2591\u2592 \u2591 \u2592\u2591 \u2592 \u2592\u2592 \u2591 \u2592 \u2591 \u2591 \u2591"," \u2591 \u2591\u2591 \u2591 \u2591 \u2592 \u2592 \u2591\u2591 \u2591 \u2591"," \u2591 \u2591 \u2591 \u2591 \u2591 \u2591 \u2591"," \u2591"];function Hs(){return[...wf]}var Fr={width:120,height:36},N={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function oe(e,t){return{width:Math.max(e??Fr.width,Fr.width),height:Math.max(t??Fr.height,Fr.height)}}var kf=["Start","Options","Exit"],Tf=["Resume","Options","Exit"],Wr=2,qr=2,Ur=2,yf=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Rf=new RegExp("\x1B\\[(?:0)?m","g"),bf=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Pf=/https?:\/\/[^\s<>"']+/g,Ys="\x1B[0m",Js="\x1B]8;;\x1B\\",P={panelBg:{bg:"0a0a0a",fg:"c0caf5"},panelMuted:{bg:"0a0a0a",fg:"565f89"},panelSelected:{bg:"1a1b26",fg:"c0caf5"},panelFocused:{bg:"1a1b26",fg:"7aa2f7"},divider:{bg:"0a0a0a",fg:"292e42"},rail:{bg:"0a0a0a",fg:"c0caf5"},overlay:{bg:"06060f",fg:"565f89"},overlayTitle:{bg:"06060f",fg:"565f89"},overlayLogo:{bg:"06060f",fg:"9ece6a"},overlaySubtitle:{bg:"06060f",fg:"41a6b5"},overlayMenuSelected:{bg:"06060f",fg:"7aa2f7"},accent:{fg:"7aa2f7"},success:{fg:"9ece6a"},pending:{fg:"e0af68"},error:{fg:"f7768e"},mutedfg:{fg:"565f89"},disabled:{fg:"3b4261"}},zs=["3d59a1","506eb8","6386d0","7aa2f7","6386d0","506eb8"];function pl(e,t={}){return Xs(e,{subtitle:"crAIg is that you?",menuItems:kf,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function ml(e,t={}){return Xs(e,{subtitle:"Control mode is paused.",menuItems:Tf,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var _r=[" GLOBAL CENTER PANEL INSPECTOR"," ? help \u2190\u2192 / hl switch tab \u2191\u2193 / jk navigate"," Esc pause / back + new tab \u2190\u2192 / hl switch mode"," Tab cycle panels a codex tab R sync PR"," q quit t terminal tab R sync PR"," x close tab X close task"," TASKS Enter attach PTY X close task"," \u2191\u2193 / jk navigate"," n new task TERMINAL MODE"," Enter attach Ctrl+] return to control mode"," Wheel / PgUp / PgDn scroll",""," Press Esc to return."],Sf=["Help"],If=5;function Kr(e,t={}){return Xs(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??Sf,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function fl(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(F(" ".repeat(e.width),r,n)),o=Hs(),i=Math.max(1,Math.floor((e.height-o.length-2-_r.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=F(Pl(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(..._r.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<_r.length;d+=1){let u=c+d;if(u>=e.height)break;let m=_r[d]??"";s[u]=F(we(" ".repeat(l)+m,e.width),r,n)}return s.join(`
|
|
101
|
+
`)}function gl(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(F(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},pe(),...a.length>0?a.map(g=>({text:g})):[{text:"No Craig errors have been logged.",tone:"muted"}],pe(),{text:"Esc returns to Options.",tone:"muted"}],u=Xt(d,e.height-2),m=Math.max(1,Math.floor((e.height-u.length)/2));for(let g=0;g<u.length;g+=1){let y=m+g;if(y>=e.height)break;let w=u[g]??pe(),b=`${" ".repeat(c)}${Gr(w.text,l)}`,V=w.tone==="selected"?P.overlayMenuSelected:w.tone==="muted"?P.overlay:P.panelBg;s[y]=F(we(b,e.width),r,V)}return s.join(`
|
|
102
|
+
`)}function hl(e,t,r={}){let n=r.color??!0,s=N.leftWidth,o=N.rightWidth,i=r.centerOnly??!1,a=e.height-N.topRailHeight-1,l=r.focusFlashActive??!1,c={bg:P.divider.bg,fg:"9ece6a"},d=l&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?c:P.divider,u=l&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?c:P.divider,m=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,g=F(we(m,e.width),n,P.rail),y=vf(t,s-Wr-qr,a,n),w=Qs(e,t,{color:n,centerOnly:i}),b=xf(t,o,a,n),V=t.inputMode==="terminal",H=[],re=[];for(let Te=0;Te<a;Te+=1)if(!i){let Ue=Br(y[Te]??pe(),s,n,"left"),nr=F("\u2502",n,d),sr=F("\u2502",n,u),or=Br(b[Te]??pe(),o,n,"right");H.push(`${Ue}${nr}`),re.push(`${sr}${or}`)}let v=V||t.modalInput?P.panelBg:P.panelMuted,ke=Cf(t.footerText,t.footerToast,e.width,n,v),vt={row:1,column:1,width:e.width,rows:[g]},st=i?null:{row:N.topRailHeight+1,column:1,width:s+N.dividerWidth,rows:H},un=i?null:{row:N.topRailHeight+1,column:w.column+w.width,width:N.dividerWidth+o,rows:re},p={row:e.height,column:1,width:e.width,rows:[ke]},qe=i?w.rows:w.rows.map((Te,Ue)=>`${H[Ue]??""}${Te}${re[Ue]??""}`);return{frame:[g,...qe,ke].join(`
|
|
103
|
+
`),center:w,regions:{rail:vt,left:st,center:w,right:un,footer:p}}}function Qs(e,t,r={}){let n=r.color??!0,s=kl(e,r.centerOnly??!1),o=Af(t,s.width,s.rowCount,n);return{row:s.row,column:s.column,width:s.width,rows:o.map(i=>Br(i,s.width,n,"center"))}}function wl(e,t,r,n={}){let s=t.tabs.find(c=>c.active)?.id??"";if(!Us(s)||t.centerHeader.tabLabel==="BROWSER"||t.terminal.error||t.terminal.rows.length===0||r.some(c=>c<0||c>=t.terminal.rows.length))return null;let o=n.color??!0,i=kl(e,n.centerOnly??!1),a=Tl(t,i.width,o).length,l=[...new Set(r)].map(c=>({terminalIndex:c,index:a+c})).filter(({index:c})=>c<i.rowCount).map(({terminalIndex:c,index:d})=>({index:d,row:Br(yl(t.terminal.rows[c]),i.width,o,"center")}));return{...i,rows:l}}function kl(e,t){return{row:N.topRailHeight+1,column:t?1:N.leftWidth+N.dividerWidth+1,width:t?e.width:e.width-N.leftWidth-N.rightWidth-N.dividerWidth*2,rowCount:e.height-N.topRailHeight-1}}function Cf(e,t,r,n,s){let o=` ${e}`;if(!t)return F(we(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=te(i),l=te(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?Gr(o,Math.max(0,r-a-3)):o,u=Math.max(1,r-te(d)-a-2),m=t.tone==="error"?Yf(i,n,s):Pt(i,n,s),g=`${d}${" ".repeat(u)}${m} `;return F(we(g,r),n,s)}function Xs(e,t){let r=new Array(e.height).fill(F(" ".repeat(e.width),t.color,P.overlay)),n=Hs(),s=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c}`),o=t.optionsMessage?["",t.optionsMessage]:[],i=[...s,...o];for(;i.length<If;)i.push("");let a=[...n,"",t.subtitle,"",...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=Pl(a[c]??"",e.width);if(c<n.length){r[l+c]=F(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=F(d,t.color,P.overlaySubtitle);continue}let u=c-(n.length+3),g=u>=0&&u<t.menuItems.length&&u===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=F(d,t.color,g)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,u=" ".repeat(Math.max(0,e.width-te(d)));r[e.height-1]=F(`${u}${to(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
|
|
104
|
+
`)}function vf(e,t,r,n){let s=Of(e.runners),o=1,i=e.leftTree.map(l=>$f(l,t,n));return[...Xt(i,r-o),s]}function Af(e,t,r,n){let s=e.tabs.find(i=>i.active)?.id??"agent",o=e.centerHeader.tabLabel==="BROWSER"||!Us(s)?e.centerTranscript.map(i=>({...i})):Ef(e);return Xt([...Tl(e,t,n),...o],r)}function Tl(e,t,r){let n=t-2,s=e.tabs.find(b=>b.active)?.label??"AGENT",o=e.inputMode==="terminal"?0:Gf(e.tabs),i=e.inputMode==="terminal"?n:s.length+1,a="\u2500".repeat(Math.max(0,i)),l=`${" ".repeat(o)}${e.inputMode==="terminal"?Pt(a,r,P.panelBg):Vr(a,r,P.panelMuted)}`,c=[`${Vr(e.centerHeader.tabLabel,r,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),d=Mf(e.tabs,r,e.focusedRegion==="center"),u=" engaged ",m=u.length+2,g=e.inputMode==="terminal"?Pt(`${u}\u25CF `,r,P.panelBg):"",y=e.inputMode==="terminal"?" ".repeat(Math.max(0,n-te(d)-m)):"";return[{text:e.inputMode==="terminal"?`${d}${y}${g}`:d},{text:l,tone:"muted"},{text:c},pe()]}function Ef(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},pe(),{text:e.terminal.error},pe(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(n=>n.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(yl)}function yl(e){return{text:eo(e.segments),segments:e.segments,fullBleed:!0}}function xf(e,t,r,n){let s=e.rightInspection?Df(e.actionMessage?[...e.rightInspection.rows.slice(0,2),{id:"action-message",text:e.actionMessage},{id:"action-message-spacer",text:""},...e.rightInspection.rows.slice(2)]:e.rightInspection.rows,r):Xt([{text:"CONTEXT"},pe(),...e.rightContext.map(o=>Lf(o,n)),...e.actionMessage?[pe(),{text:e.actionMessage}]:[]],r);return Xt(s,r)}function Df(e,t){let r=e.slice(0,2),n=e.slice(2),s=Math.max(0,t-r.length),o=n.findIndex(a=>a.focused||a.selected),i=o===-1?0:zf(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>dl(a)),...n.slice(i,i+s).map(a=>dl(a))]}function dl(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",n=`${t}${e.text}`;if(e.segments)return{text:n,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let s=e.text.indexOf(" "),o=s===-1?e.text:e.text.slice(0,s),i=s===-1?"":e.text.slice(s);return{text:n,segments:[{text:t},{text:o,style:{fg:"7aa2f7"}},{text:i}],tone:r}}return e.color?{text:n,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:n,tone:r}}function $f(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Pt("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((y,w)=>y+te(w.text),0):0,l=t-te(o)-te(s)-a,c=e.activity?`${e.selected?"\u25B8":" "} \u25CF `:"",d=e.selected?e.text:e.focused?Pt(e.text,r,P.panelBg):e.panelHeader?Vr(e.text,r,P.panelMuted):e.text,u=we(`${n}${c}${d}`,Math.max(0,l)),m=e.selected?"selected":e.muted?"muted":"default";if(e.activity){let y=`${n}${e.selected?"\u25B8":" "} `,w=u.slice(y.length+2),b=[{text:y},Rl(e.activity,e.activityAnimationFrame??0),{text:` ${w}${o}${i}`},...e.prBadge??[]];return{text:eo(b),segments:b,tone:m}}if(e.prBadge){let y=[{text:`${u}${o}${i}`},...e.prBadge];return{text:`${u}${o}${e.prBadge.map(b=>b.text).join("")}`,segments:y,tone:m}}return{text:`${u}${o}${i}`,tone:m}}function Of(e){let t=e.map(n=>{let s=n.health>=1,o=parseInt(n.count,10),i=o>1?` (${o})`:"";return{text:`${s?"\u25CF":"\u25CB"} ${n.name}${i}`,active:s}}),r=[];for(let n=0;n<t.length;n++){let s=t[n];n>0&&r.push({text:" "}),s.active?r.push({text:s.text,style:{fg:P.success.fg}}):r.push({text:s.text,style:{fg:P.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function Mf(e,t,r){return e.map(n=>{let s=n.active?r?Pt(n.label,t,P.panelBg):Vr(n.label,t,P.panelBg):to(n.label,t,P.panelBg),o=n.activity?Zs(Rl(n.activity,n.activityAnimationFrame??0),t,P.panelBg):"";return`${s}${o?` ${o}`:""}`}).join(" ")}function Rl(e,t){return{text:"\u25CF",style:{fg:e==="working"?zs[t%zs.length]??zs[0]:e==="ready"?P.success.fg:e==="error"?P.error.fg:P.panelMuted.fg}}}function Lf(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?to(e.value,t,P.panelBg):e.value}`}}function Br(e,t,r,n){let s=Nf(n,e.tone??"default"),o=jf(e,r,s);if(n==="left"){if(e.fullBleed)return F(we(o,t),r,s);let a=t-Wr-qr;if(e.rightAlign){let c=te(o),d=Math.max(0,a-c),u=`${" ".repeat(Wr)}${" ".repeat(d)}${o}${" ".repeat(qr)}`;return F(u,r,s)}let l=`${" ".repeat(Wr)}${we(o,a)}${" ".repeat(qr)}`;return F(l,r,s)}return n==="center"&&e.fullBleed?Ff(e,t,r,s):F(we(` ${o}`,t),r,s)}function Nf(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function Xt(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(pe());return r}function pe(){return{text:""}}function jf(e,t,r){return e.segments?e.segments.map(n=>Zs(n,t,r)).join(""):e.text}function Ff(e,t,r,n){let s=" ".repeat(Ur),o=Math.max(0,t-Ur*2);if(!e.segments)return F(`${s}${we(e.text,o)}${s}`,r,n);let i=qf(e.segments,o),a=`${s}${i.map(l=>Zs(l,r,n)).join("")}${s}${r?Js:""}`;return F(a,r,n)}function Zs(e,t,r){let n=e.href?`${bl(e.href)}${e.text}${Js}`:_f(e.text);return!t||!e.style?n:`${Zt(Vf(e.style,r))}${Kf(e.style)}${n}${Ys}${Zt(r)}`}function _f(e){return e.replace(Pf,t=>{let[r,n]=Wf(t);return`${bl(r)}${r}${Js}${n}`})}function Wf(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function bl(e){return`\x1B]8;;${e}\x1B\\`}function qf(e,t){let r=Uf(e,t);return Bf(r,t)}function Uf(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=te(s.text);if(o<=n){r.push(s),n-=o;continue}let i=Gr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function Bf(e,t){let r=te(eo(e));if(r>=t)return e;let n=[...e].reverse().find(s=>s.style?.bg)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function Vf(e,t){let r=e.inverse?e.bg??t.bg:e.fg,n=e.inverse?e.fg??t.fg:e.bg,s={},o=r??t.fg,i=n??t.bg;return o&&(s.fg=o),i&&(s.bg=i),s}function Kf(e){let t=[];return e.bold&&t.push("1"),e.dim&&t.push("2"),e.italic&&t.push("3"),e.underline&&t.push("4"),t.length>0?`\x1B[${t.join(";")}m`:""}function Gf(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+(r.activity?2:0)+3}return 0}function Pl(e,t){let r=Math.max(0,t-te(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function we(e,t){let r=te(e);return r>=t?Hf(e,t):e+" ".repeat(t-r)}function Hf(e,t){if(t<=0)return"";if(te(e)<=t)return e;let r=Il(e);return Gr(r,Math.max(0,t-1))+"\u2026"}function te(e){let t=0;for(let r of Array.from(Il(e)))t+=Sl(r);return t}function Gr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=Sl(s);if(n+o>t)break;r+=s,n+=o}return r}function Sl(e){let t=e.codePointAt(0);return t===void 0||t===0||t<32||t>=127&&t<160||t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65024&&t<=65039||t>=8203&&t<=8207||t>=8288&&t<=8292||t===65279?0:t>=4352&&(t<=4447||t===9001||t===9002||t>=11904&&t<=42191&&t!==12351||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65135||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=127744&&t<=129791||t>=131072&&t<=262141)?2:1}function zf(e,t,r){return Math.min(Math.max(e,t),r)}function Il(e){return e.replace(bf,"").replace(yf,"")}function eo(e){return e.map(t=>t.text).join("")}function F(e,t,r){if(!t)return e;let n=Zt(r),s=e.replace(Rf,`${Ys}${n}`);return`${n}${s}${Ys}`}function Zt(e){let t=[];return e.fg&&t.push(`38;2;${ul(e.fg).join(";")}`),e.bg&&t.push(`48;2;${ul(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function ul(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Pt(e,t,r){return Hr(e,t,P.success.fg,r)}function Yf(e,t,r){return Hr(e,t,P.error.fg,r)}function Vr(e,t,r){return Hr(e,t,P.accent.fg,r)}function to(e,t,r){return Hr(e,t,P.mutedfg.fg,r)}function Hr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${Zt(s)}${e}${Zt(n)}`}function Cl(e,t,r){let n=e.tasks.find(l=>l.ptyTabs.some(c=>c.id===t))??null,s=n?.ptyTabs.find(l=>l.id===t)??null,o=n?.worktreePath??r,i=s?.kind==="agent"?Qf(s):[],a=n?{CRAIG_WORKSPACE_ROOT:r,CRAIG_TASK_ID:n.id,...s?.kind==="agent"?{CRAIG_AGENT_TAB_ID:s.id}:{}}:{};return n?.type==="project"?{cwd:o,command:i,env:{...a,GIT_CEILING_DIRECTORIES:Jf(process.env.GIT_CEILING_DIRECTORIES,o)}}:n?{cwd:o,command:i,env:a}:{cwd:o,command:i}}function Jf(e,t){let r=(e??"").split(ro.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(ro.delimiter):[...r,t].join(ro.delimiter)}function Qf(e){return e.command.length>0?e.command:["codex"]}function vl(e,t){let r=e.ptyTabs.find(n=>n.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function Fe(e){return{columns:Math.max(20,e.width-N.leftWidth-N.rightWidth-N.dividerWidth-Ur*2),rows:Math.max(5,e.height-N.topRailHeight-5)}}function Al(e){return e.length===1||ue(e)||e==="BACKSPACE"||e==="TAB"}function _e(e){return typeof e=="string"&&new RegExp(`:(?:agent|${O.join("|")})(?:-\\d+)?$`).test(e)}function El(e,t){return e==="UP"&&t?-3:e==="DOWN"&&t?3:e==="PAGE_UP"?-5:e==="PAGE_DOWN"?5:e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function no(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function xl(e){let t=new RegExp("\x1B\\[<(\\d+);\\d+;\\d+[mM]").exec(e);if(!t?.[1])return 0;let r=Number.parseInt(t[1],10);return r===64?-3:r===65?3:0}function er(e){return $l.includes(e)?"SHIFT_ENTER":null}function so(e){return $l.some(t=>t.startsWith(e))}function Dl(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var $l=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function Ol(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
104
105
|
`||r===`\r
|
|
105
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function
|
|
106
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Ml(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Ll(e,t=null){let r=t?.split(`
|
|
106
107
|
`)??[];return e.split(`
|
|
107
|
-
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function
|
|
108
|
-
`,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""}
|
|
109
|
-
`))&&this.touchActivity(r))}writeKey(t){let r=
|
|
110
|
-
[process exited ${
|
|
108
|
+
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function zr(e,t,r,n){return e.map((s,o)=>t?.[o]===s?"":`\x1B[${r+o};${n}H${s}`).join("")}import{spawn as Rg}from"node:child_process";import{createHash as bg}from"node:crypto";import{createServer as Pg,createConnection as Vl}from"node:net";import{openSync as Sg}from"node:fs";import{mkdir as Ig,readFile as po,rm as rt,writeFile as Cg}from"node:fs/promises";import{tmpdir as vg}from"node:os";import St from"node:path";import{createRequire as ag}from"node:module";import Xf from"@xterm/headless";var Zf=1e3,eg=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function jl(e){return new Xf.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:Zf,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Fl(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function io(e,t){return new Promise(r=>{e.write(t,r)})}function _l(e,t=0){let r=e.buffer.active,n=[],s=r.getNullCell(),o=r.baseY+r.cursorY,i=Math.max(0,r.baseY-t);for(let a=0;a<e.rows;a+=1){let l=r.getLine(i+a);if(!l){n.push({segments:[]});continue}let c=[];for(let d=0;d<e.cols;d+=1){let u=l.getCell(d,s);!u||u.getWidth()===0||c.push({text:u.getChars()||" ",style:ng(u,i+a===o&&d===r.cursorX)})}n.push({segments:tg(rg(c))})}return n}function tg(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&ig(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};Wl(r.style)||(s.style=r.style),t.push(s)}return t}function rg(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Wl(r.style))break;t-=1}return e.slice(0,t)}function ng(e,t){let r={},n=Nl(e,"fg"),s=Nl(e,"bg");return n&&(r.fg=n),s&&(r.bg=s),e.isBold()&&(r.bold=!0),e.isDim()&&(r.dim=!0),e.isItalic()&&(r.italic=!0),e.isUnderline()&&(r.underline=!0),(e.isInverse()||t)&&(r.inverse=!0),r}function Nl(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let n=t==="fg"?e.isFgRGB():e.isBgRGB(),s=t==="fg"?e.getFgColor():e.getBgColor();return n?s.toString(16).padStart(6,"0"):eg[s]??sg(s)}function sg(e){if(e>=16&&e<=231){let t=e-16,r=Math.floor(t/36),n=Math.floor(t%36/6),s=t%6;return[r,n,s].map(og).map(o=>o.toString(16).padStart(2,"0")).join("")}if(e>=232&&e<=255){let t=8+(e-232)*10;return[t,t,t].map(r=>r.toString(16).padStart(2,"0")).join("")}return"e6e6e6"}function og(e){return e===0?0:55+e*40}function ig(e,t){return oo(e)===oo(t)}function oo(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Wl(e){return oo(e)===""}var lg=ag(import.meta.url),cg=/^CTRL_([A-Z])$/,dg="\x1B[6n",ug="\x1B[c",pg="\x1B[?u",mg={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
109
|
+
`,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""},Yr=class{sessions=new Map;activitySnapshots=new Map;shell;env;spawn;onUpdate;onActivity;onActivityRemoved;activityEnabled;resolveSessionSpec;attachedTabId=null;constructor(t){this.shell=t.shell??process.env.SHELL??"/bin/zsh",this.env=t.env??process.env,this.spawn=t.spawn,this.onUpdate=t.onUpdate,this.onActivity=t.onActivity,this.onActivityRemoved=t.onActivityRemoved,this.activityEnabled=t.activityEnabled??!0,this.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,n,s){let o=this.sessions.get(r);if(o)if(o.status!=="running")ao(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,ql(o,n),this.getViewState(r);let i;try{i=this.createSession(t,r,n,s)}catch(a){throw this.recordActivity({taskId:t,tabId:r,sessionState:"failed",lastActivityAt:Date.now(),exitCode:null,error:a instanceof Error?a.message:String(a)}),a}return this.sessions.set(r,i),this.notifyActivity(i),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||(r.pty.write(t),(t.includes("\r")||t.includes(`
|
|
110
|
+
`))&&this.touchActivity(r))}writeKey(t){let r=fg(t);r!==null&&this.write(r)}scrollViewport(t){let r=this.getAttachedSession();if(!r||t===0)return;let n=r.terminal.buffer.active.baseY;r.scrollbackLines=Math.max(0,Math.min(n,r.scrollbackLines-t))}resize(t){let r=this.getAttachedSession();r&&ql(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}getActivitySnapshots(){return[...this.activitySnapshots.values()]}setActivityEnabled(t){if(this.activityEnabled!==t&&(this.activityEnabled=t,!!t))for(let r of this.sessions.values())this.notifyActivity(r)}disposeSession(t){let r=this.sessions.get(t);r&&(ao(r),this.sessions.delete(t)),this.removeActivity(t),this.attachedTabId===t&&(this.attachedTabId=null)}disposeAll(){for(let t of this.sessions.values())ao(t);this.sessions.clear();for(let t of this.activitySnapshots.keys())this.onActivityRemoved?.(t);this.activitySnapshots.clear(),this.attachedTabId=null}getViewState(t){if(!t)return{status:"idle",rows:[],error:null,scrolledBack:!1};let r=this.sessions.get(t);return r?{status:r.status,rows:gg(r),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??wg().spawn,i=jl(n),a=s??this.resolveSessionSpec(t,r),l=Je({...this.env,...a.env??{}}),{executable:c,args:d}=kg(this.shell,a.command,{cwd:a.cwd,env:l}),u=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:Tg(l)}),m={taskId:t,tabId:r,pty:u,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0,rows:[],renderedScrollbackLines:null,screenDirty:!0,lastActivityAt:Date.now(),exitCode:null};return m.disposables.push(u.onData(g=>{this.touchActivity(m),yg(u,g),io(m.terminal,g).then(()=>{m.screenDirty=!0,this.onUpdate?.({tabId:m.tabId,kind:"full"})})})),m.disposables.push(u.onExit(g=>{m.status="exited",m.exitCode=g.exitCode,m.lastActivityAt=Date.now(),this.notifyActivity(m),io(m.terminal,`\r
|
|
111
|
+
[process exited ${g.exitCode}]`).then(()=>{m.screenDirty=!0,this.onUpdate?.({tabId:m.tabId,kind:"full"})})})),m}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}touchActivity(t){t.lastActivityAt=Date.now(),this.activityEnabled&&this.notifyActivity(t)}notifyActivity(t){this.activityEnabled&&this.recordActivity(this.buildActivitySnapshot(t))}recordActivity(t){this.activityEnabled&&(this.activitySnapshots.set(t.tabId,t),this.onActivity?.(t))}removeActivity(t){this.activitySnapshots.delete(t)&&this.onActivityRemoved?.(t)}buildActivitySnapshot(t){return{taskId:t.taskId,tabId:t.tabId,sessionState:t.status==="failed"?"failed":t.status==="exited"?"exited":"running",lastActivityAt:t.lastActivityAt,exitCode:t.exitCode,error:t.error}}};function fg(e){if(e.length===1)return e;let t=mg[e];if(t!==void 0)return t;let r=cg.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function ql(e,t){hg(e.pty,t),Fl(e.terminal,t),e.screenDirty=!0}function gg(e){return(e.screenDirty||e.renderedScrollbackLines!==e.scrollbackLines)&&(e.rows=_l(e.terminal,e.scrollbackLines),e.renderedScrollbackLines=e.scrollbackLines,e.screenDirty=!1),e.rows}function ao(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function hg(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function wg(){return lg("node-pty")}function kg(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Qe(t[0],r),...t.slice(1)].map(Ul).join(" ")}; exec ${Ul(e)} -l`;return{executable:e,args:["-lc",s]}}function Ul(e){return`'${e.replaceAll("'","'\\''")}'`}function Tg(e){let t={};for(let[r,n]of Object.entries(e))typeof n=="string"&&(t[r]=n);return t.TERM=t.TERM??"xterm-256color",t}function yg(e,t){for(let r=0;r<lo(t,dg);r+=1)e.write("\x1B[1;1R");for(let r=0;r<lo(t,ug);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<lo(t,pg);r+=1)e.write("\x1B[?0u")}function lo(e,t){if(t.length===0)return 0;let r=0,n=e.indexOf(t);for(;n!==-1;)r+=1,n=e.indexOf(t,n+t.length);return r}var Kl=6,Ag=new Set([Kl]),Eg=16,xg=250;async function Gl(e){let t=mo(e.paths);await Mg(t,e.paths,e.spawnDaemon);let r=await Zl(t.socketPath),n=new co(r,e);return await n.ready(),n}async function Hl(e,t={}){let r=mo(e);await Ig(e.runtimeDir,{recursive:!0}),await rt(r.socketPath,{force:!0});let n=new uo(e,t),s=Pg(o=>n.handleConnection(o));await Wg(s,r.socketPath),await Cg(r.pidPath,String(process.pid),"utf8"),await new Promise(o=>{let i=()=>{n.closeClients(),s.close(()=>o())};n.onShutdown=i,process.once("SIGTERM",i),process.once("SIGINT",i)}),await rt(r.socketPath,{force:!0}),await rt(r.pidPath,{force:!0}),n.disposeAll()}async function zl(e){let t=mo(e);return await Qr(t.socketPath)?(await Ql(t.socketPath),!0):!1}var co=class{constructor(t,r){this.socket=t;this.options=r,this.viewUpdateMode=r.viewUpdateMode??"snapshot",this.activityEnabled=r.activityEnabled??!1,t.setEncoding("utf8"),t.on("data",n=>this.handleData(String(n))),t.on("error",n=>this.rejectAll(n instanceof Error?n:new Error(String(n)))),t.on("close",()=>{this.closed||(this.closed=!0,this.rejectAll(new Error("Craig PTY daemon connection closed.")),this.failRunningActivities("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;activityCache=new Map;activityRevisionByTabId=new Map;activityRevision=0;attachedTabId=null;viewedTabId=null;subscribedTabId=null;viewUpdateMode;activityEnabled;buffer="";closed=!1;options;async ready(){let t=await this.send({type:"ping"});if(!Jl(t.protocolVersion))throw new Error("Craig PTY daemon protocol mismatch.");await this.send({type:"setViewUpdateMode",mode:this.viewUpdateMode}),await this.send({type:"setActivityEnabled",enabled:this.activityEnabled}),this.activityEnabled&&await this.refreshActivitySnapshots()}async ensureSession(t,r,n){let s=await this.send({type:"ensureSession",taskId:t,tabId:r,size:n,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r,this.viewedTabId=r;let o=s.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,o),o}async hydrateSessions(t){for(let r of t)try{let n=await this.send({type:"hydrateSession",tabId:r});n.view&&this.viewCache.set(r,n.view)}catch(n){let s=n instanceof Error?n.message:String(n);this.viewCache.set(r,{status:"failed",rows:[],error:s})}this.activityEnabled&&await this.refreshActivitySnapshots()}async pruneStale(t){await this.send({type:"pruneStale",keepTabIds:t})}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){let r=this.attachedTabId;this.send({type:"scrollViewport",lines:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}resize(t){let r=this.attachedTabId;this.send({type:"resize",size:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}setViewedTab(t){this.closed||(this.viewedTabId=t,this.viewUpdateMode==="incremental"&&this.subscribeToView(t))}setViewUpdateMode(t){if(this.closed||this.viewUpdateMode===t)return;this.viewUpdateMode=t,this.subscribedTabId=null;let r=this.viewedTabId;this.send({type:"setViewUpdateMode",mode:t}).then(n=>{r&&n.view&&this.viewCache.set(r,n.view),this.viewUpdateMode===t&&this.viewedTabId===r&&this.notifyFullUpdate(r),t==="incremental"&&this.viewUpdateMode===t&&(this.viewedTabId===r&&this.subscribedTabId===null?this.subscribedTabId=r:this.viewedTabId!==r&&this.subscribeToView(this.viewedTabId))}).catch(()=>{this.viewUpdateMode===t&&(this.subscribedTabId=null)})}setActivityEnabled(t){if(!(this.closed||this.activityEnabled===t)){if(this.activityEnabled=t,!t){for(let r of[...this.activityCache.keys()])this.removeCachedActivity(r);this.send({type:"setActivityEnabled",enabled:t}).catch(()=>{});return}this.send({type:"setActivityEnabled",enabled:t}).then(()=>this.refreshActivitySnapshots(!0)).catch(()=>{})}}disposeSession(t){this.viewCache.delete(t),this.removeCachedActivity(t),this.attachedTabId===t&&(this.attachedTabId=null),this.send({type:"disposeSession",tabId:t}).catch(()=>{})}disposeAll(){this.attachedTabId=null,!this.closed&&(this.socket.end(),this.closed=!0)}getViewState(t){return t?this.viewCache.get(t)??{status:"idle",rows:[],error:null,scrolledBack:!1}:{status:"idle",rows:[],error:null,scrolledBack:!1}}getActivitySnapshots(){return[...this.activityCache.values()]}async requestShutdown(){await this.send({type:"shutdown"})}async send(t){if(this.closed)throw new Error("Craig PTY daemon connection is closed.");let r=this.nextRequestId;this.nextRequestId+=1;let n={...t,id:r},s=new Promise((i,a)=>{this.pending.set(r,{resolve:i,reject:a})});if(this.socket.destroyed)throw this.pending.delete(r),new Error("Craig PTY daemon connection is closed.");this.socket.write(`${JSON.stringify(n)}
|
|
111
112
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
112
113
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
113
|
-
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}if(r.type==="update"){if("view"in r){this.viewCache.set(r.tabId,r.view),this.notifyFullUpdate(r.tabId);return}let n=this.viewCache.get(r.tabId)??{status:"idle",rows:[],error:null,scrolledBack:!1},s=
|
|
114
|
+
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}if(r.type==="update"){if("view"in r){this.viewCache.set(r.tabId,r.view),this.notifyFullUpdate(r.tabId);return}let n=this.viewCache.get(r.tabId)??{status:"idle",rows:[],error:null,scrolledBack:!1},s=Og(n,r.patch),o=n.rows.slice(0,r.patch.rowCount);for(let i of r.patch.rows)o[i.index]=i.row;this.viewCache.set(r.tabId,{status:r.patch.status,rows:o,error:r.patch.error,scrolledBack:r.patch.scrolledBack}),this.viewUpdateMode==="incremental"&&this.viewedTabId===r.tabId&&this.options.onUpdate?.(s?{tabId:r.tabId,kind:"full"}:{tabId:r.tabId,kind:"rows",rowIndices:r.patch.rows.map(i=>i.index)})}r.type==="activity"&&(this.recordCachedActivity(r.snapshot),this.options.onActivity?.(r.snapshot)),r.type==="activityRemoved"&&this.removeCachedActivity(r.tabId)}subscribeToView(t){this.closed||this.viewUpdateMode!=="incremental"||this.subscribedTabId===t||(this.subscribedTabId=t,this.send({type:"subscribeView",tabId:t}).then(r=>{t&&r.view&&this.viewCache.set(t,r.view),this.viewUpdateMode==="incremental"&&this.viewedTabId===t&&this.subscribedTabId===t&&this.notifyFullUpdate(t)}).catch(()=>{this.subscribedTabId===t&&(this.subscribedTabId=null)}))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}notifyFullUpdate(t){t&&this.options.onUpdate?.({tabId:t,kind:"full"})}replaceActivityCache(t,r){let n=new Map;for(let[s,o]of this.activityRevisionByTabId)o>r&&n.set(s,this.activityCache.get(s)??null);this.activityCache.clear();for(let s of t)this.activityCache.set(s.tabId,s);for(let[s,o]of n)o?this.activityCache.set(s,o):this.activityCache.delete(s)}async refreshActivitySnapshots(t=!1){let r=this.activityRevision,n=await this.send({type:"getActivitySnapshots"});if(this.replaceActivityCache(n.activities??[],r),t)for(let s of this.activityCache.values())this.options.onActivity?.(s)}recordCachedActivity(t){this.activityRevision+=1,this.activityRevisionByTabId.set(t.tabId,this.activityRevision),this.activityCache.set(t.tabId,t)}removeCachedActivity(t){this.activityRevision+=1,this.activityRevisionByTabId.set(t,this.activityRevision),this.activityCache.delete(t),this.options.onActivityRemoved?.(t)}failRunningActivities(t){for(let r of this.activityCache.values()){if(r.sessionState!=="running")continue;let n={...r,sessionState:"failed",lastActivityAt:Date.now(),error:t};this.recordCachedActivity(n),this.options.onActivity?.(n)}}},uo=class{onShutdown=null;clients=new Set;subscriptions=new Map;updateTimers=new Map;activityTimers=new Map;pendingActivities=new Map;runtime;attachedTabId=null;constructor(t,r){this.runtime=new Yr({...r,workspaceRoot:t.workspaceRoot,activityEnabled:!1,onUpdate:n=>this.handleRuntimeUpdate(n.tabId),onActivity:n=>this.handleActivityUpdate(n),onActivityRemoved:n=>this.handleActivityRemoved(n)})}handleConnection(t){let r="";this.clients.add(t),this.subscriptions.set(t,{mode:"snapshot",activityEnabled:!1,tabId:null,view:null,rowKeys:[]}),t.setEncoding("utf8"),t.on("data",s=>{r+=String(s);let o=r.indexOf(`
|
|
114
115
|
`);for(;o!==-1;){let i=r.slice(0,o);r=r.slice(o+1),this.handleLine(t,i),o=r.indexOf(`
|
|
115
|
-
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t),this.hasActivitySubscribers()||(this.runtime.setActivityEnabled(!1),this.clearPendingActivityBroadcasts())};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear();for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear(),this.runtime.setActivityEnabled(!1)}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{
|
|
116
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
116
|
+
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t),this.hasActivitySubscribers()||(this.runtime.setActivityEnabled(!1),this.clearPendingActivityBroadcasts())};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear();for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear(),this.runtime.setActivityEnabled(!1)}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{tt(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(t,n);tt(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:Kl}:{},...n.type==="getActivitySnapshots"?{activities:this.runtime.getActivitySnapshots()}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);tt(t,{id:n.id,ok:!1,error:o})}}handleRequest(t,r){switch(r.type){case"ping":return null;case"ensureSession":return this.attachedTabId=r.tabId,this.subscribe(t,r.tabId,this.runtime.ensureSession(r.taskId,r.tabId,r.size,r.spec));case"hydrateSession":return this.runtime.getViewState(r.tabId);case"write":return this.runtime.write(r.input),null;case"writeKey":return this.runtime.writeKey(r.key),null;case"scrollViewport":return this.runtime.scrollViewport(r.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(r.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(r.tabId),this.attachedTabId===r.tabId&&(this.attachedTabId=null),null;case"setViewUpdateMode":return this.setViewUpdateMode(t,r.mode);case"setActivityEnabled":return this.setActivityEnabled(t,r.enabled),null;case"subscribeView":return this.subscribe(t,r.tabId,this.runtime.getViewState(r.tabId));case"pruneStale":{let n=new Set(r.keepTabIds),s=new Set([...this.runtime.sessionTabIds(),...this.runtime.getActivitySnapshots().map(o=>o.tabId)]);for(let o of s)n.has(o)||(this.runtime.disposeSession(o),this.attachedTabId===o&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(r.tabId);case"getActivitySnapshots":return null;case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return qg(r)}}subscribe(t,r,n){let s=this.subscriptions.get(t),o=s?.mode??"snapshot";return this.subscriptions.set(t,{mode:o,activityEnabled:s?.activityEnabled??!1,tabId:r,view:n,rowKeys:n.rows.map(Jr)}),n}setViewUpdateMode(t,r){let n=this.subscriptions.get(t),s=n?.tabId??null,o=this.runtime.getViewState(s);return this.subscriptions.set(t,{mode:r,activityEnabled:n?.activityEnabled??!1,tabId:s,view:o,rowKeys:o.rows.map(Jr)}),o}setActivityEnabled(t,r){let n=this.subscriptions.get(t);if(!n)return;this.subscriptions.set(t,{...n,activityEnabled:r});let s=this.hasActivitySubscribers();this.runtime.setActivityEnabled(s),s||this.clearPendingActivityBroadcasts()}handleRuntimeUpdate(t){let r=null;for(let n of this.clients)this.subscriptions.get(n)?.mode==="snapshot"&&(r??=this.runtime.getViewState(t),tt(n,{type:"update",tabId:t,view:r}));this.scheduleBroadcastUpdate(t)}handleActivityUpdate(t){if(this.hasActivitySubscribers()){if(this.pendingActivities.set(t.tabId,t),t.sessionState!=="running"){let r=this.activityTimers.get(t.tabId);r&&(clearTimeout(r),this.activityTimers.delete(t.tabId)),this.broadcastActivity(t.tabId);return}this.activityTimers.has(t.tabId)||this.activityTimers.set(t.tabId,setTimeout(()=>{this.activityTimers.delete(t.tabId),this.broadcastActivity(t.tabId)},xg))}}handleActivityRemoved(t){let r=this.activityTimers.get(t);r&&(clearTimeout(r),this.activityTimers.delete(t)),this.pendingActivities.delete(t);for(let[n,s]of this.subscriptions)s.activityEnabled&&tt(n,{type:"activityRemoved",tabId:t})}broadcastActivity(t){let r=this.pendingActivities.get(t);if(r){this.pendingActivities.delete(t);for(let[n,s]of this.subscriptions)s.activityEnabled&&tt(n,{type:"activity",snapshot:r})}}hasActivitySubscribers(){return[...this.subscriptions.values()].some(t=>t.activityEnabled)}clearPendingActivityBroadcasts(){for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear()}scheduleBroadcastUpdate(t){this.updateTimers.has(t)||!this.hasViewSubscriber(t)||this.updateTimers.set(t,setTimeout(()=>{this.updateTimers.delete(t),this.broadcastUpdate(t)},Eg))}hasViewSubscriber(t){for(let r of this.subscriptions.values())if(r.mode==="incremental"&&r.tabId===t)return!0;return!1}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients){let s=this.subscriptions.get(n);if(!s||s.mode!=="incremental"||s.tabId!==t)continue;let o=Dg(s,r),i=$g(s.view,r);s.view=r,s.rowKeys=r.rows.map(Jr),(o.rows.length>0||i)&&tt(n,{type:"update",tabId:t,patch:o})}}};function Dg(e,t){let r=[];for(let n=0;n<t.rows.length;n+=1){let s=t.rows[n];e.rowKeys[n]!==Jr(s)&&r.push({index:n,row:s})}return{status:t.status,error:t.error,scrolledBack:t.scrolledBack??!1,rowCount:t.rows.length,rows:r}}function $g(e,t){return!e||e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==(t.scrolledBack??!1)||e.rows.length!==t.rows.length}function Og(e,t){return e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==t.scrolledBack||e.rows.length!==t.rowCount}function Jr(e){return JSON.stringify(e)}function mo(e){let t=bg("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:St.join(vg(),`craig-${t}.sock`),pidPath:St.join(e.runtimeDir,"pty-daemon.pid")}}async function Mg(e,t,r){if(await Lg(e.socketPath,1e3))return;await Qr(e.socketPath)&&(await Ql(e.socketPath),await Bl(e.socketPath,1e3)),await Qr(e.socketPath)&&(await Fg(e),await Bl(e.socketPath,1e3)),await jg(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=Ng(n),l=Sg(St.join(t.runtimeDir,"pty-daemon.log"),"a");Rg(i,a,{cwd:n,detached:!0,stdio:["ignore",l,l],env:process.env}).unref()}let s=Date.now();for(;Date.now()-s<5e3;){if(await Yl(e.socketPath))return;await fo(50)}let o=await po(St.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
117
|
+
${o.slice(-2e3)}`:""}`)}async function Yl(e){let t=await _g(e).catch(()=>null);return t?.ok===!0&&Jl(t.protocolVersion)}function Jl(e){return e!==void 0&&Ag.has(e)}async function Lg(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Yl(e))return!0;await fo(50)}return!1}function Ng(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=St.resolve(St.dirname(t),"..","node_modules",".bin","tsx");return{command:zn("tsx")??n,args:[t,"__craig-daemon",e]}}let r=process.argv.slice(1);return{command:process.execPath,args:[...process.execArgv,...r,"__craig-daemon",e]}}async function jg(e){let t=await po(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&ec(r))return}await rt(e.socketPath,{force:!0}),await rt(e.pidPath,{force:!0})}async function Qr(e){let t=await Zl(e).catch(()=>null);return t?(t.end(),!0):!1}async function Ql(e){await Xl(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Fg(e){let t=await po(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!ec(r)){await rt(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await rt(e.socketPath,{force:!0})}}async function _g(e){return Xl(e,{id:1,type:"ping"})}function Xl(e,t){return new Promise((r,n)=>{let s=Vl(e),o="",i=setTimeout(()=>{s.destroy(),n(new Error("Craig PTY daemon request timed out."))},500),a=()=>clearTimeout(i);s.setEncoding("utf8"),s.once("connect",()=>s.write(`${JSON.stringify(t)}
|
|
117
118
|
`)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let c=o.indexOf(`
|
|
118
|
-
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function
|
|
119
|
-
`)}catch{}}function
|
|
120
|
-
`}function Bf(e){return e.length===1&&e>=" "&&e!==""}import Kt from"node:path";function Il(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"\u{F06E6} ";case"js":case"jsx":case"mjs":case"cjs":return"\u{F031E} ";case"json":case"jsonc":return"\u{F0871} ";case"md":case"mdx":return"\u{F0354} ";case"yaml":case"yml":return"\u{F0B10} ";case"sh":case"bash":case"zsh":return"\u{F018D} ";case"css":case"scss":case"sass":return"\u{F031C} ";case"html":case"htm":return"\u{F031D} ";case"py":return"\u{F0320} ";case"go":return"\u{F07D3} ";case"rs":return"\u{F1617} ";case"lock":return"\u{F033E} ";case"png":case"jpg":case"jpeg":case"gif":case"svg":case"webp":return"\u{F02E9} ";default:return"\u{F0214} "}}var Cl="\u{F024B} ",vl="\u{F0DCF} ",El="\u25CB",Ls="\uEA64",Al="\uEAFE",xl="\uEBDA",Fs="\u25CB",js="\u25CF",Ws="\u2713",_s="\u2715";function Dl(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"4fc1ff";case"js":case"jsx":case"mjs":case"cjs":return"f7df1e";case"json":case"jsonc":return"fbc02d";case"md":case"mdx":return"519aba";case"yaml":case"yml":return"e06c75";case"sh":case"bash":case"zsh":return"89e051";case"css":case"scss":case"sass":return"c792ea";case"html":case"htm":return"e06c75";case"py":return"3572a5";case"go":return"00add8";case"rs":return"dea584";case"lock":return"565f89";default:return}}var $l={idle:0,working:1,ready:2,error:3};function Vt(e,t,r,n="idle"){let s=t.find(o=>o.tabId===e);return s?s.sessionState==="failed"||s.sessionState==="exited"&&s.exitCode!==0?"error":s.sessionState==="exited"?"ready":r-s.lastActivityAt<5e3?"working":"ready":n}function Us(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return Vt(t,r,n,o)}function qs(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=Us(e,s.id,t,r);$l[o]>$l[n]&&(n=o)}return n}function Ol(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&Vt(s.id,t,r)==="working"))}var Fr="empty",q={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Fl(e,t,r){let n=Gf(t,e),s=t.repos.find(y=>y.id===e.selectedRepoId)??t.repos[0]??null,o=n?t.tasks.filter(y=>y.workspaceId===n.id):t.tasks,i=n?.kind==="project"?o:s?o.filter(y=>y.repoId===s.id):[],a=i.find(y=>y.id===e.selectedTaskId)??i[0]??null,l=a?.type==="project",c=Cg(t.tasks),d=Yf(e,a),u=zf(e,a,d,r),m=u.find(y=>y.id===d)??u[0]??{id:"agent",label:"CODEX"},T=t.inspection?.taskId===a?.id?t.inspection:null,R=s?.name??"no repo",h=a?f.runners.getDisplayName(a.runner):f.runners.getDisplayName(e.selectedRunner);return{inputMode:e.inputMode,modalInput:e.taskPromptInput!==null||e.workspaceBrowser!==null,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,footerToast:e.footerToast,terminal:e.terminal,footerText:e.workspaceBrowser!==null?e.workspaceBrowser.query!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} Search: ${e.workspaceBrowser.query} \u2191\u2193 move Enter select Esc clear search`:`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up / search Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${s?`[${s.name}]`:"[no repo]"} \xB7 ${f.runners.getDisplayName(e.selectedRunner)} Ctrl+R switch runner Enter create Esc cancel \u203A ${e.taskPromptInput}${e.taskPromptError?` \u2717 ${e.taskPromptError}`:""}`:e.inputMode==="terminal"?"TERMINAL \u2191\u2193/PgUp/PgDn scroll Ctrl+] return to control":e.focusedRegion==="tasks"?e.selectedLeftItemId?.startsWith("new-task:")||e.selectedLeftItemId?.startsWith("new-task-workspace:")?`r runner [${f.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:_t(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":e.selectedLeftItemId?.startsWith("workspace:")?"n new task Enter select X remove workspace Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?a===null?"n new task Tab tasks Esc pause ? help":d===A?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${f.runners.getDisplayName(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?l?"\u2191\u2193 targets Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:Kt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Kt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:h},leftTree:Vf(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(y=>vg(y,c[y])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":m.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:R,agent:h},centerTranscript:Hf(d,e,s,a,e.workspaceBrowser,T,n),tabs:u,rightContext:Ig(s,a),rightInspection:lg(e,a,T)}}function Vf(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Kf(n,e,t.repos,t.tasks,r);let s=t.workspaces;if(s.length===0)n.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let i of s){let a=e.selectedLeftItemId===`workspace:${i.id}`;n.push({id:`workspace:${i.id}`,text:`${i.kind==="project"?"\u2261":"\u2013"} ${i.name??i.id}`,selected:a,focused:a&&e.focusedRegion==="tasks"});let l=i.kind==="project"?i.discoveredRepoIds??[]:[i.primaryRepoId],c=t.tasks.filter(d=>d.workspaceId===i.id);if(c.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of c){let u=e.selectedLeftItemId===`task:${d.id}`,m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,T={id:`task:${d.id}`,taskId:d.id,text:r?m:`${u?"\u25B8":"\u2022"} ${m}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:qs(d,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},R=Wl(d);R&&(T.prBadge=R),n.push(T)}if(i.kind==="project"){let d=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Project Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(i.kind==="repo"){let d=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}else{n.push({text:` Repos (${l.length})`,indent:0,muted:!0});for(let d of l.slice(0,6)){let u=t.repos.find(m=>m.id===d);n.push({text:` \xB7 ${u?.name??d}`,indent:0,muted:!0})}l.length>6&&n.push({text:` \xB7 ${l.length-6} more`,indent:0,muted:!0})}}let o=e.selectedLeftItemId==="new-workspace";return n.push({text:"",muted:!0}),n.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&e.focusedRegion==="tasks"}),n}function Kf(e,t,r,n,s){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let i of r){let a=t.selectedLeftItemId===`repo:${i.id}`;e.push({id:`repo:${i.id}`,text:`\u2013 ${i.name}`,selected:a,focused:a&&t.focusedRegion==="tasks"});let l=n.filter(u=>u.repoId===i.id);if(l.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let u of l){let m=t.selectedLeftItemId===`task:${u.id}`,T=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,R={id:`task:${u.id}`,taskId:u.id,text:s?T:`${m?"\u25B8":"\u2022"} ${T}`,indent:2,selected:m,focused:m&&t.focusedRegion==="tasks",...s?{activity:qs(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},h=Wl(u);h&&(R.prBadge=h),e.push(R)}let c=`new-task:${i.id}`,d=t.selectedLeftItemId===c;e.push({id:c,text:`+ New Task [${f.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:d,focused:d&&t.focusedRegion==="tasks",muted:!d})}let o=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&t.focusedRegion==="tasks"}),e}function Gf(e,t){let r=e.workspaces??[];if(!e.workspaces)return null;let n=e.tasks.find(s=>s.id===t.selectedTaskId)??null;return n?r.find(s=>s.id===n.workspaceId)??null:t.selectedWorkspaceId?r.find(s=>s.id===t.selectedWorkspaceId)??null:r[0]??null}function Hf(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,m)=>{let T=m===s.selectedIndex?"\u25B8":" ",R=u.kind==="repo"?" [git repo]":"/";return`${T} ${u.name}${R}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return fe(["Browse for a workspace to register.",s.cwd,...d?[d]:[],"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return fe(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return fe([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${f.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?fe([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this PTY-backed agent session.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):fe([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this plain task shell.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):e===A&&t.openInspectionKind==="file"?Xf(n,o,t.fileScrollOffset):e===A&&t.openInspectionKind==="diff"?Zf(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?fe(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):fe(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function zf(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Qf(i),...i.kind==="agent"&&n&&t?{activity:Us(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:Fr,label:"EMPTY",active:r===Fr,focused:e.focusedRegion==="center"&&r===Fr}];let o=e.openInspectionKind||r===A?[{id:A,label:Jf(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Yf(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===A&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??A:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??A:Fr}function Qf(e){return e.title.toUpperCase()}function Jf(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Kt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Xf(e,t,r){if(!e)return fe(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return fe(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=jl(n.path??n.title);return[{text:n.title},{text:`${n.byteLength===null?"size unknown":`${n.byteLength} bytes`} \xB7 ${n.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...eg(n.lines,r,s)]}function Zf(e,t,r){if(!e)return fe(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return fe(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=jl(n.path??n.title);return[{text:n.title},{text:`${t.diffPaths.length} changed files \xB7 ${n.lines.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...tg(n.lines,r,s)]}function fe(e){return e.map(t=>({text:t}))}function eg(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:q.lineNumber}},{text:" \u2502 ",style:{fg:q.gutter}},...Bs(o,r)],tone:"default"}})}function tg(e,t,r){let n=rg(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>ng(o,r))}function rg(e){let t=[],r=0,n=0;for(let s of e){let o=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(s);if(o){r=Number.parseInt(o[1]??"0",10),n=Number.parseInt(o[2]??"0",10);continue}if(!(s.startsWith("diff --git")||s.startsWith("index ")||s.startsWith("+++ ")||s.startsWith("--- "))&&!(s==="staged"||s==="unstaged"||s==="untracked")){if(s.startsWith("-")&&!s.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:s.slice(1),kind:"delete"}),r+=1;continue}if(s.startsWith("+")&&!s.startsWith("+++")){t.push({oldNumber:null,newNumber:n,marker:"+",text:s.slice(1),kind:"add"}),n+=1;continue}if(s.startsWith(" ")){if(r===0&&n===0)continue;t.push({oldNumber:r,newNumber:n,marker:" ",text:s.slice(1),kind:"context"}),r+=1,n+=1;continue}}}return t}function ng(e,t){let r=Ml(e.oldNumber),n=Ml(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:q.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:q.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?og(Bs(e.text,t),o.bg,o.fallbackFg):Bs(e.text,t),l=o?{fg:q.lineNumber,bg:o.bg}:{fg:q.lineNumber},c=o?{fg:q.gutter,bg:o.bg}:{fg:q.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function Ml(e){return e===null?" ":String(e).padStart(4," ")}function jl(e){let t=Kt.extname(e).toLowerCase();return[".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(t)?"javascript":[".json",".jsonc"].includes(t)?"json":[".md",".mdx"].includes(t)?"markdown":[".css",".scss"].includes(t)?"css":"plain"}function Bs(e,t){return t==="diff"?sg(e):t==="markdown"?ig(e):t==="json"?Vs(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Vs(e,/("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)|\/\/.*$|\/\*.*?\*\/|\b(const|let|var|function|return|if|else|for|while|class|interface|type|import|export|from|async|await|new|extends|implements|switch|case|break|continue|try|catch|throw|true|false|null|undefined)\b|-?\b\d+(?:\.\d+)?\b/g):[{text:e}]}function sg(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:q.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:q.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:q.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:q.diffMeta}}]:[{text:e}]}function og(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function ig(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:q.markup,bold:!0}}]:Vs(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Vs(e,t){let r=[],n=0;for(let s of e.matchAll(t)){let o=s[0],i=s.index??0;i>n&&r.push({text:e.slice(n,i)}),r.push({text:o,style:ag(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function ag(e){return e.startsWith("//")||e.startsWith("/*")?{fg:q.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:q.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:q.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:q.markup}:{fg:q.keyword}}function lg(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?_l(t.repoTargets??[]):s?.pullRequest??(t?$(t):null),i=[cg(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=Bl(e,t),l=Ks(e,r),c=fg([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...bg(e,r)]}:{title:"",rows:[...i,...Ks(e,r)]}}function cg(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=Gs(t),i=Hs(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Nl(e){return[{text:" "},Gs(e),{text:" "},Hs(e)]}function Wl(e){if(e.type==="project"&&e.repoTargets?.length){let r=_l(e.repoTargets);return r?Nl(r):null}let t=$(e);return t?.number?Nl(t):null}function _l(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=ug(r);return{number:-1,status:dg(r),draft:r.some(s=>s.draft),mergeable:r.length===t.length&&r.every(s=>s.mergeable),mergeStateStatus:null,reviewDecision:r.some(s=>s.reviewDecision==="CHANGES_REQUESTED")?"CHANGES_REQUESTED":r.some(s=>s.reviewDecision==="REVIEW_REQUIRED")?"REVIEW_REQUIRED":r.every(s=>s.reviewDecision==="APPROVED")?"APPROVED":null,requiredChecks:r.flatMap(s=>s.requiredChecks),aggregateReadiness:n}}function dg(e){return e.some(t=>t.status==="open")?"open":e.every(t=>t.status==="merged")?"merged":e.some(t=>t.status==="closed")?"closed":e[0]?.status??null}function ug(e){let t=e.map(r=>Ul(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function Gs(e){return!e||!e.number?{text:El,style:{fg:"565f89"}}:e.status==="merged"?{text:Al,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:xl,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Ls,style:{fg:"565f89"}}:{text:Ls,style:{fg:"9ece6a"}}}function Hs(e){return e?.aggregateReadiness?Ll(e.aggregateReadiness):Ll(Ul(e))}function Ll(e){return e==="failed"?{text:_s,style:{fg:"f7768e"}}:e==="pending"?{text:js,style:{fg:"e0af68"}}:e==="success"?{text:Ws,style:{fg:"9ece6a"}}:{text:Fs,style:{fg:"565f89"}}}function Ul(e){let t=e?.requiredChecks??null;return e?.status==="merged"?"success":e?.status==="closed"||!e?.number||!t||t.length===0?"none":t.some(r=>r.status==="failed")||e.reviewDecision==="CHANGES_REQUESTED"?"failed":t.every(r=>r.status==="success"||r.status==="skipped")?ql(e)?"failed":pg(e)?"success":"pending":"pending"}function pg(e){return!!(e.mergeable&&!e.draft&&!ql(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function ql(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function Bl(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return mg(e,t);let r=$(t),n=Kl("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var Lr=32;function mg(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,m=Lr-u.length-1,T=c.length>m?c.slice(0,m-1)+"\u2026":c,R=Lr-T.length-u.length;r.push({id:`project-review:${i.repoId}`,text:T+" ".repeat(Math.max(1,R))+u,selected:a,focused:l,muted:!0})}else{let d=Gs(i.pullRequest),u=Hs(i.pullRequest),m=`${d.text} ${u.text}`,T=Lr-m.length-1,R=c.length>T?c.slice(0,T-1)+"\u2026":c,h=Lr-R.length-m.length,y=R+" ".repeat(Math.max(1,h));r.push({id:`project-review:${i.repoId}`,text:y+m,selected:a,focused:l,segments:[{text:y},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...Kl("target",o.branch,o.pullRequest))),r}function Vl(e,t,r=null){return 3+Bl(e,t).length+Ks(e,r).length}function Kl(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=gg(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:hg(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Gl(r.lastSyncedAt)}`,muted:!0}),s.push({id:n("checks-spacer"),text:""}),s.push({id:n("checks-header"),text:"Checks"}),r.requiredChecks.length?s.push(...r.requiredChecks.map(kg)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,m)=>wg(u,n(`comment:${m}`))))),s}function fg(e,t){if(t.focusedRegion!=="inspector"||t.inspectionMode!=="review"||e.length===0)return e;let r=Math.max(0,Math.min(t.reviewScrollOffset,e.length-1));return e.map((n,s)=>({...n,selected:t.reviewScrollOffset===0&&n.selected||s===r,focused:t.reviewScrollOffset===0&&n.focused||s===r}))}function gg(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function hg(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Gl(e){if(!e)return"--";let t=Date.now()-new Date(e).getTime(),r=Math.floor(t/1e3);if(r<60)return`${r}s ago`;let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let s=Math.floor(n/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function kg(e){let{icon:t,color:r}=Rg(e.status),n=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${n.padEnd(16," ")} ${yg(e.status)}`,color:r,muted:!1}}function wg(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Gl(e.createdAt)}`:"",s=Tg(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function Tg(e,t){let r=e.split(/\s+/).filter(Boolean);if(r.length===0)return[];let n=[],s="";for(let o of r){if(!s){s=o;continue}`${s} ${o}`.length<=t?s=`${s} ${o}`:(n.push(s),s=o)}return s&&n.push(s),n}function Rg(e){switch(e){case"success":return{icon:Ws,color:"9ece6a"};case"pending":return{icon:js,color:"e0af68"};case"failed":return{icon:_s,color:"f7768e"};case"skipped":return{icon:Fs,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function yg(e){return e==="success"?"passing":e==="failed"?"failing":e}function bg(e,t){if(!t)return[{id:"empty",text:"No file index. Select a task with local changes.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.fileRows.length===0)return[{id:"empty",text:"No Git-visible files.",muted:!0}];let r=new Map(t.diffRows.map(l=>[l.path,l.status])),n=zs(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?Cl:vl:Il(l.label),m=l.kind==="directory"?"7aa2f7":Dl(l.label),T=" ".repeat(l.depth),R=m?{text:u,style:{fg:m}}:{text:u},h=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},y=[{text:T},R,h];return{id:l.path,text:`${T}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:y}})]}function zs(e,t){let r=new Set(t);return e.filter(n=>{let s=n.path.split("/");for(let o=1;o<s.length;o+=1)if(r.has(s.slice(0,o).join("/")))return!1;return!0})}function Ks(e,t){if(!t)return[{id:"empty",text:"No task diff index.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.diffRows.length===0)return[{id:"empty",text:t.filePaths.some(s=>s.startsWith("repo_"))?"No changes in project task worktrees. Edits in the original repos are outside this task.":"No local changes.",muted:!0}];if(Pg(t))return Sg(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>Hl(o,e,t))))}return r}function Pg(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Sg(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>Hl(c,e,t,s.length+1))))}}return r}function Hl(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Ig(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:f.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Kt.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function Cg(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function vg(e,t){return{name:f.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function zl(e,t,r,n,s=null){if(s)return Eg(e,t,r,n,s);let o=ks(e,t,{centerOnly:n});return Ag(r,o)?{output:Dr(o.rows,r.rows,o.row,o.column),region:o}:null}function Eg(e,t,r,n,s){let o=Oa(e,t,s,{centerOnly:n});if(!o||!xg(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:c})=>i[l]===c?"":(i[l]=c,`\x1B[${o.row+l};${o.column}H${c}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function Ag(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function xg(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}function Yl(e,t,r){let n={...e},s="";for(let o of r){let i=e[o],a=t[o];if(!Dg(i,a))return null;!i||!a||(s+=Dr(a.rows,i.rows,a.row,a.column),n[o]=a)}return{output:s,regions:n}}function Dg(e,t){return!e||!t?e===t:e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}var $g=["tasks","center","inspector"];function Og(e,t,r){if(t==="ESCAPE")return w({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return w({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return Qs(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Xs({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return w({state:{...e,fileSearchQuery:n},changed:!0})}return w({state:e})}function Xs(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Ta(t)?w({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):w({state:e});if(e.fileSearchQuery!==null)return Og(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return w({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return w({state:e,exit:!0});if(t==="ESCAPE")return w({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return w({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(Tr(e.selectedLeftItemId)||Rr(e.selectedLeftItemId)))return w({state:{...e,selectedRunner:wr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Ql(e,1);if(t==="SHIFT_TAB"||t==="[")return Ql(e,-1);if(t==="z"||t==="Z")return w({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===A?Me(e,-1,r):Qs(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===A?Me(e,1,r):Qs(e,1,r);if(t==="PAGE_UP")return Me(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Me(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Me(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Me(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??O,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return w({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=Ug(e,t);return w({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return w({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&_t(e.selectedLeftItemId)&&e.selectedTaskId)return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Sa(e.selectedLeftItemId)&&e.selectedWorkspaceId)return w({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Zl(e.activeTab,r.ptyTabIds??[]))return w({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Ys(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Jl(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Ys(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Jl(e,1)}if(pe(t)){if(e.focusedRegion==="tasks"&&(Tr(e.selectedLeftItemId)||Rr(e.selectedLeftItemId))){let n=ds(e.selectedLeftItemId),s=us(e.selectedLeftItemId);return w({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return w({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&_t(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return w({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:mt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Zl(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return w({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:mt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===A)return w({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return w({state:Lg({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return w({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:A,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?w({state:{...e,selectedDiffPath:n,activeTab:A,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?w({state:e}):e.selectedActionId==="refresh-checks"?w({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return w({state:e})}function Me(e,t,r){if(t===0)return w({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?ec(e,t,r):e.inspectionMode==="review"?Xl(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):w({state:e});if(e.focusedRegion==="center"&&e.activeTab===A){if(e.openInspectionKind==="file")return Xl(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return Fg(e,t,r)}return w({state:e})}function Ql(e,t){return jr(e,"focusedRegion",$g,t)}function Ys(e,t,r){let n=jr(e,"activeTab",r&&r.length>0?r:qg(e),t);return!n.changed||ya(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Qs(e,t,r){if(e.focusedRegion==="tasks")return Mg(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Ys(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return ec(e,t,r);if(r.projectTargetIds?.length){let s=Js(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=Js(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:A,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:jr(e,"selectedActionId",fa,t)}return jr(e,"selectedActionId",is,t)}function Mg(e,t,r){let n=Js(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=cs(n.state.selectedLeftItemId);if(s?.kind==="workspace")return{...n,state:{...n.state,selectedWorkspaceId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="task")return{...n,state:{...n.state,selectedTaskId:s.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="repo")return{...n,state:{...n.state,selectedRepoId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};let o=ds(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=us(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Ng(e,t){if(e.inspectionMode===t)return w({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?A:e.activeTab;return w({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Jl(e,t){return Ng(e,_g(e.inspectionMode,as,t))}function ec(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return w({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=Se(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return w({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return w({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?A:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Lg(e){if(!e.selectedFileTreePath)return e;let t=new Set(e.collapsedFileTreePaths);return t.has(e.selectedFileTreePath)?t.delete(e.selectedFileTreePath):t.add(e.selectedFileTreePath),{...e,collapsedFileTreePaths:[...t].sort((r,n)=>r.localeCompare(n)),actionMessage:null}}function Xl(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=Se(e[t]+r,0,o);return i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Fg(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return jg(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=Se(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=Se(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:A,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?w({state:e}):w({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:A,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?w({state:e}):w({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=Se(i,0,o);return c===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function jg(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=Se(e.diffScrollOffset+t,0,o),a=Wg(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?w({state:e}):w({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function Wg(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function jr(e,t,r,n){let s=r.indexOf(e[t]),o=Se(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Js(e,t,r,n,s=!1){if(r.length===0)return w({state:e});let o=r.indexOf(e[t]??r[0]??""),i=Se(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?w({state:e}):w({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function _g(e,t,r){let n=t.indexOf(e);return t[Se(n+r,0,t.length-1)]??e}function w(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function Zl(e,t){return t.includes(e)}function Ug(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function qg(e){return[e.selectedPtyTabId,e.openInspectionKind?A:null].filter(t=>typeof t=="string")}function Se(e,t,r){return Math.min(r,Math.max(t,e))}var tc=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await ae(n.paths,e.selectedTaskId),i=t??Bg(o,e.activeTab,e.preferredPtyTabKind),a=oc(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await P(n.paths,l),l});return{updatedTask:s,nextShell:{activeTab:s.selectedPtyTabId??e.activeTab,selectedPtyTabId:s.selectedPtyTabId,preferredPtyTabKind:s.ptyTabs.at(-1)?.kind??e.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${s.ptyTabs.at(-1)?.title??"tab"}`}}},rc=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await ae(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await P(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},nc=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await ae(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await P(t.paths,{...n,selectedPtyTabId:e.activeTab})})},sc=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await ae(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await P(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=oc(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await ae(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await P(t.paths,{...s,selectedPtyTabId:o.id});return}await P(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Bg(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function oc(e,t,r,n={}){let s=r??e.runner,o=f.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(T=>T.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),m=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...m?{runner:m}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?f.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var ht=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},ic=async(e,t,r,n,s)=>{f.runners.assertEnabled(n,s.config);let o=t?await s.taskService.provisionProjectTask(s.paths,t,r,{runner:n,config:s.config}):await s.taskService.provisionTask(s.paths,e??"",r,{runner:n,config:s.config});try{let l=Be();Ve(f.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new ht(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},ac=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},lc=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await ae(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},cc=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Wr=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await tt.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var dc=async(e,t)=>{if(!e.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await t.taskService.listTasks(t.paths,{workspaceId:e.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${e.selectedWorkspaceId} while task records still reference it.`);return await t.workspaceService.archiveWorkspace(t.paths,e.selectedWorkspaceId),{nextShell:{selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${(await t.workspaceService.removeWorkspace(t.paths,e.selectedWorkspaceId,{listTasks:t.taskService.listTasks})).workspaceId}`}}};var uc=async(e,t,r)=>{let n=f.runners.setRunnerEnabled(r.config,e,t);return await f.save(r.paths,n),n},pc=async(e,t,r)=>{let n=f.runners.setRunnerPath(r.config,e,t);return await f.save(r.paths,n),n},mc=async(e,t,r)=>{let n=f.previews.setEnabled(r.config,e,t);return await f.save(r.paths,n),n};var Vg=250;function Ie(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function Qe(e,t){return Pe(t,e.ptyRuntime.getViewState(kt(e,t)))}function kt(e,t){let r=Ie(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function g(e,t){return Qe(e,Ia(t,e.model))}function fc(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:g(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function gc(e,t,r){return fc(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return fc(e,t,{tone:"error",message:r})}function W(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return tt.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function L(e,t){if(!e.uiStateFile)return;e.runtimeState=ka(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Ce({uiStateFile:e.uiStateFile},r),()=>Ce({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Kg(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function _(e){return{paths:e.paths,config:e.config,taskService:E,workspaceService:H,queueTaskMutation:t=>Kg(e,t)}}function Zs(e,t){let r=Ie(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?zs(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:He(e.model),centerTabIds:Pa(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:Vl(t,r,s),pageRows:Math.max(5,le(e.activeTerminal.width,e.activeTerminal.height).height-N.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function hc(e,t){await nc(t,_(e))}async function Q(e){e.model=await De(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:g(e,e.state.shell)}:e.state={...e.state,shell:g(e,e.state.shell)}}function kc(e,t){e.model={...e.model,tasks:[...e.model.tasks.filter(r=>r.id!==t.id),t].sort((r,n)=>r.id.localeCompare(n.id))}}async function _r(e,t){let r=++e.inspectionRefreshSequence,n=ps(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await ra(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await De(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},L(e,e.state.shell),e.render())}function wc(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&_r(e,r).catch(n=>{let s=W(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Vg))}function Tc(e,t){t!==0&&(e.pendingInspectionScrollLines+=t,!e.inspectionScrollRenderTimer&&(e.inspectionScrollRenderTimer=setTimeout(()=>{e.inspectionScrollRenderTimer=null;let r=e.pendingInspectionScrollLines;if(e.pendingInspectionScrollLines=0,r===0||e.state.mode!=="main"||e.state.shell.inputMode!=="control")return;let n=Me(e.state.shell,r,Zs(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),e.render(),_r(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),e.render()}},16)))}function eo(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function to(e){let t=e.model.tasks.flatMap(r=>r.ptyTabs.map(n=>n.id));await e.ptyRuntime.pruneStale?.(t),await e.ptyRuntime.hydrateSessions?.(t)}function yc(e){to(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function bc(e,t){let r=g(e,t),n=Ie(e.model.tasks,r),s=kt(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return Pe(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,$e(le(e.activeTerminal.width,e.activeTerminal.height)));return Pe({...r,inputMode:"control"},i)}function ro(e){let t=e.state.mode==="main"&&e.state.shell.inputMode==="terminal"?"terminal":"control";t!==e.inputCaptureMode&&(e.inputCaptureMode=t,e.activeTerminal.grabInput(t==="terminal"?{mouse:"button"}:!0))}async function no(e,t){try{let r=g(e,t),n=Ie(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await Rc(e,n),await Q(e),s=n.selectedPtyTabId)}n&&!s&&(n=await Rc(e,n),await Q(e),s=n.selectedPtyTabId);let o=g(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:Pe({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},L(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,$e(le(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Oe(s),e.lastTerminalKey=null,e.state={mode:"main",shell:Pe({...o,inputMode:"terminal"},i)},L(e,e.state.shell)}catch(r){let n=W(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Oe(t.selectedPtyTabId)&&(await Gg(e,t.selectedTaskId,n).catch(()=>{}),await Q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,wa(g(e,t),n),n)},L(e,e.state.shell)}e.render()}async function Gg(e,t,r){await ac(t,r,_(e))}async function Pc(e,t,r,n){let s=g(e,t),{nextShell:o}=await tc(s,r,n,_(e));return await Q(e),g(e,{...s,...o})}async function Sc(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await rc(r,_(e));return e.ptyRuntime.disposeSession(n.id),await Q(e),g(e,{...r,...s})}async function Ic(e,t){let r=g(e,t),n=He(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await lc(r,_(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await Q(e),g(e,{...r,...i,selectedLeftItemId:Hg(n,He(e.model),s)})}async function Cc(e,t){let r=g(e,t),{nextShell:n}=await dc(r,_(e));return await Q(e),g(e,{...r,...n})}async function Rc(e,t){return sc(t,_(e))}function Ur(e,t){e.pendingScrollLines+=t,!e.scrollRenderTimer&&(e.scrollRenderTimer=setTimeout(()=>{e.scrollRenderTimer=null;let r=e.pendingScrollLines;e.pendingScrollLines=0,r!==0&&(e.ptyRuntime.scrollViewport(r),e.state={mode:"main",shell:Qe(e,e.state.shell)},e.render())},16))}function Hg(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Ec(e,t,r){if(r?.aborted||e.state.mode!=="main")return;let n=vc(e),s=t.takeDueTasks(e.model.tasks,n);if(s.length!==0)try{if(await cc(s,_(e)),r?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;let o=await De(e.workspaceRoot,e.state.shell,e.enabledRunnerIds);if(r?.aborted)return;t.recordSuccess(s.map(i=>o.tasks.find(a=>a.id===i.id)??i),vc(e)),e.model=o,e.state={mode:"main",shell:g(e,e.state.shell)},e.render()}catch(o){if(r?.aborted)return;t.recordFailure(s,o);let i=o instanceof Error?o.message:"Background PR discovery failed.";i!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=i,Wr("background PR polling",o,_(e)))}}function vc(e){return e.state.mode!=="main"?{selectedTaskId:null,reviewVisible:!1}:{selectedTaskId:e.state.shell.selectedTaskId,reviewVisible:e.state.shell.inspectionMode==="review"}}async function Ac(e,t){let r=g(e,t),n=Ie(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await E.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await Q(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await E.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await Q(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${$(a)?.requiredChecks.length??0} reported`)}return g(e,{...gc(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}var zg={pendingForegroundMs:5e3,pendingBackgroundMs:15e3,stableForegroundMs:3e4,stableBackgroundMs:6e4,discoveryForegroundMs:6e4,discoveryBackgroundMs:18e4,rateLimitBaseMs:6e4,rateLimitMaxMs:15*6e4},qr=class{scheduledTasks=new Map;now;intervals;minimumIntervalMs;rateLimitFailures=0;notBefore=0;constructor(t={}){this.minimumIntervalMs=Math.max(1e3,t.minimumIntervalMs??5e3),this.intervals={...zg,...t.intervals},this.now=t.now??Date.now}takeDueTasks(t,r){let n=this.now(),s=new Set(t.map(i=>i.id));for(let i of this.scheduledTasks.keys())s.has(i)||this.scheduledTasks.delete(i);let o=[];for(let i of t){let a=this.getTaskIntervalMs(i,r);if(a===null){this.scheduledTasks.delete(i.id);continue}let l=this.scheduledTasks.get(i.id);if(!l){this.scheduledTasks.set(i.id,{intervalMs:a,nextPollAt:n}),n>=this.notBefore&&o.push(i);continue}a<l.intervalMs&&(l.nextPollAt=Math.min(l.nextPollAt,n+a)),l.intervalMs=a,n>=this.notBefore&&n>=l.nextPollAt&&o.push(i)}return o}recordSuccess(t,r){let n=this.now();this.rateLimitFailures=0,this.notBefore=0;for(let s of t){let o=this.getTaskIntervalMs(s,r);o===null?this.scheduledTasks.delete(s.id):this.scheduledTasks.set(s.id,{intervalMs:o,nextPollAt:n+o})}}recordFailure(t,r){let n=this.now(),s=r instanceof he,o=s?Math.min(this.intervals.rateLimitBaseMs*2**this.rateLimitFailures,this.intervals.rateLimitMaxMs):Math.max(this.minimumIntervalMs,this.intervals.pendingBackgroundMs);s&&(this.rateLimitFailures+=1,this.notBefore=n+o);for(let i of t){let a=this.scheduledTasks.get(i.id);a&&(a.nextPollAt=n+o)}}getTaskIntervalMs(t,r){let n=Yg(t),s=t.id===r.selectedTaskId&&r.reviewVisible;if(n.length>0){let o=n.some(Qg);return this.withMinimum(o?s?this.intervals.pendingForegroundMs:this.intervals.pendingBackgroundMs:s?this.intervals.stableForegroundMs:this.intervals.stableBackgroundMs)}return t.status==="checked"?this.withMinimum(s?this.intervals.discoveryForegroundMs:this.intervals.discoveryBackgroundMs):null}withMinimum(t){return Math.max(t,this.minimumIntervalMs)}};function Yg(e){return e.type==="project"&&e.repoTargets?.length?e.repoTargets.map(t=>t.pullRequest).filter(t=>t.status==="open"):e.prs.filter(t=>t.status==="open")}function Qg(e){return e.requiredChecks.some(t=>t.status==="pending"||t.status==="unknown")}import th from"node:path";import{readdir as Jg,stat as Xg}from"node:fs/promises";import xc from"node:path";async function Zg(e){let t=await Jg(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=xc.join(e,n.name);r.push({name:n.name,path:s,kind:await eh(s)?"repo":"directory"})}return r.sort((n,s)=>n.kind!==s.kind?n.kind==="repo"?-1:1:n.name.localeCompare(s.name)),{cwd:e,entries:r,selectedIndex:0,query:null,error:null}}function Dc(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function $c(e){let{spawn:t}=await import("node:child_process"),r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await new Promise((n,s)=>{let o=t(r,[e],{stdio:"ignore",detached:!0});o.unref(),o.on("error",s),o.on("spawn",n)})}async function Br(e,t){let r=await Zg(t);e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function eh(e){let t=xc.join(e,".git");return await Xg(t).catch(()=>null)!==null}function Oc(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Mc(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function rh(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:g(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await ic(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,_(e));n=s.task,kc(e,n);let o=g(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??Ba(n,"agent"),$e(le(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Oe(o.selectedPtyTabId),e.state={mode:"main",shell:Pe(o,i)},L(e,e.state.shell)}catch(s){s instanceof ht&&(n=s.task);let o=W(e,"create task",s,"Failed to create task.");n&&!(s instanceof ht)?(await P(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await Q(e).catch(()=>{})):n&&(await P(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await Q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function nh(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(pe(t)){rh(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:g(e,{...r,selectedRunner:wr(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}Ra(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function sh(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Dc(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){Br(e,th.dirname(r.cwd)).catch(s=>{let o=W(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||pe(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){Br(e,s.path).catch(i=>{let a=W(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=_(e);o.addWorkspace(e.paths,s.path).then(async i=>{await Q(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},L(e,e.state.shell),e.render()}).catch(i=>{let a=W(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function oh(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=bl(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;ih(e,n)}}}async function ih(e,t){let r;try{r=await tt.readRecentErrorLines(e.paths)}catch(n){let s=W(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function ah(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Sl(Oc(e),e.config,t,e.enabledRunnerIds);if(r.kind==="noop")return;if(r.kind==="back"){let s=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...s!==void 0?{parentVariant:s}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,runnerOptions:r.state},e.render();return}(r.kind==="save-enabled"?uc(r.runner,r.enabled,_(e)):pc(r.runner,r.path,_(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=f.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:g(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:f.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=W(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,g(e,e.state.shell),o),runnerOptions:{...Oc(e),message:o}},e.render()})}function lh(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=Pl(Mc(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}mc(r.feature,r.enabled,_(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,r.feature==="incrementalCenterPane"&&e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),r.feature==="agentActivityIndicators"&&e.setAgentActivityEnabled(r.enabled),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=W(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:j(e,g(e,e.state.shell),s),previewOptions:{...Mc(e),message:s}},e.render()})}}function Nc(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){nh(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){sh(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){dh(e),e.render();return}e.focusFlashUntil!==null&&(e.focusFlashUntil=null,e.focusFlashTimer&&(clearTimeout(e.focusFlashTimer),e.focusFlashTimer=null))}if(e.state.mode==="main"){let n=Xs(e.state.shell,r,Zs(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&pe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=Bt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(ch(e,r))return;e.lastTerminalKey=Va(r)?{key:r,at:Date.now()}:null;let o=Ka(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){Ur(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){Br(e,e.workspaceRoot).catch(s=>{let o=W(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Pc(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{no(e,s)}).catch(s=>{let o=W(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Sc(e,n.state).then(s=>{e.state={mode:"main",shell:s},L(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ac(e,n.state).then(s=>{e.state={mode:"main",shell:s},L(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=Ie(e.model.tasks,n.state),o=s?$(s)?.url??null:null;o?$c(o).catch(i=>{let a=W(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){Ic(e,n.state).then(s=>{e.state={mode:"main",shell:s},L(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Cc(e,n.state).then(s=>{e.state={mode:"main",shell:s},L(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){no(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},L(e,e.state.shell),(e.state.shell.focusedRegion!=="tasks"||!e.renderTaskNavigation())&&e.render(),e.state.shell.focusedRegion==="tasks"){wc(e,e.state.shell);return}_r(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},hc(e,e.state.shell).catch(()=>{}),L(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){oh(e,r);return}if(e.state.variant==="runners"){ah(e,r);return}if(e.state.variant==="previews"){lh(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||pe(r)){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render()}return}if(e.state.optionsMessage){(r==="ESCAPE"||pe(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(pe(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;bc(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},L(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=W(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,g(e,e.state.shell),i)},L(e,e.state.shell),e.render()})}):yc(e);return}if(e.state.menuIndex===1){let n=e.state.variant==="boot"||e.state.variant==="pause"?e.state.variant:void 0;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}e.exit(0)}}function Lc(e,t){let r=Qa(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=Bt(o);if(i){jc(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(Ss(o)){e.pendingTerminalKeySequence.raw=o,Fc(e);return}Vr(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},L(e,e.state.shell),e.render();return}let n=Ga(r);if(n!==0){Ur(e,n);return}let s=Bt(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
119
|
+
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function Bl(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await Qr(e))return;await fo(50)}}function Zl(e){return new Promise((t,r)=>{let n=Vl(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Wg(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function tt(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
120
|
+
`)}catch{}}function ec(e){try{return process.kill(e,0),!0}catch{return!1}}function fo(e){return new Promise(t=>setTimeout(t,e))}function qg(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var go=["Runners","Feature Previews","Error Log","Help"],rc={incrementalCenterPane:"Incremental center pane",agentActivityIndicators:"Agent activity indicators"};function ho(e,t){return O.map(r=>{let n=f.runners.getProfile(r),s=e.runners?.[r]?.enabled!==!1,o=e.runners?.[r]?.path?.trim(),i=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:o&&o.length>0?o:`default (${n.executable})`;return`${n.displayName} ${s?"enabled":"disabled"} ${i}`})}function nc(e){return e.message?e.message:e.pathEdit?"Type an executable path. Enter saves. Empty resets to default. Esc cancels.":"Enter toggles. E edits the executable path."}function sc(e){return de.map(t=>`${f.previews.isEnabled(e,t)?"[x]":"[ ]"} ${rc[t]}`)}function oc(e){return e.message??"Experimental features may change or be removed. Enter toggles."}function ic(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(go.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Xr(t)?e===0?{kind:"runners"}:e===1?{kind:"previews"}:e===2?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function ac(e,t,r){if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(de.length-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(!Xr(r))return{kind:"noop",state:e};let n=de[e.menuIndex]??de[0],s=!f.previews.isEnabled(t,n);return{kind:"save-enabled",feature:n,enabled:s,state:{...e,message:`${rc[n]} ${s?"enabled":"disabled"}.`}}}function lc(e,t,r,n){if(e.pathEdit)return Ug({...e,pathEdit:e.pathEdit},t,r);let s=ho(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(s-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let a=O[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Xr(r))return{kind:"noop",state:e};let o=O[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${f.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Ug(e,t,r){if(r==="ESCAPE")return{kind:"render",state:tc({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Xr(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:tc({...e,message:s.length>0?`${f.runners.getProfile(n).displayName} executable saved.`:`${f.runners.getProfile(n).displayName} executable reset to default.`})}}return Bg(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function tc(e){let t={...e};return delete t.pathEdit,t}function Xr(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
121
|
+
`}function Bg(e){return e.length===1&&e>=" "&&e!==""}import rr from"node:path";function cc(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"\u{F06E6} ";case"js":case"jsx":case"mjs":case"cjs":return"\u{F031E} ";case"json":case"jsonc":return"\u{F0871} ";case"md":case"mdx":return"\u{F0354} ";case"yaml":case"yml":return"\u{F0B10} ";case"sh":case"bash":case"zsh":return"\u{F018D} ";case"css":case"scss":case"sass":return"\u{F031C} ";case"html":case"htm":return"\u{F031D} ";case"py":return"\u{F0320} ";case"go":return"\u{F07D3} ";case"rs":return"\u{F1617} ";case"lock":return"\u{F033E} ";case"png":case"jpg":case"jpeg":case"gif":case"svg":case"webp":return"\u{F02E9} ";default:return"\u{F0214} "}}var dc="\u{F024B} ",uc="\u{F0DCF} ",pc="\u25CB",wo="\uEA64",mc="\uEAFE",fc="\uEBDA",ko="\u25CB",To="\u25CF",yo="\u2713",Ro="\u2715";function gc(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"4fc1ff";case"js":case"jsx":case"mjs":case"cjs":return"f7df1e";case"json":case"jsonc":return"fbc02d";case"md":case"mdx":return"519aba";case"yaml":case"yml":return"e06c75";case"sh":case"bash":case"zsh":return"89e051";case"css":case"scss":case"sass":return"c792ea";case"html":case"htm":return"e06c75";case"py":return"3572a5";case"go":return"00add8";case"rs":return"dea584";case"lock":return"565f89";default:return}}var hc={idle:0,working:1,ready:2,error:3};function tr(e,t,r,n="idle"){let s=t.find(o=>o.tabId===e);return s?s.sessionState==="failed"||s.sessionState==="exited"&&s.exitCode!==0?"error":s.sessionState==="exited"?"ready":r-s.lastActivityAt<5e3?"working":"ready":n}function bo(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return tr(t,r,n,o)}function Po(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=bo(e,s.id,t,r);hc[o]>hc[n]&&(n=o)}return n}function wc(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&tr(s.id,t,r)==="working"))}var en="empty",B={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Rc(e,t,r){let n=Gg(t,e),s=t.repos.find(b=>b.id===e.selectedRepoId)??t.repos[0]??null,o=n?t.tasks.filter(b=>b.workspaceId===n.id):t.tasks,i=n?.kind==="project"?o:s?o.filter(b=>b.repoId===s.id):[],a=i.find(b=>b.id===e.selectedTaskId)??i[0]??null,l=a?.type==="project",c=Ch(t.tasks),d=Yg(e,a),u=zg(e,a,d,r),m=u.find(b=>b.id===d)??u[0]??{id:"agent",label:"CODEX"},g=t.inspection?.taskId===a?.id?t.inspection:null,y=s?.name??"no repo",w=a?f.runners.getDisplayName(a.runner):f.runners.getDisplayName(e.selectedRunner);return{inputMode:e.inputMode,modalInput:e.taskPromptInput!==null||e.workspaceBrowser!==null,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,footerToast:e.footerToast,terminal:e.terminal,footerText:e.workspaceBrowser!==null?e.workspaceBrowser.query!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} Search: ${e.workspaceBrowser.query} \u2191\u2193 move Enter select Esc clear search`:`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up / search Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${s?`[${s.name}]`:"[no repo]"} \xB7 ${f.runners.getDisplayName(e.selectedRunner)} Ctrl+R switch runner Enter create Esc cancel \u203A ${e.taskPromptInput}${e.taskPromptError?` \u2717 ${e.taskPromptError}`:""}`:e.inputMode==="terminal"?"TERMINAL \u2191\u2193/PgUp/PgDn scroll Ctrl+] return to control":e.focusedRegion==="tasks"?e.selectedLeftItemId?.startsWith("new-task:")||e.selectedLeftItemId?.startsWith("new-task-workspace:")?`r runner [${f.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Qt(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":e.selectedLeftItemId?.startsWith("workspace:")?"n new task Enter select X remove workspace Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?a===null?"n new task Tab tasks Esc pause ? help":d===x?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${f.runners.getDisplayName(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?l?"\u2191\u2193 targets Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:rr.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${rr.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Vg(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(b=>vh(b,c[b])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":m.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:w},centerTranscript:Hg(d,e,s,a,e.workspaceBrowser,g,n),tabs:u,rightContext:Ih(s,a),rightInspection:lh(e,a,g)}}function Vg(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Kg(n,e,t.repos,t.tasks,r);let s=t.workspaces;if(s.length===0)n.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let i of s){let a=e.selectedLeftItemId===`workspace:${i.id}`;n.push({id:`workspace:${i.id}`,text:`${i.kind==="project"?"\u2261":"\u2013"} ${i.name??i.id}`,selected:a,focused:a&&e.focusedRegion==="tasks"});let l=i.kind==="project"?i.discoveredRepoIds??[]:[i.primaryRepoId],c=t.tasks.filter(d=>d.workspaceId===i.id);if(c.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of c){let u=e.selectedLeftItemId===`task:${d.id}`,m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,g={id:`task:${d.id}`,taskId:d.id,text:r?m:`${u?"\u25B8":"\u2022"} ${m}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:Po(d,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},y=Pc(d);y&&(g.prBadge=y),n.push(g)}if(i.kind==="project"){let d=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Project Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(i.kind==="repo"){let d=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}else{n.push({text:` Repos (${l.length})`,indent:0,muted:!0});for(let d of l.slice(0,6)){let u=t.repos.find(m=>m.id===d);n.push({text:` \xB7 ${u?.name??d}`,indent:0,muted:!0})}l.length>6&&n.push({text:` \xB7 ${l.length-6} more`,indent:0,muted:!0})}}let o=e.selectedLeftItemId==="new-workspace";return n.push({text:"",muted:!0}),n.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&e.focusedRegion==="tasks"}),n}function Kg(e,t,r,n,s){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let i of r){let a=t.selectedLeftItemId===`repo:${i.id}`;e.push({id:`repo:${i.id}`,text:`\u2013 ${i.name}`,selected:a,focused:a&&t.focusedRegion==="tasks"});let l=n.filter(u=>u.repoId===i.id);if(l.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let u of l){let m=t.selectedLeftItemId===`task:${u.id}`,g=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,y={id:`task:${u.id}`,taskId:u.id,text:s?g:`${m?"\u25B8":"\u2022"} ${g}`,indent:2,selected:m,focused:m&&t.focusedRegion==="tasks",...s?{activity:Po(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},w=Pc(u);w&&(y.prBadge=w),e.push(y)}let c=`new-task:${i.id}`,d=t.selectedLeftItemId===c;e.push({id:c,text:`+ New Task [${f.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:d,focused:d&&t.focusedRegion==="tasks",muted:!d})}let o=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&t.focusedRegion==="tasks"}),e}function Gg(e,t){let r=e.workspaces??[];if(!e.workspaces)return null;let n=e.tasks.find(s=>s.id===t.selectedTaskId)??null;return n?r.find(s=>s.id===n.workspaceId)??null:t.selectedWorkspaceId?r.find(s=>s.id===t.selectedWorkspaceId)??null:r[0]??null}function Hg(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,m)=>{let g=m===s.selectedIndex?"\u25B8":" ",y=u.kind==="repo"?" [git repo]":"/";return`${g} ${u.name}${y}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return me(["Browse for a workspace to register.",s.cwd,...d?[d]:[],"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return me(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return me([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${f.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?me([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this PTY-backed agent session.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):me([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this plain task shell.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):e===x&&t.openInspectionKind==="file"?Xg(n,o,t.fileScrollOffset):e===x&&t.openInspectionKind==="diff"?Zg(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?me(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):me(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function zg(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Jg(i),...i.kind==="agent"&&n&&t?{activity:bo(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:en,label:"EMPTY",active:r===en,focused:e.focusedRegion==="center"&&r===en}];let o=e.openInspectionKind||r===x?[{id:x,label:Qg(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Yg(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===x&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??x:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??x:en}function Jg(e){return e.title.toUpperCase()}function Qg(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?rr.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Xg(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return me(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=bc(n.path??n.title);return[{text:n.title},{text:`${n.byteLength===null?"size unknown":`${n.byteLength} bytes`} \xB7 ${n.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...eh(n.lines,r,s)]}function Zg(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return me(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=bc(n.path??n.title);return[{text:n.title},{text:`${t.diffPaths.length} changed files \xB7 ${n.lines.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...th(n.lines,r,s)]}function me(e){return e.map(t=>({text:t}))}function eh(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:B.lineNumber}},{text:" \u2502 ",style:{fg:B.gutter}},...So(o,r)],tone:"default"}})}function th(e,t,r){let n=rh(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>nh(o,r))}function rh(e){let t=[],r=0,n=0;for(let s of e){let o=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(s);if(o){r=Number.parseInt(o[1]??"0",10),n=Number.parseInt(o[2]??"0",10);continue}if(!(s.startsWith("diff --git")||s.startsWith("index ")||s.startsWith("+++ ")||s.startsWith("--- "))&&!(s==="staged"||s==="unstaged"||s==="untracked")){if(s.startsWith("-")&&!s.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:s.slice(1),kind:"delete"}),r+=1;continue}if(s.startsWith("+")&&!s.startsWith("+++")){t.push({oldNumber:null,newNumber:n,marker:"+",text:s.slice(1),kind:"add"}),n+=1;continue}if(s.startsWith(" ")){if(r===0&&n===0)continue;t.push({oldNumber:r,newNumber:n,marker:" ",text:s.slice(1),kind:"context"}),r+=1,n+=1;continue}}}return t}function nh(e,t){let r=kc(e.oldNumber),n=kc(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:B.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:B.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?oh(So(e.text,t),o.bg,o.fallbackFg):So(e.text,t),l=o?{fg:B.lineNumber,bg:o.bg}:{fg:B.lineNumber},c=o?{fg:B.gutter,bg:o.bg}:{fg:B.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function kc(e){return e===null?" ":String(e).padStart(4," ")}function bc(e){let t=rr.extname(e).toLowerCase();return[".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(t)?"javascript":[".json",".jsonc"].includes(t)?"json":[".md",".mdx"].includes(t)?"markdown":[".css",".scss"].includes(t)?"css":"plain"}function So(e,t){return t==="diff"?sh(e):t==="markdown"?ih(e):t==="json"?Io(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Io(e,/("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)|\/\/.*$|\/\*.*?\*\/|\b(const|let|var|function|return|if|else|for|while|class|interface|type|import|export|from|async|await|new|extends|implements|switch|case|break|continue|try|catch|throw|true|false|null|undefined)\b|-?\b\d+(?:\.\d+)?\b/g):[{text:e}]}function sh(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:B.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:B.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:B.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:B.diffMeta}}]:[{text:e}]}function oh(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function ih(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:B.markup,bold:!0}}]:Io(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Io(e,t){let r=[],n=0;for(let s of e.matchAll(t)){let o=s[0],i=s.index??0;i>n&&r.push({text:e.slice(n,i)}),r.push({text:o,style:ah(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function ah(e){return e.startsWith("//")||e.startsWith("/*")?{fg:B.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:B.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:B.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:B.markup}:{fg:B.keyword}}function lh(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?Sc(t.repoTargets??[]):s?.pullRequest??(t?A(t):null),i=[ch(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=vc(e,t),l=Co(e,r),c=fh([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...bh(e,r)]}:{title:"",rows:[...i,...Co(e,r)]}}function ch(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=vo(t),i=Ao(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Tc(e){return[{text:" "},vo(e),{text:" "},Ao(e)]}function Pc(e){if(e.type==="project"&&e.repoTargets?.length){let r=Sc(e.repoTargets);return r?Tc(r):null}let t=A(e);return t?.number?Tc(t):null}function Sc(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=uh(r);return{number:-1,status:dh(r),draft:r.some(s=>s.draft),mergeable:r.length===t.length&&r.every(s=>s.mergeable),mergeStateStatus:null,reviewDecision:r.some(s=>s.reviewDecision==="CHANGES_REQUESTED")?"CHANGES_REQUESTED":r.some(s=>s.reviewDecision==="REVIEW_REQUIRED")?"REVIEW_REQUIRED":r.every(s=>s.reviewDecision==="APPROVED")?"APPROVED":null,requiredChecks:r.flatMap(s=>s.requiredChecks),aggregateReadiness:n}}function dh(e){return e.some(t=>t.status==="open")?"open":e.every(t=>t.status==="merged")?"merged":e.some(t=>t.status==="closed")?"closed":e[0]?.status??null}function uh(e){let t=e.map(r=>Ic(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function vo(e){return!e||!e.number?{text:pc,style:{fg:"565f89"}}:e.status==="merged"?{text:mc,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:fc,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:wo,style:{fg:"565f89"}}:{text:wo,style:{fg:"9ece6a"}}}function Ao(e){return e?.aggregateReadiness?yc(e.aggregateReadiness):yc(Ic(e))}function yc(e){return e==="failed"?{text:Ro,style:{fg:"f7768e"}}:e==="pending"?{text:To,style:{fg:"e0af68"}}:e==="success"?{text:yo,style:{fg:"9ece6a"}}:{text:ko,style:{fg:"565f89"}}}function Ic(e){let t=e?.requiredChecks??null;return e?.status==="merged"?"success":e?.status==="closed"||!e?.number||!t||t.length===0?"none":t.some(r=>r.status==="failed")||e.reviewDecision==="CHANGES_REQUESTED"?"failed":t.every(r=>r.status==="success"||r.status==="skipped")?Cc(e)?"failed":ph(e)?"success":"pending":"pending"}function ph(e){return!!(e.mergeable&&!e.draft&&!Cc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function Cc(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function vc(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return mh(e,t);let r=A(t),n=Ec("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var Zr=32;function mh(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,m=Zr-u.length-1,g=c.length>m?c.slice(0,m-1)+"\u2026":c,y=Zr-g.length-u.length;r.push({id:`project-review:${i.repoId}`,text:g+" ".repeat(Math.max(1,y))+u,selected:a,focused:l,muted:!0})}else{let d=vo(i.pullRequest),u=Ao(i.pullRequest),m=`${d.text} ${u.text}`,g=Zr-m.length-1,y=c.length>g?c.slice(0,g-1)+"\u2026":c,w=Zr-y.length-m.length,b=y+" ".repeat(Math.max(1,w));r.push({id:`project-review:${i.repoId}`,text:b+m,selected:a,focused:l,segments:[{text:b},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...Ec("target",o.branch,o.pullRequest))),r}function Ac(e,t,r=null){return 3+vc(e,t).length+Co(e,r).length}function Ec(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=gh(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:hh(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${xc(r.lastSyncedAt)}`,muted:!0}),s.push({id:n("checks-spacer"),text:""}),s.push({id:n("checks-header"),text:"Checks"}),r.requiredChecks.length?s.push(...r.requiredChecks.map(wh)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,m)=>kh(u,n(`comment:${m}`))))),s}function fh(e,t){if(t.focusedRegion!=="inspector"||t.inspectionMode!=="review"||e.length===0)return e;let r=Math.max(0,Math.min(t.reviewScrollOffset,e.length-1));return e.map((n,s)=>({...n,selected:t.reviewScrollOffset===0&&n.selected||s===r,focused:t.reviewScrollOffset===0&&n.focused||s===r}))}function gh(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function hh(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function xc(e){if(!e)return"--";let t=Date.now()-new Date(e).getTime(),r=Math.floor(t/1e3);if(r<60)return`${r}s ago`;let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let s=Math.floor(n/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function wh(e){let{icon:t,color:r}=yh(e.status),n=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${n.padEnd(16," ")} ${Rh(e.status)}`,color:r,muted:!1}}function kh(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${xc(e.createdAt)}`:"",s=Th(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function Th(e,t){let r=e.split(/\s+/).filter(Boolean);if(r.length===0)return[];let n=[],s="";for(let o of r){if(!s){s=o;continue}`${s} ${o}`.length<=t?s=`${s} ${o}`:(n.push(s),s=o)}return s&&n.push(s),n}function yh(e){switch(e){case"success":return{icon:yo,color:"9ece6a"};case"pending":return{icon:To,color:"e0af68"};case"failed":return{icon:Ro,color:"f7768e"};case"skipped":return{icon:ko,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Rh(e){return e==="success"?"passing":e==="failed"?"failing":e}function bh(e,t){if(!t)return[{id:"empty",text:"No file index. Select a task with local changes.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.fileRows.length===0)return[{id:"empty",text:"No Git-visible files.",muted:!0}];let r=new Map(t.diffRows.map(l=>[l.path,l.status])),n=Eo(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?dc:uc:cc(l.label),m=l.kind==="directory"?"7aa2f7":gc(l.label),g=" ".repeat(l.depth),y=m?{text:u,style:{fg:m}}:{text:u},w=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},b=[{text:g},y,w];return{id:l.path,text:`${g}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:b}})]}function Eo(e,t){let r=new Set(t);return e.filter(n=>{let s=n.path.split("/");for(let o=1;o<s.length;o+=1)if(r.has(s.slice(0,o).join("/")))return!1;return!0})}function Co(e,t){if(!t)return[{id:"empty",text:"No task diff index.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.diffRows.length===0)return[{id:"empty",text:t.filePaths.some(s=>s.startsWith("repo_"))?"No changes in project task worktrees. Edits in the original repos are outside this task.":"No local changes.",muted:!0}];if(Ph(t))return Sh(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>Dc(o,e,t))))}return r}function Ph(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Sh(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>Dc(c,e,t,s.length+1))))}}return r}function Dc(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Ih(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:f.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:rr.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function Ch(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function vh(e,t){return{name:f.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function $c(e,t,r,n,s=null){if(s)return Ah(e,t,r,n,s);let o=Qs(e,t,{centerOnly:n});return Eh(r,o)?{output:zr(o.rows,r.rows,o.row,o.column),region:o}:null}function Ah(e,t,r,n,s){let o=wl(e,t,s,{centerOnly:n});if(!o||!xh(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:c})=>i[l]===c?"":(i[l]=c,`\x1B[${o.row+l};${o.column}H${c}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function Eh(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function xh(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}function Oc(e,t,r){let n={...e},s="";for(let o of r){let i=e[o],a=t[o];if(!Dh(i,a))return null;!i||!a||(s+=zr(a.rows,i.rows,a.row,a.column),n[o]=a)}return{output:s,regions:n}}function Dh(e,t){return!e||!t?e===t:e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}var $h=["tasks","center","inspector"];function Oh(e,t,r){if(t==="ESCAPE")return T({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return T({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return Do(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Oo({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return T({state:{...e,fileSearchQuery:n},changed:!0})}return T({state:e})}function Oo(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return nl(t)?T({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):T({state:e});if(e.fileSearchQuery!==null)return Oh(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return T({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return T({state:e,exit:!0});if(t==="ESCAPE")return T({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return T({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(Nr(e.selectedLeftItemId)||jr(e.selectedLeftItemId)))return T({state:{...e,selectedRunner:Lr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Mc(e,1);if(t==="SHIFT_TAB"||t==="[")return Mc(e,-1);if(t==="z"||t==="Z")return T({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===x?We(e,-1,r):Do(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===x?We(e,1,r):Do(e,1,r);if(t==="PAGE_UP")return We(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return We(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return We(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return We(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??O,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return T({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=qh(e,t);return T({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return T({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return T({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return T({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Qt(e.selectedLeftItemId)&&e.selectedTaskId)return T({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&ll(e.selectedLeftItemId)&&e.selectedWorkspaceId)return T({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&jc(e.activeTab,r.ptyTabIds??[]))return T({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return xo(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Lc(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return xo(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Lc(e,1)}if(ue(t)){if(e.focusedRegion==="tasks"&&(Nr(e.selectedLeftItemId)||jr(e.selectedLeftItemId))){let n=Vs(e.selectedLeftItemId),s=Ks(e.selectedLeftItemId);return T({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return T({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Qt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return T({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Rt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&jc(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return T({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Rt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===x)return T({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return T({state:Nh({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return T({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:x,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?T({state:{...e,selectedDiffPath:n,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?T({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):T({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?T({state:e}):e.selectedActionId==="refresh-checks"?T({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?T({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):T({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return T({state:e})}function We(e,t,r){if(t===0)return T({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?Fc(e,t,r):e.inspectionMode==="review"?Nc(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):T({state:e});if(e.focusedRegion==="center"&&e.activeTab===x){if(e.openInspectionKind==="file")return Nc(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return jh(e,t,r)}return T({state:e})}function Mc(e,t){return tn(e,"focusedRegion",$h,t)}function xo(e,t,r){let n=tn(e,"activeTab",r&&r.length>0?r:Uh(e),t);return!n.changed||ol(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Rt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Do(e,t,r){if(e.focusedRegion==="tasks")return Mh(e,t,r.leftItemIds);if(e.focusedRegion==="center")return xo(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Fc(e,t,r);if(r.projectTargetIds?.length){let s=$o(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=$o(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:tn(e,"selectedActionId",Xa,t)}return tn(e,"selectedActionId",Ws,t)}function Mh(e,t,r){let n=$o(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Bs(n.state.selectedLeftItemId);if(s?.kind==="workspace")return{...n,state:{...n.state,selectedWorkspaceId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="task")return{...n,state:{...n.state,selectedTaskId:s.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="repo")return{...n,state:{...n.state,selectedRepoId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};let o=Vs(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=Ks(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Lh(e,t){if(e.inspectionMode===t)return T({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?x:e.activeTab;return T({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Lc(e,t){return Lh(e,Wh(e.inspectionMode,qs,t))}function Fc(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return T({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=ve(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return T({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return T({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?x:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Nh(e){if(!e.selectedFileTreePath)return e;let t=new Set(e.collapsedFileTreePaths);return t.has(e.selectedFileTreePath)?t.delete(e.selectedFileTreePath):t.add(e.selectedFileTreePath),{...e,collapsedFileTreePaths:[...t].sort((r,n)=>r.localeCompare(n)),actionMessage:null}}function Nc(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=ve(e[t]+r,0,o);return i===e[t]?T({state:e}):T({state:{...e,[t]:i,actionMessage:null},changed:!0})}function jh(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Fh(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=ve(i,0,o);return d===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=ve(i,0,o);return d===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?T({state:{...e,selectedDiffPath:d,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?T({state:e}):T({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?T({state:{...e,selectedDiffPath:d,activeTab:x,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?T({state:e}):T({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=ve(i,0,o);return c===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function Fh(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=ve(e.diffScrollOffset+t,0,o),a=_h(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?T({state:e}):T({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function _h(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function tn(e,t,r,n){let s=r.indexOf(e[t]),o=ve(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?T({state:e}):T({state:{...e,[t]:i,actionMessage:null},changed:!0})}function $o(e,t,r,n,s=!1){if(r.length===0)return T({state:e});let o=r.indexOf(e[t]??r[0]??""),i=ve(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?T({state:e}):T({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function Wh(e,t,r){let n=t.indexOf(e);return t[ve(n+r,0,t.length-1)]??e}function T(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function jc(e,t){return t.includes(e)}function qh(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Rt(e.activeTab)??e.preferredPtyTabKind}function Uh(e){return[e.selectedPtyTabId,e.openInspectionKind?x:null].filter(t=>typeof t=="string")}function ve(e,t,r){return Math.min(r,Math.max(t,e))}var _c=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>E(n.paths,e.selectedTaskId,o=>{let i=t??Bh(o,e.activeTab,e.preferredPtyTabKind),a=Bc(o,i,r??void 0,n.config);return{...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id}}));return{updatedTask:s,nextShell:{activeTab:s.selectedPtyTabId??e.activeTab,selectedPtyTabId:s.selectedPtyTabId,preferredPtyTabKind:s.ptyTabs.at(-1)?.kind??e.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${s.ptyTabs.at(-1)?.title??"tab"}`}}},Wc=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s={closedTab:null,nextSelectedTab:null};if(await E(t.paths,e.selectedTaskId,o=>{let i=o.ptyTabs.findIndex(l=>l.id===e.activeTab);if(i===-1)throw new Error("Only PTY tabs can be closed.");s.closedTab=o.ptyTabs[i];let a=o.ptyTabs.filter(l=>l.id!==s.closedTab.id);return s.nextSelectedTab=a[Math.min(i,a.length-1)]??null,{...o,ptyTabs:a,selectedPtyTabId:s.nextSelectedTab?.id??null}}),!s.closedTab)throw new Error("Only PTY tabs can be closed.");return{closedTab:s.closedTab,nextSelectedTab:s.nextSelectedTab}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},qc=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{await E(t.paths,r,n=>!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab?n:{...n,selectedPtyTabId:e.activeTab})})},Uc=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{await E(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:s})}),{...e,selectedPtyTabId:r.id};let n=Bc(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{await E(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id}})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Bh(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Bc(e,t,r,n={}){let s=r??e.runner,o=f.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(g=>g.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),m=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...m?{runner:m}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?f.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var It=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Vc=async(e,t,r,n,s)=>{f.runners.assertEnabled(n,s.config);let o=t?await s.taskService.provisionProjectTask(s.paths,t,r,{runner:n,config:s.config}):await s.taskService.provisionTask(s.paths,e??"",r,{runner:n,config:s.config});try{let l=Je();Qe(f.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new It(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},Kc=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Gc=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await Dt(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},Hc=async(e,t)=>(await t.taskService.prs.discoverOrRefreshMany(t.paths,e),Promise.all(e.map(r=>Dt(t.paths,r.id)))),rn=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await lt.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var zc=async(e,t)=>{if(!e.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await t.taskService.listTasks(t.paths,{workspaceId:e.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${e.selectedWorkspaceId} while task records still reference it.`);return await t.workspaceService.archiveWorkspace(t.paths,e.selectedWorkspaceId),{nextShell:{selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${(await t.workspaceService.removeWorkspace(t.paths,e.selectedWorkspaceId,{listTasks:t.taskService.listTasks})).workspaceId}`}}};var Yc=async(e,t,r)=>{let n=f.runners.setRunnerEnabled(r.config,e,t);return await f.save(r.paths,n),n},Jc=async(e,t,r)=>{let n=f.runners.setRunnerPath(r.config,e,t);return await f.save(r.paths,n),n},Qc=async(e,t,r)=>{let n=f.previews.setEnabled(r.config,e,t);return await f.save(r.paths,n),n};var Vh=250;function Ae(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function nt(e,t){return Ce(t,e.ptyRuntime.getViewState(Ct(e,t)))}function Ct(e,t){let r=Ae(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function h(e,t){return nt(e,cl(t,e.model))}function Xc(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:h(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Zc(e,t,r){return Xc(e,t,r?{tone:"success",message:r}:null)}function _(e,t,r){return Xc(e,t,{tone:"error",message:r})}function W(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return lt.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function j(e,t){if(!e.uiStateFile)return;e.runtimeState=tl(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Ee({uiStateFile:e.uiStateFile},r),()=>Ee({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Kh(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function U(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:G,queueTaskMutation:t=>Kh(e,t)}}function Mo(e,t){let r=Ae(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?Eo(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:et(e.model),centerTabIds:al(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:Ac(t,r,s),pageRows:Math.max(5,oe(e.activeTerminal.width,e.activeTerminal.height).height-N.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function ed(e,t){await qc(t,U(e))}async function Y(e){e.model=await bt(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:h(e,e.state.shell)}:e.state={...e.state,shell:h(e,e.state.shell)}}function nn(e,t){e.model={...e.model,tasks:[...e.model.tasks.filter(r=>r.id!==t.id),t].sort((r,n)=>r.id.localeCompare(n.id))}}async function sn(e,t){let r=++e.inspectionRefreshSequence,n=Gs(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await Wa(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await bt(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,e.state.shell)},j(e,e.state.shell),e.render())}function td(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&sn(e,r).catch(n=>{let s=W(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Vh))}function rd(e,t){t!==0&&(e.pendingInspectionScrollLines+=t,!e.inspectionScrollRenderTimer&&(e.inspectionScrollRenderTimer=setTimeout(()=>{e.inspectionScrollRenderTimer=null;let r=e.pendingInspectionScrollLines;if(e.pendingInspectionScrollLines=0,r===0||e.state.mode!=="main"||e.state.shell.inputMode!=="control")return;let n=We(e.state.shell,r,Mo(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render(),sn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render()}},16)))}function Lo(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function No(e){let t=e.model.tasks.flatMap(r=>r.ptyTabs.map(n=>n.id));await e.ptyRuntime.pruneStale?.(t),await e.ptyRuntime.hydrateSessions?.(t)}function sd(e){No(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,e.state.shell)},e.render())})}async function od(e,t){let r=h(e,t),n=Ae(e.model.tasks,r),s=Ct(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return Ce(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));return Ce({...r,inputMode:"control"},i)}function jo(e){let t=e.state.mode==="main"&&e.state.shell.inputMode==="terminal"?"terminal":"control";t!==e.inputCaptureMode&&(e.inputCaptureMode=t,e.activeTerminal.grabInput(t==="terminal"?{mouse:"button"}:!0))}async function Fo(e,t){try{let r=h(e,t),n=Ae(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await nd(e,n),await Y(e),s=n.selectedPtyTabId)}n&&!s&&(n=await nd(e,n),await Y(e),s=n.selectedPtyTabId);let o=h(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:Ce({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},j(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=_e(s),e.lastTerminalKey=null,e.state={mode:"main",shell:Ce({...o,inputMode:"terminal"},i)},j(e,e.state.shell)}catch(r){let n=W(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&_e(t.selectedPtyTabId)&&(await Gh(e,t.selectedTaskId,n).catch(()=>{}),await Y(e).catch(()=>{})),e.state={mode:"main",shell:_(e,rl(h(e,t),n),n)},j(e,e.state.shell)}e.render()}async function Gh(e,t,r){await Kc(t,r,U(e))}async function id(e,t,r,n){let s=h(e,t),{nextShell:o}=await _c(s,r,n,U(e));return await Y(e),h(e,{...s,...o})}async function ad(e,t){let r=h(e,t),{closedTab:n,nextShell:s}=await Wc(r,U(e));return e.ptyRuntime.disposeSession(n.id),await Y(e),h(e,{...r,...s})}async function ld(e,t){let r=h(e,t),n=et(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Gc(r,U(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await Y(e),h(e,{...r,...i,selectedLeftItemId:Hh(n,et(e.model),s)})}async function cd(e,t){let r=h(e,t),{nextShell:n}=await zc(r,U(e));return await Y(e),h(e,{...r,...n})}async function nd(e,t){return Uc(t,U(e))}function on(e,t){e.pendingScrollLines+=t,!e.scrollRenderTimer&&(e.scrollRenderTimer=setTimeout(()=>{e.scrollRenderTimer=null;let r=e.pendingScrollLines;e.pendingScrollLines=0,r!==0&&(e.ptyRuntime.scrollViewport(r),e.state={mode:"main",shell:nt(e,e.state.shell)},e.render())},16))}function Hh(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function ud(e,t,r){if(r?.aborted||e.state.mode!=="main")return;let n=dd(e),s=t.takeDueTasks(e.model.tasks,n);if(s.length!==0)try{let o=await Hc(s,U(e));if(r?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;for(let i of o)nn(e,i);t.recordSuccess(o,dd(e)),e.state={mode:"main",shell:h(e,e.state.shell)},e.render()}catch(o){if(r?.aborted)return;t.recordFailure(s,o);let i=o instanceof Error?o.message:"Background PR discovery failed.";i!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=i,rn("background PR polling",o,U(e)))}}function dd(e){return e.state.mode!=="main"?{selectedTaskId:null,reviewVisible:!1}:{selectedTaskId:e.state.shell.selectedTaskId,reviewVisible:e.state.shell.inspectionMode==="review"}}async function pd(e,t){let r=h(e,t),n=Ae(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await C.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await Y(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await C.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await Y(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${A(a)?.requiredChecks.length??0} reported`)}return h(e,{...Zc(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}var zh={pendingForegroundMs:5e3,pendingBackgroundMs:15e3,stableForegroundMs:3e4,stableBackgroundMs:6e4,discoveryForegroundMs:6e4,discoveryBackgroundMs:18e4,rateLimitBaseMs:6e4,rateLimitMaxMs:15*6e4},an=class{scheduledTasks=new Map;now;intervals;minimumIntervalMs;rateLimitFailures=0;notBefore=0;constructor(t={}){this.minimumIntervalMs=Math.max(1e3,t.minimumIntervalMs??5e3),this.intervals={...zh,...t.intervals},this.now=t.now??Date.now}takeDueTasks(t,r){let n=this.now(),s=new Set(t.map(i=>i.id));for(let i of this.scheduledTasks.keys())s.has(i)||this.scheduledTasks.delete(i);let o=[];for(let i of t){let a=this.getTaskIntervalMs(i,r);if(a===null){this.scheduledTasks.delete(i.id);continue}let l=this.scheduledTasks.get(i.id);if(!l){this.scheduledTasks.set(i.id,{intervalMs:a,nextPollAt:n}),n>=this.notBefore&&o.push(i);continue}a<l.intervalMs&&(l.nextPollAt=Math.min(l.nextPollAt,n+a)),l.intervalMs=a,n>=this.notBefore&&n>=l.nextPollAt&&o.push(i)}return o}recordSuccess(t,r){let n=this.now();this.rateLimitFailures=0,this.notBefore=0;for(let s of t){let o=this.getTaskIntervalMs(s,r);o===null?this.scheduledTasks.delete(s.id):this.scheduledTasks.set(s.id,{intervalMs:o,nextPollAt:n+o})}}recordFailure(t,r){let n=this.now(),s=r instanceof ge,o=s?Math.min(this.intervals.rateLimitBaseMs*2**this.rateLimitFailures,this.intervals.rateLimitMaxMs):Math.max(this.minimumIntervalMs,this.intervals.pendingBackgroundMs);s&&(this.rateLimitFailures+=1,this.notBefore=n+o);for(let i of t){let a=this.scheduledTasks.get(i.id);a&&(a.nextPollAt=n+o)}}getTaskIntervalMs(t,r){let n=Yh(t),s=t.id===r.selectedTaskId&&r.reviewVisible;if(n.length>0){let o=n.some(Jh);return this.withMinimum(o?s?this.intervals.pendingForegroundMs:this.intervals.pendingBackgroundMs:s?this.intervals.stableForegroundMs:this.intervals.stableBackgroundMs)}return t.status==="checked"?this.withMinimum(s?this.intervals.discoveryForegroundMs:this.intervals.discoveryBackgroundMs):null}withMinimum(t){return Math.max(t,this.minimumIntervalMs)}};function Yh(e){return e.type==="project"&&e.repoTargets?.length?e.repoTargets.map(t=>t.pullRequest).filter(t=>t.status==="open"):e.prs.filter(t=>t.status==="open")}function Jh(e){return e.requiredChecks.some(t=>t.status==="pending"||t.status==="unknown")}import tw from"node:path";import{readdir as Qh,stat as Xh}from"node:fs/promises";import md from"node:path";async function Zh(e){let t=await Qh(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=md.join(e,n.name);r.push({name:n.name,path:s,kind:await ew(s)?"repo":"directory"})}return r.sort((n,s)=>n.kind!==s.kind?n.kind==="repo"?-1:1:n.name.localeCompare(s.name)),{cwd:e,entries:r,selectedIndex:0,query:null,error:null}}function fd(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function gd(e){let{spawn:t}=await import("node:child_process"),r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await new Promise((n,s)=>{let o=t(r,[e],{stdio:"ignore",detached:!0});o.unref(),o.on("error",s),o.on("spawn",n)})}async function ln(e,t){let r=await Zh(t);e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function ew(e){let t=md.join(e,".git");return await Xh(t).catch(()=>null)!==null}function hd(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function wd(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function rw(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:h(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:h(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:h(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Vc(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,U(e));n=s.task,nn(e,n);let o=h(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??vl(n,"agent"),Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=_e(o.selectedPtyTabId),e.state={mode:"main",shell:Ce(o,i)},j(e,e.state.shell)}catch(s){s instanceof It&&(n=s.task);let o=W(e,"create task",s,"Failed to create task.");n&&!(s instanceof It)?(await E(e.paths,n.id,i=>({...i,status:"draft",runnerSession:{...i.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o})).catch(()=>{}),await Y(e).catch(()=>{})):n&&(await E(e.paths,n.id,i=>({...i,lastFailureReason:o})).catch(()=>{}),await Y(e).catch(()=>{})),e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function nw(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:h(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ue(t)){rw(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:h(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:h(e,{...r,selectedRunner:Lr(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}sl(t)&&(e.state={mode:"main",shell:h(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function sw(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=fd(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){ln(e,tw.dirname(r.cwd)).catch(s=>{let o=W(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ue(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){ln(e,s.path).catch(i=>{let a=W(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=U(e);o.addWorkspace(e.paths,s.path).then(async i=>{await Y(e);let a=i.repos[0]??null,l=h(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},j(e,e.state.shell),e.render()}).catch(i=>{let a=W(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function ow(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=ic(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;iw(e,n)}}}async function iw(e,t){let r;try{r=await lt.readRecentErrorLines(e.paths)}catch(n){let s=W(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function aw(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=lc(hd(e),e.config,t,e.enabledRunnerIds);if(r.kind==="noop")return;if(r.kind==="back"){let s=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...s!==void 0?{parentVariant:s}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,runnerOptions:r.state},e.render();return}(r.kind==="save-enabled"?Yc(r.runner,r.enabled,U(e)):Jc(r.runner,r.path,U(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=f.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:h(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:f.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=W(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:_(e,h(e,e.state.shell),o),runnerOptions:{...hd(e),message:o}},e.render()})}function lw(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=ac(wd(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}Qc(r.feature,r.enabled,U(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,r.feature==="incrementalCenterPane"&&e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),r.feature==="agentActivityIndicators"&&e.setAgentActivityEnabled(r.enabled),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=W(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:_(e,h(e,e.state.shell),s),previewOptions:{...wd(e),message:s}},e.render()})}}function kd(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){nw(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){sw(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){dw(e),e.render();return}e.focusFlashUntil!==null&&(e.focusFlashUntil=null,e.focusFlashTimer&&(clearTimeout(e.focusFlashTimer),e.focusFlashTimer=null))}if(e.state.mode==="main"){let n=Oo(e.state.shell,r,Mo(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ue(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=er(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(cw(e,r))return;e.lastTerminalKey=Al(r)?{key:r,at:Date.now()}:null;let o=El(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){on(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:h(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){ln(e,e.workspaceRoot).catch(s=>{let o=W(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:_(e,h(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){id(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Fo(e,s)}).catch(s=>{let o=W(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){ad(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){pd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=Ae(e.model.tasks,n.state),o=s?A(s)?.url??null:null;o?gd(o).catch(i=>{let a=W(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:_(e,h(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:_(e,h(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){ld(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){cd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){Fo(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),(e.state.shell.focusedRegion!=="tasks"||!e.renderTaskNavigation())&&e.render(),e.state.shell.focusedRegion==="tasks"){td(e,e.state.shell);return}sn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:h(e,n.state)},ed(e,e.state.shell).catch(()=>{}),j(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:h(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){ow(e,r);return}if(e.state.variant==="runners"){aw(e,r);return}if(e.state.variant==="previews"){lw(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ue(r)){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render()}return}if(e.state.optionsMessage){(r==="ESCAPE"||ue(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:h(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ue(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:h(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;od(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},j(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=W(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:_(e,h(e,e.state.shell),i)},j(e,e.state.shell),e.render()})}):sd(e);return}if(e.state.menuIndex===1){let n=e.state.variant==="boot"||e.state.variant==="pause"?e.state.variant:void 0;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}e.exit(0)}}function Td(e,t){let r=Ml(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=er(o);if(i){Rd(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(so(o)){e.pendingTerminalKeySequence.raw=o,yd(e);return}cn(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:h(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},j(e,e.state.shell),e.render();return}let n=xl(r);if(n!==0){on(e,n);return}let s=er(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
121
122
|
`&&r!==`\r
|
|
122
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),Ya(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function ch(e,t){if(e.pendingTerminalKeySequence){let r=Ha(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=Bt(n);if(s)return jc(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(Ss(n))return e.pendingTerminalKeySequence.raw=n,Fc(e),!0}return Vr(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>Vr(e),30)},!0)}function Fc(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>Vr(e),30))}function Vr(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function jc(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function Wc(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){Tc(e,Ps(t));return}let r=Ps(t);r!==0&&Ur(e,r)}function dh(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var Kr=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=so(t.resolutionMs??1e3,"Heartbeat resolution"),this.now=t.now??Date.now,this.onError=t.onError}register(t){if(this.jobs.has(t.id))throw new Error(`Heartbeat job "${t.id}" is already registered.`);let r={...t,intervalMs:so(t.intervalMs,`Heartbeat job "${t.id}" interval`),inFlight:!1,nextRunAt:this.timer?this.now()+t.intervalMs:null};this.jobs.set(t.id,r)}start(){if(this.timer)return;let t=this.now();for(let r of this.jobs.values())r.nextRunAt=t+r.intervalMs;this.abortController=new AbortController,this.timer=setInterval(()=>this.tick(),this.resolutionMs)}stop(){this.abortController?.abort(),this.abortController=null,this.timer&&(clearInterval(this.timer),this.timer=null);for(let t of this.jobs.values())t.nextRunAt=null}setResolutionMs(t){let r=so(t,"Heartbeat resolution");r!==this.resolutionMs&&(this.resolutionMs=r,this.timer&&(clearInterval(this.timer),this.timer=setInterval(()=>this.tick(),this.resolutionMs)))}tick(){let t=this.abortController?.signal;if(!t)return;let r=this.now();for(let n of this.jobs.values())n.inFlight||n.nextRunAt===null||r<n.nextRunAt||(n.inFlight=!0,n.nextRunAt=r+n.intervalMs,Promise.resolve().then(()=>n.run(t)).catch(s=>{if(!t.aborted)return Promise.resolve(this.onError(n.id,s)).catch(()=>{})}).finally(()=>{n.inFlight=!1}))}};function so(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var _c=1e3,mh=ph(import.meta.url),fh=mh("terminal-kit"),gh=fh.terminal;function io(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Uc(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function hh(e,t){return e?e.tabId!==t.tabId?{tabId:t.tabId,kind:"full"}:e.kind==="full"||t.kind==="full"?{tabId:t.tabId,kind:"full"}:{tabId:t.tabId,kind:"rows",rowIndices:[...new Set([...e.rowIndices,...t.rowIndices])]}:t}async function qc(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ee(t),n=await f.load(r),s=f.runners.getEnabled(n),o=e.uiStateFile?await Ze({uiStateFile:e.uiStateFile}):null,i=await De(t,void 0,s),a=Wt(ha(o,n),i);i=await De(t,a,s);let l={current:i},c=()=>{},d=()=>{},u=()=>{},m={workspaceRoot:t,onUpdate:R=>c(R),onActivity:R=>d(R),onActivityRemoved:R=>u(R),resolveSessionSpec:(R,h)=>qa(l.current,h,t)},T=e.ptyRuntime??await ll({...m,paths:r,viewUpdateMode:f.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:f.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(R=>{let h=e.terminal??gh,y=null,B=null,z=null,se=null,C=null,we=0,wt=!1,Je=new Map,Gr=new qr({minimumIntervalMs:(n.github?.watchIntervalSeconds??5)*1e3}),p,Ne=new Kr({resolutionMs:f.previews.isEnabled(n,"agentActivityIndicators")?150:_c,onError:(k,M)=>Wr(`heartbeat job "${k}"`,M,_(p))});p={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Wt(a,i)},get model(){return l.current},set model(k){l.current=k},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,lastBackgroundPrPollError:null,versionText:`Craig v${f.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:h,ptyRuntime:T,resolve:R,render:()=>{},renderTaskNavigation:()=>!1,exit:k=>R(k),setAgentActivityEnabled:k=>{Ne.setResolutionMs(k?150:_c),p.ptyRuntime.setActivityEnabled?.(k)}},p.setAgentActivityEnabled(f.previews.isEnabled(n,"agentActivityIndicators")),c=k=>{p.state.mode==="main"&&(C=hh(C,k),p.ptyRenderTimer||(p.ptyRenderTimer=setTimeout(()=>{p.ptyRenderTimer=null;let M=C;if(C=null,p.state.mode==="main"){let J=Qe(p,p.state.shell);if(p.state={mode:"main",shell:J},!f.previews.isEnabled(p.config,"incrementalCenterPane")||!se||!B){p.render();return}let X=le(h.width,h.height),Tt={...se,terminal:J.terminal},Fe=zl(X,Tt,B,J.centerZoomed,M?.kind==="rows"?M.rowIndices:null);if(!Fe){p.render();return}Fe.output.length>0&&h.noFormat(Fe.output),se=Tt,B=Fe.region,z&&(z={...z,center:Fe.region}),y=null,h.hideCursor(!0)}},f.previews.isEnabled(p.config,"incrementalCenterPane")?0:50)))},d=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&Oe(k.tabId)&&Je.get(k.tabId)!==Vt(k.tabId,[k],Date.now())&&p.render()},u=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&Oe(k)&&Je.get(k)!=="idle"&&p.render()};let Te=k=>{let M=le(h.width,h.height),J=f.previews.isEnabled(p.config,"agentActivityIndicators"),de=J?p.ptyRuntime.getActivitySnapshots?.()??[]:[],X=Date.now(),Tt=Fl(g(p,k.shell),p.model,J?{snapshots:de,now:X,animationFrame:we}:void 0);if(Je.clear(),J)for(let Vc of p.model.tasks)for(let Hr of Vc.ptyTabs)Hr.kind==="agent"&&Je.set(Hr.id,Vt(Hr.id,de,X));let Fe=$a(M,Tt,{centerOnly:k.shell.centerZoomed,focusFlashActive:p.focusFlashUntil!==null&&Date.now()<p.focusFlashUntil});return{data:Tt,presentation:Fe}},Le=(k,M,J,de)=>{if(!z)return!1;let X=Yl(z,M.regions,J);return X?(X.output.length>0&&h.noFormat(X.output),se=k,z=X.regions,B=X.regions.center,y=de?M.frame:null,h.hideCursor(!0),!0):!1};p.renderTaskNavigation=()=>{if(p.state.mode!=="main"||p.pendingClear||!f.previews.isEnabled(p.config,"incrementalCenterPane"))return!1;ro(p),p.ptyRuntime.setViewedTab?.(kt(p,p.state.shell));let{data:k,presentation:M}=Te(p.state);return Le(k,M,["rail","left","center","footer"],!1)},p.render=()=>{ro(p);let k=p.state;p.ptyRuntime.setViewedTab?.(k.mode==="main"?kt(p,k.shell):null);let M=le(h.width,h.height),J,de=null;if(k.mode==="main"){let X=Te(k);if(de=X.presentation,J=de.frame,f.previews.isEnabled(p.config,"incrementalCenterPane")&&!p.pendingClear&&Le(X.data,de,["rail","left","center","right","footer"],!0))return;se=X.data,B=de.center}else J=k.variant==="boot"?Ea(M,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="pause"?Aa(M,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="options"?Er(M,{menuIndex:k.menuIndex,optionsMenuItems:Ms}):k.variant==="runners"?Er(M,{menuIndex:io(k).menuIndex,optionsMenuItems:Ns(p.config,io(k)),optionsMessage:Tl(io(k)),optionsSubtitle:"Runners"}):k.variant==="previews"?Er(M,{menuIndex:Uc(k).menuIndex,optionsMenuItems:Rl(p.config),optionsMessage:yl(Uc(k)),optionsSubtitle:"Feature Previews - Experimental"}):k.variant==="error-log"?Da(M,{errorLogPath:k.errorLog?.path??r.errorLogFile,errorLogLines:k.errorLog?.lines??[]}):xa(M),se=null,B=null,z=null;p.pendingClear&&(h.moveTo(1,1),h.eraseDisplayBelow(),p.pendingClear=!1,y=null),h.noFormat(Ja(J,y)),y=J,z=de?.regions??null,h.hideCursor(!0)};let Gt=k=>Nc(p,k),Ht=k=>Lc(p,k),zt=k=>Wc(p,k),Bc=()=>{process.stdout.off("resize",ao),process.off("SIGCONT",lo),h.removeListener("key",Gt),h.removeListener("unknown",Ht),h.removeListener("mouse",zt),p.scrollRenderTimer&&(clearTimeout(p.scrollRenderTimer),p.scrollRenderTimer=null),p.inspectionScrollRenderTimer&&(clearTimeout(p.inspectionScrollRenderTimer),p.inspectionScrollRenderTimer=null),p.leftNavInspectionTimer&&(clearTimeout(p.leftNavInspectionTimer),p.leftNavInspectionTimer=null),p.pendingTerminalKeySequence&&(clearTimeout(p.pendingTerminalKeySequence.timer),p.pendingTerminalKeySequence=null),p.ptyRenderTimer&&(clearTimeout(p.ptyRenderTimer),p.ptyRenderTimer=null),p.footerToastTimer&&(clearTimeout(p.footerToastTimer),p.footerToastTimer=null),p.focusFlashTimer&&(clearTimeout(p.focusFlashTimer),p.focusFlashTimer=null),Ne.stop(),p.ptyRuntime.disposeAll(),h.grabInput(!1),h.hideCursor(!1),h.fullscreen(!1)};p.exit=k=>{Bc(),R(k)};let ao=()=>{eo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize($e(le(h.width,h.height))),p.state={mode:"main",shell:Qe(p,p.state.shell)}),p.render()},lo=()=>{eo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize($e(le(h.width,h.height))),p.state={mode:"main",shell:Qe(p,p.state.shell)}),p.render()};process.stdout.on("resize",ao),process.on("SIGCONT",lo),h.grabInput(!0),p.inputCaptureMode="control",h.hideCursor(!0),h.fullscreen(!0),h.on("key",Gt),h.on("unknown",Ht),h.on("mouse",zt),Ne.register({id:"github.pull-requests",intervalMs:1e3,run:k=>Ec(p,Gr,k)}),Ne.register({id:"agent.activity-indicators",intervalMs:150,run:()=>{if(!f.previews.isEnabled(p.config,"agentActivityIndicators")){we=0,wt=!1;return}let k=Date.now(),M=Ol(p.model.tasks,p.ptyRuntime.getActivitySnapshots?.()??[],k);(M||wt)&&(we=(we+1)%6,p.state.mode==="main"&&p.render()),wt=M}}),Ne.start(),f.version.checkForUpdate().then(k=>{k.updateAvailable&&k.latest&&(p.updateText=`Update available: v${k.latest}`,p.render())}),p.bootHydrationReady=to(p).catch(()=>{}),p.render()})}async function kh(){try{if(process.argv[2]==="__craig-daemon"){let e=process.argv[3]??process.cwd(),t=ee(e);return await cl(t),0}if(process.argv[2]==="__craig-daemon-shutdown"){let e=process.argv[3]??process.cwd(),t=ee(e);return await dl(t),0}}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
123
|
-
`),1}return
|
|
123
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),Ol(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function cw(e,t){if(e.pendingTerminalKeySequence){let r=Dl(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=er(n);if(s)return Rd(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(so(n))return e.pendingTerminalKeySequence.raw=n,yd(e),!0}return cn(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>cn(e),30)},!0)}function yd(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>cn(e),30))}function cn(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function Rd(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function bd(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){rd(e,no(t));return}let r=no(t);r!==0&&on(e,r)}function dw(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var dn=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=_o(t.resolutionMs??1e3,"Heartbeat resolution"),this.now=t.now??Date.now,this.onError=t.onError}register(t){if(this.jobs.has(t.id))throw new Error(`Heartbeat job "${t.id}" is already registered.`);let r={...t,intervalMs:_o(t.intervalMs,`Heartbeat job "${t.id}" interval`),inFlight:!1,nextRunAt:this.timer?this.now()+t.intervalMs:null};this.jobs.set(t.id,r)}start(){if(this.timer)return;let t=this.now();for(let r of this.jobs.values())r.nextRunAt=t+r.intervalMs;this.abortController=new AbortController,this.timer=setInterval(()=>this.tick(),this.resolutionMs)}stop(){this.abortController?.abort(),this.abortController=null,this.timer&&(clearInterval(this.timer),this.timer=null);for(let t of this.jobs.values())t.nextRunAt=null}setResolutionMs(t){let r=_o(t,"Heartbeat resolution");r!==this.resolutionMs&&(this.resolutionMs=r,this.timer&&(clearInterval(this.timer),this.timer=setInterval(()=>this.tick(),this.resolutionMs)))}tick(){let t=this.abortController?.signal;if(!t)return;let r=this.now();for(let n of this.jobs.values())n.inFlight||n.nextRunAt===null||r<n.nextRunAt||(n.inFlight=!0,n.nextRunAt=r+n.intervalMs,Promise.resolve().then(()=>n.run(t)).catch(s=>{if(!t.aborted)return Promise.resolve(this.onError(n.id,s)).catch(()=>{})}).finally(()=>{n.inFlight=!1}))}};function _o(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var Pd=1e3,mw=pw(import.meta.url),fw=mw("terminal-kit"),gw=fw.terminal;function qo(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Sd(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function hw(e,t){return e?e.tabId!==t.tabId?{tabId:t.tabId,kind:"full"}:e.kind==="full"||t.kind==="full"?{tabId:t.tabId,kind:"full"}:{tabId:t.tabId,kind:"rows",rowIndices:[...new Set([...e.rowIndices,...t.rowIndices])]}:t}async function Id(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=Z(t),n=await f.load(r),s=f.runners.getEnabled(n),o=e.uiStateFile?await it({uiStateFile:e.uiStateFile}):null,i=await bt(t,void 0,s),a=Jt(el(o,n),i);i=await bt(t,a,s);let l={current:i},c=()=>{},d=()=>{},u=()=>{},m={workspaceRoot:t,onUpdate:y=>c(y),onActivity:y=>d(y),onActivityRemoved:y=>u(y),resolveSessionSpec:(y,w)=>Cl(l.current,w,t)},g=e.ptyRuntime??await Gl({...m,paths:r,viewUpdateMode:f.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:f.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(y=>{let w=e.terminal??gw,b=null,V=null,H=null,re=null,v=null,ke=0,vt=!1,st=new Map,un=new an({minimumIntervalMs:(n.github?.watchIntervalSeconds??5)*1e3}),p,qe=new dn({resolutionMs:f.previews.isEnabled(n,"agentActivityIndicators")?150:Pd,onError:(k,L)=>rn(`heartbeat job "${k}"`,L,U(p))});p={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Jt(a,i)},get model(){return l.current},set model(k){l.current=k},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,lastBackgroundPrPollError:null,versionText:`Craig v${f.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:w,ptyRuntime:g,resolve:y,render:()=>{},renderTaskNavigation:()=>!1,exit:k=>y(k),setAgentActivityEnabled:k=>{qe.setResolutionMs(k?150:Pd),p.ptyRuntime.setActivityEnabled?.(k)}},p.setAgentActivityEnabled(f.previews.isEnabled(n,"agentActivityIndicators")),c=k=>{p.state.mode==="main"&&(v=hw(v,k),p.ptyRenderTimer||(p.ptyRenderTimer=setTimeout(()=>{p.ptyRenderTimer=null;let L=v;if(v=null,p.state.mode==="main"){let J=nt(p,p.state.shell);if(p.state={mode:"main",shell:J},!f.previews.isEnabled(p.config,"incrementalCenterPane")||!re||!V){p.render();return}let Q=oe(w.width,w.height),At={...re,terminal:J.terminal},Be=$c(Q,At,V,J.centerZoomed,L?.kind==="rows"?L.rowIndices:null);if(!Be){p.render();return}Be.output.length>0&&w.noFormat(Be.output),re=At,V=Be.region,H&&(H={...H,center:Be.region}),b=null,w.hideCursor(!0)}},f.previews.isEnabled(p.config,"incrementalCenterPane")?0:50)))},d=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&_e(k.tabId)&&st.get(k.tabId)!==tr(k.tabId,[k],Date.now())&&p.render()},u=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&_e(k)&&st.get(k)!=="idle"&&p.render()};let Te=k=>{let L=oe(w.width,w.height),J=f.previews.isEnabled(p.config,"agentActivityIndicators"),ce=J?p.ptyRuntime.getActivitySnapshots?.()??[]:[],Q=Date.now(),At=Rc(h(p,k.shell),p.model,J?{snapshots:ce,now:Q,animationFrame:ke}:void 0);if(st.clear(),J)for(let vd of p.model.tasks)for(let pn of vd.ptyTabs)pn.kind==="agent"&&st.set(pn.id,tr(pn.id,ce,Q));let Be=hl(L,At,{centerOnly:k.shell.centerZoomed,focusFlashActive:p.focusFlashUntil!==null&&Date.now()<p.focusFlashUntil});return{data:At,presentation:Be}},Ue=(k,L,J,ce)=>{if(!H)return!1;let Q=Oc(H,L.regions,J);return Q?(Q.output.length>0&&w.noFormat(Q.output),re=k,H=Q.regions,V=Q.regions.center,b=ce?L.frame:null,w.hideCursor(!0),!0):!1};p.renderTaskNavigation=()=>{if(p.state.mode!=="main"||p.pendingClear||!f.previews.isEnabled(p.config,"incrementalCenterPane"))return!1;jo(p),p.ptyRuntime.setViewedTab?.(Ct(p,p.state.shell));let{data:k,presentation:L}=Te(p.state);return Ue(k,L,["rail","left","center","footer"],!1)},p.render=()=>{jo(p);let k=p.state;p.ptyRuntime.setViewedTab?.(k.mode==="main"?Ct(p,k.shell):null);let L=oe(w.width,w.height),J,ce=null;if(k.mode==="main"){let Q=Te(k);if(ce=Q.presentation,J=ce.frame,f.previews.isEnabled(p.config,"incrementalCenterPane")&&!p.pendingClear&&Ue(Q.data,ce,["rail","left","center","right","footer"],!0))return;re=Q.data,V=ce.center}else J=k.variant==="boot"?pl(L,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="pause"?ml(L,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="options"?Kr(L,{menuIndex:k.menuIndex,optionsMenuItems:go}):k.variant==="runners"?Kr(L,{menuIndex:qo(k).menuIndex,optionsMenuItems:ho(p.config,qo(k)),optionsMessage:nc(qo(k)),optionsSubtitle:"Runners"}):k.variant==="previews"?Kr(L,{menuIndex:Sd(k).menuIndex,optionsMenuItems:sc(p.config),optionsMessage:oc(Sd(k)),optionsSubtitle:"Feature Previews - Experimental"}):k.variant==="error-log"?gl(L,{errorLogPath:k.errorLog?.path??r.errorLogFile,errorLogLines:k.errorLog?.lines??[]}):fl(L),re=null,V=null,H=null;p.pendingClear&&(w.moveTo(1,1),w.eraseDisplayBelow(),p.pendingClear=!1,b=null),w.noFormat(Ll(J,b)),b=J,H=ce?.regions??null,w.hideCursor(!0)};let nr=k=>kd(p,k),sr=k=>Td(p,k),or=k=>bd(p,k),Cd=()=>{process.stdout.off("resize",Uo),process.off("SIGCONT",Bo),w.removeListener("key",nr),w.removeListener("unknown",sr),w.removeListener("mouse",or),p.scrollRenderTimer&&(clearTimeout(p.scrollRenderTimer),p.scrollRenderTimer=null),p.inspectionScrollRenderTimer&&(clearTimeout(p.inspectionScrollRenderTimer),p.inspectionScrollRenderTimer=null),p.leftNavInspectionTimer&&(clearTimeout(p.leftNavInspectionTimer),p.leftNavInspectionTimer=null),p.pendingTerminalKeySequence&&(clearTimeout(p.pendingTerminalKeySequence.timer),p.pendingTerminalKeySequence=null),p.ptyRenderTimer&&(clearTimeout(p.ptyRenderTimer),p.ptyRenderTimer=null),p.footerToastTimer&&(clearTimeout(p.footerToastTimer),p.footerToastTimer=null),p.focusFlashTimer&&(clearTimeout(p.focusFlashTimer),p.focusFlashTimer=null),qe.stop(),p.ptyRuntime.disposeAll(),w.grabInput(!1),w.hideCursor(!1),w.fullscreen(!1)};p.exit=k=>{Cd(),y(k)};let Uo=()=>{Lo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize(Fe(oe(w.width,w.height))),p.state={mode:"main",shell:nt(p,p.state.shell)}),p.render()},Bo=()=>{Lo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize(Fe(oe(w.width,w.height))),p.state={mode:"main",shell:nt(p,p.state.shell)}),p.render()};process.stdout.on("resize",Uo),process.on("SIGCONT",Bo),w.grabInput(!0),p.inputCaptureMode="control",w.hideCursor(!0),w.fullscreen(!0),w.on("key",nr),w.on("unknown",sr),w.on("mouse",or),qe.register({id:"github.pull-requests",intervalMs:1e3,run:k=>ud(p,un,k)}),qe.register({id:"agent.activity-indicators",intervalMs:150,run:()=>{if(!f.previews.isEnabled(p.config,"agentActivityIndicators")){ke=0,vt=!1;return}let k=Date.now(),L=wc(p.model.tasks,p.ptyRuntime.getActivitySnapshots?.()??[],k);(L||vt)&&(ke=(ke+1)%6,p.state.mode==="main"&&p.render()),vt=L}}),qe.start(),f.version.checkForUpdate().then(k=>{k.updateAvailable&&k.latest&&(p.updateText=`Update available: v${k.latest}`,p.render())}),p.bootHydrationReady=No(p).catch(()=>{}),p.render()})}async function ww(){try{if(process.argv[2]==="__craig-daemon"){let e=process.argv[3]??process.cwd(),t=Z(e);return await Hl(t),0}if(process.argv[2]==="__craig-daemon-shutdown"){let e=process.argv[3]??process.cwd(),t=Z(e);return await zl(t),0}}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
124
|
+
`),1}return ja({argv:process.argv.slice(2),cwd:process.cwd(),env:process.env,isInputTty:process.stdin.isTTY===!0,isOutputTty:process.stdout.isTTY===!0,writeStdout:e=>process.stdout.write(e),writeStderr:e=>process.stderr.write(e),runInteractive:e=>Id({uiStateFile:Z(e).uiStateFile,workspaceRoot:e})})}var kw=await ww();process.exit(kw);
|