craig-cli 0.7.7 → 0.7.8
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 +52 -52
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await
|
|
4
|
-
`)};var
|
|
2
|
+
var ul=Object.defineProperty;var ur=(e,t)=>{for(var r in t)ul(e,r,{get:t[r],enumerable:!0})};import{readFile as hl}from"node:fs/promises";import{randomUUID as pl}from"node:crypto";import{open as fl,readFile as mm,rename as ml,rm as gl}from"node:fs/promises";import pr from"node:path";async function M(e,t){let r=pr.dirname(e),n=pr.join(r,`.${pr.basename(e)}.${process.pid}.${Date.now()}.${pl()}.tmp`),s=await fl(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await ml(n,e)}catch(o){throw await s.close().catch(()=>{}),await gl(n,{force:!0}).catch(()=>{}),o}}async function Me(e){try{let t=await hl(e.uiStateFile,"utf8"),r=JSON.parse(t);return kl(r,e.uiStateFile)}catch(t){if(Tl(t))return null;throw t}}async function me(e,t){await M(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function St(){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 kl(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")||!je(e,"inputMode")||!je(e,"focusedRegion")||!je(e,"activeTab")||!je(e,"inspectorSection")||!je(e,"inspectionMode")||!Pt(e,"openInspectionKind")||!Pt(e,"selectedFileTreePath")||!Pt(e,"selectedFilePath")||!Pt(e,"selectedDiffPath")||!wl(e,"collapsedFileTreePaths")||!je(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 je(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Pt(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function wl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function Tl(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var fr={};ur(fr,{RUNNER_IDS:()=>A,assertEnabled:()=>cs,buildCommand:()=>ps,getConfiguredProfile:()=>bt,getDefault:()=>ls,getDisplayName:()=>us,getEnabled:()=>It,getProfile:()=>Oe,isRunnerType:()=>Ct,parse:()=>ds,setRunnerEnabled:()=>fs,setRunnerPath:()=>ms});var A=["codex","cursor","claude"];var as={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 Oe=e=>as[e];var bt=(e,t={})=>{let r=Oe(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var It=(e={})=>A.filter(t=>e.runners?.[t]?.enabled!==!1);var ls=(e={})=>{let t=It(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 cs=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var Ct=e=>A.includes(e);var ds=e=>{if(!e||e.length===0)return"codex";if(!Ct(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${A.join(", ")}.`);return e};var us=e=>Oe(e).displayName;var ps=(e,t,r={})=>{let n=[bt(e,r).executable];return t&&t.length>0&&n.push(t),n};var fs=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var ms=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};import{mkdir as Rl,readFile as yl,writeFile as Pl}from"node:fs/promises";import Sl from"node:path";var bl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",gs=async e=>{try{return await yl(e,"utf8")}catch(t){if(bl(t))return null;throw t}},hs=async(e,t)=>{await Rl(Sl.dirname(e),{recursive:!0}),await Pl(e,t,"utf8")};var vt=(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(!A.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${A.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.`)}return r};var mr=async(e,t={readConfigFile:gs})=>{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 vt(n,e.configFile)};var gr=async(e,t,r={writeConfigFile:hs})=>{vt(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var hr={};ur(hr,{checkForUpdate:()=>ks,getCurrent:()=>Et});var Et=()=>{try{return"0.7.8"}catch{return"unknown"}};var Il="https://registry.npmjs.org/craig-cli/latest",Cl=3600*1e3,vl={value:null},El=(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},ks=async(e={fetch:globalThis.fetch,getCurrent:Et,cache:vl})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<Cl)return e.cache.value.result;let n=null;try{let o=await e.fetch(Il,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&El(n,t)};return e.cache.value={result:s,cachedAt:r},s};var h={load:mr,save:gr,runners:fr,version:hr};function ws(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
|
|
5
5
|
|
|
6
|
-
`+
|
|
6
|
+
`+U());return{mode:"command",command:{kind:"addRepo",path:r}}}if(t.length>=3&&t[0]==="workspace"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Workspace path cannot be empty.
|
|
7
7
|
|
|
8
|
-
`+
|
|
8
|
+
`+U());return{mode:"command",command:{kind:"addWorkspace",path:r}}}if(t.length===2&&t[0]==="repo"&&t[1]==="list")return{mode:"command",command:{kind:"listRepos"}};if(t.length===3&&t[0]==="repo"&&t[1]==="remove")return{mode:"command",command:{kind:"removeRepo",repoId:t[2].trim()}};if(t.length>=2&&t.length<=3&&t[0]==="workspace"&&t[1]==="list"){let r=t[2]==="--archived";if(t.length===3&&!r)throw new Error(`Unsupported command: ${t.join(" ")}
|
|
9
9
|
|
|
10
|
-
${
|
|
10
|
+
${U()}`);return{mode:"command",command:{kind:"listWorkspaces",archived:r}}}if(t.length===3&&t[0]==="workspace"&&t[1]==="archive")return{mode:"command",command:{kind:"archiveWorkspace",workspaceId:t[2].trim()}};if(t.length===3&&t[0]==="workspace"&&t[1]==="restore")return{mode:"command",command:{kind:"restoreWorkspace",workspaceId:t[2].trim()}};if(t.length===3&&t[0]==="workspace"&&t[1]==="remove")return{mode:"command",command:{kind:"removeWorkspace",workspaceId:t[2].trim()}};if(t.length>=2&&t[0]==="task"&&t[1]==="new"){let r=t.indexOf("--repo"),n=t.indexOf("--workspace"),s=t.indexOf("--runner");if(r===-1&&n===-1)throw new Error(`Task creation now requires '--repo <repo-id>' or '--workspace <workspace-id>'.
|
|
11
11
|
|
|
12
|
-
`+
|
|
12
|
+
`+U());if(r!==-1&&n!==-1)throw new Error(`Task creation accepts either '--repo' or '--workspace', not both.
|
|
13
13
|
|
|
14
|
-
`+
|
|
14
|
+
`+U());let o=r===-1?void 0:t[r+1]?.trim()??"",i=n===-1?void 0:t[n+1]?.trim()??"",a=s===-1?void 0:h.runners.parse(t[s+1]?.trim()??""),c=t.filter((d,p)=>p>1&&p!==r&&p!==r+1&&p!==n&&p!==n+1&&p!==s&&p!==s+1).join(" ").trim();if(o!==void 0&&o.length===0)throw new Error(`Repo id cannot be empty.
|
|
15
15
|
|
|
16
|
-
`+
|
|
16
|
+
`+U());if(i!==void 0&&i.length===0)throw new Error(`Workspace id cannot be empty.
|
|
17
17
|
|
|
18
|
-
`+
|
|
18
|
+
`+U());if(c.length===0)throw new Error(`Task prompt cannot be empty.
|
|
19
19
|
|
|
20
|
-
`+
|
|
20
|
+
`+U());return{mode:"command",command:{kind:"createTask",...o?{repoId:o}:{},...i?{workspaceId:i}:{},prompt:c,...a?{runner:a}:{}}}}if(t.length>=2&&t.length<=4&&t[0]==="task"&&t[1]==="list"){if(t.length===2)return{mode:"command",command:{kind:"listTasks"}};if(t.length===4&&t[2]==="--repo")return{mode:"command",command:{kind:"listTasks",repoId:t[3].trim()}};throw new Error(`Unsupported command: ${t.join(" ")}
|
|
21
21
|
|
|
22
|
-
${
|
|
22
|
+
${U()}`)}if(t.length===3&&t[0]==="task"&&t[1]==="attach")return{mode:"command",command:{kind:"attachTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="show")return{mode:"command",command:{kind:"showTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="logs")return{mode:"command",command:{kind:"streamTaskLogs",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="diff")return{mode:"command",command:{kind:"showTaskDiff",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="focus")return{mode:"command",command:{kind:"focusTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="open")return{mode:"command",command:{kind:"openTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="check")return{mode:"command",command:{kind:"runChecks",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="commit")return{mode:"command",command:{kind:"commitTask",taskId:re(t[2])}};if(t.length===4&&t[0]==="link"&&t[1]==="add")return{mode:"command",command:{kind:"addTaskLink",taskId:re(t[2]),repoId:Al(t[3])}};if(t.length===3&&t[0]==="link"&&t[1]==="list")return{mode:"command",command:{kind:"listTaskLinks",taskId:re(t[2])}};throw new Error(`Unsupported command: ${t.join(" ")}
|
|
23
23
|
|
|
24
|
-
${
|
|
24
|
+
${U()}`)}function U(){return["Craig commands:"," craig Show the Craig phase 0 placeholder"," craig repo add 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 Remove a registered repo"," craig workspace list List active workspaces"," craig workspace list --archived List archived workspaces"," craig workspace archive Archive a workspace"," craig workspace restore Restore an archived workspace"," craig workspace remove Remove an archived workspace"," craig task new --repo <repo-id> [--runner codex|cursor|claude] <prompt> Create a new Craig repo task"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude] <prompt> Create a new Craig workspace task"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task show Show details for a Craig task"," craig task logs Stream Craig-managed logs for a task"," craig task diff Show the current worktree diff for a task"," craig task attach Attach to a live task session"," craig task focus Focus the tmux pane for a task"," craig task open Open the task worktree or print its path"," craig task check Run configured checks for a task"," craig task commit Commit all task worktree changes"," craig link add Add a linked repo to a task"," craig link list List linked repos for a task"].join(`
|
|
25
25
|
`)}function re(e){let t=e.trim();if(t.length===0)throw new Error(`Task id cannot be empty.
|
|
26
26
|
|
|
27
|
-
${
|
|
27
|
+
${U()}`);return t}function Al(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
28
28
|
|
|
29
|
-
${K()}`);return t}var F=(e,t)=>{let r=fr(e);if(!bl(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},fr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:mr(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:vl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Il(t.repoTargets),runnerSession:t.runnerSession??Sl(t),checks:Ll(t),lastCommit:t.lastCommit??null,prs:Ml(t),artifacts:Wl(t),cleanup:_l(t)}},Sl=e=>{if(typeof e.title!="string")return null;let t=mr(e.runner);return{command:h.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},bl=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"&&h.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"&&hs(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||Cl(t.repoTargets))&&xl(t.runnerSession)&&Al(t.prompt)&&ks(t.checks)&&ws(t.lastCommit)&&$l(t.prs)&&jl(t.artifacts)&&Rs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Il=e=>{if(Array.isArray(e))return e.filter(gs)},Cl=e=>Array.isArray(e)&&e.every(gs),gs=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)&&ks(t.checks)&&ws(t.lastCommit)&&Ts(t.pullRequest)&&Rs(t.cleanup)},vl=e=>{if(hs(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 El(e.id,e.title,t,mr(e.runner))},El=(e,t,r,n)=>{let s=h.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:h.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},mr=e=>e&&h.runners.isRunnerType(e)?e:"codex",hs=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"),xl=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),Al=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",ks=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"),ws=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Ts=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Dl(e.requiredChecks),Dl=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)),$l=e=>Array.isArray(e)&&e.every(Ts),jl=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),Rs=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),Ll=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Ml=e=>{if(Array.isArray(e.prs))return e.prs.map(Ol);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:ys(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Ps(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ol=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:ys(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Fl(t.reviewDecision),requiredChecks:Ps(t.requiredChecks),comments:Nl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},ys=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Fl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Nl=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}]}):[],Ps=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})):[],Wl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},_l=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as cc}from"node:fs/promises";import{readFile as ql,readdir as Bl,rm as Ul}from"node:fs/promises";import Ss from"node:path";var gr=(e,t)=>Ss.join(e.workspacesDir,`${t}.json`),Kl=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"):[]}},bs=(e,t)=>{let r=Kl(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},Pe=async(e,t)=>{let r=gr(e,t),n=await ql(r,"utf8");return bs(JSON.parse(n),r)},Se=async(e,t)=>{await M(gr(e,t.id),{...t,updatedAt:new Date().toISOString()})},q=async e=>{let t=await Bl(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Pe(e,Ss.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Is=async(e,t)=>{await Ul(gr(e,t),{force:!0})};import{readFile as Vl,readdir as Gl,rm as Hl}from"node:fs/promises";import Cs from"node:path";var hr=(e,t)=>Cs.join(e.reposDir,`${t}.json`),vs=(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},X=async(e,t)=>{let r=hr(e,t),n=await Vl(r,"utf8");return vs(JSON.parse(n),r)},kr=async(e,t)=>{await M(hr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Je=async e=>{let t=await Gl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>X(e,Cs.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Es=async(e,t)=>{await Hl(hr(e,t),{force:!0})};import{readFile as zl}from"node:fs/promises";var Ql=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"},vt=(e,t,r)=>{if(!Ql(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},V=async e=>{let t=await zl(e.indexFile,"utf8");return vt(JSON.parse(t),e.workspaceRoot,e.indexFile)},le=async(e,t)=>{await M(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as ec,stat as tc}from"node:fs/promises";import Ne from"node:path";import{realpath as Ds}from"node:fs/promises";import $s from"node:path";import{execFile as Yl}from"node:child_process";import{promisify as Jl}from"node:util";var xs=Jl(Yl);async function T(e,t,r={}){try{let n=await xs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(As(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function E(e,t,r={}){try{let n=await xs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(As(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function As(e){return e instanceof Error}var wr=async e=>{try{let r=(await T("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Ds(r).catch(()=>$s.resolve(r)),Ds(e).catch(()=>$s.resolve(e))]);return n===s}catch{return!1}},Tr=async e=>{let t=await E("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 E("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await T("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as se,readFile as Xl}from"node:fs/promises";import G from"node:path";function ne(e){let t=G.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:G.join(t,"index.json"),reposDir:G.join(t,"repos"),workspacesDir:G.join(t,"workspaces"),sessionsDir:G.join(t,"sessions"),runtimeDir:G.join(t,"runtime"),uiStateFile:G.join(t,"runtime","ui-state.json"),tasksDir:G.join(t,"tasks"),jobsDir:G.join(t,"jobs"),logsDir:G.join(t,"logs"),errorLogFile:G.join(t,"logs","errors.log"),artifactsDir:G.join(t,"artifacts"),worktreesDir:G.join(t,"worktrees"),configFile:G.join(t,"config.json")}}var Zl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Fe=async e=>{let t=ne(e);await se(t.craigDir,{recursive:!0}),await Promise.all([se(t.reposDir,{recursive:!0}),se(t.workspacesDir,{recursive:!0}),se(t.sessionsDir,{recursive:!0}),se(t.runtimeDir,{recursive:!0}),se(t.tasksDir,{recursive:!0}),se(t.jobsDir,{recursive:!0}),se(t.logsDir,{recursive:!0}),se(t.artifactsDir,{recursive:!0}),se(t.worktreesDir,{recursive:!0})]);try{let s=await Xl(t.indexFile,"utf8"),o=JSON.parse(s);return vt(o,e,t.indexFile)}catch(s){if(!Zl(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 M(t.indexFile,n),n};var js=(e,t,r)=>{let n=new Date().toISOString();return{id:rc(e,Ne.basename(t)),name:Ne.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Ls=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},rc=(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},nc=(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},Ms=async(e,t)=>{let r=await V(e);await le(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},sc=async(e,t)=>{let r=await ec(t,{withFileTypes:!0}),n=await Je(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ne.join(t,o.name);if(!await wr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await Tr(i);s.push(a?Ls(a,l):js([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},oc=async(e,t)=>{let r=await Tr(t),n=await Je(e),s=n.find(p=>p.rootPath===t)??null,o=s?Ls(s,r):js(n,t,r),i=`workspace_${o.id}`,l=(await q(e)).find(p=>p.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 kr(e,o),l||await Se(e,d),await Ms(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},ic=async(e,t)=>{let r=await sc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await q(e),s=nc(n,Ne.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:Ne.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=>kr(e,c))),await Se(e,l),await Ms(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Xe=async(e,t)=>{await Fe(e.workspaceRoot);let r=Ne.resolve(e.workspaceRoot,t);if(!(await tc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await wr(r)?oc(e,r):ic(e,r)};var Rr=async(e,t,r={listWorkspaceRecords:q,ensureCraigState:Fe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var yr=async(e,t,r={readWorkspace:Pe,writeWorkspace:Se})=>{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 Pr=async(e,t)=>{let n={...await Pe(e,t),status:"active",archivedAt:null};await Se(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 be=async(e,t,r={deleteWorkspace:Is,readCraigIndex:V,writeCraigIndex:le})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Sr=async(e,t,r)=>{let n=await Pe(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 be(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var br={};ar(br,{addRepo:()=>Os,listRegisteredRepos:()=>Fs,removeRepo:()=>Ns});import ac from"node:path";import{stat as lc}from"node:fs/promises";var Os=async(e,t)=>{let r=ac.resolve(e.workspaceRoot,t);if(!(await lc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Xe(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 Fs=async(e,t={listRepos:Je,ensureCraigState:Fe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ns=async(e,t,r)=>{let n=await X(e,t),o=(await q(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=>be(e,c.id))),await Es(e,t);let l=await V(e);return await le(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Q={addWorkspace:Xe,listWorkspaces:Rr,archiveWorkspace:yr,restoreWorkspace:Pr,removeWorkspace:Sr,removeWorkspaceRecord:be,repos:br};var H=async(e,t)=>{let r=await cc(Cr(e,t),"utf8");return JSON.parse(r)},Y=async(e,t)=>{let r=await H(e,t);return F(r,Cr(e,t))},y=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await M(Cr(e,t.id),r)},Ir=async(e,t)=>{let r=await V(e);r.taskIds.includes(t)||await le(e,{...r,taskIds:[...r.taskIds,t]})},Cr=(e,t)=>`${e.tasksDir}/${t}.json`;var v=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ge=e=>e.status==="merged"||e.status==="closed",We=(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}},Ze=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return xt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},xt=e=>e.mergeable&&!dc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),dc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",vr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),et=(e,t)=>{let r=e.isDraft??!1,n=uc(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:pc(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:hc(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}},uc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,pc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,tt=e=>{let t=e.map(n=>fc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||mc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},fc=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:_s(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:gc(t)}:null},mc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Et(e)&&!Et(t)?!0:!Et(e)&&Et(t)?!1:Ws(t.status)>=Ws(e.status),Et=e=>e.conclusion?.toUpperCase()==="CANCELLED",Ws=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},gc=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},hc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(kc).filter(r=>r!==null).slice(-4):[]},kc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=wc(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},wc=e=>e.replace(/\s+/g," ").trim(),_s=(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?_s(n,n):"unknown"};import{access as Tc}from"node:fs/promises";import qs from"node:path";var S=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw bc(n)?new Error(`Craig task "${t}" was not found.`):n}},N=async e=>{if(!await Er(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},_e=(e,t)=>t.artifacts.logPath?qs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:qs.join(e.workspaceRoot,t.artifacts.logPath):null,rt=async(e,t)=>{let r=await Er(t.worktreePath),n=_e(e,t),s=n?await Er(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Rc(t),lastCommitSummary:yc(t),prSummary:Pc(t),cleanupSummary:Sc(t)}},Er=async e=>{try{return await Tc(e),!0}catch{return!1}},Rc=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}`},yc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Pc=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})
|
|
29
|
+
${U()}`);return t}var F=(e,t)=>{let r=kr(e);if(!Dl(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},kr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:wr(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:jl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:$l(t.repoTargets),runnerSession:t.runnerSession??xl(t),checks:ql(t),lastCommit:t.lastCommit??null,prs:Bl(t),artifacts:Gl(t),cleanup:Hl(t)}},xl=e=>{if(typeof e.title!="string")return null;let t=wr(e.runner);return{command:h.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Dl=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"&&h.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"&&Rs(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||Ll(t.repoTargets))&&Ol(t.runnerSession)&&Fl(t.prompt)&&ys(t.checks)&&Ps(t.lastCommit)&&Wl(t.prs)&&_l(t.artifacts)&&bs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},$l=e=>{if(Array.isArray(e))return e.filter(Ts)},Ll=e=>Array.isArray(e)&&e.every(Ts),Ts=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)&&ys(t.checks)&&Ps(t.lastCommit)&&Ss(t.pullRequest)&&bs(t.cleanup)},jl=e=>{if(Rs(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 Ml(e.id,e.title,t,wr(e.runner))},Ml=(e,t,r,n)=>{let s=h.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:h.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},wr=e=>e&&h.runners.isRunnerType(e)?e:"codex",Rs=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"),Ol=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),Fl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",ys=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"),Ps=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Ss=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Nl(e.requiredChecks),Nl=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)),Wl=e=>Array.isArray(e)&&e.every(Ss),_l=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),bs=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),ql=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Bl=e=>{if(Array.isArray(e.prs))return e.prs.map(Ul);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Is(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Cs(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ul=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:Is(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Kl(t.reviewDecision),requiredChecks:Cs(t.requiredChecks),comments:Vl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Is=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Kl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Vl=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}]}):[],Cs=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})):[],Gl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Hl=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as hc}from"node:fs/promises";import{readFile as zl,readdir as Ql,rm as Yl}from"node:fs/promises";import vs from"node:path";var Tr=(e,t)=>vs.join(e.workspacesDir,`${t}.json`),Jl=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"):[]}},Es=(e,t)=>{let r=Jl(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},Pe=async(e,t)=>{let r=Tr(e,t),n=await zl(r,"utf8");return Es(JSON.parse(n),r)},Se=async(e,t)=>{await M(Tr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Q=async e=>{let t=await Ql(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Pe(e,vs.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},As=async(e,t)=>{await Yl(Tr(e,t),{force:!0})};import{readFile as Xl,readdir as Zl,rm as ec}from"node:fs/promises";import xs from"node:path";var Rr=(e,t)=>xs.join(e.reposDir,`${t}.json`),Ds=(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},X=async(e,t)=>{let r=Rr(e,t),n=await Xl(r,"utf8");return Ds(JSON.parse(n),r)},yr=async(e,t)=>{await M(Rr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Je=async e=>{let t=await Zl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>X(e,xs.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},$s=async(e,t)=>{await ec(Rr(e,t),{force:!0})};import{readFile as tc}from"node:fs/promises";var rc=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"},At=(e,t,r)=>{if(!rc(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},K=async e=>{let t=await tc(e.indexFile,"utf8");return At(JSON.parse(t),e.workspaceRoot,e.indexFile)},le=async(e,t)=>{await M(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as ac,stat as lc}from"node:fs/promises";import Ne from"node:path";import{realpath as Ms}from"node:fs/promises";import Os from"node:path";import{execFile as nc}from"node:child_process";import{promisify as sc}from"node:util";var Ls=sc(nc);async function T(e,t,r={}){try{let n=await Ls(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(js(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function E(e,t,r={}){try{let n=await Ls(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(js(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function js(e){return e instanceof Error}var Pr=async e=>{try{let r=(await T("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Ms(r).catch(()=>Os.resolve(r)),Ms(e).catch(()=>Os.resolve(e))]);return n===s}catch{return!1}},Sr=async e=>{let t=await E("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 E("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await T("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as se,readFile as oc}from"node:fs/promises";import V from"node:path";function ne(e){let t=V.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:V.join(t,"index.json"),reposDir:V.join(t,"repos"),workspacesDir:V.join(t,"workspaces"),sessionsDir:V.join(t,"sessions"),runtimeDir:V.join(t,"runtime"),uiStateFile:V.join(t,"runtime","ui-state.json"),tasksDir:V.join(t,"tasks"),jobsDir:V.join(t,"jobs"),logsDir:V.join(t,"logs"),errorLogFile:V.join(t,"logs","errors.log"),artifactsDir:V.join(t,"artifacts"),worktreesDir:V.join(t,"worktrees"),configFile:V.join(t,"config.json")}}var ic=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Fe=async e=>{let t=ne(e);await se(t.craigDir,{recursive:!0}),await Promise.all([se(t.reposDir,{recursive:!0}),se(t.workspacesDir,{recursive:!0}),se(t.sessionsDir,{recursive:!0}),se(t.runtimeDir,{recursive:!0}),se(t.tasksDir,{recursive:!0}),se(t.jobsDir,{recursive:!0}),se(t.logsDir,{recursive:!0}),se(t.artifactsDir,{recursive:!0}),se(t.worktreesDir,{recursive:!0})]);try{let s=await oc(t.indexFile,"utf8"),o=JSON.parse(s);return At(o,e,t.indexFile)}catch(s){if(!ic(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 M(t.indexFile,n),n};var Fs=(e,t,r)=>{let n=new Date().toISOString();return{id:cc(e,Ne.basename(t)),name:Ne.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Ns=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},cc=(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},dc=(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},Ws=async(e,t)=>{let r=await K(e);await le(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},uc=async(e,t)=>{let r=await ac(t,{withFileTypes:!0}),n=await Je(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ne.join(t,o.name);if(!await Pr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await Sr(i);s.push(a?Ns(a,l):Fs([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},pc=async(e,t)=>{let r=await Sr(t),n=await Je(e),s=n.find(p=>p.rootPath===t)??null,o=s?Ns(s,r):Fs(n,t,r),i=`workspace_${o.id}`,l=(await Q(e)).find(p=>p.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 yr(e,o),l||await Se(e,d),await Ws(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},fc=async(e,t)=>{let r=await uc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Q(e),s=dc(n,Ne.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:Ne.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=>yr(e,c))),await Se(e,l),await Ws(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Xe=async(e,t)=>{await Fe(e.workspaceRoot);let r=Ne.resolve(e.workspaceRoot,t);if(!(await lc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Pr(r)?pc(e,r):fc(e,r)};var br=async(e,t,r={listWorkspaceRecords:Q,ensureCraigState:Fe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Ir=async(e,t,r={readWorkspace:Pe,writeWorkspace:Se})=>{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 Cr=async(e,t)=>{let n={...await Pe(e,t),status:"active",archivedAt:null};await Se(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 be=async(e,t,r={deleteWorkspace:As,readCraigIndex:K,writeCraigIndex:le})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var vr=async(e,t,r)=>{let n=await Pe(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 be(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Er={};ur(Er,{addRepo:()=>_s,listRegisteredRepos:()=>qs,removeRepo:()=>Bs});import mc from"node:path";import{stat as gc}from"node:fs/promises";var _s=async(e,t)=>{let r=mc.resolve(e.workspaceRoot,t);if(!(await gc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Xe(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 qs=async(e,t={listRepos:Je,ensureCraigState:Fe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Bs=async(e,t,r)=>{let n=await X(e,t),o=(await Q(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=>be(e,c.id))),await $s(e,t);let l=await K(e);return await le(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var G={addWorkspace:Xe,listWorkspaces:br,archiveWorkspace:Ir,restoreWorkspace:Cr,removeWorkspace:vr,removeWorkspaceRecord:be,repos:Er};var H=async(e,t)=>{let r=await hc(xr(e,t),"utf8");return JSON.parse(r)},Y=async(e,t)=>{let r=await H(e,t);return F(r,xr(e,t))},y=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await M(xr(e,t.id),r)},Ar=async(e,t)=>{let r=await K(e);r.taskIds.includes(t)||await le(e,{...r,taskIds:[...r.taskIds,t]})},xr=(e,t)=>`${e.tasksDir}/${t}.json`;var v=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ge=e=>e.status==="merged"||e.status==="closed",We=(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}},Ze=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Dt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Dt=e=>e.mergeable&&!kc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),kc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Dr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),et=(e,t)=>{let r=e.isDraft??!1,n=wc(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:Tc(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:Sc(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}},wc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Tc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,tt=e=>{let t=e.map(n=>Rc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||yc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},Rc=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:Ks(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:Pc(t)}:null},yc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):xt(e)&&!xt(t)?!0:!xt(e)&&xt(t)?!1:Us(t.status)>=Us(e.status),xt=e=>e.conclusion?.toUpperCase()==="CANCELLED",Us=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},Pc=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},Sc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(bc).filter(r=>r!==null).slice(-4):[]},bc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=Ic(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},Ic=e=>e.replace(/\s+/g," ").trim(),Ks=(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?Ks(n,n):"unknown"};import{access as Cc}from"node:fs/promises";import Vs from"node:path";var S=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Dc(n)?new Error(`Craig task "${t}" was not found.`):n}},N=async e=>{if(!await $r(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},_e=(e,t)=>t.artifacts.logPath?Vs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Vs.join(e.workspaceRoot,t.artifacts.logPath):null,rt=async(e,t)=>{let r=await $r(t.worktreePath),n=_e(e,t),s=n?await $r(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:vc(t),lastCommitSummary:Ec(t),prSummary:Ac(t),cleanupSummary:xc(t)}},$r=async e=>{try{return await Cc(e),!0}catch{return!1}},vc=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}`},Ec=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Ac=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})
|
|
30
30
|
${o.join(`
|
|
31
|
-
`)}`}let t=v(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})`},
|
|
32
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}};var
|
|
31
|
+
`)}`}let t=v(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})`},xc=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",Dc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Gs=async(e,t)=>{let r=await E("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.")},Lr=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await E("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 $c(e,s);await T("git",["worktree","add","-b",t,r,i],{cwd:e})},$c=async(e,t)=>(await E("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await E("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await E("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,$t=async e=>{let t=await E("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},Hs=async e=>{await T("git",["add","-A"],{cwd:e})},zs=async(e,t)=>{await T("git",["commit","-m",t],{cwd:e})},Qs=async e=>{let t=await T("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",n=""]=t.stdout.trim().split(`
|
|
32
|
+
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}};var Ys=async(e,t)=>{await T("git",["worktree","remove","--force",t],{cwd:e})};var jr=async e=>qe(e,e.repoRoot),qe=async(e,t)=>{let r=await K(e),n=Js(new Date),s=Xs(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await Gs(t,i))return o;s+=1}},nt=async e=>{let t=await K(e),r=Js(new Date),n=Xs(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},Js=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},Xs=(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 Mr=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{let n=await K(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(Lc(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}},Lc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Zs=["merge_ready","pr_open","checked","review","running","draft"],Or=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),Fr=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(jc)[0]?.id??null,jc=(e,t)=>{let r=eo(e.status),n=eo(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},eo=e=>{let t=Zs.indexOf(e);return t>=0?t:Zs.length};import to from"node:path";var Ie=(e,t)=>t?to.isAbsolute(t)?t:to.join(e.repoRoot,t):null;import{mkdir as st,rm as Mc,writeFile as Lt}from"node:fs/promises";import C from"node:path";var no=["AGENTS","md"].join("."),Be=async(e,t,r,n={})=>{let s=await X(e,t),o=await _c(e,s.id),i=await qe(e,s.rootPath),a=n.sessionId??null,l=`craig/${i}`,c=C.join(e.worktreesDir,s.id,i),d=C.join(e.logsDir,`${i}.log`),p=C.join(e.artifactsDir,i);await st(C.dirname(c),{recursive:!0}),await st(p,{recursive:!0}),await Lt(d,"","utf8");let f=Oc(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 y(e,f),await Ar(e,i),await Lr(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:f}},ot=async(e,t,r,n={})=>{let s=(await Q(e)).find(k=>k.id===t&&k.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 k=await Be(e,s.primaryRepoId,r,n);return{...k,bundlePath:k.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await nt(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,p=C.join(e.craigDir,"task-bundles",i),f=C.join(e.logsDir,`${i}.log`),u=C.join(e.artifactsDir,i);await st(p,{recursive:!0}),await st(u,{recursive:!0}),await Lt(f,"","utf8");let w=await Promise.all(o.map(k=>X(e,k))),R=Nc(w),x=await Promise.all(w.map(k=>Fc(e,k,i,d,C.join(p,R.get(k.id))))),B=x.find(k=>k.status==="ready")??x[0];if(!x.some(k=>k.status==="ready"))throw await Mc(p,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${x.map(k=>`${k.repoId}: ${k.failureReason??"unknown error"}`).join("; ")}`);await Lt(C.join(p,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:x.map(k=>({repoId:k.repoId,repoName:w.find(Ye=>Ye.id===k.repoId)?.name??k.repoId,path:C.relative(p,k.worktreePath),status:k.status,worktreePath:k.worktreePath,failureReason:k.failureReason}))},null,2),"utf8"),await Lt(C.join(p,no),Wc({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:x,bundlePath:p}),"utf8");let fe=it(i,r,a,l,n.config??{}),ae={id:i,title:r,slug:so(r),type:"project",status:"draft",runner:l,repoId:B.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:fe[0]?.id??null,linkedRepoIds:o.filter(k=>k!==B.repoId),repoRoot:p,worktreePath:p,branch:d,bundlePath:p,selectedRepoTargetId:B.repoId,repoTargets:x,ptyTabs:fe,runnerSession:{command:h.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:B.checks,lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,f),checkSummaryPath:C.relative(e.workspaceRoot,C.join(u,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(u,"pr-status.json"))},cleanup:jt(),lastFailureReason:x.every(k=>k.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await y(e,ae),await Ar(e,i),{repoId:B.repoId,repoRoot:p,sessionId:c,workspaceId:s.id,task:ae,bundlePath:p,repoTargets:x}},it=(e,t,r,n="codex",s={})=>{let o=h.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:h.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Oc=(e,t)=>{let r=new Date().toISOString(),n=it(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:so(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:h.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:{...Nr(C.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,C.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:jt(),lastFailureReason:null,createdAt:r,updatedAt:r}},Fc=async(e,t,r,n,s)=>{await st(C.dirname(s),{recursive:!0});try{return await Lr(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Nr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:ro(),cleanup:jt()}}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:Nr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:ro(),cleanup:jt()}}},Nc=e=>{let t=new Set(["manifest.json",no]),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},Wc=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=C.relative(e.bundlePath,n.worktreePath),i=n.status==="ready"?"ready":`unavailable: ${n.failureReason??"unknown error"}`;return`- \`${o}/\` - ${s} (${n.repoId}, ${i})`}).join(`
|
|
33
33
|
`);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(`
|
|
34
|
-
`)},Lr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Xs=()=>({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}),$t=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),jc=async(e,t)=>{let n=(await q(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},eo=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import po from"node:path";import{readFile as Lc,rm as gk}from"node:fs/promises";import Mc from"node:path";var he=async(e,t)=>{let r=await Lc(Mr(e,t),"utf8"),n=JSON.parse(r);return Oc(n,Mr(e,t))},Ce=async(e,t)=>{await M(Mr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Mr=(e,t)=>Mc.join(e.sessionsDir,`${t}.json`);function Oc(e,t){let r=Wc(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")||!Nc(r.attach)||!Fc(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 Fc(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 Nc(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 Wc(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 _c}from"node:child_process";import{createHash as qc}from"node:crypto";import Bc from"node:path";function jt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Uc="craig",to=async(e,t,r)=>{let n=Or(e,t),s=Vc(),o=await T("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Hc(o.stdout);return await Kc(e,n),i};var Kc=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 T("tmux",n,{cwd:e})},ro=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},no=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var so=async(e,t,r)=>{await T("tmux",["pipe-pane","-o","-t",e,`cat >> ${jt(t)}`],{cwd:r})},Lt=async(e,t,r,n)=>{let s=n??io(e);if(r?await T("tmux",["select-window","-t",r],{cwd:e}):await T("tmux",["select-window","-t",t],{cwd:e}),await T("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await T("tmux",["switch-client","-t",s],{cwd:e});return}await Qc(e,["attach-session","-t",s])};var oo=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var io=e=>{let r=Bc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=qc("sha1").update(e).digest("hex").slice(0,8);return`${Uc}-${r}-${n}`},Or=(e,t)=>`${io(e)}-${t.toLowerCase()}`,Vc=()=>{let e=Gc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Gc=()=>{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},Hc=e=>{let t=zc(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]}},zc=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Qc=async(e,t)=>{await new Promise((r,n)=>{let s=_c("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 Yc,constants as Jc}from"node:fs";import{homedir as ao}from"node:os";import ke from"node:path";var Xc=[ke.join(ao(),".local","bin"),ke.join(ao(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function co(e=process.env){return Zc([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Xc])}function ve(e=process.env){return{...e,PATH:co(e).join(ke.delimiter)}}function Fr(e,t={}){if(e.includes(ke.sep)){let r=ke.isAbsolute(e)?e:ke.resolve(t.cwd??process.cwd(),e);return lo(r)?r:null}for(let r of co(t.env)){let n=ke.join(r,e);if(lo(n))return n}return null}function Ee(e,t={}){let r=Fr(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 lo(e){try{return Yc(e,Jc.X_OK),!0}catch{return!1}}function Zc(e){return[...new Set(e)]}var at={async create(e,t){let r=await to(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await so(r.paneId,t.logPath,t.repoRoot);let n=await uo({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||Or(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 Ce(e,s),s},async attach(e,t,r){let n=await at.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Lt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ce(e,s),s},async resize(e,t,r,n){await ro(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ce(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 Ce(e,n),n},async snapshot(e,t){return ed(e,t)}},Nr={async prepare(e,t){let n=e.runnerSession.command[0],s=ve();await T(Ee(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ee(r[0],{cwd:e.worktreePath,env:ve()});await no(t.session.paneId,[n,...r.slice(1)].map(s=>jt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},ed=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return uo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},uo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Wr=async(e,t,r,n={})=>{let s=r.trim(),o=await h.load(e),i=n.runner??h.runners.getDefault(o);if(h.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 ot(e,n.workspaceId,s,{runner:i,config:o}):await Be(e,t,s,{runner:i,config:o}),l=a.task,c=h.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?po.resolve(e.workspaceRoot,l.artifacts.logPath):po.join(e.logsDir,`${l.id}.log`);try{await Nr.prepare(l,{repoRoot:a.repoRoot});let f=await at.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Nr.launch(l,{repoRoot:a.repoRoot,session:f});let u=new Date().toISOString();f={...f,status:"running",startedAt:u,command:c};let w={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:u,lastKnownState:"running",exitCode:null,exitedAt:null}};return await y(e,w),await Ce(e,f),{kind:"createTask",taskId:w.id,repoId:w.repoId,workspaceId:w.workspaceId,sessionId:f.id,status:w.status,branch:w.branch,worktreePath:w.worktreePath,runner:w.runner}}catch(f){let u={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await y(e,u),f}};import{mkdir as dd}from"node:fs/promises";import ud from"node:path";var fo=3,td=1e3,rd=1e4,Ue=async e=>{let t=await E("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var mo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await T("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Mt=async(e,t)=>{let r=await T("gh",ko(e),{cwd:t});return JSON.parse(r.stdout)},Ot=async(e,t)=>{let r=await E("gh",ko(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},go=async(e,t,r)=>{if(r.length===0)return[];let n=ld(r),s=await nd(e,["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`]),i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=cd(c);return{id:a.id,found:d!==null,view:d}})},ho=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:ad(t.stdout.trim())},nd=async(e,t)=>{let r;for(let n=0;n<=fo;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===fo||!sd(s))throw s;await id(od(n))}throw r},sd=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")},od=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||td,r=Math.min(t*2**e,rd),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},id=e=>new Promise(t=>setTimeout(t,e)),ko=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],ad=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},ld=e=>`
|
|
34
|
+
`)},Nr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),ro=()=>({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}),jt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),_c=async(e,t)=>{let n=(await Q(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},so=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import ho from"node:path";import{readFile as qc,rm as bk}from"node:fs/promises";import Bc from"node:path";var he=async(e,t)=>{let r=await qc(Wr(e,t),"utf8"),n=JSON.parse(r);return Uc(n,Wr(e,t))},Ce=async(e,t)=>{await M(Wr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Wr=(e,t)=>Bc.join(e.sessionsDir,`${t}.json`);function Uc(e,t){let r=Gc(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")||!Vc(r.attach)||!Kc(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 Kc(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 Vc(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 Gc(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 Hc}from"node:child_process";import{createHash as zc}from"node:crypto";import Qc from"node:path";function Mt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Yc="craig",oo=async(e,t,r)=>{let n=_r(e,t),s=Xc(),o=await T("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=ed(o.stdout);return await Jc(e,n),i};var Jc=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 T("tmux",n,{cwd:e})},io=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},ao=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var lo=async(e,t,r)=>{await T("tmux",["pipe-pane","-o","-t",e,`cat >> ${Mt(t)}`],{cwd:r})},Ot=async(e,t,r,n)=>{let s=n??uo(e);if(r?await T("tmux",["select-window","-t",r],{cwd:e}):await T("tmux",["select-window","-t",t],{cwd:e}),await T("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await T("tmux",["switch-client","-t",s],{cwd:e});return}await rd(e,["attach-session","-t",s])};var co=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var uo=e=>{let r=Qc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=zc("sha1").update(e).digest("hex").slice(0,8);return`${Yc}-${r}-${n}`},_r=(e,t)=>`${uo(e)}-${t.toLowerCase()}`,Xc=()=>{let e=Zc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Zc=()=>{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},ed=e=>{let t=td(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]}},td=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),rd=async(e,t)=>{await new Promise((r,n)=>{let s=Hc("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 nd,constants as sd}from"node:fs";import{homedir as po}from"node:os";import ke from"node:path";var od=[ke.join(po(),".local","bin"),ke.join(po(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function mo(e=process.env){return id([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:od])}function ve(e=process.env){return{...e,PATH:mo(e).join(ke.delimiter)}}function qr(e,t={}){if(e.includes(ke.sep)){let r=ke.isAbsolute(e)?e:ke.resolve(t.cwd??process.cwd(),e);return fo(r)?r:null}for(let r of mo(t.env)){let n=ke.join(r,e);if(fo(n))return n}return null}function Ee(e,t={}){let r=qr(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 fo(e){try{return nd(e,sd.X_OK),!0}catch{return!1}}function id(e){return[...new Set(e)]}var at={async create(e,t){let r=await oo(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await lo(r.paneId,t.logPath,t.repoRoot);let n=await go({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||_r(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 Ce(e,s),s},async attach(e,t,r){let n=await at.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Ot(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ce(e,s),s},async resize(e,t,r,n){await io(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ce(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 Ce(e,n),n},async snapshot(e,t){return ad(e,t)}},Br={async prepare(e,t){let n=e.runnerSession.command[0],s=ve();await T(Ee(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ee(r[0],{cwd:e.worktreePath,env:ve()});await ao(t.session.paneId,[n,...r.slice(1)].map(s=>Mt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},ad=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return go({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},go=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Ur=async(e,t,r,n={})=>{let s=r.trim(),o=await h.load(e),i=n.runner??h.runners.getDefault(o);if(h.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 ot(e,n.workspaceId,s,{runner:i,config:o}):await Be(e,t,s,{runner:i,config:o}),l=a.task,c=h.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?ho.resolve(e.workspaceRoot,l.artifacts.logPath):ho.join(e.logsDir,`${l.id}.log`);try{await Br.prepare(l,{repoRoot:a.repoRoot});let f=await at.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Br.launch(l,{repoRoot:a.repoRoot,session:f});let u=new Date().toISOString();f={...f,status:"running",startedAt:u,command:c};let w={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:u,lastKnownState:"running",exitCode:null,exitedAt:null}};return await y(e,w),await Ce(e,f),{kind:"createTask",taskId:w.id,repoId:w.repoId,workspaceId:w.workspaceId,sessionId:f.id,status:w.status,branch:w.branch,worktreePath:w.worktreePath,runner:w.runner}}catch(f){let u={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await y(e,u),f}};import{mkdir as kd}from"node:fs/promises";import wd from"node:path";var ko=3,ld=1e3,cd=1e4,Ue=async e=>{let t=await E("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var wo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await T("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Ft=async(e,t)=>{let r=await T("gh",yo(e),{cwd:t});return JSON.parse(r.stdout)},Nt=async(e,t)=>{let r=await E("gh",yo(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},To=async(e,t,r)=>{if(r.length===0)return[];let n=gd(r),s=await dd(e,["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`]),i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=hd(c);return{id:a.id,found:d!==null,view:d}})},Ro=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:md(t.stdout.trim())},dd=async(e,t)=>{let r;for(let n=0;n<=ko;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===ko||!ud(s))throw s;await fd(pd(n))}throw r},ud=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")},pd=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||ld,r=Math.min(t*2**e,cd),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},fd=e=>new Promise(t=>setTimeout(t,e)),yo=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],md=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},gd=e=>`
|
|
35
35
|
query CraigPullRequestBatch($owner: String!, $name: String!) {
|
|
36
36
|
repository(owner: $owner, name: $name) {
|
|
37
37
|
${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(`
|
|
@@ -110,56 +110,56 @@ fragment PrFields on PullRequest {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
`,
|
|
113
|
+
`,hd=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??r.commits?.nodes?.[0]?.commit?.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 Ae=async(e,t)=>{let r=Ie(e,t.artifacts.prStatusPath);r&&(await kd(wd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,prs:t.prs}))},lt=async(e,t,r,n,s={readRawTask:H,validateTaskRecord:F,writeTask:y,writePrStatusArtifact:Ae})=>{let o=et(r,n),i=We(t,o),a=Ze(i.prs),l={...i,status:a};await s.writePrStatusArtifact(e,l);let c=await s.readRawTask(e,t.id),d=s.validateTaskRecord(c,`${e.tasksDir}/${t.id}.json`),p=d.status==="closed"?d.status:a,f=We({...d,status:p},o);return await s.writeTask(e,f),f},ct=async(e,t)=>{let r=v(t),n=r?.number?String(r.number):t.branch,s=await Ft(n,t.worktreePath);return lt(e,t,s,r)},dt=async(e,t)=>{let r=await Nt(t.branch,t.worktreePath);return r?{discovered:!0,task:await lt(e,t,r,null)}:{discovered:!1,task:t}};var Ke=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await Ft(n,r.worktreePath),a=So(i);return r.pullRequest=a,await Po(e,t,r.repoId,a),"synced"}let s=await Nt(n,r.worktreePath);if(!s)return"not_found";let o=So(s);return r.pullRequest=o,await Po(e,t,r.repoId,o),"discovered"},Po=async(e,t,r,n)=>{let s=await H(e,t.id),o=F(s,`${e.tasksDir}/${t.id}.json`),i=(o.repoTargets??t.repoTargets??[]).map(l=>l.repoId===r?{...l,pullRequest:n}:l),a={...o,repoTargets:i};return await y(e,a),a},So=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Td(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Rd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),Td=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Rd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var ut=async(e,t)=>{let r=await S(e,t),n=v(r);return n?.number?(await Ue(r.worktreePath),ge(n)?(await dt(e,r)).task:ct(e,r)):r},Vr=async(e,t)=>{let r=await S(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Ve(e,t),S(e,t);let n=v(r);if(await N(r),await Ue(r.worktreePath),!n?.number||ge(n)){let o=await dt(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await Ae(e,o.task),o.task}let s=await ct(e,r);return await Ae(e,s),s},Ve=async(e,t)=>{let r=await S(e,t),n=(r.repoTargets??[]).filter(a=>a.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let a of n){await Ue(a.worktreePath);let l=a.pullRequest.number?await Ke(e,r,a):await Ke(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await H(e,r.id),i=F(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=Io(i),await y(e,i)),s},Gr=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=Kr(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let c of s.repoTargets.filter(d=>d.status==="ready")){let d={id:`${s.id}:${c.repoId}`,task:s,targetRepoId:c.repoId,worktreePath:c.worktreePath,selector:c.pullRequest.number?String(c.pullRequest.number):c.branch,mode:c.pullRequest.number?"number":"head"};await bo(n,d).catch(async()=>{try{let p=c.pullRequest.number?await Ke(e,s,c):await Ke(e,s,c).catch(()=>"not_found");Wt(o,p,c.pullRequest.number??null,c.pullRequest.url??null)}catch{}})}continue}let i=v(s),a=i?.number&&!ge(i),l={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):s.branch,mode:a?"number":"head"};await bo(n,l).catch(async()=>{try{let{disposition:c,task:d}=await _t(e,s.id),p=v(d);Wt(o,c,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await Ue(s.worktreePath);let o=await To(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=Kr(r,a.task),c=i.get(a.id);if(!c?.found||!c.view){Wt(l,"not_found",null,null);continue}if(a.targetRepoId){let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await yd(e,p,a.targetRepoId,c.view)}else{let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await lt(e,p,c.view,v(p))}Wt(l,a.mode==="number"?"synced":"discovered",c.view.number,c.view.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await H(e,s.id),i=F(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=Io(i),await y(e,i))}return t.map(s=>Kr(r,s))},_t=async(e,t)=>{let r=await S(e,t);await N(r),await Ue(r.worktreePath);let n=v(r);if(n?.number&&!ge(n))return{disposition:"synced",task:await ct(e,r)};let s=await dt(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},Io=e=>{let t=(e.repoTargets??[]).filter(n=>n.status==="ready"),r=t.map(n=>n.pullRequest).filter(n=>!!n.number);return r.length===0?e.status:r.every(n=>n.status==="merged")?"merged":r.length===t.length&&r.every(Id)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},yd=async(e,t,r,n)=>{let s=Pd(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await y(e,i),i},Pd=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Sd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:bd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),Sd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,bd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,bo=async(e,t)=>{let r=await Ro(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]})},Kr=(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):!!v(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},Wt=(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},Id=e=>e.mergeable&&e.reviewDecision!=="REVIEW_REQUIRED"&&e.reviewDecision!=="CHANGES_REQUESTED"&&e.mergeStateStatus!=="REVIEW_REQUIRED"&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped");var Hr=async(e,t)=>{let r=await S(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Ve(e,t),r=await S(e,t)):r.prs.some(o=>o.number)&&(r=await ut(e,t))}catch{}let n=await rt(e,r),s=r.sessionId?await he(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var zr=async(e,t)=>{let r=await S(e,t);if(await N(r),(await T("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await Cd(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},Cd=async e=>{let t=[],r=await T("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await vd(e);for(let s of n){let o=await E("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
|
|
114
114
|
|
|
115
|
-
`)},
|
|
116
|
-
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as yd}from"node:child_process";import{access as Pd}from"node:fs/promises";var Vr=async(e,t)=>{let r=await S(e,t),n=_e(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await Pd(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Gr=async e=>{await new Promise((t,r)=>{let n=!1,s=yd("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 Sd}from"node:fs/promises";import bd from"node:path";var Hr=async(e,t)=>{let r=await S(e,t);if(await N(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 At(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 h.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 y(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await E("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 Po(e,r),await y(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 Po(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Po=async(e,t)=>{let r=Ie(e,t.artifacts.checkSummaryPath);r&&(await Sd(bd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var zr=async(e,t)=>{let r=await S(e,t);await N(r);let n=await At(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 Us(r.worktreePath),await Ks(r.worktreePath,s);let o=await Vs(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await y(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Id}from"node:fs/promises";var Qr=async(e,t)=>{let r=await S(e,t),n=await Cd(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await y(e,s),s},Cd=async e=>{try{return await Id(e),!0}catch{return!1}};var Yr=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await oo(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 Gs(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 y(e,t)};var Jr=async(e,t,r)=>{let[n,s]=await Promise.all([S(e,t),X(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 y(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Xr=async(e,t)=>{let r=await S(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>X(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Zr=async(e,t)=>{let r=await S(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([X(e,r.repoId),he(e,r.sessionId)]),o=await at.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var en=async(e,t)=>{let r=await S(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await he(e,r.sessionId).catch(s=>{throw vd(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 Lt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},vd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Ed}from"node:child_process";var tn=async(e,t)=>{let r=await S(e,t);await N(r);let s=(await h.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 xd(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},xd=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Ed(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 rn=async(e,t,r)=>{let n=await Y(e,t);await y(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},nn=async(e,t,r)=>{let n=await Y(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await y(e,s),s},sn=async(e,t)=>{let r=await Y(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 y(e,s),s};var on=async(e,t,r="merge",n)=>{let s=await S(e,t),o=n??v(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await mo(s.worktreePath,o,r)};var b={listTasks:Dr,getTask:S,provisionTask:Be,provisionProjectTask:ot,createTask:Wr,showTask:Ur,showTaskDiff:Kr,prepareTaskLogs:Vr,streamTaskLogs:Gr,runChecks:Hr,commitTask:zr,closeTask:Qr,cleanupTask:Yr,addTaskLink:Jr,listTaskLinks:Xr,sortTasksForDisplay:$r,resolveSelectedTaskId:jr,allocateTaskId:Ar,allocateTaskIdForRepo:qe,allocateProjectTaskId:nt,createDefaultTaskPtyTabs:it,assertTaskWorktreeExists:N,resolveTaskLogPath:_e,buildTaskInspection:rt,resolveArtifactPath:Ie,attachTask:Zr,focusTask:en,openTask:tn,markRunnerFailed:rn,recordStartupFailure:nn,markTaskStarted:sn,prs:{refresh:ut,refreshChecks:qr,discoverOrRefresh:Nt,discoverOrRefreshAll:Ve,discoverOrRefreshMany:Br,merge:on,getPrimaryPr:v,isPrTerminal:ge,isMergeReady:xt,deriveTaskStatus:Ze,upsertPr:We,normalizePr:et,summarizeRequiredChecks:vr,writePrStatusArtifact:xe}};async function So(e,t){switch(e.kind){case"addWorkspace":{let r=await Q.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await an(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Q.repos.addRepo(t.paths,e.path);return await an(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Q.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Me({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await q(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Q.repos.removeRepo(t.paths,e.repoId,{listTasks:b.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return Q.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Q.archiveWorkspace(t.paths,e.workspaceId);return await Ad(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Q.restoreWorkspace(t.paths,e.workspaceId);return await an(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Q.removeWorkspace(t.paths,e.workspaceId,{listTasks:b.listTasks});case"createTask":return b.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?b.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):b.listTasks(t.paths);case"attachTask":return b.attachTask(t.paths,e.taskId);case"addTaskLink":return b.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return b.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return b.showTask(t.paths,e.taskId);case"showSelectedTask":return b.showTask(t.paths,Ae(t,"show"));case"streamTaskLogs":return b.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return b.prepareTaskLogs(t.paths,Ae(t,"logs"));case"showTaskDiff":return b.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return b.showTaskDiff(t.paths,Ae(t,"diff"));case"focusTask":return b.focusTask(t.paths,e.taskId);case"focusSelectedTask":return b.focusTask(t.paths,Ae(t,"focus"));case"openTask":return b.openTask(t.paths,e.taskId);case"openSelectedTask":return b.openTask(t.paths,Ae(t,"open"));case"runChecks":return b.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return b.runChecks(t.paths,Ae(t,"check"));case"commitTask":return b.commitTask(t.paths,e.taskId);case"commitSelectedTask":return b.commitTask(t.paths,Ae(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return Dd(e)}}async function an(e,t,r){let n=await Me({uiStateFile:e.uiStateFile})??yt();await me({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Ad(e,t){let r=await Me({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await me({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Dd(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ae(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 bo(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(`
|
|
115
|
+
`)},vd=async e=>(await T("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
116
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Ed}from"node:child_process";import{access as Ad}from"node:fs/promises";var Qr=async(e,t)=>{let r=await S(e,t),n=_e(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await Ad(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Yr=async e=>{await new Promise((t,r)=>{let n=!1,s=Ed("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 xd}from"node:fs/promises";import Dd from"node:path";var Jr=async(e,t)=>{let r=await S(e,t);if(await N(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 $t(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 h.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 y(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await E("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 Co(e,r),await y(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 Co(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Co=async(e,t)=>{let r=Ie(e,t.artifacts.checkSummaryPath);r&&(await xd(Dd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var Xr=async(e,t)=>{let r=await S(e,t);await N(r);let n=await $t(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 Hs(r.worktreePath),await zs(r.worktreePath,s);let o=await Qs(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await y(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as $d}from"node:fs/promises";var Zr=async(e,t)=>{let r=await S(e,t),n=await Ld(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await y(e,s),s},Ld=async e=>{try{return await $d(e),!0}catch{return!1}};var en=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await co(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 Ys(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 y(e,t)};var tn=async(e,t,r)=>{let[n,s]=await Promise.all([S(e,t),X(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 y(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},rn=async(e,t)=>{let r=await S(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>X(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var nn=async(e,t)=>{let r=await S(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([X(e,r.repoId),he(e,r.sessionId)]),o=await at.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var sn=async(e,t)=>{let r=await S(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await he(e,r.sessionId).catch(s=>{throw jd(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 Ot(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},jd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Md}from"node:child_process";var on=async(e,t)=>{let r=await S(e,t);await N(r);let s=(await h.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 Od(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Od=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Md(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 an=async(e,t,r)=>{let n=await Y(e,t);await y(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},ln=async(e,t,r)=>{let n=await Y(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await y(e,s),s},cn=async(e,t)=>{let r=await Y(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 y(e,s),s};var dn=async(e,t,r="merge",n)=>{let s=await S(e,t),o=n??v(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await wo(s.worktreePath,o,r)};var b={listTasks:Mr,getTask:S,provisionTask:Be,provisionProjectTask:ot,createTask:Ur,showTask:Hr,showTaskDiff:zr,prepareTaskLogs:Qr,streamTaskLogs:Yr,runChecks:Jr,commitTask:Xr,closeTask:Zr,cleanupTask:en,addTaskLink:tn,listTaskLinks:rn,sortTasksForDisplay:Or,resolveSelectedTaskId:Fr,allocateTaskId:jr,allocateTaskIdForRepo:qe,allocateProjectTaskId:nt,createDefaultTaskPtyTabs:it,assertTaskWorktreeExists:N,resolveTaskLogPath:_e,buildTaskInspection:rt,resolveArtifactPath:Ie,attachTask:nn,focusTask:sn,openTask:on,markRunnerFailed:an,recordStartupFailure:ln,markTaskStarted:cn,prs:{refresh:ut,refreshChecks:Vr,discoverOrRefresh:_t,discoverOrRefreshAll:Ve,discoverOrRefreshMany:Gr,merge:dn,getPrimaryPr:v,isPrTerminal:ge,isMergeReady:Dt,deriveTaskStatus:Ze,upsertPr:We,normalizePr:et,summarizeRequiredChecks:Dr,writePrStatusArtifact:Ae}};async function vo(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 un(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await G.repos.addRepo(t.paths,e.path);return await un(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return G.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Me({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Q(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await G.repos.removeRepo(t.paths,e.repoId,{listTasks:b.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await me({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 Fd(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await G.restoreWorkspace(t.paths,e.workspaceId);return await un(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return G.removeWorkspace(t.paths,e.workspaceId,{listTasks:b.listTasks});case"createTask":return b.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?b.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):b.listTasks(t.paths);case"attachTask":return b.attachTask(t.paths,e.taskId);case"addTaskLink":return b.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return b.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return b.showTask(t.paths,e.taskId);case"showSelectedTask":return b.showTask(t.paths,xe(t,"show"));case"streamTaskLogs":return b.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return b.prepareTaskLogs(t.paths,xe(t,"logs"));case"showTaskDiff":return b.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return b.showTaskDiff(t.paths,xe(t,"diff"));case"focusTask":return b.focusTask(t.paths,e.taskId);case"focusSelectedTask":return b.focusTask(t.paths,xe(t,"focus"));case"openTask":return b.openTask(t.paths,e.taskId);case"openSelectedTask":return b.openTask(t.paths,xe(t,"open"));case"runChecks":return b.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return b.runChecks(t.paths,xe(t,"check"));case"commitTask":return b.commitTask(t.paths,e.taskId);case"commitSelectedTask":return b.commitTask(t.paths,xe(t,"commit"));case"help":return{kind:"help",text:U()};case"exit":return{kind:"exit"};default:return Nd(e)}}async function un(e,t,r){let n=await Me({uiStateFile:e.uiStateFile})??St();await me({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Fd(e,t){let r=await Me({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await me({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Nd(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function xe(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 Eo(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(`
|
|
117
117
|
`);case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
|
|
118
118
|
`);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(`
|
|
119
119
|
`);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(`
|
|
120
120
|
`);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(`
|
|
121
121
|
`);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(`
|
|
122
|
-
`);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} ${
|
|
123
|
-
`);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}
|
|
122
|
+
`);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} ${qd(t)} ${Bd(t)} ${t.title}`)].join(`
|
|
123
|
+
`);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}`,...Wd(e)].join(`
|
|
124
124
|
`);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(`
|
|
125
|
-
`);default:return
|
|
126
|
-
`).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
|
|
127
|
-
`)){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 pt(e){return(await E("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await E("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function
|
|
128
|
-
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return
|
|
129
|
-
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await T("git",["diff","--cached","--stat","--patch",`--unified=${
|
|
130
|
-
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await T("git",["diff","--stat","--patch",`--unified=${
|
|
131
|
-
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await E("git",["diff","--no-index","--stat","--patch",`--unified=${
|
|
125
|
+
`);default:return _d(e)}}function Wd(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 _d(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function qd(e){return e.checks.status}function Bd(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"}`:"-"}import{createRequire as om}from"node:module";import{readFile as Ud,stat as Kd}from"node:fs/promises";import pn from"node:path";var Vd=200*1024,Gd=500*1024,qt="100000";async function xo(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return Hd(e,t,r);try{let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),o=s?await pt(e.worktreePath):null,[i,a]=await Promise.all([Ut(e.worktreePath,n),s?fn(e.worktreePath,s,t.diffRows,o):Promise.resolve(q("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 Hd(e,t,r){let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([$o(e,n),(async()=>{if(!s)return q("No diff selected","No local changes found.","empty");let l=Bt(e,s),c=l?await pt(l.target.worktreePath).catch(()=>null):null;return Lo(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function Do(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return zd(e,t);try{await N(e);let r=await pt(e.worktreePath),[n,s]=await Promise.all([jo(e.worktreePath),Mo(e.worktreePath,r)]),o=[...new Set(s.map(p=>p.path))],i=we(t.selectedFilePath??null,n),a=we(t.selectedDiffPath??null,o),[l,c]=await Promise.all([Ut(e.worktreePath,i),a?fn(e.worktreePath,a,s,r):Promise.resolve(q("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:No(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:q("Files unavailable",n,"error"),selectedDiff:q("Diff unavailable",n,"error"),error:n}}}async function zd(e,t){let r=(e.repoTargets??[]).filter(f=>f.status==="ready"),n=await Promise.all(r.map(async f=>{let u=await pt(f.worktreePath).catch(()=>null),[w,R]=await Promise.all([jo(f.worktreePath).catch(()=>[]),Mo(f.worktreePath,u).catch(()=>[])]);return{target:f,baseRef:u,targetFiles:w,targetDiffRows:R}})),s=[],o=[];for(let{target:f,targetFiles:u,targetDiffRows:w}of n)s.push(...u.map(R=>`${f.repoId}/${R}`)),o.push(...w.map(R=>({...R,path:`${f.repoId}/${R.path}`})));let i=[...new Set(o.map(f=>f.path))].sort(),a=we(t.selectedFilePath??null,s),l=we(t.selectedDiffPath??null,i),[c,d]=await Promise.all([$o(e,a),(async()=>{if(!l)return q("No diff selected","No local changes found.","empty");let f=Bt(e,l),u=f?n.find(w=>w.target.repoId===f.target.repoId):null;return Lo(e,l,o,u?.baseRef??null)})()]),p=l?{[l]:d}:{};return{taskId:e.id,fileRows:No(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:p,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function $o(e,t){let r=Bt(e,t);if(!r)return q("No file selected","No Git-visible files found.","empty");let n=await Ut(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function Lo(e,t,r,n=null){let s=Bt(e,t);return s?{...await fn(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}:q(t,"Repo target is unavailable.","error",t)}function Bt(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 jo(e){let t=await T("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Wo(t.stdout)}async function Mo(e,t){let[r,n,s,o]=await Promise.all([Qd(e,t),Ao(e,"staged"),Ao(e,"unstaged"),Yd(e)]);return[...r,...n,...s,...o]}async function Qd(e,t){if(!t)return[];let[r,n]=await Promise.all([T("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),T("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=Oo(r.stdout),o=Fo(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 Ao(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([T("git",[...r,"--name-status"],{cwd:e}),T("git",[...r,"--numstat"],{cwd:e})]),o=Oo(n.stdout),i=Fo(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 Yd(e){let t=await T("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Wo(t.stdout);return await Promise.all(r.map(async s=>{let o=await Ut(e,s),i=o.status==="ready"?Jd(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function Oo(e){return e.split(`
|
|
126
|
+
`).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 Fo(e){let t=new Map;for(let r of e.split(`
|
|
127
|
+
`)){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 pt(e){return(await E("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await E("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function Ut(e,t){if(!t)return q("No file selected","No Git-visible files found.","empty");let r=Xd(e,t);try{let n=await Kd(r);if(n.size>Vd)return q(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Ud(r);return Zd(s)?q(t,"Binary file preview is not available in Craig.","binary",t,s.byteLength):{path:t,status:"ready",title:t,lines:s.toString("utf8").split(`
|
|
128
|
+
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return q(t,s,"missing",t,null)}}async function fn(e,t,r,n=null){if(!t)return q("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 pt(e);if(a){let l=await T("git",["diff","--stat","--patch",`--unified=${qt}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
129
|
+
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await T("git",["diff","--cached","--stat","--patch",`--unified=${qt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
130
|
+
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await T("git",["diff","--stat","--patch",`--unified=${qt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
|
|
131
|
+
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await E("git",["diff","--no-index","--stat","--patch",`--unified=${qt}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
|
|
132
132
|
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
133
133
|
|
|
134
|
-
`);return i.length>
|
|
135
|
-
`):["No diff for this file."],byteLength:i.length}}function
|
|
136
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Vd(e,t){let r=ln.resolve(e,t),n=ln.resolve(e);if(r!==n&&!r.startsWith(`${n}${ln.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Gd(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function B(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Hd=["tasks","center","inspector","actions"],_o=["agent","terminal"],qo=[],I="inspection",uR=[..._o,...qo],Bo=["commit","push","refresh-checks","close-task"],zd=["refresh-checks","close-task"],Uo=["task","checks","pr","setup-run","actions","next-action"],Ko=["diff","files","review"];function Vo(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=uu(e?.openInspectionKind)??r,s=h.runners.getEnabled(t);return{inputMode:fu(e?.inputMode),focusedRegion:cu(e?.focusedRegion),selectedRepoId:ce(e?.selectedRepoId),selectedWorkspaceId:ce(e?.selectedWorkspaceId),selectedTaskId:ce(e?.selectedTaskId),selectedPtyTabId:ce(e?.selectedPtyTabId),selectedLeftItemId:Pu(ce(e?.selectedTaskId)),activeTab:r?I:ce(e?.activeTab)??"agent",preferredPtyTabKind:pu(e?.preferredPtyTabKind),inspectorSection:ft(e?.inspectorSection,Uo,"task"),inspectionMode:du(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:ce(e?.selectedFileTreePath),selectedFilePath:ce(e?.selectedFilePath),selectedDiffPath:ce(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:ft(e?.selectedActionId,Bo,"commit"),selectedProjectTargetId:null,selectedRunner:mu(e?.selectedRunner,s,h.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:Qd(),centerZoomed:!1}}function Qd(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Go(e,t){return{...e??yt(),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 gt(e,t,r={}){let n=Ru(e,t),s=Zo(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(p=>p.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(p=>p.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,...hu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:iu(e,t,c?.id??null),...ku(e,t,c?.id??null),selectedDiffPath:ou(e,t,c?.id??null),inspectorSection:ft(e.inspectorSection,Uo,"task")}}function Yd(e,t,r){if(t==="ESCAPE")return g({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return g({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return un(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return mn({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return g({state:{...e,fileSearchQuery:n},changed:!0})}return g({state:e})}function mn(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Jd(t)?g({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):g({state:e});if(e.fileSearchQuery!==null)return Yd(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return g({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return g({state:e,exit:!0});if(t==="ESCAPE")return g({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return g({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(pn(e.selectedLeftItemId)||fn(e.selectedLeftItemId)))return g({state:{...e,selectedRunner:gn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Oo(e,1);if(t==="SHIFT_TAB"||t==="[")return Oo(e,-1);if(t==="z"||t==="Z")return g({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,-1,r):un(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):un(e,1,r);if(t==="PAGE_UP")return Te(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Te(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Te(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Te(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??x,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return g({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=gu(e,t);return g({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 g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return g({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId)return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Su(e.selectedLeftItemId)&&e.selectedWorkspaceId)return g({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Wo(e.activeTab,r.ptyTabIds??[]))return g({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return dn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fo(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return dn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fo(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(pn(e.selectedLeftItemId)||fn(e.selectedLeftItemId))){let n=ei(e.selectedLeftItemId),s=ti(e.selectedLeftItemId);return g({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 g({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return g({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"&&Wo(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return g({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===I)return g({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 g({state:ru({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return g({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:I,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?g({state:{...e,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?g({state:e}):e.selectedActionId==="refresh-checks"?g({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return g({state:e})}function ue(e,t){return{...e,terminal:t}}function Ho(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Jd(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function oe(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
137
|
-
`}function zo(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Qo(e){return Yo(e)||mt(e)!==null}function Xd(e){return qo.includes(e)}function Yo(e){return _o.includes(e)}function Jo(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var Zd=["tasks","center","inspector"];function Oo(e,t){return Bt(e,"focusedRegion",Zd,t)}function dn(e,t,r){let n=Bt(e,"activeTab",r&&r.length>0?r:Tu(e),t);return!n.changed||Xd(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function un(e,t,r){if(e.focusedRegion==="tasks")return eu(e,t,r.leftItemIds);if(e.focusedRegion==="center")return dn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:n}if(r.projectTargetIds?.length){let n=Ut(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return Bt(e,"selectedActionId",zd,t)}return Bt(e,"selectedActionId",Bo,t)}function eu(e,t,r){let n=Ut(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Zo(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=ei(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=ti(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Te(e,t,r){if(t===0)return g({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?No(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):g({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return No(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return nu(e,t,r)}return g({state:e})}function tu(e,t){if(e.inspectionMode===t)return g({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return g({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Fo(e,t){return tu(e,lu(e.inspectionMode,Ko,t))}function Xo(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return g({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=de(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return g({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return g({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?I:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function ru(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 No(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=de(e[t]+r,0,o);return i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function nu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return su(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=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?g({state:e}):g({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?g({state:e}):g({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=de(i,0,o);return c===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function su(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=de(e.diffScrollOffset+t,0,o),a=au(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?g({state:e}):g({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function ou(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function iu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function au(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Bt(e,t,r,n){let s=r.indexOf(e[t]),o=de(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Ut(e,t,r,n,s=!1){if(r.length===0)return g({state:e});let o=r.indexOf(e[t]??r[0]??""),i=de(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?g({state:e}):g({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function lu(e,t,r){let n=t.indexOf(e);return t[de(n+r,0,t.length-1)]??e}function g(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 ft(e,t,r){return t.includes(e??"")?e:r}function cu(e){return e==="tabs"?"center":ft(e,Hd,"tasks")}function du(e,t){return e==="checks"||e==="actions"||e==="review"?"review":ft(e,Ko,t)}function uu(e){return e==="file"||e==="diff"?e:null}function pu(e){return e==="terminal"?"terminal":"agent"}function fu(e){return e==="terminal"?"terminal":"control"}function mu(e,t=[...x],r="codex"){return e&&h.runners.isRunnerType(e)&&t.includes(e)?e:r}function gn(e,t=x){let r=t.length>0?t:x,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function mt(e){let t=x.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function gu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function hu(e,t,r){if(!e)return{activeTab:t===I?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(Yo(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??I,selectedPtyTabId:l?.id??null}}if(t===I)return{activeTab:I,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??I,selectedPtyTabId:i?.id??null}}function ku(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?wu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function wu(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 Tu(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function Wo(e,t){return t.includes(e)}function Ru(e,t){let r=yu(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 yu(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 Zo(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 ce(e){return typeof e=="string"?e:null}function Pu(e){return e?`task:${e}`:null}function Kt(e){return typeof e=="string"&&e.startsWith("task:")}function pn(e){return typeof e=="string"&&e.startsWith("new-task:")}function fn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Su(e){return typeof e=="string"&&e.startsWith("workspace:")}function ei(e){return pn(e)?e.slice(9):null}function ti(e){return fn(e)?e.slice(19):null}function de(e,t,r){return Math.min(r,Math.max(t,e))}async function Re(e,t,r){let n=ne(e),[s,o,i]=await Promise.all([Q.repos.listRegisteredRepos(n).then(d=>d.repos),q(n),b.listTasks(n)]),a=hn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await vo(a,l):null;return{workspaceRoot:e,workspaces:o.filter(d=>d.status==="active"),repos:s,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function hn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ri(e,t){return gt(e,t)}function ni(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}import Sn from"node:path";import RR from"picocolors";var bu=[" \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 kn(){return[...bu]}var Vt={width:120,height:36},Z={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ee(e,t){return{width:Math.max(e??Vt.width,Vt.width),height:Math.max(t??Vt.height,Vt.height)}}var Iu=["Start","Options","Exit"],Cu=["Resume","Options","Exit"],zt=2,Qt=2,Yt=2,vu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Eu=new RegExp("\x1B\\[(?:0)?m","g"),xu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Au=/https?:\/\/[^\s<>"']+/g,wn="\x1B[0m",Tn="\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"}};function ii(e,t={}){return yn(e,{subtitle:"crAIg is that you?",menuItems:Iu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function ai(e,t={}){return yn(e,{subtitle:"Control mode is paused.",menuItems:Cu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var Gt=[" 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."],Du=["Help"];function Rn(e,t={}){return yn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??Du,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function li(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o=kn(),i=Math.max(1,Math.floor((e.height-o.length-2-Gt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=$(fi(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...Gt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<Gt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=Gt[d]??"";s[p]=$(ie(" ".repeat(l)+f,e.width),r,n)}return s.join(`
|
|
138
|
-
`)}function
|
|
139
|
-
`)}function
|
|
140
|
-
`)}function
|
|
141
|
-
`)}function
|
|
134
|
+
`);return i.length>Gd?q(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?q(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(`
|
|
135
|
+
`):["No diff for this file."],byteLength:i.length}}function No(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 we(e,t){return e&&t.includes(e)?e:t[0]??null}function Jd(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Wo(e){return[...new Set(e.split(`
|
|
136
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Xd(e,t){let r=pn.resolve(e,t),n=pn.resolve(e);if(r!==n&&!r.startsWith(`${n}${pn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Zd(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function q(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var eu=["tasks","center","inspector","actions"],Ko=["agent","terminal"],Vo=[],I="inspection",RR=[...Ko,...Vo],Go=["commit","push","refresh-checks","close-task"],tu=["refresh-checks","close-task"],Ho=["task","checks","pr","setup-run","actions","next-action"],zo=["diff","files","review"];function Qo(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=wu(e?.openInspectionKind)??r,s=h.runners.getEnabled(t);return{inputMode:Ru(e?.inputMode),focusedRegion:hu(e?.focusedRegion),selectedRepoId:ce(e?.selectedRepoId),selectedWorkspaceId:ce(e?.selectedWorkspaceId),selectedTaskId:ce(e?.selectedTaskId),selectedPtyTabId:ce(e?.selectedPtyTabId),selectedLeftItemId:Au(ce(e?.selectedTaskId)),activeTab:r?I:ce(e?.activeTab)??"agent",preferredPtyTabKind:Tu(e?.preferredPtyTabKind),inspectorSection:ft(e?.inspectorSection,Ho,"task"),inspectionMode:ku(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:ce(e?.selectedFileTreePath),selectedFilePath:ce(e?.selectedFilePath),selectedDiffPath:ce(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:ft(e?.selectedActionId,Go,"commit"),selectedProjectTargetId:null,selectedRunner:yu(e?.selectedRunner,s,h.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:ru(),centerZoomed:!1}}function ru(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Yo(e,t){return{...e??St(),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 gt(e,t,r={}){let n=vu(e,t),s=ni(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(p=>p.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(p=>p.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,...Su(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:fu(e,t,c?.id??null),...bu(e,t,c?.id??null),selectedDiffPath:pu(e,t,c?.id??null),inspectorSection:ft(e.inspectorSection,Ho,"task")}}function nu(e,t,r){if(t==="ESCAPE")return g({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return g({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return gn(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return wn({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return g({state:{...e,fileSearchQuery:n},changed:!0})}return g({state:e})}function wn(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return su(t)?g({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):g({state:e});if(e.fileSearchQuery!==null)return nu(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return g({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return g({state:e,exit:!0});if(t==="ESCAPE")return g({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return g({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(hn(e.selectedLeftItemId)||kn(e.selectedLeftItemId)))return g({state:{...e,selectedRunner:Tn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return _o(e,1);if(t==="SHIFT_TAB"||t==="[")return _o(e,-1);if(t==="z"||t==="Z")return g({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,-1,r):gn(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):gn(e,1,r);if(t==="PAGE_UP")return Te(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Te(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Te(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Te(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??A,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return g({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=Pu(e,t);return g({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 g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return g({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Gt(e.selectedLeftItemId)&&e.selectedTaskId)return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&xu(e.selectedLeftItemId)&&e.selectedWorkspaceId)return g({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Uo(e.activeTab,r.ptyTabIds??[]))return g({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return mn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return qo(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return mn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return qo(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(hn(e.selectedLeftItemId)||kn(e.selectedLeftItemId))){let n=si(e.selectedLeftItemId),s=oi(e.selectedLeftItemId);return g({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 g({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Gt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return g({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"&&Uo(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return g({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===I)return g({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 g({state:cu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return g({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:I,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?g({state:{...e,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?g({state:e}):e.selectedActionId==="refresh-checks"?g({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return g({state:e})}function ue(e,t){return{...e,terminal:t}}function Jo(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function su(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function oe(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
137
|
+
`}function Xo(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Zo(e){return ei(e)||mt(e)!==null}function ou(e){return Vo.includes(e)}function ei(e){return Ko.includes(e)}function ti(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var iu=["tasks","center","inspector"];function _o(e,t){return Kt(e,"focusedRegion",iu,t)}function mn(e,t,r){let n=Kt(e,"activeTab",r&&r.length>0?r:Cu(e),t);return!n.changed||ou(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function gn(e,t,r){if(e.focusedRegion==="tasks")return au(e,t,r.leftItemIds);if(e.focusedRegion==="center")return mn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return ri(e,t,r);if(e.inspectionMode==="diff"){let n=Vt(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:n}if(r.projectTargetIds?.length){let n=Vt(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return Kt(e,"selectedActionId",tu,t)}return Kt(e,"selectedActionId",Go,t)}function au(e,t,r){let n=Vt(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=ni(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=si(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=oi(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Te(e,t,r){if(t===0)return g({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return ri(e,t,r);if(e.inspectionMode==="diff"){let n=Vt(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?Bo(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):g({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return Bo(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return du(e,t,r)}return g({state:e})}function lu(e,t){if(e.inspectionMode===t)return g({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return g({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function qo(e,t){return lu(e,gu(e.inspectionMode,zo,t))}function ri(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return g({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=de(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return g({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return g({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?I:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function cu(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 Bo(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=de(e[t]+r,0,o);return i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function du(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return uu(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=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?g({state:e}):g({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?g({state:e}):g({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=de(i,0,o);return c===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function uu(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=de(e.diffScrollOffset+t,0,o),a=mu(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?g({state:e}):g({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function pu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function fu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function mu(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Kt(e,t,r,n){let s=r.indexOf(e[t]),o=de(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Vt(e,t,r,n,s=!1){if(r.length===0)return g({state:e});let o=r.indexOf(e[t]??r[0]??""),i=de(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?g({state:e}):g({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function gu(e,t,r){let n=t.indexOf(e);return t[de(n+r,0,t.length-1)]??e}function g(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 ft(e,t,r){return t.includes(e??"")?e:r}function hu(e){return e==="tabs"?"center":ft(e,eu,"tasks")}function ku(e,t){return e==="checks"||e==="actions"||e==="review"?"review":ft(e,zo,t)}function wu(e){return e==="file"||e==="diff"?e:null}function Tu(e){return e==="terminal"?"terminal":"agent"}function Ru(e){return e==="terminal"?"terminal":"control"}function yu(e,t=[...A],r="codex"){return e&&h.runners.isRunnerType(e)&&t.includes(e)?e:r}function Tn(e,t=A){let r=t.length>0?t:A,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function mt(e){let t=A.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Pu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function Su(e,t,r){if(!e)return{activeTab:t===I?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(ei(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??I,selectedPtyTabId:l?.id??null}}if(t===I)return{activeTab:I,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??I,selectedPtyTabId:i?.id??null}}function bu(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?Iu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function Iu(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 Cu(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function Uo(e,t){return t.includes(e)}function vu(e,t){let r=Eu(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 Eu(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 ni(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 ce(e){return typeof e=="string"?e:null}function Au(e){return e?`task:${e}`:null}function Gt(e){return typeof e=="string"&&e.startsWith("task:")}function hn(e){return typeof e=="string"&&e.startsWith("new-task:")}function kn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function xu(e){return typeof e=="string"&&e.startsWith("workspace:")}function si(e){return hn(e)?e.slice(9):null}function oi(e){return kn(e)?e.slice(19):null}function de(e,t,r){return Math.min(r,Math.max(t,e))}async function Re(e,t,r){let n=ne(e),[s,o]=await Promise.all([G.repos.listRegisteredRepos(n),G.listWorkspaces(n,{archived:!1})]),i=await b.listTasks(n),a=Rn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await Do(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function Rn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ii(e,t){return gt(e,t)}function ht(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}import vn from"node:path";import AR from"picocolors";var Du=[" \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 yn(){return[...Du]}var Ht={width:120,height:36},Z={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ee(e,t){return{width:Math.max(e??Ht.width,Ht.width),height:Math.max(t??Ht.height,Ht.height)}}var $u=["Start","Options","Exit"],Lu=["Resume","Options","Exit"],Yt=2,Jt=2,Xt=2,ju=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Mu=new RegExp("\x1B\\[(?:0)?m","g"),Ou=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Fu=/https?:\/\/[^\s<>"']+/g,Pn="\x1B[0m",Sn="\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"}};function ci(e,t={}){return In(e,{subtitle:"crAIg is that you?",menuItems:$u,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function di(e,t={}){return In(e,{subtitle:"Control mode is paused.",menuItems:Lu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var zt=[" 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."],Nu=["Help"];function bn(e,t={}){return In(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??Nu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function ui(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o=yn(),i=Math.max(1,Math.floor((e.height-o.length-2-zt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=$(hi(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...zt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<zt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=zt[d]??"";s[p]=$(ie(" ".repeat(l)+f,e.width),r,n)}return s.join(`
|
|
138
|
+
`)}function pi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill($(" ".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"},J(),...a.length>0?a.map(u=>({text:u})):[{text:"No Craig errors have been logged.",tone:"muted"}],J(),{text:"Esc returns to Options.",tone:"muted"}],p=kt(d,e.height-2),f=Math.max(1,Math.floor((e.height-p.length)/2));for(let u=0;u<p.length;u+=1){let w=f+u;if(w>=e.height)break;let R=p[u]??J(),x=`${" ".repeat(c)}${er(R.text,l)}`,B=R.tone==="selected"?P.overlayMenuSelected:R.tone==="muted"?P.overlay:P.panelBg;s[w]=$(ie(x,e.width),r,B)}return s.join(`
|
|
139
|
+
`)}function fi(e,t,r={}){let n=r.color??!0,s=Z.leftWidth,o=Z.rightWidth,i=Z.dividerWidth,a=r.centerOnly??!1,l=a?e.width:e.width-s-o-i*2,c=e.height-Z.topRailHeight-1,d=r.focusFlashActive??!1,p={bg:P.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:P.divider,u=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:P.divider,w=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,R=$(ie(w,e.width),n,P.rail),x=_u(t,s-Yt-Jt,c,n),B=qu(t,l,c,n),fe=Uu(t,o,c,n),ae=t.inputMode==="terminal",k=[];for(let Le=0;Le<c;Le+=1){if(a){k.push(Qt(B[Le]??J(),l,n,"center"));continue}let il=Qt(x[Le]??J(),s,n,"left"),al=$("\u2502",n,f),ll=Qt(B[Le]??J(),l,n,"center"),cl=$("\u2502",n,u),dl=Qt(fe[Le]??J(),o,n,"right");k.push(`${il}${al}${ll}${cl}${dl}`)}let Ye=ae||t.modalInput?P.panelBg:P.panelMuted,ol=Wu(t.footerText,t.footerToast,e.width,n,Ye);return[R,...k,ol].join(`
|
|
140
|
+
`)}function Wu(e,t,r,n,s){let o=` ${e}`;if(!t)return $(ie(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=z(i),l=z(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?er(o,Math.max(0,r-a-3)):o,p=Math.max(1,r-z(d)-a-2),f=t.tone==="error"?lp(i,n,s):Ge(i,n,s),u=`${d}${" ".repeat(p)}${f} `;return $(ie(u,r),n,s)}function In(e,t){let r=new Array(e.height).fill($(" ".repeat(e.width),t.color,P.overlay)),n=yn(),s=Math.max(...t.menuItems.map(c=>c.length)),o=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c.padEnd(s)}`),i=t.optionsMessage?["",t.optionsMessage]:[],a=[...n,"",t.subtitle,"",...o,...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=hi(a[c]??"",e.width);if(c<n.length){r[l+c]=$(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=$(d,t.color,P.overlaySubtitle);continue}let p=c-(n.length+3),u=p>=0&&p<t.menuItems.length&&p===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=$(d,t.color,u)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,p=" ".repeat(Math.max(0,e.width-z(d)));r[e.height-1]=$(`${p}${Cn(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
|
|
141
|
+
`)}function _u(e,t,r,n){let s=Gu(e.runners),o=1,i=e.leftTree.map(l=>Vu(l,t,n));return[...kt(i,r-o),s]}function qu(e,t,r,n){let s=t-2,o=e.tabs.find(k=>k.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:op(e.tabs),a=e.inputMode==="terminal"?s:o.length+1,l="\u2500".repeat(Math.max(0,a)),c=`${" ".repeat(i)}${e.inputMode==="terminal"?Ge(l,n,P.panelBg):Zt(l,n,P.panelMuted)}`,d=[`${Zt(e.centerHeader.tabLabel,n,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),p=e.tabs.find(k=>k.active)?.id??"agent",f=e.centerHeader.tabLabel==="BROWSER"||!Zo(p)?e.centerTranscript.map(k=>({...k})):Bu(e),u=Hu(e.tabs,n,e.focusedRegion==="center"),w=" engaged ",R=w.length+2,x=e.inputMode==="terminal"?Ge(`${w}\u25CF `,n,P.panelBg):"",B=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-z(u)-R)):"",ae=[{text:e.inputMode==="terminal"?`${u}${B}${x}`:u},{text:c,tone:"muted"},{text:d},J(),...f];return kt(ae,r)}function Bu(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},J(),{text:e.terminal.error},J(),{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(n=>({text:Ti(n.segments),segments:n.segments,fullBleed:!0}))}function Uu(e,t,r,n){let s=e.rightInspection?Ku(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):kt([{text:"CONTEXT"},J(),...e.rightContext.map(o=>zu(o,n)),...e.actionMessage?[J(),{text:e.actionMessage}]:[]],r);return kt(s,r)}function Ku(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:ap(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>ai(a)),...n.slice(i,i+s).map(a=>ai(a))]}function ai(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 Vu(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Ge("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((u,w)=>u+z(w.text),0):0,l=t-z(o)-z(s)-a,c=e.selected?e.text:e.focused?Ge(e.text,r,P.panelBg):e.panelHeader?Zt(e.text,r,P.panelMuted):e.text,d=ie(`${n}${c}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let u=[{text:`${d}${o}${i}`},...e.prBadge];return{text:`${d}${o}${e.prBadge.map(R=>R.text).join("")}`,segments:u,tone:p}}return{text:`${d}${o}${i}`,tone:p}}function Gu(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 Hu(e,t,r){return e.map(n=>n.active?r?Ge(n.label,t,P.panelBg):Zt(n.label,t,P.panelBg):Cn(n.label,t,P.panelBg)).join(" ")}function zu(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Cn(e.value,t,P.panelBg):e.value}`}}function Qt(e,t,r,n){let s=Qu(n,e.tone??"default"),o=Yu(e,r,s);if(n==="left"){if(e.fullBleed)return $(ie(o,t),r,s);let a=t-Yt-Jt;if(e.rightAlign){let c=z(o),d=Math.max(0,a-c),p=`${" ".repeat(Yt)}${" ".repeat(d)}${o}${" ".repeat(Jt)}`;return $(p,r,s)}let l=`${" ".repeat(Yt)}${ie(o,a)}${" ".repeat(Jt)}`;return $(l,r,s)}return n==="center"&&e.fullBleed?Ju(e,t,r,s):$(ie(` ${o}`,t),r,s)}function Qu(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function kt(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(J());return r}function J(){return{text:""}}function Yu(e,t,r){return e.segments?e.segments.map(n=>mi(n,t,r)).join(""):e.text}function Ju(e,t,r,n){let s=" ".repeat(Xt),o=Math.max(0,t-Xt*2);if(!e.segments)return $(`${s}${ie(e.text,o)}${s}`,r,n);let i=ep(e.segments,o),a=`${s}${i.map(l=>mi(l,r,n)).join("")}${s}${r?Sn:""}`;return $(a,r,n)}function mi(e,t,r){let n=e.href?`${gi(e.href)}${e.text}${Sn}`:Xu(e.text);return!t||!e.style?n:`${wt(np(e.style,r))}${sp(e.style)}${n}${Pn}${wt(r)}`}function Xu(e){return e.replace(Fu,t=>{let[r,n]=Zu(t);return`${gi(r)}${r}${Sn}${n}`})}function Zu(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function gi(e){return`\x1B]8;;${e}\x1B\\`}function ep(e,t){let r=tp(e,t);return rp(r,t)}function tp(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=z(s.text);if(o<=n){r.push(s),n-=o;continue}let i=er(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function rp(e,t){let r=z(Ti(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 np(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 sp(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 op(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function hi(e,t){let r=Math.max(0,t-z(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ie(e,t){let r=z(e);return r>=t?ip(e,t):e+" ".repeat(t-r)}function ip(e,t){if(t<=0)return"";if(z(e)<=t)return e;let r=wi(e);return er(r,Math.max(0,t-1))+"\u2026"}function z(e){let t=0;for(let r of Array.from(wi(e)))t+=ki(r);return t}function er(e,t){let r="",n=0;for(let s of Array.from(e)){let o=ki(s);if(n+o>t)break;r+=s,n+=o}return r}function ki(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 ap(e,t,r){return Math.min(Math.max(e,t),r)}function wi(e){return e.replace(Ou,"").replace(ju,"")}function Ti(e){return e.map(t=>t.text).join("")}function $(e,t,r){if(!t)return e;let n=wt(r),s=e.replace(Mu,`${Pn}${n}`);return`${n}${s}${Pn}`}function wt(e){let t=[];return e.fg&&t.push(`38;2;${li(e.fg).join(";")}`),e.bg&&t.push(`48;2;${li(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function li(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Ge(e,t,r){return tr(e,t,P.success.fg,r)}function lp(e,t,r){return tr(e,t,P.error.fg,r)}function Zt(e,t,r){return tr(e,t,P.accent.fg,r)}function Cn(e,t,r){return tr(e,t,P.mutedfg.fg,r)}function tr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${wt(s)}${e}${wt(n)}`}function Ri(e,t,r){let n=e.tasks.find(a=>a.ptyTabs.some(l=>l.id===t))??null,s=n?.ptyTabs.find(a=>a.id===t)??null,o=n?.worktreePath??r,i=s?.kind==="agent"?dp(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:cp(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function cp(e,t){let r=(e??"").split(vn.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(vn.delimiter):[...r,t].join(vn.delimiter)}function dp(e){return e.command.length>0?e.command:["codex"]}function yi(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 ye(e){return{columns:Math.max(20,e.width-Z.leftWidth-Z.rightWidth-Z.dividerWidth-Xt*2),rows:Math.max(5,e.height-Z.topRailHeight-5)}}function Pi(e){return e.length===1||oe(e)||e==="BACKSPACE"||e==="TAB"}function Tt(e){return typeof e=="string"&&new RegExp(`:(?:agent|${A.join("|")})(?:-\\d+)?$`).test(e)}function Si(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 En(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function bi(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 Rt(e){return Ci.includes(e)?"SHIFT_ENTER":null}function An(e){return Ci.some(t=>t.startsWith(e))}function Ii(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var Ci=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function vi(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
142
142
|
`||r===`\r
|
|
143
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function
|
|
144
|
-
`).map((t,r)=>`\x1B[${r+1};1H${t}`).join("")}import{spawn as
|
|
145
|
-
`,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:""},
|
|
146
|
-
[process exited ${u.exitCode}]`).then(()=>{this.onUpdate?.(f.tabId)})})),f}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function
|
|
143
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Ei(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Ai(e){return e.split(`
|
|
144
|
+
`).map((t,r)=>`\x1B[${r+1};1H${t}`).join("")}import{spawn as Lp}from"node:child_process";import{createHash as jp}from"node:crypto";import{createServer as Mp,createConnection as Ni}from"node:net";import{openSync as Op}from"node:fs";import{mkdir as Fp,readFile as On,rm as De,writeFile as Np}from"node:fs/promises";import{tmpdir as Wp}from"node:os";import He from"node:path";import{createRequire as Rp}from"node:module";import up from"@xterm/headless";var pp=1e3,fp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function Di(e){return new up.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:pp,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function $i(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Dn(e,t){return new Promise(r=>{e.write(t,r)})}function Li(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 p=l.getCell(d,s);!p||p.getWidth()===0||c.push({text:p.getChars()||" ",style:hp(p,i+a===o&&d===r.cursorX)})}n.push({segments:mp(gp(c))})}return n}function mp(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&Tp(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};ji(r.style)||(s.style=r.style),t.push(s)}return t}function gp(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!ji(r.style))break;t-=1}return e.slice(0,t)}function hp(e,t){let r={},n=xi(e,"fg"),s=xi(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 xi(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"):fp[s]??kp(s)}function kp(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(wp).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 wp(e){return e===0?0:55+e*40}function Tp(e,t){return xn(e)===xn(t)}function xn(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function ji(e){return xn(e)===""}var yp=Rp(import.meta.url),Pp=/^CTRL_([A-Z])$/,Sp="\x1B[6n",bp="\x1B[c",Ip="\x1B[?u",Cp={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
145
|
+
`,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:""},rr=class{sessions=new Map;shell;env;spawn;onUpdate;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.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,n,s){let o=this.sessions.get(r);if(o)if(o.status!=="running")$n(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,Mi(o,n),this.getViewState(r);let i=this.createSession(t,r,n,s);return this.sessions.set(r,i),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||r.pty.write(t)}writeKey(t){let r=vp(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&&Mi(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&($n(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())$n(t);this.sessions.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:Li(r.terminal,r.scrollbackLines),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??Ap().spawn,i=Di(n),a=s??this.resolveSessionSpec(t,r),l=ve({...this.env,...a.env??{}}),{executable:c,args:d}=xp(this.shell,a.command,{cwd:a.cwd,env:l}),p=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:Dp(l)}),f={taskId:t,tabId:r,pty:p,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0};return f.disposables.push(p.onData(u=>{$p(p,u),Dn(f.terminal,u).then(()=>{this.onUpdate?.(f.tabId)})})),f.disposables.push(p.onExit(u=>{f.status="exited",Dn(f.terminal,`\r
|
|
146
|
+
[process exited ${u.exitCode}]`).then(()=>{this.onUpdate?.(f.tabId)})})),f}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function vp(e){if(e.length===1)return e;let t=Cp[e];if(t!==void 0)return t;let r=Pp.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function Mi(e,t){Ep(e.pty,t),$i(e.terminal,t)}function $n(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function Ep(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Ap(){return yp("node-pty")}function xp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Ee(t[0],r),...t.slice(1)].map(Oi).join(" ")}; exec ${Oi(e)} -l`;return{executable:e,args:["-lc",s]}}function Oi(e){return`'${e.replaceAll("'","'\\''")}'`}function Dp(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 $p(e,t){for(let r=0;r<Ln(t,Sp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Ln(t,bp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Ln(t,Ip);r+=1)e.write("\x1B[?0u")}function Ln(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 Fn=3;async function Wi(e){let t=Nn(e.paths);await _p(t,e.paths,e.spawnDaemon);let r=await Vi(t.socketPath),n=new jn(r,e);return await n.ready(),n}async function _i(e,t={}){let r=Nn(e);await Fp(e.runtimeDir,{recursive:!0}),await De(r.socketPath,{force:!0});let n=new Mn(e,t),s=Mp(o=>n.handleConnection(o));await Gp(s,r.socketPath),await Np(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 De(r.socketPath,{force:!0}),await De(r.pidPath,{force:!0}),n.disposeAll()}async function qi(e){let t=Nn(e);return await sr(t.socketPath)?(await Ui(t.socketPath),!0):!1}var jn=class{constructor(t,r){this.socket=t;this.options=r,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=!0,this.rejectAll(new Error("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;attachedTabId=null;buffer="";closed=!1;options;async ready(){if((await this.send({type:"ping"})).protocolVersion!==Fn)throw new Error("Craig PTY daemon protocol mismatch.")}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;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})}}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){this.send({type:"scrollViewport",lines:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}resize(t){this.send({type:"resize",size:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}disposeSession(t){this.viewCache.delete(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}}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)}
|
|
147
147
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
148
148
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
149
|
-
`)}}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}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},
|
|
149
|
+
`)}}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}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},Mn=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new rr({...r,workspaceRoot:t.workspaceRoot,onUpdate:n=>this.broadcastUpdate(n)})}handleConnection(t){let r="";this.clients.add(t),t.setEncoding("utf8"),t.on("data",n=>{r+=String(n);let s=r.indexOf(`
|
|
150
150
|
`);for(;s!==-1;){let o=r.slice(0,s);r=r.slice(s+1),this.handleLine(t,o),s=r.indexOf(`
|
|
151
|
-
`)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{
|
|
152
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
151
|
+
`)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{nr(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(n);nr(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:Fn}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);nr(t,{id:n.id,ok:!1,error:o})}}handleRequest(t){switch(t.type){case"ping":return null;case"ensureSession":return this.attachedTabId=t.tabId,this.runtime.ensureSession(t.taskId,t.tabId,t.size,t.spec);case"hydrateSession":return this.runtime.getViewState(t.tabId);case"write":return this.runtime.write(t.input),null;case"writeKey":return this.runtime.writeKey(t.key),null;case"scrollViewport":return this.runtime.scrollViewport(t.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(t.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(t.tabId),this.attachedTabId===t.tabId&&(this.attachedTabId=null),null;case"pruneStale":{let r=new Set(t.keepTabIds);for(let n of this.runtime.sessionTabIds())r.has(n)||(this.runtime.disposeSession(n),this.attachedTabId===n&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(t.tabId);case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return Hp(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients)nr(n,{type:"update",tabId:t,view:r})}};function Nn(e){let t=jp("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:He.join(Wp(),`craig-${t}.sock`),pidPath:He.join(e.runtimeDir,"pty-daemon.pid")}}async function _p(e,t,r){if(await qp(e.socketPath,1e3))return;await sr(e.socketPath)&&(await Ui(e.socketPath),await Fi(e.socketPath,1e3)),await sr(e.socketPath)&&(await Kp(e),await Fi(e.socketPath,1e3)),await Up(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=Bp(n),l=Op(He.join(t.runtimeDir,"pty-daemon.log"),"a");Lp(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 Bi(e.socketPath))return;await Wn(50)}let o=await On(He.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
152
|
+
${o.slice(-2e3)}`:""}`)}async function Bi(e){let t=await Vp(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===Fn}async function qp(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Bi(e))return!0;await Wn(50)}return!1}function Bp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=He.resolve(He.dirname(t),"..","node_modules",".bin","tsx");return{command:qr("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 Up(e){let t=await On(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Gi(r))return}await De(e.socketPath,{force:!0}),await De(e.pidPath,{force:!0})}async function sr(e){let t=await Vi(e).catch(()=>null);return t?(t.end(),!0):!1}async function Ui(e){await Ki(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Kp(e){let t=await On(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!Gi(r)){await De(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await De(e.socketPath,{force:!0})}}async function Vp(e){return Ki(e,{id:1,type:"ping"})}function Ki(e,t){return new Promise((r,n)=>{let s=Ni(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)}
|
|
153
153
|
`)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let c=o.indexOf(`
|
|
154
|
-
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(p){n(p instanceof Error?p:new Error(String(p)))}}),s.once("close",()=>a())})}async function
|
|
155
|
-
`)}catch{}}function
|
|
156
|
-
`}function Bp(e){return e.length===1&&e>=" "&&e!==""}import Tt from"node:path";function Hi(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 zi="\u{F024B} ",Qi="\u{F0DCF} ",Yi="\u25CB",Nn="\uEA64",Ji="\uEAFE",Xi="\uEBDA",Wn="\u25CB",_n="\u25CF",qn="\u2713",Bn="\u2715";function Zi(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 sr="empty",O={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function na(e,t){let r=Vp(t,e),n=t.repos.find(R=>R.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(R=>R.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(R=>R.repoId===n.id):[],i=o.find(R=>R.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=vf(t.tasks),c=zp(e,i),d=Hp(e,i,c),p=d.find(R=>R.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,u=n?.name??"no repo",w=i?h.runners.getDisplayName(i.runner):h.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 ${n?`[${n.name}]`:"[no repo]"} \xB7 ${h.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 [${h.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Kt(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"?i===null?"n new task Tab tasks Esc pause ? help":c===I?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${h.runners.getDisplayName(e.centerTabRunner??i?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?a?"\u2191\u2193 targets Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"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:Tt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Tt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Up(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(R=>Ef(R,l[R])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:u,agent:w},centerTranscript:Gp(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Cf(n,i),rightInspection:lf(e,i,f)}}function Up(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Kp(r,e,t.repos,t.tasks);let n=t.workspaces;if(n.length===0)r.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let o of n){let i=e.selectedLeftItemId===`workspace:${o.id}`;r.push({id:`workspace:${o.id}`,text:`${o.kind==="project"?"\u2261":"\u2013"} ${o.name??o.id}`,selected:i,focused:i&&e.focusedRegion==="tasks"});let a=o.kind==="project"?o.discoveredRepoIds??[]:[o.primaryRepoId],l=t.tasks.filter(c=>c.workspaceId===o.id);if(l.length===0)r.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of l){let d=e.selectedLeftItemId===`task:${c.id}`,p=d?"\u25B8":"\u2022",f=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,u={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},w=oa(c);w&&(u.prBadge=w),r.push(u)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}if(o.kind==="repo"){let c=`new-task:${o.primaryRepoId}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}else{r.push({text:` Repos (${a.length})`,indent:0,muted:!0});for(let c of a.slice(0,6)){let d=t.repos.find(p=>p.id===c);r.push({text:` \xB7 ${d?.name??c}`,indent:0,muted:!0})}a.length>6&&r.push({text:` \xB7 ${a.length-6} more`,indent:0,muted:!0})}}let s=e.selectedLeftItemId==="new-workspace";return r.push({text:"",muted:!0}),r.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&e.focusedRegion==="tasks"}),r}function Kp(e,t,r,n){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let o of r){let i=t.selectedLeftItemId===`repo:${o.id}`;e.push({id:`repo:${o.id}`,text:`\u2013 ${o.name}`,selected:i,focused:i&&t.focusedRegion==="tasks"});let a=n.filter(d=>d.repoId===o.id);if(a.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of a){let p=t.selectedLeftItemId===`task:${d.id}`,f=p?"\u25B8":"\u2022",u=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,w={id:`task:${d.id}`,taskId:d.id,text:`${f} ${u}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},R=oa(d);R&&(w.prBadge=R),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${h.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let s=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&t.focusedRegion==="tasks"}),e}function Vp(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 Gp(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(p=>p.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((p,f)=>{let u=f===s.selectedIndex?"\u25B8":" ",w=p.kind==="repo"?" [git repo]":"/";return`${u} ${p.name}${w}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return te(["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 te(["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 te([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${h.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?te([`${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."]):te([`${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===I&&t.openInspectionKind==="file"?Jp(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?Xp(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?te(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):te(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Hp(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:Qp(o)}))??[];if(!t)return[{id:sr,label:"EMPTY",active:r===sr,focused:e.focusedRegion==="center"&&r===sr}];let s=e.openInspectionKind||r===I?[{id:I,label:Yp(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function zp(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===I&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??I:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??I:sr}function Qp(e){return e.title.toUpperCase()}function Yp(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Tt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Jp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return te(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=sa(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:""},...Zp(n.lines,r,s)]}function Xp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return te(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=sa(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:""},...ef(n.lines,r,s)]}function te(e){return e.map(t=>({text:t}))}function Zp(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:O.lineNumber}},{text:" \u2502 ",style:{fg:O.gutter}},...Un(o,r)],tone:"default"}})}function ef(e,t,r){let n=tf(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>rf(o,r))}function tf(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 rf(e,t){let r=ea(e.oldNumber),n=ea(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:O.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:O.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?sf(Un(e.text,t),o.bg,o.fallbackFg):Un(e.text,t),l=o?{fg:O.lineNumber,bg:o.bg}:{fg:O.lineNumber},c=o?{fg:O.gutter,bg:o.bg}:{fg:O.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function ea(e){return e===null?" ":String(e).padStart(4," ")}function sa(e){let t=Tt.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 Un(e,t){return t==="diff"?nf(e):t==="markdown"?of(e):t==="json"?Kn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Kn(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 nf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:O.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:O.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:O.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:O.diffMeta}}]:[{text:e}]}function sf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function of(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:O.markup,bold:!0}}]:Kn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Kn(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:af(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function af(e){return e.startsWith("//")||e.startsWith("/*")?{fg:O.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:O.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:O.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:O.markup}:{fg:O.keyword}}function lf(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"?ia(t.repoTargets??[]):s?.pullRequest??(t?v(t):null),i=[cf(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ca(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Pf(e,r)]}:{title:"",rows:[...i,...Sf(e,r)]}}function cf(e,t){let r=e.inspectionMode,n=[{label:"CHANGES",active:r==="diff"},{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=Vn(t),i=Gn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function ta(e){return[{text:" "},Vn(e),{text:" "},Gn(e)]}function oa(e){if(e.type==="project"&&e.repoTargets?.length){let r=ia(e.repoTargets);return r?ta(r):null}let t=v(e);return t?.number?ta(t):null}function ia(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=uf(r);return{number:-1,status:df(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 df(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 uf(e){let t=e.map(r=>aa(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 Vn(e){return!e||!e.number?{text:Yi,style:{fg:"565f89"}}:e.status==="merged"?{text:Ji,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Xi,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Nn,style:{fg:"565f89"}}:{text:Nn,style:{fg:"9ece6a"}}}function Gn(e){return e?.aggregateReadiness?ra(e.aggregateReadiness):ra(aa(e))}function ra(e){return e==="failed"?{text:Bn,style:{fg:"f7768e"}}:e==="pending"?{text:_n,style:{fg:"e0af68"}}:e==="success"?{text:qn,style:{fg:"9ece6a"}}:{text:Wn,style:{fg:"565f89"}}}function aa(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")?la(e)?"failed":pf(e)?"success":"pending":"pending"}function pf(e){return!!(e.mergeable&&!e.draft&&!la(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function la(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function ca(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return ff(e,t);let r=v(t),n=ua("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}),mf(n,e)}var nr=32;function ff(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 p=i.failureReason?i.failureReason.slice(0,14):i.status,f=nr-p.length-1,u=c.length>f?c.slice(0,f-1)+"\u2026":c,w=nr-u.length-p.length;r.push({id:`project-review:${i.repoId}`,text:u+" ".repeat(Math.max(1,w))+p,selected:a,focused:l,muted:!0})}else{let d=Vn(i.pullRequest),p=Gn(i.pullRequest),f=`${d.text} ${p.text}`,u=nr-f.length-1,w=c.length>u?c.slice(0,u-1)+"\u2026":c,R=nr-w.length-f.length,A=w+" ".repeat(Math.max(1,R));r.push({id:`project-review:${i.repoId}`,text:A+f,selected:a,focused:l,segments:[{text:A},{...d,text:d.text},{text:" "},{...p,text:p.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(...ua("target",o.branch,o.pullRequest))),r}function da(e,t){return ca(e,t).length}function ua(e,t,r){let n=p=>`${e}-${p}`;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=gf(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:hf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${pa(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(kf)):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((p,f)=>wf(p,n(`comment:${f}`))))),s}function mf(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 gf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function hf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function pa(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 kf(e){let{icon:t,color:r}=Rf(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," ")} ${yf(e.status)}`,color:r,muted:!1}}function wf(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${pa(e.createdAt)}`:"",s=Tf(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 Tf(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 Rf(e){switch(e){case"success":return{icon:qn,color:"9ece6a"};case"pending":return{icon:_n,color:"e0af68"};case"failed":return{icon:Bn,color:"f7768e"};case"skipped":return{icon:Wn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function yf(e){return e==="success"?"passing":e==="failed"?"failing":e}function Pf(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=Hn(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,p=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?zi:Qi:Hi(l.label),f=l.kind==="directory"?"7aa2f7":Zi(l.label),u=" ".repeat(l.depth),w=f?{text:p,style:{fg:f}}:{text:p},R=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},A=[{text:u},w,R];return{id:l.path,text:`${u}${p}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:A}})]}function Hn(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 Sf(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(bf(t))return If(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=>fa(o,e,t))))}return r}function bf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function If(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=>fa(c,e,t,s.length+1))))}}return r}function fa(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 Cf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:h.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Tt.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 vf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Ef(e,t){return{name:h.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as xf,mkdir as Af,readFile as Df}from"node:fs/promises";import $f from"node:path";var ma=80,zn=async(e,t)=>{await Af($f.dirname(e.errorLogFile),{recursive:!0}),await xf(e.errorLogFile,jf(t),"utf8")},ga=async(e,t)=>{try{await zn(e,t)}catch{}},Qn=async(e,t=ma)=>{try{let n=(await Df(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
157
|
-
`).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(
|
|
154
|
+
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(p){n(p instanceof Error?p:new Error(String(p)))}}),s.once("close",()=>a())})}async function Fi(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await sr(e))return;await Wn(50)}}function Vi(e){return new Promise((t,r)=>{let n=Ni(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Gp(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function nr(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
155
|
+
`)}catch{}}function Gi(e){try{return process.kill(e,0),!0}catch{return!1}}function Wn(e){return new Promise(t=>setTimeout(t,e))}function Hp(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var _n=["Runners","Error Log","Help"];function qn(e,t){return A.map(r=>{let n=h.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 zi(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 Qi(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(_n.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Bn(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Yi(e,t,r,n){if(e.pathEdit)return zp({...e,pathEdit:e.pathEdit},t,r);let s=qn(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=A[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Bn(r))return{kind:"noop",state:e};let o=A[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:`${h.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function zp(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Hi({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Bn(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Hi({...e,message:s.length>0?`${h.runners.getProfile(n).displayName} executable saved.`:`${h.runners.getProfile(n).displayName} executable reset to default.`})}}return Qp(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Hi(e){let t={...e};return delete t.pathEdit,t}function Bn(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
156
|
+
`}function Qp(e){return e.length===1&&e>=" "&&e!==""}import yt from"node:path";function Ji(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 Xi="\u{F024B} ",Zi="\u{F0DCF} ",ea="\u25CB",Un="\uEA64",ta="\uEAFE",ra="\uEBDA",Kn="\u25CB",Vn="\u25CF",Gn="\u2713",Hn="\u2715";function na(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 ir="empty",O={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function aa(e,t){let r=Xp(t,e),n=t.repos.find(R=>R.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(R=>R.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(R=>R.repoId===n.id):[],i=o.find(R=>R.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=jf(t.tasks),c=tf(e,i),d=ef(e,i,c),p=d.find(R=>R.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,u=n?.name??"no repo",w=i?h.runners.getDisplayName(i.runner):h.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 ${n?`[${n.name}]`:"[no repo]"} \xB7 ${h.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 [${h.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Gt(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"?i===null?"n new task Tab tasks Esc pause ? help":c===I?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${h.runners.getDisplayName(e.centerTabRunner??i?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?a?"\u2191\u2193 targets Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"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:yt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${yt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Yp(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(R=>Mf(R,l[R])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:u,agent:w},centerTranscript:Zp(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Lf(n,i),rightInspection:gf(e,i,f)}}function Yp(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Jp(r,e,t.repos,t.tasks);let n=t.workspaces;if(n.length===0)r.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let o of n){let i=e.selectedLeftItemId===`workspace:${o.id}`;r.push({id:`workspace:${o.id}`,text:`${o.kind==="project"?"\u2261":"\u2013"} ${o.name??o.id}`,selected:i,focused:i&&e.focusedRegion==="tasks"});let a=o.kind==="project"?o.discoveredRepoIds??[]:[o.primaryRepoId],l=t.tasks.filter(c=>c.workspaceId===o.id);if(l.length===0)r.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of l){let d=e.selectedLeftItemId===`task:${c.id}`,p=d?"\u25B8":"\u2022",f=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,u={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},w=ca(c);w&&(u.prBadge=w),r.push(u)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}if(o.kind==="repo"){let c=`new-task:${o.primaryRepoId}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}else{r.push({text:` Repos (${a.length})`,indent:0,muted:!0});for(let c of a.slice(0,6)){let d=t.repos.find(p=>p.id===c);r.push({text:` \xB7 ${d?.name??c}`,indent:0,muted:!0})}a.length>6&&r.push({text:` \xB7 ${a.length-6} more`,indent:0,muted:!0})}}let s=e.selectedLeftItemId==="new-workspace";return r.push({text:"",muted:!0}),r.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&e.focusedRegion==="tasks"}),r}function Jp(e,t,r,n){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let o of r){let i=t.selectedLeftItemId===`repo:${o.id}`;e.push({id:`repo:${o.id}`,text:`\u2013 ${o.name}`,selected:i,focused:i&&t.focusedRegion==="tasks"});let a=n.filter(d=>d.repoId===o.id);if(a.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of a){let p=t.selectedLeftItemId===`task:${d.id}`,f=p?"\u25B8":"\u2022",u=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,w={id:`task:${d.id}`,taskId:d.id,text:`${f} ${u}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},R=ca(d);R&&(w.prBadge=R),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${h.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let s=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&t.focusedRegion==="tasks"}),e}function Xp(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 Zp(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(p=>p.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((p,f)=>{let u=f===s.selectedIndex?"\u25B8":" ",w=p.kind==="repo"?" [git repo]":"/";return`${u} ${p.name}${w}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return te(["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 te(["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 te([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${h.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?te([`${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."]):te([`${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===I&&t.openInspectionKind==="file"?sf(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?of(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?te(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):te(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function ef(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:rf(o)}))??[];if(!t)return[{id:ir,label:"EMPTY",active:r===ir,focused:e.focusedRegion==="center"&&r===ir}];let s=e.openInspectionKind||r===I?[{id:I,label:nf(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function tf(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===I&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??I:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??I:ir}function rf(e){return e.title.toUpperCase()}function nf(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?yt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function sf(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return te(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=la(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:""},...af(n.lines,r,s)]}function of(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return te(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=la(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:""},...lf(n.lines,r,s)]}function te(e){return e.map(t=>({text:t}))}function af(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:O.lineNumber}},{text:" \u2502 ",style:{fg:O.gutter}},...zn(o,r)],tone:"default"}})}function lf(e,t,r){let n=cf(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>df(o,r))}function cf(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 df(e,t){let r=sa(e.oldNumber),n=sa(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:O.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:O.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?pf(zn(e.text,t),o.bg,o.fallbackFg):zn(e.text,t),l=o?{fg:O.lineNumber,bg:o.bg}:{fg:O.lineNumber},c=o?{fg:O.gutter,bg:o.bg}:{fg:O.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function sa(e){return e===null?" ":String(e).padStart(4," ")}function la(e){let t=yt.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 zn(e,t){return t==="diff"?uf(e):t==="markdown"?ff(e):t==="json"?Qn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Qn(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 uf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:O.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:O.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:O.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:O.diffMeta}}]:[{text:e}]}function pf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function ff(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:O.markup,bold:!0}}]:Qn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Qn(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:mf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function mf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:O.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:O.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:O.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:O.markup}:{fg:O.keyword}}function gf(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"?da(t.repoTargets??[]):s?.pullRequest??(t?v(t):null),i=[hf(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...fa(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Af(e,r)]}:{title:"",rows:[...i,...xf(e,r)]}}function hf(e,t){let r=e.inspectionMode,n=[{label:"CHANGES",active:r==="diff"},{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=Yn(t),i=Jn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function oa(e){return[{text:" "},Yn(e),{text:" "},Jn(e)]}function ca(e){if(e.type==="project"&&e.repoTargets?.length){let r=da(e.repoTargets);return r?oa(r):null}let t=v(e);return t?.number?oa(t):null}function da(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=wf(r);return{number:-1,status:kf(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 kf(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 wf(e){let t=e.map(r=>ua(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 Yn(e){return!e||!e.number?{text:ea,style:{fg:"565f89"}}:e.status==="merged"?{text:ta,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:ra,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Un,style:{fg:"565f89"}}:{text:Un,style:{fg:"9ece6a"}}}function Jn(e){return e?.aggregateReadiness?ia(e.aggregateReadiness):ia(ua(e))}function ia(e){return e==="failed"?{text:Hn,style:{fg:"f7768e"}}:e==="pending"?{text:Vn,style:{fg:"e0af68"}}:e==="success"?{text:Gn,style:{fg:"9ece6a"}}:{text:Kn,style:{fg:"565f89"}}}function ua(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")?pa(e)?"failed":Tf(e)?"success":"pending":"pending"}function Tf(e){return!!(e.mergeable&&!e.draft&&!pa(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function pa(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function fa(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return Rf(e,t);let r=v(t),n=ga("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}),yf(n,e)}var or=32;function Rf(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 p=i.failureReason?i.failureReason.slice(0,14):i.status,f=or-p.length-1,u=c.length>f?c.slice(0,f-1)+"\u2026":c,w=or-u.length-p.length;r.push({id:`project-review:${i.repoId}`,text:u+" ".repeat(Math.max(1,w))+p,selected:a,focused:l,muted:!0})}else{let d=Yn(i.pullRequest),p=Jn(i.pullRequest),f=`${d.text} ${p.text}`,u=or-f.length-1,w=c.length>u?c.slice(0,u-1)+"\u2026":c,R=or-w.length-f.length,x=w+" ".repeat(Math.max(1,R));r.push({id:`project-review:${i.repoId}`,text:x+f,selected:a,focused:l,segments:[{text:x},{...d,text:d.text},{text:" "},{...p,text:p.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(...ga("target",o.branch,o.pullRequest))),r}function ma(e,t){return fa(e,t).length}function ga(e,t,r){let n=p=>`${e}-${p}`;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=Pf(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:Sf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${ha(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(bf)):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((p,f)=>If(p,n(`comment:${f}`))))),s}function yf(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 Pf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function Sf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function ha(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 bf(e){let{icon:t,color:r}=vf(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," ")} ${Ef(e.status)}`,color:r,muted:!1}}function If(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${ha(e.createdAt)}`:"",s=Cf(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 Cf(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 vf(e){switch(e){case"success":return{icon:Gn,color:"9ece6a"};case"pending":return{icon:Vn,color:"e0af68"};case"failed":return{icon:Hn,color:"f7768e"};case"skipped":return{icon:Kn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Ef(e){return e==="success"?"passing":e==="failed"?"failing":e}function Af(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=Xn(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,p=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?Xi:Zi:Ji(l.label),f=l.kind==="directory"?"7aa2f7":na(l.label),u=" ".repeat(l.depth),w=f?{text:p,style:{fg:f}}:{text:p},R=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},x=[{text:u},w,R];return{id:l.path,text:`${u}${p}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:x}})]}function Xn(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 xf(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(Df(t))return $f(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=>ka(o,e,t))))}return r}function Df(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function $f(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=>ka(c,e,t,s.length+1))))}}return r}function ka(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 Lf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:h.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:yt.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 jf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Mf(e,t){return{name:h.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as Of,mkdir as Ff,readFile as Nf}from"node:fs/promises";import Wf from"node:path";var wa=80,Zn=async(e,t)=>{await Ff(Wf.dirname(e.errorLogFile),{recursive:!0}),await Of(e.errorLogFile,_f(t),"utf8")},Ta=async(e,t)=>{try{await Zn(e,t)}catch{}},es=async(e,t=wa)=>{try{let n=(await Nf(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
157
|
+
`).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(qf(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},Ra=async(e,t=wa)=>es(e,t);function _f(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(`
|
|
158
158
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
159
159
|
`)}
|
|
160
160
|
|
|
161
|
-
`}function Lf(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ze={appendErrorLog:zn,appendErrorLogBestEffort:ga,readErrorLog:Qn,readRecentErrorLines:ha};var ka=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 Y(n.paths,e.selectedTaskId),i=t??Mf(o,e.activeTab,e.preferredPtyTabKind),a=ya(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await y(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"}`}}},wa=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 Y(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 y(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}`}}},Ta=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await Y(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await y(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Ra=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await y(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=ya(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await y(t.paths,{...s,selectedPtyTabId:o.id});return}await y(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Mf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function ya(e,t,r,n={}){let s=r??e.runner,o=h.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(u=>u.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let p=new Date().toISOString(),f=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...f?{runner:f}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?h.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Qe=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Pa=async(e,t,r,n,s)=>{h.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=ve();await T(Ee(h.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{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 Qe(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}},Sa=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},ba=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 Y(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}`}}},Ia=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Ca=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await ze.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var va=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 Ea=async(e,t,r)=>{let n=h.runners.setRunnerEnabled(r.config,e,t);return await h.save(r.paths,n),n},xa=async(e,t,r)=>{let n=h.runners.setRunnerPath(r.config,e,t);return await h.save(r.paths,n),n};function pe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function $e(e,t){return ue(t,e.ptyRuntime.getViewState(Yn(e,t)))}function Yn(e,t){let r=pe(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 m(e,t){return $e(e,ri(t,e.model))}function Aa(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:m(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Da(e,t,r){return Aa(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return Aa(e,t,{tone:"error",message:r})}function L(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return ze.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function D(e,t){if(!e.uiStateFile)return;e.runtimeState=Go(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>me({uiStateFile:e.uiStateFile},r),()=>me({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Of(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function W(e){return{paths:e.paths,config:e.config,taskService:b,workspaceService:Q,queueTaskMutation:t=>Of(e,t)}}function Jn(e,t){let r=pe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,o=Hn(s?.fileRows??[],t.collapsedFileTreePaths);return{leftItemIds:ni(e.model),centerTabIds:Jo(r,t),ptyTabIds:r?.ptyTabs.map(i=>i.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:o.map(i=>i.path),fileTreeFileIds:o.filter(i=>i.kind==="file").map(i=>i.path),fileTreeDirectoryIds:o.filter(i=>i.kind==="directory").map(i=>i.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:da(t,r),pageRows:Math.max(5,ee(e.activeTerminal.width,e.activeTerminal.height).height-Z.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(i=>i.repoId)??[]}}async function $a(e,t){await Ta(t,W(e))}async function _(e){e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:m(e,e.state.shell)}:e.state={...e.state,shell:m(e,e.state.shell)}}async function Xn(e,t){let r=++e.inspectionRefreshSequence,n=hn(e.model.tasks,t),s=e.model.inspection,o;if(n&&s?.taskId===n.id){let i={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},a=await Co(n,s,i);if(r!==e.inspectionRefreshSequence)return;o={...e.model,inspection:a}}else if(o=await Re(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=o,e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},D(e,e.state.shell),e.render())}function ja(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=Te(e.state.shell,r,Jn(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),Xn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render()}},16)))}function Zn(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function es(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 Ma(e){es(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.render())})}async function Oa(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=Yn(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 ue(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));return ue({...r,inputMode:"control"},i)}function Fa(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 ts(e,t){try{let r=m(e,t),n=pe(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 La(e,n),await _(e),s=n.selectedPtyTabId)}n&&!s&&(n=await La(e,n),await _(e),s=n.selectedPtyTabId);let o=m(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:ue({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},D(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},i)},D(e,e.state.shell)}catch(r){let n=L(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&wt(t.selectedPtyTabId)&&(await Ff(e,t.selectedTaskId,n).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,Ho(m(e,t),n),n)},D(e,e.state.shell)}e.render()}async function Ff(e,t,r){await Sa(t,r,W(e))}async function Na(e,t,r,n){let s=m(e,t),{nextShell:o}=await ka(s,r,n,W(e));return await _(e),m(e,{...s,...o})}async function Wa(e,t){let r=m(e,t),{closedTab:n,nextShell:s}=await wa(r,W(e));return e.ptyRuntime.disposeSession(n.id),await _(e),m(e,{...r,...s})}async function _a(e,t){let r=m(e,t),{closedTabIds:n,nextShell:s}=await ba(r,W(e));for(let o of n)e.ptyRuntime.disposeSession(o);return await _(e),m(e,{...r,...s})}async function qa(e,t){let r=m(e,t),{nextShell:n}=await va(r,W(e));return await _(e),m(e,{...r,...n})}async function La(e,t){return Ra(t,W(e))}function or(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:$e(e,e.state.shell)},e.render())},16))}async function Ba(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await Ia(e.model.tasks,W(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:m(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,Ca("background PR polling",t,W(e)))}finally{e.prPollInFlight=!1}}}async function Ua(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await b.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await _(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await b.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await _(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${v(a)?.requiredChecks.length??0} reported`)}return m(e,{...Da(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Bf from"node:path";import{readdir as Nf,stat as Wf}from"node:fs/promises";import Ka from"node:path";async function _f(e){let t=await Nf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Ka.join(e,n.name);r.push({name:n.name,path:s,kind:await qf(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 Va(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Ga(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 ir(e,t){let r=await _f(t);e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function qf(e){let t=Ka.join(e,".git");return await Wf(t).catch(()=>null)!==null}function Ha(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Uf(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:m(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:m(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Pa(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,W(e));n=s.task,await _(e);let o=m(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??wi(n,"agent"),ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(o.selectedPtyTabId),e.state={mode:"main",shell:ue(o,i)},D(e,e.state.shell)}catch(s){s instanceof Qe&&(n=s.task);let o=L(e,"create task",s,"Failed to create task.");n&&!(s instanceof Qe)?(await y(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})):n&&(await y(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,m(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 Kf(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:m(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(oe(t)){Uf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:m(e,{...r,selectedRunner:gn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}zo(t)&&(e.state={mode:"main",shell:m(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Vf(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:m(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:m(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:m(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:m(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Va(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:m(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:m(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"){ir(e,Bf.dirname(r.cwd)).catch(s=>{let o=L(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||oe(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){ir(e,s.path).catch(i=>{let a=L(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=W(e);o.addWorkspace(e.paths,s.path).then(async i=>{await _(e);let a=i.repos[0]??null,l=m(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},D(e,e.state.shell),e.render()}).catch(i=>{let a=L(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function Gf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Vi(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==="error-log"){let n=e.state.parentVariant;Hf(e,n)}}}async function Hf(e,t){let r;try{r=await ze.readRecentErrorLines(e.paths)}catch(n){let s=L(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 zf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Gi(Ha(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"?Ea(r.runner,r.enabled,W(e)):xa(r.runner,r.path,W(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=h.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:m(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:h.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=L(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,m(e,e.state.shell),o),runnerOptions:{...Ha(e),message:o}},e.render()})}function za(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){Kf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Vf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Qf(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=mn(e.state.shell,r,Jn(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&oe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1),e.lastTerminalKey=Ti(r)?{key:r,at:Date.now()}:null;let s=Ri(r,e.state.shell.terminal.scrolledBack??!1);if(s!==0){or(e,s);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:m(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){ir(e,e.workspaceRoot).catch(s=>{let o=L(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,m(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Na(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{ts(e,s)}).catch(s=>{let o=L(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Wa(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ua(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=pe(e.model.tasks,n.state),o=s?v(s)?.url??null:null;o?Ga(o).catch(i=>{let a=L(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,m(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,m(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){_a(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){qa(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){ts(e,n.state);return}if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),Xn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:m(e,n.state)},$a(e,e.state.shell).catch(()=>{}),D(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:2,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:m(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Gf(e,r);return}if(e.state.variant==="runners"){zf(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||oe(r)){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(e.state.optionsMessage){(r==="ESCAPE"||oe(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:m(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(oe(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:m(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;Oa(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},D(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=L(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,m(e,e.state.shell),i)},D(e,e.state.shell),e.render()})}):Ma(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 Qa(e,t){let r=bi(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},D(e,e.state.shell),e.render();return}let n=yi(r);if(n!==0){or(e,n);return}let s=Pi(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
161
|
+
`}function qf(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ze={appendErrorLog:Zn,appendErrorLogBestEffort:Ta,readErrorLog:es,readRecentErrorLines:Ra};var ya=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 Y(n.paths,e.selectedTaskId),i=t??Bf(o,e.activeTab,e.preferredPtyTabKind),a=Ia(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await y(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"}`}}},Pa=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 Y(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 y(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}`}}},Sa=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await Y(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await y(t.paths,{...n,selectedPtyTabId:e.activeTab})})},ba=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await y(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=Ia(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await y(t.paths,{...s,selectedPtyTabId:o.id});return}await y(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Bf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Ia(e,t,r,n={}){let s=r??e.runner,o=h.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(u=>u.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let p=new Date().toISOString(),f=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...f?{runner:f}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?h.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Qe=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Ca=async(e,t,r,n,s)=>{h.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=ve();await T(Ee(h.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{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 Qe(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}},va=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Ea=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 Y(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}`}}},Aa=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},xa=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await ze.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var Da=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 $a=async(e,t,r)=>{let n=h.runners.setRunnerEnabled(r.config,e,t);return await h.save(r.paths,n),n},La=async(e,t,r)=>{let n=h.runners.setRunnerPath(r.config,e,t);return await h.save(r.paths,n),n};function pe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function $e(e,t){return ue(t,e.ptyRuntime.getViewState(ts(e,t)))}function ts(e,t){let r=pe(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 m(e,t){return $e(e,ii(t,e.model))}function ja(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:m(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Ma(e,t,r){return ja(e,t,r?{tone:"success",message:r}:null)}function L(e,t,r){return ja(e,t,{tone:"error",message:r})}function j(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return ze.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function D(e,t){if(!e.uiStateFile)return;e.runtimeState=Yo(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>me({uiStateFile:e.uiStateFile},r),()=>me({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Uf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function W(e){return{paths:e.paths,config:e.config,taskService:b,workspaceService:G,queueTaskMutation:t=>Uf(e,t)}}function rs(e,t){let r=pe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,o=Xn(s?.fileRows??[],t.collapsedFileTreePaths);return{leftItemIds:ht(e.model),centerTabIds:ti(r,t),ptyTabIds:r?.ptyTabs.map(i=>i.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:o.map(i=>i.path),fileTreeFileIds:o.filter(i=>i.kind==="file").map(i=>i.path),fileTreeDirectoryIds:o.filter(i=>i.kind==="directory").map(i=>i.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:ma(t,r),pageRows:Math.max(5,ee(e.activeTerminal.width,e.activeTerminal.height).height-Z.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(i=>i.repoId)??[]}}async function Oa(e,t){await Sa(t,W(e))}async function _(e){e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:m(e,e.state.shell)}:e.state={...e.state,shell:m(e,e.state.shell)}}async function ar(e,t){let r=++e.inspectionRefreshSequence,n=Rn(e.model.tasks,t),s=e.model.inspection,o;if(n&&s?.taskId===n.id){let i={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},a=await xo(n,s,i);if(r!==e.inspectionRefreshSequence)return;o={...e.model,inspection:a}}else if(o=await Re(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=o,e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},D(e,e.state.shell),e.render())}function Fa(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)&&ar(e,r).catch(n=>{let s=j(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},120))}function Na(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=Te(e.state.shell,r,rs(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),ar(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render()}},16)))}function ns(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function ss(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 _a(e){ss(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.render())})}async function qa(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=ts(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 ue(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));return ue({...r,inputMode:"control"},i)}function Ba(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 os(e,t){try{let r=m(e,t),n=pe(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 Wa(e,n),await _(e),s=n.selectedPtyTabId)}n&&!s&&(n=await Wa(e,n),await _(e),s=n.selectedPtyTabId);let o=m(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:ue({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},D(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Tt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},i)},D(e,e.state.shell)}catch(r){let n=j(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Tt(t.selectedPtyTabId)&&(await Kf(e,t.selectedTaskId,n).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:L(e,Jo(m(e,t),n),n)},D(e,e.state.shell)}e.render()}async function Kf(e,t,r){await va(t,r,W(e))}async function Ua(e,t,r,n){let s=m(e,t),{nextShell:o}=await ya(s,r,n,W(e));return await _(e),m(e,{...s,...o})}async function Ka(e,t){let r=m(e,t),{closedTab:n,nextShell:s}=await Pa(r,W(e));return e.ptyRuntime.disposeSession(n.id),await _(e),m(e,{...r,...s})}async function Va(e,t){let r=m(e,t),n=ht(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Ea(r,W(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await _(e),m(e,{...r,...i,selectedLeftItemId:Vf(n,ht(e.model),s)})}async function Ga(e,t){let r=m(e,t),{nextShell:n}=await Da(r,W(e));return await _(e),m(e,{...r,...n})}async function Wa(e,t){return ba(t,W(e))}function lr(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:$e(e,e.state.shell)},e.render())},16))}function Vf(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 Ha(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await Aa(e.model.tasks,W(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:m(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,xa("background PR polling",t,W(e)))}finally{e.prPollInFlight=!1}}}async function za(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await b.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await _(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await b.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await _(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${v(a)?.requiredChecks.length??0} reported`)}return m(e,{...Ma(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Yf from"node:path";import{readdir as Gf,stat as Hf}from"node:fs/promises";import Qa from"node:path";async function zf(e){let t=await Gf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Qa.join(e,n.name);r.push({name:n.name,path:s,kind:await Qf(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 Ya(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Ja(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 cr(e,t){let r=await zf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Qf(e){let t=Qa.join(e,".git");return await Hf(t).catch(()=>null)!==null}function Xa(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Jf(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:m(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:m(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Ca(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,W(e));n=s.task,await _(e);let o=m(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??yi(n,"agent"),ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Tt(o.selectedPtyTabId),e.state={mode:"main",shell:ue(o,i)},D(e,e.state.shell)}catch(s){s instanceof Qe&&(n=s.task);let o=j(e,"create task",s,"Failed to create task.");n&&!(s instanceof Qe)?(await y(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})):n&&(await y(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:L(e,m(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 Xf(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:m(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(oe(t)){Jf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:m(e,{...r,selectedRunner:Tn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}Xo(t)&&(e.state={mode:"main",shell:m(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Zf(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:m(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:m(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:m(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:m(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Ya(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:m(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:m(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"){cr(e,Yf.dirname(r.cwd)).catch(s=>{let o=j(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||oe(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){cr(e,s.path).catch(i=>{let a=j(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=W(e);o.addWorkspace(e.paths,s.path).then(async i=>{await _(e);let a=i.repos[0]??null,l=m(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},D(e,e.state.shell),e.render()}).catch(i=>{let a=j(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function em(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Qi(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==="error-log"){let n=e.state.parentVariant;tm(e,n)}}}async function tm(e,t){let r;try{r=await ze.readRecentErrorLines(e.paths)}catch(n){let s=j(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 rm(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Yi(Xa(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"?$a(r.runner,r.enabled,W(e)):La(r.runner,r.path,W(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=h.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:m(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:h.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=j(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:L(e,m(e,e.state.shell),o),runnerOptions:{...Xa(e),message:o}},e.render()})}function Za(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){Xf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Zf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){sm(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=wn(e.state.shell,r,rs(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&oe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=Rt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(nm(e,r))return;e.lastTerminalKey=Pi(r)?{key:r,at:Date.now()}:null;let o=Si(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){lr(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:m(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){cr(e,e.workspaceRoot).catch(s=>{let o=j(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:L(e,m(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Ua(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{os(e,s)}).catch(s=>{let o=j(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:L(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Ka(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:L(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){za(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:L(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=pe(e.model.tasks,n.state),o=s?v(s)?.url??null:null;o?Ja(o).catch(i=>{let a=j(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:L(e,m(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:L(e,m(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){Va(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:L(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Ga(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:L(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){os(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){Fa(e,e.state.shell);return}ar(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:L(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:m(e,n.state)},Oa(e,e.state.shell).catch(()=>{}),D(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:2,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:m(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){em(e,r);return}if(e.state.variant==="runners"){rm(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||oe(r)){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(e.state.optionsMessage){(r==="ESCAPE"||oe(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:m(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(oe(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:m(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;qa(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},D(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=j(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:L(e,m(e,e.state.shell),i)},D(e,e.state.shell),e.render()})}):_a(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 el(e,t){let r=Ei(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=Rt(o);if(i){rl(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(An(o)){e.pendingTerminalKeySequence.raw=o,tl(e);return}dr(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},D(e,e.state.shell),e.render();return}let n=bi(r);if(n!==0){lr(e,n);return}let s=Rt(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
162
162
|
`&&r!==`\r
|
|
163
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),
|
|
163
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),vi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function nm(e,t){if(e.pendingTerminalKeySequence){let r=Ii(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=Rt(n);if(s)return rl(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(An(n))return e.pendingTerminalKeySequence.raw=n,tl(e),!0}return dr(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>dr(e),30)},!0)}function tl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>dr(e),30))}function dr(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function rl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function nl(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){Na(e,En(t));return}let r=En(t);r!==0&&lr(e,r)}function sm(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var im=om(import.meta.url),am=im("terminal-kit"),lm=am.terminal;function is(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}async function sl(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ne(t),n=await h.load(r),s=h.runners.getEnabled(n),o=e.uiStateFile?await Me({uiStateFile:e.uiStateFile}):null,i=await Re(t,void 0,s),a=gt(Qo(o,n),i);i=await Re(t,a,s);let l=()=>{},c={workspaceRoot:t,onUpdate:()=>l(),resolveSessionSpec:(p,f)=>Ri(i,f,t)},d=e.ptyRuntime??await Wi({...c,paths:r});return new Promise(p=>{let f=e.terminal??lm,u={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:gt(a,i)},model:i,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,prPollTimer:null,prPollInFlight:!1,lastBackgroundPrPollError:null,versionText:`Craig v${h.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:f,ptyRuntime:d,resolve:p,render:()=>{},exit:k=>p(k)};l=()=>{u.state.mode==="main"&&(u.state={mode:"main",shell:$e(u,u.state.shell)},u.ptyRenderTimer||(u.ptyRenderTimer=setTimeout(()=>{u.ptyRenderTimer=null,u.state.mode==="main"&&u.render()},50)))},u.render=()=>{Ba(u);let k=ee(f.width,f.height),Ye=u.state.mode==="main"?fi(k,aa(m(u,u.state.shell),u.model),{centerOnly:u.state.shell.centerZoomed,focusFlashActive:u.focusFlashUntil!==null&&Date.now()<u.focusFlashUntil}):u.state.variant==="boot"?ci(k,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="pause"?di(k,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="options"?bn(k,{menuIndex:u.state.menuIndex,optionsMenuItems:_n}):u.state.variant==="runners"?bn(k,{menuIndex:is(u.state).menuIndex,optionsMenuItems:qn(u.config,is(u.state)),optionsMessage:zi(is(u.state)),optionsSubtitle:"Runners"}):u.state.variant==="error-log"?pi(k,{errorLogPath:u.state.errorLog?.path??r.errorLogFile,errorLogLines:u.state.errorLog?.lines??[]}):ui(k);u.pendingClear&&(f.moveTo(1,1),f.eraseDisplayBelow(),u.pendingClear=!1),f.noFormat(Ai(Ye)),f.hideCursor(!0)};let w=k=>Za(u,k),R=k=>el(u,k),x=k=>nl(u,k),B=()=>{process.stdout.off("resize",fe),process.off("SIGCONT",ae),f.removeListener("key",w),f.removeListener("unknown",R),f.removeListener("mouse",x),u.scrollRenderTimer&&(clearTimeout(u.scrollRenderTimer),u.scrollRenderTimer=null),u.inspectionScrollRenderTimer&&(clearTimeout(u.inspectionScrollRenderTimer),u.inspectionScrollRenderTimer=null),u.leftNavInspectionTimer&&(clearTimeout(u.leftNavInspectionTimer),u.leftNavInspectionTimer=null),u.pendingTerminalKeySequence&&(clearTimeout(u.pendingTerminalKeySequence.timer),u.pendingTerminalKeySequence=null),u.ptyRenderTimer&&(clearTimeout(u.ptyRenderTimer),u.ptyRenderTimer=null),u.footerToastTimer&&(clearTimeout(u.footerToastTimer),u.footerToastTimer=null),u.focusFlashTimer&&(clearTimeout(u.focusFlashTimer),u.focusFlashTimer=null),u.prPollTimer&&(clearInterval(u.prPollTimer),u.prPollTimer=null),u.ptyRuntime.disposeAll(),f.grabInput(!1),f.hideCursor(!1),f.fullscreen(!1)};u.exit=k=>{B(),p(k)};let fe=()=>{ns(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()},ae=()=>{ns(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()};process.stdout.on("resize",fe),process.on("SIGCONT",ae),f.grabInput(!0),u.inputCaptureMode="control",f.hideCursor(!0),f.fullscreen(!0),f.on("key",w),f.on("unknown",R),f.on("mouse",x),u.prPollTimer=setInterval(()=>{Ha(u)},(u.config.github?.watchIntervalSeconds??5)*1e3),h.version.checkForUpdate().then(k=>{k.updateAvailable&&k.latest&&(u.updateText=`Update available: v${k.latest}`,u.render())}),u.bootHydrationReady=ss(u).catch(()=>{}),u.render()})}async function cm(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=ne(i);return await _i(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=ne(i);return await qi(a),0}let e=ws(process.argv.slice(2)),t=process.cwd(),r=ne(t),n={paths:r};if(e.mode==="interactive")return await sl({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await vo(e.command,n),o=Eo(s);return o.length>0&&process.stdout.write(`${o}
|
|
164
164
|
`),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
165
|
-
`),1}}var
|
|
165
|
+
`),1}}var dm=await cm();process.exit(dm);
|