craig-cli 0.7.5 → 0.7.6
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 +61 -61
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var nl=Object.defineProperty;var ar=(e,t)=>{for(var r in t)nl(e,r,{get:t[r],enumerable:!0})};import{readFile as ll}from"node:fs/promises";import{randomUUID as sl}from"node:crypto";import{open as ol,readFile as nm,rename as il,rm as al}from"node:fs/promises";import lr from"node:path";async function M(e,t){let r=lr.dirname(e),n=lr.join(r,`.${lr.basename(e)}.${process.pid}.${Date.now()}.${sl()}.tmp`),s=await ol(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await il(n,e)}catch(o){throw await s.close().catch(()=>{}),await al(n,{force:!0}).catch(()=>{}),o}}async function Me(e){try{let t=await ll(e.uiStateFile,"utf8"),r=JSON.parse(t);return cl(r,e.uiStateFile)}catch(t){if(ul(t))return null;throw t}}async function me(e,t){await M(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function yt(){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 cl(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")||!Le(e,"inputMode")||!Le(e,"focusedRegion")||!Le(e,"activeTab")||!Le(e,"inspectorSection")||!Le(e,"inspectionMode")||!Rt(e,"openInspectionKind")||!Rt(e,"selectedFileTreePath")||!Rt(e,"selectedFilePath")||!Rt(e,"selectedDiffPath")||!dl(e,"collapsedFileTreePaths")||!Le(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 Le(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Rt(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function dl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function ul(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var cr={};ar(cr,{RUNNER_IDS:()=>x,assertEnabled:()=>ns,buildCommand:()=>is,getConfiguredProfile:()=>Pt,getDefault:()=>rs,getDisplayName:()=>os,getEnabled:()=>bt,getProfile:()=>Oe,isRunnerType:()=>St,parse:()=>ss,setRunnerEnabled:()=>as,setRunnerPath:()=>ls});var x=["codex","cursor","claude"];var ts={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=>ts[e];var Pt=(e,t={})=>{let r=Oe(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var bt=(e={})=>x.filter(t=>e.runners?.[t]?.enabled!==!1);var rs=(e={})=>{let t=bt(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 ns=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var St=e=>x.includes(e);var ss=e=>{if(!e||e.length===0)return"codex";if(!St(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${x.join(", ")}.`);return e};var os=e=>Oe(e).displayName;var is=(e,t,r={})=>{let n=[Pt(e,r).executable];return t&&t.length>0&&n.push(t),n};var as=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var ls=(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 pl,readFile as fl,writeFile as ml}from"node:fs/promises";import gl from"node:path";var hl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",cs=async e=>{try{return await fl(e,"utf8")}catch(t){if(hl(t))return null;throw t}},ds=async(e,t)=>{await pl(gl.dirname(e),{recursive:!0}),await ml(e,t,"utf8")};var It=(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(!x.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${x.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 dr=async(e,t={readConfigFile:cs})=>{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 It(n,e.configFile)};var ur=async(e,t,r={writeConfigFile:ds})=>{It(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var pr={};ar(pr,{checkForUpdate:()=>us,getCurrent:()=>Ct});var Ct=()=>{try{return"0.7.6"}catch{return"unknown"}};var kl="https://registry.npmjs.org/craig-cli/latest",wl=3600*1e3,Tl={value:null},Rl=(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},us=async(e={fetch:globalThis.fetch,getCurrent:Ct,cache:Tl})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<wl)return e.cache.value.result;let n=null;try{let o=await e.fetch(kl,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&Rl(n,t)};return e.cache.value={result:s,cachedAt:r},s};var g={load:dr,save:ur,runners:cr,version:pr};function ps(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.
|
|
4
5
|
|
|
5
|
-
`+
|
|
6
|
+
`+K());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.
|
|
6
7
|
|
|
7
|
-
`+
|
|
8
|
+
`+K());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(" ")}
|
|
8
9
|
|
|
9
|
-
${
|
|
10
|
+
${K()}`);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>'.
|
|
10
11
|
|
|
11
|
-
`+
|
|
12
|
+
`+K());if(r!==-1&&n!==-1)throw new Error(`Task creation accepts either '--repo' or '--workspace', not both.
|
|
12
13
|
|
|
13
|
-
`+
|
|
14
|
+
`+K());let o=r===-1?void 0:t[r+1]?.trim()??"",i=n===-1?void 0:t[n+1]?.trim()??"",a=s===-1?void 0:g.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.
|
|
14
15
|
|
|
15
|
-
`+
|
|
16
|
+
`+K());if(i!==void 0&&i.length===0)throw new Error(`Workspace id cannot be empty.
|
|
16
17
|
|
|
17
|
-
`+
|
|
18
|
+
`+K());if(c.length===0)throw new Error(`Task prompt cannot be empty.
|
|
18
19
|
|
|
19
|
-
`+
|
|
20
|
+
`+K());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(" ")}
|
|
20
21
|
|
|
21
|
-
${
|
|
22
|
+
${K()}`)}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:yl(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(" ")}
|
|
22
23
|
|
|
23
|
-
${
|
|
24
|
-
`)}function
|
|
24
|
+
${K()}`)}function K(){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
|
+
`)}function re(e){let t=e.trim();if(t.length===0)throw new Error(`Task id cannot be empty.
|
|
25
26
|
|
|
26
|
-
${
|
|
27
|
+
${K()}`);return t}function yl(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
27
28
|
|
|
28
|
-
${Z()}`);return t}var G=(e,t)=>{let r=Fr(e);if(!yl(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: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:Sl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Pl(t.repoTargets),runnerSession:t.runnerSession??Tl(t),checks:Dl(t),lastCommit:t.lastCommit??null,prs:$l(t),artifacts:Ol(t),cleanup:Nl(t)}},Tl=e=>{if(typeof e.title!="string")return null;let t=Wr(e.runner);return{command:S.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},yl=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"&&S.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"&&Bs(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||bl(t.repoTargets))&&Cl(t.runnerSession)&&xl(t.prompt)&&Us(t.checks)&&qs(t.lastCommit)&&El(t.prs)&&Al(t.artifacts)&&Vs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Pl=e=>{if(Array.isArray(e))return e.filter(_s)},bl=e=>Array.isArray(e)&&e.every(_s),_s=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)&&Us(t.checks)&&qs(t.lastCommit)&&Ks(t.pullRequest)&&Vs(t.cleanup)},Sl=e=>{if(Bs(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 Il(e.id,e.title,t,Wr(e.runner))},Il=(e,t,r,n)=>{let s=S.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:S.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Wr=e=>e&&S.runners.isRunnerType(e)?e:"codex",Bs=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"),Cl=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),xl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Us=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"),qs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Ks=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&vl(e.requiredChecks),vl=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)),El=e=>Array.isArray(e)&&e.every(Ks),Al=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),Vs=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),Dl=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},$l=e=>{if(Array.isArray(e.prs))return e.prs.map(Ll);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Gs(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Hs(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ll=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:Gs(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:jl(t.reviewDecision),requiredChecks:Hs(t.requiredChecks),comments:Ml(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Gs=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,jl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Ml=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}]}):[],Hs=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})):[],Ol=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Nl=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as gc}from"node:fs/promises";import{randomUUID as Fl}from"node:crypto";import{open as Wl,readFile as kg,rename as _l,rm as Bl}from"node:fs/promises";import _r from"node:path";async function B(e,t){let r=_r.dirname(e),n=_r.join(r,`.${_r.basename(e)}.${process.pid}.${Date.now()}.${Fl()}.tmp`),s=await Wl(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
29
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await _l(n,e)}catch(o){throw await s.close().catch(()=>{}),await Bl(n,{force:!0}).catch(()=>{}),o}}import{readFile as Ul,readdir as ql,rm as Kl}from"node:fs/promises";import zs from"node:path";var Br=(e,t)=>zs.join(e.workspacesDir,`${t}.json`),Vl=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"):[]}},Ys=(e,t)=>{let r=Vl(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},Ne=async(e,t)=>{let r=Br(e,t),n=await Ul(r,"utf8");return Ys(JSON.parse(n),r)},Fe=async(e,t)=>{await B(Br(e,t.id),{...t,updatedAt:new Date().toISOString()})},ie=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=>Ne(e,zs.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Qs=async(e,t)=>{await Kl(Br(e,t),{force:!0})};import{readFile as Gl,readdir as Hl,rm as zl}from"node:fs/promises";import Js from"node:path";var Ur=(e,t)=>Js.join(e.reposDir,`${t}.json`),Xs=(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},ue=async(e,t)=>{let r=Ur(e,t),n=await Gl(r,"utf8");return Xs(JSON.parse(n),r)},qr=async(e,t)=>{await B(Ur(e,t.id),{...t,updatedAt:new Date().toISOString()})},pt=async e=>{let t=await Hl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>ue(e,Js.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Zs=async(e,t)=>{await zl(Ur(e,t),{force:!0})};import{readFile as Yl}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"},Bt=(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},ee=async e=>{let t=await Yl(e.indexFile,"utf8");return Bt(JSON.parse(t),e.workspaceRoot,e.indexFile)},ye=async(e,t)=>{await B(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as oc,stat as ic}from"node:fs/promises";import Ze from"node:path";import{readFile as Jl}from"node:fs/promises";async function J(e){try{let t=await Jl(e.uiStateFile,"utf8"),r=JSON.parse(t);return Xl(r,e.uiStateFile)}catch(t){if(ec(t))return null;throw t}}async function Y(e,t){await B(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function we(){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 Xl(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")||!Ut(e,"openInspectionKind")||!Ut(e,"selectedFileTreePath")||!Ut(e,"selectedFilePath")||!Ut(e,"selectedDiffPath")||!Zl(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 Ut(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Zl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function ec(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{realpath as ro}from"node:fs/promises";import no from"node:path";import{execFile as tc}from"node:child_process";import{promisify as rc}from"node:util";var eo=rc(tc);async function v(e,t,r={}){try{let n=await eo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(to(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function M(e,t,r={}){try{let n=await eo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(to(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function to(e){return e instanceof Error}var Kr=async e=>{try{let r=(await v("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([ro(r).catch(()=>no.resolve(r)),ro(e).catch(()=>no.resolve(e))]);return n===s}catch{return!1}},Vr=async e=>{let t=await M("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 M("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await v("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as Re,readFile as nc}from"node:fs/promises";import te from"node:path";function Pe(e){let t=te.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:te.join(t,"index.json"),reposDir:te.join(t,"repos"),workspacesDir:te.join(t,"workspaces"),sessionsDir:te.join(t,"sessions"),runtimeDir:te.join(t,"runtime"),uiStateFile:te.join(t,"runtime","ui-state.json"),tasksDir:te.join(t,"tasks"),jobsDir:te.join(t,"jobs"),logsDir:te.join(t,"logs"),errorLogFile:te.join(t,"logs","errors.log"),artifactsDir:te.join(t,"artifacts"),worktreesDir:te.join(t,"worktrees"),configFile:te.join(t,"config.json")}}var sc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Xe=async e=>{let t=Pe(e);await Re(t.craigDir,{recursive:!0}),await Promise.all([Re(t.reposDir,{recursive:!0}),Re(t.workspacesDir,{recursive:!0}),Re(t.sessionsDir,{recursive:!0}),Re(t.runtimeDir,{recursive:!0}),Re(t.tasksDir,{recursive:!0}),Re(t.jobsDir,{recursive:!0}),Re(t.logsDir,{recursive:!0}),Re(t.artifactsDir,{recursive:!0}),Re(t.worktreesDir,{recursive:!0})]);try{let s=await nc(t.indexFile,"utf8"),o=JSON.parse(s);return Bt(o,e,t.indexFile)}catch(s){if(!sc(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 B(t.indexFile,n),n};var so=(e,t,r)=>{let n=new Date().toISOString();return{id:ac(e,Ze.basename(t)),name:Ze.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},oo=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},ac=(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},lc=(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},io=async(e,t)=>{let r=await ee(e);await ye(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},ao=async(e,t,r)=>{let n=await J({uiStateFile:e.uiStateFile})??we();await Y({uiStateFile:e.uiStateFile},{...n,selectedRepoId:r,selectedWorkspaceId:t.id,selectedTaskId:null})},cc=async(e,t)=>{let r=await oc(t,{withFileTypes:!0}),n=await pt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ze.join(t,o.name);if(!await Kr(i))continue;let l=n.find(d=>d.rootPath===i)??s.find(d=>d.rootPath===i),c=await Vr(i);s.push(l?oo(l,c):so([...n,...s],i,c))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},dc=async(e,t)=>{let r=await Vr(t),n=await pt(e),s=n.find(g=>g.rootPath===t)??null,o=s?oo(s,r):so(n,t,r),i=`workspace_${o.id}`,c=(await ie(e)).find(g=>g.id===i)??null,d=new Date().toISOString(),u=c??{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:d,updatedAt:d};return await qr(e,o),c||await Fe(e,u),await io(e,{repoIds:[o.id],workspaceIds:[u.id]}),await ao(e,u,o.id),{kind:"createWorkspace",workspace:u,repos:[o],created:!c}},uc=async(e,t)=>{let r=await cc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await ie(e),s=lc(n,Ze.basename(t)),o=n.find(d=>d.kind==="project"&&d.rootPath===t)??null,i=new Date().toISOString(),l=r.map(d=>d.id),c=o?{...o,discoveredRepoIds:l,primaryRepoId:l[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:Ze.basename(t),rootPath:t,primaryRepoId:l[0]??"",discoveredRepoIds:l,branch:"project",status:"active",linkedRepoIds:l,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(d=>qr(e,d))),await Fe(e,c),await io(e,{repoIds:l,workspaceIds:[c.id]}),await ao(e,c,l[0]??null),{kind:"createWorkspace",workspace:c,repos:r,created:!o}},ft=async(e,t)=>{await Xe(e.workspaceRoot);let r=Ze.resolve(e.workspaceRoot,t);if(!(await ic(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Kr(r)?dc(e,r):uc(e,r)};var Gr=async(e,t,r={listWorkspaceRecords:ie,ensureCraigState:Xe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Hr=async(e,t,r={readWorkspace:Ne,writeWorkspace:Fe,readUiState:J,writeUiState:Y})=>{let s={...await r.readWorkspace(e,t),status:"archived",archivedAt:new Date().toISOString()};await r.writeWorkspace(e,s);let o=await r.readUiState({uiStateFile:e.uiStateFile});return o&&o.selectedWorkspaceId===t&&await r.writeUiState({uiStateFile:e.uiStateFile},{...o,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null}),{kind:"archiveWorkspace",workspaceId:s.id,status:s.status,branch:s.branch}};var zr=async(e,t)=>{let n={...await Ne(e,t),status:"active",archivedAt:null};await Fe(e,n);let s=await J({uiStateFile:e.uiStateFile})??null;return await Y({uiStateFile:e.uiStateFile},{...s??we(),selectedWorkspaceId:n.id,selectedRepoId:n.kind==="project"?n.discoveredRepoIds?.[0]??null:n.primaryRepoId,selectedTaskId:null}),{kind:"restoreWorkspace",workspaceId:n.id,status:n.status,branch:n.branch}};var We=async(e,t,r={deleteWorkspace:Qs,readCraigIndex:ee,writeCraigIndex:ye})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var pc=async(e,t)=>{let r=await J({uiStateFile:e.uiStateFile});!r||r.selectedWorkspaceId!==t||await Y({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})},Yr=async(e,t,r)=>{let n=await Ne(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 We(e,t),await pc(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Qr={};Lr(Qr,{addRepo:()=>lo,listRegisteredRepos:()=>co,removeRepo:()=>uo});import fc from"node:path";import{stat as mc}from"node:fs/promises";var lo=async(e,t)=>{let r=fc.resolve(e.workspaceRoot,t);if(!(await mc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await ft(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 co=async(e,t={listRepos:pt,ensureCraigState:Xe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var uo=async(e,t,r)=>{let n=await ue(e,t),o=(await ie(e)).filter(u=>u.primaryRepoId===t),i=o.filter(u=>u.status==="active"),l=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(l.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(u=>We(e,u.id))),await Zs(e,t);let c=await ee(e);await ye(e,{...c,repoIds:c.repoIds.filter(u=>u!==t)});let d=await J({uiStateFile:e.uiStateFile});return d?.selectedRepoId===t&&await Y({uiStateFile:e.uiStateFile},{...d,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var re={addWorkspace:ft,listWorkspaces:Gr,archiveWorkspace:Hr,restoreWorkspace:zr,removeWorkspace:Yr,removeWorkspaceRecord:We,repos:Qr};var ne=async(e,t)=>{let r=await gc(Xr(e,t),"utf8");return JSON.parse(r)},pe=async(e,t)=>{let r=await ne(e,t);return G(r,Xr(e,t))},A=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await B(Xr(e,t.id),r)},Jr=async(e,t)=>{let r=await ee(e);r.taskIds.includes(t)||await ye(e,{...r,taskIds:[...r.taskIds,t]})},Xr=(e,t)=>`${e.tasksDir}/${t}.json`;var O=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,Ee=e=>e.status==="merged"||e.status==="closed",et=(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}},mt=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Kt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Kt=e=>e.mergeable&&!hc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),hc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Zr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),gt=(e,t)=>{let r=e.isDraft??!1,n=kc(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:wc(e.reviewDecision??null),requiredChecks:ht(e.statusCheckRollup),comments:Pc(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}},kc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,wc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,ht=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||Tc(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:fo(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:yc(t)}:null},Tc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):qt(e)&&!qt(t)?!0:!qt(e)&&qt(t)?!1:po(t.status)>=po(e.status),qt=e=>e.conclusion?.toUpperCase()==="CANCELLED",po=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},yc=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},Pc=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=Sc(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},Sc=e=>e.replace(/\s+/g," ").trim(),fo=(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?fo(n,n):"unknown"};import{access as Ic}from"node:fs/promises";import mo from"node:path";var $=async(e,t,r={readRawTask:ne,validateTaskRecord:G})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Ac(n)?new Error(`Craig task "${t}" was not found.`):n}},H=async e=>{if(!await en(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},tt=(e,t)=>t.artifacts.logPath?mo.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:mo.join(e.workspaceRoot,t.artifacts.logPath):null,kt=async(e,t)=>{let r=await en(t.worktreePath),n=tt(e,t),s=n?await en(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Cc(t),lastCommitSummary:xc(t),prSummary:vc(t),cleanupSummary:Ec(t)}},en=async e=>{try{return await Ic(e),!0}catch{return!1}},Cc=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}`},xc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",vc=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(c=>c.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(c=>` ${c.repoId} #${c.pullRequest.number} ${c.pullRequest.status??"unknown"}`),i=s.reduce((c,d)=>{let u=d.pullRequest.status??"unknown";return c[u]=(c[u]??0)+1,c},{}),l=Object.entries(i).map(([c,d])=>`${d} ${c}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${l})
|
|
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:Cl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Sl(t.repoTargets),runnerSession:t.runnerSession??Pl(t),checks:jl(t),lastCommit:t.lastCommit??null,prs:Ll(t),artifacts:Nl(t),cleanup:Wl(t)}},Pl=e=>{if(typeof e.title!="string")return null;let t=mr(e.runner);return{command:g.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"&&g.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"&&ms(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||Il(t.repoTargets))&&El(t.runnerSession)&&xl(t.prompt)&&gs(t.checks)&&hs(t.lastCommit)&&Dl(t.prs)&&$l(t.artifacts)&&ws(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Sl=e=>{if(Array.isArray(e))return e.filter(fs)},Il=e=>Array.isArray(e)&&e.every(fs),fs=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)&&gs(t.checks)&&hs(t.lastCommit)&&ks(t.pullRequest)&&ws(t.cleanup)},Cl=e=>{if(ms(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 vl(e.id,e.title,t,mr(e.runner))},vl=(e,t,r,n)=>{let s=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:g.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},mr=e=>e&&g.runners.isRunnerType(e)?e:"codex",ms=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"),El=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),xl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",gs=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"),hs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",ks=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Al(e.requiredChecks),Al=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)),Dl=e=>Array.isArray(e)&&e.every(ks),$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),ws=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),jl=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Ll=e=>{if(Array.isArray(e.prs))return e.prs.map(Ml);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Ts(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Rs(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ml=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:Ts(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Ol(t.reviewDecision),requiredChecks:Rs(t.requiredChecks),comments:Fl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Ts=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Ol=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Fl=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}]}):[],Rs=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})):[],Nl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Wl=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as lc}from"node:fs/promises";import{readFile as _l,readdir as Bl,rm as ql}from"node:fs/promises";import ys from"node:path";var gr=(e,t)=>ys.join(e.workspacesDir,`${t}.json`),Ul=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"):[]}},Ps=(e,t)=>{let r=Ul(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 _l(r,"utf8");return Ps(JSON.parse(n),r)},be=async(e,t)=>{await M(gr(e,t.id),{...t,updatedAt:new Date().toISOString()})},B=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,ys.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},bs=async(e,t)=>{await ql(gr(e,t),{force:!0})};import{readFile as Kl,readdir as Vl,rm as Gl}from"node:fs/promises";import Ss from"node:path";var hr=(e,t)=>Ss.join(e.reposDir,`${t}.json`),Is=(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 Kl(r,"utf8");return Is(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 Vl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>X(e,Ss.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Cs=async(e,t)=>{await Gl(hr(e,t),{force:!0})};import{readFile as Hl}from"node:fs/promises";var zl=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(!zl(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 Hl(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 Zl,stat as ec}from"node:fs/promises";import Ne from"node:path";import{realpath as xs}from"node:fs/promises";import As from"node:path";import{execFile as Yl}from"node:child_process";import{promisify as Ql}from"node:util";var vs=Ql(Yl);async function T(e,t,r={}){try{let n=await vs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Es(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 vs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Es(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Es(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([xs(r).catch(()=>As.resolve(r)),xs(e).catch(()=>As.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 Jl}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 Xl=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 Jl(t.indexFile,"utf8"),o=JSON.parse(s);return vt(o,e,t.indexFile)}catch(s){if(!Xl(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 Ds=(e,t,r)=>{let n=new Date().toISOString();return{id:tc(e,Ne.basename(t)),name:Ne.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},$s=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},tc=(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},rc=(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},js=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])]})},nc=async(e,t)=>{let r=await Zl(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?$s(a,l):Ds([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},sc=async(e,t)=>{let r=await Tr(t),n=await Je(e),s=n.find(p=>p.rootPath===t)??null,o=s?$s(s,r):Ds(n,t,r),i=`workspace_${o.id}`,l=(await B(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 be(e,d),await js(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},oc=async(e,t)=>{let r=await nc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await B(e),s=rc(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 be(e,l),await js(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 ec(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await wr(r)?sc(e,r):oc(e,r)};var Rr=async(e,t,r={listWorkspaceRecords:B,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:be})=>{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 be(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 Se=async(e,t,r={deleteWorkspace:bs,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 br=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 Se(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Sr={};ar(Sr,{addRepo:()=>Ls,listRegisteredRepos:()=>Ms,removeRepo:()=>Os});import ic from"node:path";import{stat as ac}from"node:fs/promises";var Ls=async(e,t)=>{let r=ic.resolve(e.workspaceRoot,t);if(!(await ac(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 Ms=async(e,t={listRepos:Je,ensureCraigState:Fe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Os=async(e,t,r)=>{let n=await X(e,t),o=(await B(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=>Se(e,c.id))),await Cs(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 Y={addWorkspace:Xe,listWorkspaces:Rr,archiveWorkspace:yr,restoreWorkspace:Pr,removeWorkspace:br,removeWorkspaceRecord:Se,repos:Sr};var H=async(e,t)=>{let r=await lc(Cr(e,t),"utf8");return JSON.parse(r)},Q=async(e,t)=>{let r=await H(e,t);return F(r,Cr(e,t))},R=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&&!cc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),cc=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=dc(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:uc(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:gc(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}},dc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,uc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,tt=e=>{let t=e.map(n=>pc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||fc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},pc=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:Ns(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:mc(t)}:null},fc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Et(e)&&!Et(t)?!0:!Et(e)&&Et(t)?!1:Fs(t.status)>=Fs(e.status),Et=e=>e.conclusion?.toUpperCase()==="CANCELLED",Fs=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},mc=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},gc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(hc).filter(r=>r!==null).slice(-4):[]},hc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=kc(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},kc=e=>e.replace(/\s+/g," ").trim(),Ns=(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?Ns(n,n):"unknown"};import{access as wc}from"node:fs/promises";import Ws from"node:path";var b=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?Ws.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Ws.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:Tc(t),lastCommitSummary:Rc(t),prSummary:yc(t),cleanupSummary:Pc(t)}},Er=async e=>{try{return await wc(e),!0}catch{return!1}},Tc=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}`},Rc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",yc=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=
|
|
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})`},Pc=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",bc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var _s=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.")},xr=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 Sc(e,s);await T("git",["worktree","add","-b",t,r,i],{cwd:e})},Sc=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,At=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},Bs=async e=>{await T("git",["add","-A"],{cwd:e})},qs=async(e,t)=>{await T("git",["commit","-m",t],{cwd:e})},Us=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 Ks=async(e,t)=>{await T("git",["worktree","remove","--force",t],{cwd:e})};var Ar=async e=>Be(e,e.repoRoot),Be=async(e,t)=>{let r=await V(e),n=Vs(new Date),s=Gs(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await _s(t,i))return o;s+=1}},nt=async e=>{let t=await V(e),r=Vs(new Date),n=Gs(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},Vs=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},Gs=(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 Dr=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{let n=await V(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(Ic(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}},Ic=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Hs=["merge_ready","pr_open","checked","review","running","draft"],$r=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),jr=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(Cc)[0]?.id??null,Cc=(e,t)=>{let r=zs(e.status),n=zs(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},zs=e=>{let t=Hs.indexOf(e);return t>=0?t:Hs.length};import Ys from"node:path";var Ie=(e,t)=>t?Ys.isAbsolute(t)?t:Ys.join(e.repoRoot,t):null;import{mkdir as st,rm as vc,writeFile as Dt}from"node:fs/promises";import C from"node:path";var Js=["AGENTS","md"].join("."),qe=async(e,t,r,n={})=>{let s=await X(e,t),o=await $c(e,s.id),i=await Be(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 Dt(d,"","utf8");let f=Ec(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 R(e,f),await Ir(e,i),await xr(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 B(e)).find(h=>h.id===t&&h.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 h=await qe(e,s.primaryRepoId,r,n);return{...h,bundlePath:h.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 Dt(f,"","utf8");let w=await Promise.all(o.map(h=>X(e,h))),P=Ac(w),D=await Promise.all(w.map(h=>xc(e,h,i,d,C.join(p,P.get(h.id))))),U=D.find(h=>h.status==="ready")??D[0];if(!D.some(h=>h.status==="ready"))throw await vc(p,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${D.map(h=>`${h.repoId}: ${h.failureReason??"unknown error"}`).join("; ")}`);await Dt(C.join(p,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:D.map(h=>({repoId:h.repoId,repoName:w.find(Qe=>Qe.id===h.repoId)?.name??h.repoId,path:C.relative(p,h.worktreePath),status:h.status,worktreePath:h.worktreePath,failureReason:h.failureReason}))},null,2),"utf8"),await Dt(C.join(p,Js),Dc({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:D,bundlePath:p}),"utf8");let fe=it(i,r,a,l,n.config??{}),ae={id:i,title:r,slug:Xs(r),type:"project",status:"draft",runner:l,repoId:U.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:fe[0]?.id??null,linkedRepoIds:o.filter(h=>h!==U.repoId),repoRoot:p,worktreePath:p,branch:d,bundlePath:p,selectedRepoTargetId:U.repoId,repoTargets:D,ptyTabs:fe,runnerSession:{command:g.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:U.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:$t(),lastFailureReason:D.every(h=>h.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await R(e,ae),await Ir(e,i),{repoId:U.repoId,repoRoot:p,sessionId:c,workspaceId:s.id,task:ae,bundlePath:p,repoTargets:D}},it=(e,t,r,n="codex",s={})=>{let o=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:g.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Ec=(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:Xs(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:g.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:{...Lr(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:$t(),lastFailureReason:null,createdAt:r,updatedAt:r}},xc=async(e,t,r,n,s)=>{await st(C.dirname(s),{recursive:!0});try{return await xr(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Qs(),cleanup:$t()}}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:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Qs(),cleanup:$t()}}},Ac=e=>{let t=new Set(["manifest.json",Js]),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},Dc=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
|
-
`)},an=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Io=()=>({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}),Ht=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),Wc=async(e,t)=>{let n=(await ie(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},xo=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import Wo from"node:path";import{readFile as qc,rm as vk}from"node:fs/promises";import Kc from"node:path";function vo(e,t){let r=Uc(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")||!Bc(r.attach)||!_c(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 _c(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 Bc(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 Uc(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??""}}var Ae=async(e,t)=>{let r=await qc(ln(e,t),"utf8"),n=JSON.parse(r);return vo(n,ln(e,t))},Be=async(e,t)=>{await B(ln(e,t.id),{...t,updatedAt:new Date().toISOString()})};var ln=(e,t)=>Kc.join(e.sessionsDir,`${t}.json`);import{spawn as Vc}from"node:child_process";import{createHash as Gc}from"node:crypto";import Hc from"node:path";function zt(e){return`'${e.replace(/'/g,"'\\''")}'`}var zc="craig",Eo=async(e,t,r)=>{let n=cn(e,t),s=Qc(),o=await v("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Xc(o.stdout);return await Yc(e,n),i};var Yc=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 v("tmux",n,{cwd:e})},Ao=async(e,t,r)=>{await v("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},Do=async(e,t,r)=>{await v("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var $o=async(e,t,r)=>{await v("tmux",["pipe-pane","-o","-t",e,`cat >> ${zt(t)}`],{cwd:r})},Yt=async(e,t,r,n)=>{let s=n??jo(e);if(r?await v("tmux",["select-window","-t",r],{cwd:e}):await v("tmux",["select-window","-t",t],{cwd:e}),await v("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await v("tmux",["switch-client","-t",s],{cwd:e});return}await ed(e,["attach-session","-t",s])};var Lo=async(e,t)=>{await v("tmux",["kill-session","-t",t],{cwd:e})};var jo=e=>{let r=Hc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Gc("sha1").update(e).digest("hex").slice(0,8);return`${zc}-${r}-${n}`},cn=(e,t)=>`${jo(e)}-${t.toLowerCase()}`,Qc=()=>{let e=Jc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Jc=()=>{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},Xc=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),ed=async(e,t)=>{await new Promise((r,n)=>{let s=Vc("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 td,constants as rd}from"node:fs";import{homedir as Mo}from"node:os";import De from"node:path";var nd=[De.join(Mo(),".local","bin"),De.join(Mo(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function No(e=process.env){return sd([...(e.PATH??"").split(De.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:nd])}function Ue(e=process.env){return{...e,PATH:No(e).join(De.delimiter)}}function dn(e,t={}){if(e.includes(De.sep)){let r=De.isAbsolute(e)?e:De.resolve(t.cwd??process.cwd(),e);return Oo(r)?r:null}for(let r of No(t.env)){let n=De.join(r,e);if(Oo(n))return n}return null}function qe(e,t={}){let r=dn(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 Oo(e){try{return td(e,rd.X_OK),!0}catch{return!1}}function sd(e){return[...new Set(e)]}var Pt={async create(e,t){let r=await Eo(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await $o(r.paneId,t.logPath,t.repoRoot);let n=await Fo({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||cn(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 Be(e,s),s},async attach(e,t,r){let n=await Pt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Yt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Be(e,s),s},async resize(e,t,r,n){await Ao(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Be(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 Be(e,n),n},async snapshot(e,t){return od(e,t)}},un={async prepare(e,t){let n=e.runnerSession.command[0],s=Ue();await v(qe(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=qe(r[0],{cwd:e.worktreePath,env:Ue()});await Do(t.session.paneId,[n,...r.slice(1)].map(s=>zt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},od=async(e,t)=>{let r=await M("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return Fo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},Fo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var pn=async(e,t,r,n={})=>{let s=r.trim(),o=await S.load(e),i=n.runner??S.runners.getDefault(o);if(S.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 l=n.workspaceId?await Tt(e,n.workspaceId,s,{runner:i,config:o}):await nt(e,t,s,{runner:i,config:o}),c=l.task,d=S.runners.buildCommand(i,s,o),u=`session_${c.id}`,g=c.artifacts.logPath?Wo.resolve(e.workspaceRoot,c.artifacts.logPath):Wo.join(e.logsDir,`${c.id}.log`);try{await un.prepare(c,{repoRoot:l.repoRoot});let w=await Pt.create(e,{sessionId:u,taskId:c.id,repoId:l.repoId,workspaceId:l.workspaceId,repoRoot:l.repoRoot,worktreePath:c.worktreePath,logPath:g,command:d});await un.launch(c,{repoRoot:l.repoRoot,session:w});let R=new Date().toISOString();w={...w,status:"running",startedAt:R,command:d};let I={...c,status:"running",runner:i,sessionId:w.id,selectedPtyTabId:c.selectedPtyTabId,runnerSession:{command:w.command,pid:null,startedAt:R,lastKnownState:"running",exitCode:null,exitedAt:null}};return await A(e,I),await Be(e,w),await Y({uiStateFile:e.uiStateFile},{...await J({uiStateFile:e.uiStateFile})??we(),selectedRepoId:I.repoId,selectedWorkspaceId:I.workspaceId,selectedTaskId:I.id,selectedPtyTabId:I.selectedPtyTabId}),{kind:"createTask",taskId:I.id,repoId:I.repoId,workspaceId:I.workspaceId,sessionId:w.id,status:I.status,branch:I.branch,worktreePath:I.worktreePath,runner:I.runner}}catch(w){let R={...c,sessionId:null,status:"draft",runnerSession:{...c.runnerSession,lastKnownState:"failed"},lastFailureReason:w instanceof Error?w.message:"Unknown Craig error"};throw await A(e,R),w}};import{mkdir as gd}from"node:fs/promises";import hd from"node:path";var _o=3,id=1e3,ad=1e4,st=async e=>{let t=await M("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Bo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await v("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Qt=async(e,t)=>{let r=await v("gh",Ko(e),{cwd:t});return JSON.parse(r.stdout)},Jt=async(e,t)=>{let r=await M("gh",Ko(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Uo=async(e,t,r)=>{if(r.length===0)return[];let n=fd(r),s=await ld(e,["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`]),i=JSON.parse(s.stdout).data?.repository??{};return r.map((l,c)=>{let d=i[`item${c}`],u=md(d);return{id:l.id,found:u!==null,view:u}})},qo=async e=>{let t=await M("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:pd(t.stdout.trim())},ld=async(e,t)=>{let r;for(let n=0;n<=_o;n+=1)try{return await v("gh",t,{cwd:e})}catch(s){if(r=s,n===_o||!cd(s))throw s;await ud(dd(n))}throw r},cd=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")},dd=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||id,r=Math.min(t*2**e,ad),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},ud=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"],pd=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},fd=e=>`
|
|
34
|
+
`)},Lr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Qs=()=>({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}),$c=async(e,t)=>{let n=(await B(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},Xs=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import co from"node:path";import{readFile as jc,rm as fk}from"node:fs/promises";import Lc from"node:path";var he=async(e,t)=>{let r=await jc(Mr(e,t),"utf8"),n=JSON.parse(r);return Mc(n,Mr(e,t))},Ce=async(e,t)=>{await M(Mr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Mr=(e,t)=>Lc.join(e.sessionsDir,`${t}.json`);function Mc(e,t){let r=Nc(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")||!Fc(r.attach)||!Oc(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 Oc(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 Fc(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 Nc(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 Wc}from"node:child_process";import{createHash as _c}from"node:crypto";import Bc from"node:path";function jt(e){return`'${e.replace(/'/g,"'\\''")}'`}var qc="craig",Zs=async(e,t,r)=>{let n=Or(e,t),s=Kc(),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=Gc(o.stdout);return await Uc(e,n),i};var Uc=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})},eo=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},to=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var ro=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??so(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 zc(e,["attach-session","-t",s])};var no=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var so=e=>{let r=Bc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=_c("sha1").update(e).digest("hex").slice(0,8);return`${qc}-${r}-${n}`},Or=(e,t)=>`${so(e)}-${t.toLowerCase()}`,Kc=()=>{let e=Vc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Vc=()=>{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},Gc=e=>{let t=Hc(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]}},Hc=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),zc=async(e,t)=>{await new Promise((r,n)=>{let s=Wc("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 Qc}from"node:fs";import{homedir as oo}from"node:os";import ke from"node:path";var Jc=[ke.join(oo(),".local","bin"),ke.join(oo(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ao(e=process.env){return Xc([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Jc])}function ve(e=process.env){return{...e,PATH:ao(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 io(r)?r:null}for(let r of ao(t.env)){let n=ke.join(r,e);if(io(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 io(e){try{return Yc(e,Qc.X_OK),!0}catch{return!1}}function Xc(e){return[...new Set(e)]}var at={async create(e,t){let r=await Zs(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await ro(r.paneId,t.logPath,t.repoRoot);let n=await lo({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 eo(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 Zc(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 to(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(){}},Zc=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return lo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},lo=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 g.load(e),i=n.runner??g.runners.getDefault(o);if(g.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 qe(e,t,s,{runner:i,config:o}),l=a.task,c=g.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?co.resolve(e.workspaceRoot,l.artifacts.logPath):co.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 R(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 R(e,u),f}};import{mkdir as cd}from"node:fs/promises";import dd from"node:path";var uo=3,ed=1e3,td=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 po=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",go(e),{cwd:t});return JSON.parse(r.stdout)},Ot=async(e,t)=>{let r=await E("gh",go(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},fo=async(e,t,r)=>{if(r.length===0)return[];let n=ad(r),s=await rd(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=ld(c);return{id:a.id,found:d!==null,view:d}})},mo=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:id(t.stdout.trim())},rd=async(e,t)=>{let r;for(let n=0;n<=uo;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===uo||!nd(s))throw s;await od(sd(n))}throw r},nd=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")},sd=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||ed,r=Math.min(t*2**e,td),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},od=e=>new Promise(t=>setTimeout(t,e)),go=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],id=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},ad=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
|
+
`,ld=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 xe=async(e,t)=>{let r=Ie(e,t.artifacts.prStatusPath);r&&(await cd(dd.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:R,writePrStatusArtifact:xe})=>{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 Mt(n,t.worktreePath);return lt(e,t,s,r)},dt=async(e,t)=>{let r=await Ot(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 Mt(n,r.worktreePath),a=ko(i);return r.pullRequest=a,await ho(e,t,r.repoId,a),"synced"}let s=await Ot(n,r.worktreePath);if(!s)return"not_found";let o=ko(s);return r.pullRequest=o,await ho(e,t,r.repoId,o),"discovered"},ho=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 R(e,a),a},ko=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:ud(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:pd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),ud=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,pd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var ut=async(e,t)=>{let r=await b(e,t),n=v(r);return n?.number?(await Ue(r.worktreePath),ge(n)?(await dt(e,r)).task:ct(e,r)):r},Br=async(e,t)=>{let r=await b(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Ve(e,t),b(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 xe(e,o.task),o.task}let s=await ct(e,r);return await xe(e,s),s},Ve=async(e,t)=>{let r=await b(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=To(i),await R(e,i)),s},qr=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=_r(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 wo(n,d).catch(async()=>{try{let p=c.pullRequest.number?await Ke(e,s,c):await Ke(e,s,c).catch(()=>"not_found");Ft(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 wo(n,l).catch(async()=>{try{let{disposition:c,task:d}=await Nt(e,s.id),p=v(d);Ft(o,c,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await Ue(s.worktreePath);let o=await fo(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=_r(r,a.task),c=i.get(a.id);if(!c?.found||!c.view){Ft(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 fd(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))}Ft(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=To(i),await R(e,i))}return t.map(s=>_r(r,s))},Nt=async(e,t)=>{let r=await b(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}},To=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(kd)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},fd=async(e,t,r,n)=>{let s=md(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await R(e,i),i},md=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:gd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:hd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),gd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,hd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,wo=async(e,t)=>{let r=await mo(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]})},_r=(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},Ft=(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},kd=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 Ur=async(e,t)=>{let r=await b(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Ve(e,t),r=await b(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 Kr=async(e,t)=>{let r=await b(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 wd(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},wd=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 Td(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 Cd}from"node:child_process";import{access as xd}from"node:fs/promises";var wn=async(e,t)=>{let r=await $(e,t),n=tt(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await xd(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Rn=async e=>{await new Promise((t,r)=>{let n=!1,s=Cd("tail",["-n","+1","-f",e],{stdio:"inherit"}),o=()=>{n=!0,s.kill("SIGINT")};process.on("SIGINT",o),s.on("error",l=>{i(),r(l)}),s.on("exit",(l,c)=>{if(i(),n||c==="SIGINT"){t();return}if(l===0){t();return}r(new Error(`tail -n +1 -f ${e} failed with exit code ${l??"unknown"}.`))});function i(){process.off("SIGINT",o)}})};import{mkdir as vd}from"node:fs/promises";import Ed from"node:path";var Tn=async(e,t)=>{let r=await $(e,t);if(await H(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 Vt(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 S.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 A(e,r);let o=[];for(let i of s){let l=new Date().toISOString(),c=await M("sh",["-lc",i],{cwd:r.worktreePath}),d=new Date().toISOString(),u=c.exitCode??1;if(o.push({command:i,startedAt:l,finishedAt:d,exitCode:u}),u!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=d,r.status="review",r.lastFailureReason=c.stderr.trim()||c.stdout.trim()||`Check command failed: ${i}`,await Yo(e,r),await A(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 Yo(e,r),await A(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Yo=async(e,t)=>{let r=_e(e,t.artifacts.checkSummaryPath);r&&(await vd(Ed.dirname(r),{recursive:!0}),await B(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var yn=async(e,t)=>{let r=await $(e,t);await H(r);let n=await Vt(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 ho(r.worktreePath),await ko(r.worktreePath,s);let o=await wo(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await A(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Ad}from"node:fs/promises";var Pn=async(e,t)=>{let r=await $(e,t),n=await Dd(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await A(e,s),s},Dd=async e=>{try{return await Ad(e),!0}catch{return!1}};var bn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await Ae(e,t.sessionId);await Lo(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 Ro(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 A(e,t)};var Sn=async(e,t,r)=>{let[n,s]=await Promise.all([$(e,t),ue(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 A(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},In=async(e,t)=>{let r=await $(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>ue(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Cn=async(e,t)=>{let r=await $(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([ue(e,r.repoId),Ae(e,r.sessionId)]),o=await Pt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var xn=async(e,t)=>{let r=await $(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await Ae(e,r.sessionId).catch(s=>{throw $d(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 Yt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},$d=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Ld}from"node:child_process";var vn=async(e,t)=>{let r=await $(e,t);await H(r);let s=(await S.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 jd(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},jd=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Ld(s,o,{cwd:t,stdio:"inherit"});i.on("error",n),i.on("exit",l=>{if(l===0){r();return}n(new Error(`${e.join(" ")} failed with exit code ${l??"unknown"}.`))})})};var En=async(e,t,r)=>{let n=await pe(e,t);await A(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},An=async(e,t,r)=>{let n=await pe(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await A(e,s),s},Dn=async(e,t)=>{let r=await pe(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 A(e,s),s};var $n=async(e,t,r="merge",n)=>{let s=await $(e,t),o=n??O(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Bo(s.worktreePath,o,r)};var D={listTasks:nn,getTask:$,provisionTask:nt,provisionProjectTask:Tt,createTask:pn,showTask:hn,showTaskDiff:kn,prepareTaskLogs:wn,streamTaskLogs:Rn,runChecks:Tn,commitTask:yn,closeTask:Pn,cleanupTask:bn,addTaskLink:Sn,listTaskLinks:In,sortTasksForDisplay:sn,resolveSelectedTaskId:on,allocateTaskId:rn,allocateTaskIdForRepo:rt,allocateProjectTaskId:wt,createDefaultTaskPtyTabs:yt,assertTaskWorktreeExists:H,resolveTaskLogPath:tt,buildTaskInspection:kt,resolveArtifactPath:_e,attachTask:Cn,focusTask:xn,openTask:vn,markRunnerFailed:En,recordStartupFailure:An,markTaskStarted:Dn,prs:{refresh:Ct,refreshChecks:mn,discoverOrRefresh:Zt,discoverOrRefreshAll:it,discoverOrRefreshMany:gn,merge:$n,getPrimaryPr:O,isPrTerminal:Ee,isMergeReady:Kt,deriveTaskStatus:mt,upsertPr:et,normalizePr:gt,summarizeRequiredChecks:Zr,writePrStatusArtifact:Ke}};async function Qo(e,t){switch(e.kind){case"addWorkspace":return re.addWorkspace(t.paths,e.path);case"addRepo":return re.repos.addRepo(t.paths,e.path);case"listRepos":return re.repos.listRegisteredRepos(t.paths);case"removeRepo":return re.repos.removeRepo(t.paths,e.repoId,{listTasks:D.listTasks});case"listWorkspaces":return re.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":return re.archiveWorkspace(t.paths,e.workspaceId);case"restoreWorkspace":return re.restoreWorkspace(t.paths,e.workspaceId);case"removeWorkspace":return re.removeWorkspace(t.paths,e.workspaceId,{listTasks:D.listTasks});case"createTask":return D.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?D.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):D.listTasks(t.paths);case"attachTask":return D.attachTask(t.paths,e.taskId);case"addTaskLink":return D.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return D.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return D.showTask(t.paths,e.taskId);case"showSelectedTask":return D.showTask(t.paths,Ve(t,"show"));case"streamTaskLogs":return D.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return D.prepareTaskLogs(t.paths,Ve(t,"logs"));case"showTaskDiff":return D.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return D.showTaskDiff(t.paths,Ve(t,"diff"));case"focusTask":return D.focusTask(t.paths,e.taskId);case"focusSelectedTask":return D.focusTask(t.paths,Ve(t,"focus"));case"openTask":return D.openTask(t.paths,e.taskId);case"openSelectedTask":return D.openTask(t.paths,Ve(t,"open"));case"runChecks":return D.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return D.runChecks(t.paths,Ve(t,"check"));case"commitTask":return D.commitTask(t.paths,e.taskId);case"commitSelectedTask":return D.commitTask(t.paths,Ve(t,"commit"));case"help":return{kind:"help",text:Z()};case"exit":return{kind:"exit"};default:return Md(e)}}function Md(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ve(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 Jo(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
|
+
`)},Td=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 Rd}from"node:child_process";import{access as yd}from"node:fs/promises";var Vr=async(e,t)=>{let r=await b(e,t),n=_e(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await yd(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=Rd("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 Pd}from"node:fs/promises";import bd from"node:path";var Hr=async(e,t)=>{let r=await b(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 g.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 R(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 Ro(e,r),await R(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 Ro(e,r),await R(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Ro=async(e,t)=>{let r=Ie(e,t.artifacts.checkSummaryPath);r&&(await Pd(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 b(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 Bs(r.worktreePath),await qs(r.worktreePath,s);let o=await Us(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await R(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Sd}from"node:fs/promises";var Yr=async(e,t)=>{let r=await b(e,t),n=await Id(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await R(e,s),s},Id=async e=>{try{return await Sd(e),!0}catch{return!1}};var Qr=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await no(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 Ks(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 R(e,t)};var Jr=async(e,t,r)=>{let[n,s]=await Promise.all([b(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 R(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Xr=async(e,t)=>{let r=await b(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 b(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 b(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 Cd(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}},Cd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as vd}from"node:child_process";var tn=async(e,t)=>{let r=await b(e,t);await N(r);let s=(await g.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 Ed(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Ed=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=vd(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 Q(e,t);await R(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 Q(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await R(e,s),s},sn=async(e,t)=>{let r=await Q(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 R(e,s),s};var on=async(e,t,r="merge",n)=>{let s=await b(e,t),o=n??v(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await po(s.worktreePath,o,r)};var S={listTasks:Dr,getTask:b,provisionTask:qe,provisionProjectTask:ot,createTask:Wr,showTask:Ur,showTaskDiff:Kr,prepareTaskLogs:Vr,streamTaskLogs:Gr,runChecks:Hr,commitTask:zr,closeTask:Yr,cleanupTask:Qr,addTaskLink:Jr,listTaskLinks:Xr,sortTasksForDisplay:$r,resolveSelectedTaskId:jr,allocateTaskId:Ar,allocateTaskIdForRepo:Be,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:Br,discoverOrRefresh:Nt,discoverOrRefreshAll:Ve,discoverOrRefreshMany:qr,merge:on,getPrimaryPr:v,isPrTerminal:ge,isMergeReady:xt,deriveTaskStatus:Ze,upsertPr:We,normalizePr:et,summarizeRequiredChecks:vr,writePrStatusArtifact:xe}};async function yo(e,t){switch(e.kind){case"addWorkspace":{let r=await Y.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 Y.repos.addRepo(t.paths,e.path);return await an(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Y.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Me({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await B(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Y.repos.removeRepo(t.paths,e.repoId,{listTasks:S.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 Y.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Y.archiveWorkspace(t.paths,e.workspaceId);return await xd(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Y.restoreWorkspace(t.paths,e.workspaceId);return await an(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Y.removeWorkspace(t.paths,e.workspaceId,{listTasks:S.listTasks});case"createTask":return S.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?S.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):S.listTasks(t.paths);case"attachTask":return S.attachTask(t.paths,e.taskId);case"addTaskLink":return S.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return S.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return S.showTask(t.paths,e.taskId);case"showSelectedTask":return S.showTask(t.paths,Ae(t,"show"));case"streamTaskLogs":return S.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return S.prepareTaskLogs(t.paths,Ae(t,"logs"));case"showTaskDiff":return S.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return S.showTaskDiff(t.paths,Ae(t,"diff"));case"focusTask":return S.focusTask(t.paths,e.taskId);case"focusSelectedTask":return S.focusTask(t.paths,Ae(t,"focus"));case"openTask":return S.openTask(t.paths,e.taskId);case"openSelectedTask":return S.openTask(t.paths,Ae(t,"open"));case"runChecks":return S.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return S.runChecks(t.paths,Ae(t,"check"));case"commitTask":return S.commitTask(t.paths,e.taskId);case"commitSelectedTask":return S.commitTask(t.paths,Ae(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return Ad(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 xd(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 Ad(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 Po(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} ${jd(t)} ${Ld(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}`,...Dd(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
|
-
`).filter(
|
|
127
|
-
`).
|
|
128
|
-
`)}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
${l.stdout.trimEnd()}`)}let i=s.join(`
|
|
138
|
-
|
|
139
|
-
`)
|
|
140
|
-
`)
|
|
141
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function tu(e,t){let r=Mn.resolve(e,t),n=Mn.resolve(e);if(r!==n&&!r.startsWith(`${n}${Mn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function ru(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function X(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}import At from"node:path";function pi(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 fi="\u{F024B} ",mi="\u{F0DCF} ",gi="\u25CB",Nn="\uEA64",hi="\uEAFE",ki="\uEBDA",Fn="\u25CB",Wn="\u25CF",_n="\u2713",Bn="\u2715";function wi(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 nu=["tasks","center","inspector","actions"],Si=["agent","terminal"],Ii=[],L="inspection",DT=[...Si,...Ii],Ci=["commit","push","refresh-checks","close-task"],su=["refresh-checks","close-task"],xi=["task","checks","pr","setup-run","actions","next-action"],vi=["diff","files","review"];function Ei(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=Tu(e?.openInspectionKind)??r,s=S.runners.getEnabled(t);return{inputMode:Pu(e?.inputMode),focusedRegion:wu(e?.focusedRegion),selectedRepoId:be(e?.selectedRepoId),selectedWorkspaceId:be(e?.selectedWorkspaceId),selectedTaskId:be(e?.selectedTaskId),selectedPtyTabId:be(e?.selectedPtyTabId),selectedLeftItemId:Du(be(e?.selectedTaskId)),activeTab:r?L:be(e?.activeTab)??"agent",preferredPtyTabKind:yu(e?.preferredPtyTabKind),inspectorSection:vt(e?.inspectorSection,xi,"task"),inspectionMode:Ru(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:be(e?.selectedFileTreePath),selectedFilePath:be(e?.selectedFilePath),selectedDiffPath:be(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:vt(e?.selectedActionId,Ci,"commit"),selectedProjectTargetId:null,selectedRunner:bu(e?.selectedRunner,s,S.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,workspaceBrowser:null,terminal:ou(),centerZoomed:!1}}function ou(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Ai(e,t){return{...e??we(),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 ar(e,t,r={}){let n=Eu(e,t),s=Fi(n),o=(s?.kind==="workspace"?t.workspaces?.find(u=>u.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(u=>u.id===t.tasks.find(g=>g.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(u=>u.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,l=((s?.kind==="repo"?t.repos.find(u=>u.id===s.id)??null:s?.kind==="task"?t.repos.find(u=>u.id===t.tasks.find(g=>g.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(u=>u.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(u.id))??null:null)??(o?.kind!=="project"?t.repos.find(u=>u.id===o?.primaryRepoId)??null:null)??t.repos.find(u=>u.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,c=o?t.tasks.filter(u=>u.workspaceId===o.id):l?t.tasks.filter(u=>u.repoId===l):[],d=(s?.kind==="task"?c.find(u=>u.id===s.id)??null:null)??c.find(u=>u.id===e.selectedTaskId)??c[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:l,selectedTaskId:d?.id??null,...Iu(d,e.activeTab,e.selectedPtyTabId),selectedFilePath:gu(e,t,d?.id??null),...Cu(e,t,d?.id??null),selectedDiffPath:mu(e,t,d?.id??null),inspectorSection:vt(e.inspectorSection,xi,"task")}}function Di(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return iu(t)?b({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):b({state:e});if(t==="q"||t==="Q")return b({state:e,exit:!0});if(t==="ESCAPE")return b({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return b({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(qn(e.selectedLeftItemId)||Kn(e.selectedLeftItemId)))return b({state:{...e,selectedRunner:Vn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Ri(e,1);if(t==="SHIFT_TAB"||t==="[")return Ri(e,-1);if(t==="z"||t==="Z")return b({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===L?Le(e,-1,r):Ti(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===L?Le(e,1,r):Ti(e,1,r);if(t==="PAGE_UP")return Le(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Le(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Le(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Le(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??N,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return b({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=Su(e,t);return b({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 b({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return b({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return b({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&ir(e.selectedLeftItemId)&&e.selectedTaskId)return b({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&$u(e.selectedLeftItemId)&&e.selectedWorkspaceId)return b({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&bi(e.activeTab,r.ptyTabIds??[]))return b({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Un(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return yi(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Un(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return yi(e,1)}if(Ie(t)){if(e.focusedRegion==="tasks"&&(qn(e.selectedLeftItemId)||Kn(e.selectedLeftItemId))){let n=Wi(e.selectedLeftItemId),s=_i(e.selectedLeftItemId);return b({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 b({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&ir(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return b({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Et(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&bi(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return b({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Et(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===L)return b({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 b({state:uu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return b({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:L,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?b({state:{...e,activeTab:L,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?b({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):b({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?b({state:e}):e.selectedActionId==="refresh-checks"?b({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?b({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):b({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return b({state:e})}function Ge(e,t){return{...e,terminal:t}}function $i(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function iu(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function Ie(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
142
|
-
`}function Li(e){return e.length===1&&e>=" "&&e!=="\x7F"}function ji(e){return Mi(e)||Et(e)!==null}function au(e){return Ii.includes(e)}function Mi(e){return Si.includes(e)}function Oi(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[L]:[]]}var lu=["tasks","center","inspector"];function Ri(e,t){return sr(e,"focusedRegion",lu,t)}function Un(e,t,r){let n=sr(e,"activeTab",r&&r.length>0?r:vu(e),t);return!n.changed||au(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Et(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Ti(e,t,r){if(e.focusedRegion==="tasks")return cu(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Un(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ni(e,t,r);if(e.inspectionMode==="diff"){let n=or(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:L,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:n}if(r.projectTargetIds?.length){let n=or(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return sr(e,"selectedActionId",su,t)}return sr(e,"selectedActionId",Ci,t)}function cu(e,t,r){let n=or(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Fi(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=Wi(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=_i(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Le(e,t,r){if(t===0)return b({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ni(e,t,r);if(e.inspectionMode==="diff"){let n=or(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?Pi(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):b({state:e})}if(e.focusedRegion==="center"&&e.activeTab===L){if(e.openInspectionKind==="file")return Pi(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return pu(e,t,r)}return b({state:e})}function du(e,t){if(e.inspectionMode===t)return b({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?L:e.activeTab;return b({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 yi(e,t){return du(e,ku(e.inspectionMode,vi,t))}function Ni(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return b({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=Se(o===-1?0:o+t,0,n.length-1),l=n[i]??null;if(l===e.selectedFileTreePath)return b({state:e});let c=l!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(l);return b({state:{...e,selectedFileTreePath:l,selectedFilePath:c?l:e.selectedFilePath,activeTab:c?L:e.activeTab,openInspectionKind:c?"file":e.openInspectionKind,fileScrollOffset:c?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:c})}function uu(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 Pi(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=Se(e[t]+r,0,o);return i===e[t]?b({state:e}):b({state:{...e,[t]:i,actionMessage:null},changed:!0})}function pu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return fu(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,l=r.diffPathIds??[];if(l.length===0||!e.selectedDiffPath){let u=Se(i,0,o);return u===e.diffScrollOffset?b({state:e}):b({state:{...e,diffScrollOffset:u,actionMessage:null},changed:!0})}let c=l.indexOf(e.selectedDiffPath);if(c===-1){let u=Se(i,0,o);return u===e.diffScrollOffset?b({state:e}):b({state:{...e,diffScrollOffset:u,actionMessage:null},changed:!0})}if(t>0&&i>o){let u=l[c+1]??null;return u?b({state:{...e,selectedDiffPath:u,activeTab:L,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?b({state:e}):b({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let u=l[c-1]??null;return u?b({state:{...e,selectedDiffPath:u,activeTab:L,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?b({state:e}):b({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let d=Se(i,0,o);return d===e.diffScrollOffset?b({state:e}):b({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}function fu(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=Se(e.diffScrollOffset+t,0,o),l=hu(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&l===e.selectedDiffPath?b({state:e}):b({state:{...e,diffScrollOffset:i,selectedDiffPath:l,actionMessage:null},changed:!0})}function mu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function gu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function hu(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function sr(e,t,r,n){let s=r.indexOf(e[t]),o=Se(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?b({state:e}):b({state:{...e,[t]:i,actionMessage:null},changed:!0})}function or(e,t,r,n,s=!1){if(r.length===0)return b({state:e});let o=r.indexOf(e[t]??r[0]??""),i=Se(o===-1?0:o+n,0,r.length-1),l=r[i]??null;return l===e[t]?b({state:e}):b({state:{...e,[t]:l,actionMessage:null},changed:!0,refreshInspection:s})}function ku(e,t,r){let n=t.indexOf(e);return t[Se(n+r,0,t.length-1)]??e}function b(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 vt(e,t,r){return t.includes(e??"")?e:r}function wu(e){return e==="tabs"?"center":vt(e,nu,"tasks")}function Ru(e,t){return e==="checks"||e==="actions"||e==="review"?"review":vt(e,vi,t)}function Tu(e){return e==="file"||e==="diff"?e:null}function yu(e){return e==="terminal"?"terminal":"agent"}function Pu(e){return e==="terminal"?"terminal":"control"}function bu(e,t=[...N],r="codex"){return e&&S.runners.isRunnerType(e)&&t.includes(e)?e:r}function Vn(e,t=N){let r=t.length>0?t:N,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function Et(e){let t=N.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Su(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Et(e.activeTab)??e.preferredPtyTabKind}function Iu(e,t,r){if(!e)return{activeTab:t===L?t:"agent",selectedPtyTabId:null};let n=e.ptyTabs.find(l=>l.id===r)??null,s=e.selectedPtyTabId?e.ptyTabs.find(l=>l.id===e.selectedPtyTabId)??null:null,o=e.ptyTabs.find(l=>l.id===t)??null;if(o)return{activeTab:o.id,selectedPtyTabId:o.id};if(Mi(t)){let c=e.ptyTabs.find(d=>d.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:c?.id??L,selectedPtyTabId:c?.id??null}}if(t===L)return{activeTab:L,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??L,selectedPtyTabId:i?.id??null}}function Cu(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?xu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function xu(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 vu(e){return[e.selectedPtyTabId,e.openInspectionKind?L:null].filter(t=>typeof t=="string")}function bi(e,t){return t.includes(e)}function Eu(e,t){let r=Au(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 Au(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 Fi(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 be(e){return typeof e=="string"?e:null}function Du(e){return e?`task:${e}`:null}function ir(e){return typeof e=="string"&&e.startsWith("task:")}function qn(e){return typeof e=="string"&&e.startsWith("new-task:")}function Kn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function $u(e){return typeof e=="string"&&e.startsWith("workspace:")}function Wi(e){return qn(e)?e.slice(9):null}function _i(e){return Kn(e)?e.slice(19):null}function Se(e,t,r){return Math.min(r,Math.max(t,e))}var cr="empty",q={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Ki(e,t){let r=Mu(t,e),n=t.repos.find(T=>T.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(T=>T.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(T=>T.repoId===n.id):[],i=o.find(T=>T.id===e.selectedTaskId)??o[0]??null,l=i?.type==="project",c=kp(t.tasks),d=Fu(e,i),u=Nu(e,i,d),g=u.find(T=>T.id===d)??u[0]??{id:"agent",label:"CODEX"},w=t.inspection?.taskId===i?.id?t.inspection:null,R=n?.name??"no repo",I=i?S.runners.getDisplayName(i.runner):S.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?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${n?`[${n.name}]`:"[no repo]"} \xB7 ${S.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 [${S.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:ir(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":d===L?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${S.runners.getDisplayName(e.centerTabRunner??i?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?l?"\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"?"\u2191\u2193 navigate Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:At.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${At.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:I},leftTree:Lu(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(T=>wp(T,c[T])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":g.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:R,agent:I},centerTranscript:Ou(d,e,n,i,e.workspaceBrowser,w,r),tabs:u,rightContext:hp(n,i),rightInspection:Ju(e,i,w)}}function Lu(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return ju(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 l=o.kind==="project"?o.discoveredRepoIds??[]:[o.primaryRepoId],c=t.tasks.filter(d=>d.workspaceId===o.id);if(c.length===0)r.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of c){let u=e.selectedLeftItemId===`task:${d.id}`,g=u?"\u25B8":"\u2022",w=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,R={id:`task:${d.id}`,taskId:d.id,text:`${g} ${w}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks"},I=Gi(d);I&&(R.prBadge=I),r.push(R)}if(o.kind==="project"){let d=`new-task-workspace:${o.id}`,u=e.selectedLeftItemId===d;r.push({id:d,text:`+ New Project Task [${S.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(o.kind==="repo"){let d=`new-task:${o.primaryRepoId}`,u=e.selectedLeftItemId===d;r.push({id:d,text:`+ New Task [${S.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}else{r.push({text:` Repos (${l.length})`,indent:0,muted:!0});for(let d of l.slice(0,6)){let u=t.repos.find(g=>g.id===d);r.push({text:` \xB7 ${u?.name??d}`,indent:0,muted:!0})}l.length>6&&r.push({text:` \xB7 ${l.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 ju(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 l=n.filter(u=>u.repoId===o.id);if(l.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let u of l){let g=t.selectedLeftItemId===`task:${u.id}`,w=g?"\u25B8":"\u2022",R=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,I={id:`task:${u.id}`,taskId:u.id,text:`${w} ${R}`,indent:2,selected:g,focused:g&&t.focusedRegion==="tasks"},T=Gi(u);T&&(I.prBadge=T),e.push(I)}let c=`new-task:${o.id}`,d=t.selectedLeftItemId===c;e.push({id:c,text:`+ New Task [${S.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:d,focused:d&&t.focusedRegion==="tasks",muted:!d})}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 Mu(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 Ou(e,t,r,n,s,o=null,i=null){if(s){let c=s.entries.length===0?["No directories or git repos here."]:s.entries.map((d,u)=>{let g=u===s.selectedIndex?"\u25B8":" ",w=d.kind==="repo"?" [git repo]":"/";return`${g} ${d.name}${w}`});return me(["Browse for a workspace to register.",s.cwd,"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return me(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let c=i?.kind==="project",d=c?i.name??"this workspace":r.name,u=c?"Project Task":"Task";return me([`No tasks in ${d}.`,"",`Press n or choose + New ${u} to create one with ${S.runners.getDisplayName(t.selectedRunner)}.`])}let l=n.ptyTabs.find(c=>c.id===e)??null;return l?l.kind==="agent"?me([`${l.title} tab ready for ${n.id}.`,"","Press Enter to attach this PTY-backed agent session.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):me([`${l.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===L&&t.openInspectionKind==="file"?Bu(n,o,t.fileScrollOffset):e===L&&t.openInspectionKind==="diff"?Uu(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?me(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):me(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Nu(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:Wu(o)}))??[];if(!t)return[{id:cr,label:"EMPTY",active:r===cr,focused:e.focusedRegion==="center"&&r===cr}];let s=e.openInspectionKind||r===L?[{id:L,label:_u(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function Fu(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===L&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??L:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??L:cr}function Wu(e){return e.title.toUpperCase()}function _u(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?At.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Bu(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return me(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=Vi(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:""},...qu(n.lines,r,s)]}function Uu(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return me(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=Vi(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:""},...Ku(n.lines,r,s)]}function me(e){return e.map(t=>({text:t}))}function qu(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 l=s+i+1;return{text:`${`${String(l).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(l).padStart(n," "),style:{fg:q.lineNumber}},{text:" \u2502 ",style:{fg:q.gutter}},...Gn(o,r)],tone:"default"}})}function Ku(e,t,r){let n=Vu(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>Gu(o,r))}function Vu(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 Gu(e,t){let r=Bi(e.oldNumber),n=Bi(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:q.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:q.diffAdd}:null,i=`${s} \u2502 ${e.text}`,l=o?zu(Gn(e.text,t),o.bg,o.fallbackFg):Gn(e.text,t),c=o?{fg:q.lineNumber,bg:o.bg}:{fg:q.lineNumber},d=o?{fg:q.gutter,bg:o.bg}:{fg:q.gutter};return{text:i,segments:[{text:s,style:c},{text:" \u2502 ",style:d},...l],fullBleed:o!==null}}function Bi(e){return e===null?" ":String(e).padStart(4," ")}function Vi(e){let t=At.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 Gn(e,t){return t==="diff"?Hu(e):t==="markdown"?Yu(e):t==="json"?Hn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Hn(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 Hu(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:q.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:q.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:q.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:q.diffMeta}}]:[{text:e}]}function zu(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function Yu(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:q.markup,bold:!0}}]:Hn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Hn(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:Qu(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function Qu(e){return e.startsWith("//")||e.startsWith("/*")?{fg:q.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:q.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:q.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:q.markup}:{fg:q.keyword}}function Ju(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(l=>l.repoId===n)??null:null,o=t?.type==="project"?Hi(t.repoTargets??[]):s?.pullRequest??(t?O(t):null),i=[Xu(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...Qi(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...up(e,r)]}:{title:"",rows:[...i,...fp(e,r)]}}function Xu(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 c=0;c<n.length;c++){let d=n[c];c>0&&s.push({text:" "});let u=d.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:d.label,style:{fg:u}})}let o=zn(t),i=Yn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(c=>c.text).join(""),segments:s}}function Ui(e){return[{text:" "},zn(e),{text:" "},Yn(e)]}function Gi(e){if(e.type==="project"&&e.repoTargets?.length){let r=Hi(e.repoTargets);return r?Ui(r):null}let t=O(e);return t?.number?Ui(t):null}function Hi(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=ep(r);return{number:-1,status:Zu(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 Zu(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 ep(e){let t=e.map(r=>zi(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 zn(e){return!e||!e.number?{text:gi,style:{fg:"565f89"}}:e.status==="merged"?{text:hi,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:ki,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Nn,style:{fg:"565f89"}}:{text:Nn,style:{fg:"9ece6a"}}}function Yn(e){return e?.aggregateReadiness?qi(e.aggregateReadiness):qi(zi(e))}function qi(e){return e==="failed"?{text:Bn,style:{fg:"f7768e"}}:e==="pending"?{text:Wn,style:{fg:"e0af68"}}:e==="success"?{text:_n,style:{fg:"9ece6a"}}:{text:Fn,style:{fg:"565f89"}}}function zi(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")?Yi(e)?"failed":tp(e)?"success":"pending":"pending"}function tp(e){return!!(e.mergeable&&!e.draft&&!Yi(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function Yi(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function Qi(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return rp(e,t);let r=O(t),n=Xi("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}),np(n,e)}var lr=32;function rp(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let l=s===i.repoId,c=e.focusedRegion==="inspector"&&l,d=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let g=i.failureReason?i.failureReason.slice(0,14):i.status,w=lr-g.length-1,R=d.length>w?d.slice(0,w-1)+"\u2026":d,I=lr-R.length-g.length;r.push({id:`project-review:${i.repoId}`,text:R+" ".repeat(Math.max(1,I))+g,selected:l,focused:c,muted:!0})}else{let u=zn(i.pullRequest),g=Yn(i.pullRequest),w=`${u.text} ${g.text}`,R=lr-w.length-1,I=d.length>R?d.slice(0,R-1)+"\u2026":d,T=lr-I.length-w.length,a=I+" ".repeat(Math.max(1,T));r.push({id:`project-review:${i.repoId}`,text:a+w,selected:l,focused:c,segments:[{text:a},{...u,text:u.text},{text:" "},{...g,text:g.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(...Xi("target",o.branch,o.pullRequest))),r}function Ji(e,t){return Qi(e,t).length}function Xi(e,t,r){let n=g=>`${e}-${g}`;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??"?",l=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${l}`,muted:!0});let c=sp(r.reviewDecision,r.mergeStateStatus),d=c&&c!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";c?s.push({id:n("pr-merge"),text:`${d} \xB7 ${c}`,muted:!0,segments:[{text:d},{text:" \xB7 "},{text:c,style:{fg:op(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:d,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Zi(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(ip)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let u=r.comments??[];return u.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${u.length})`}),s.push(...u.slice(-4).flatMap((g,w)=>ap(g,n(`comment:${w}`))))),s}function np(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 sp(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function op(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Zi(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 ip(e){let{icon:t,color:r}=cp(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," ")} ${dp(e.status)}`,color:r,muted:!1}}function ap(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Zi(e.createdAt)}`:"",s=lp(e.body,30),o=s.slice(0,4),i=o.length<s.length,l=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((c,d)=>({id:`${t}:body:${d}`,text:` ${i&&d===o.length-1?`${c}\u2026`:c}`,muted:!0}))];return l.push({id:`${t}:spacer`,text:"",muted:!0}),l}function lp(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 cp(e){switch(e){case"success":return{icon:_n,color:"9ece6a"};case"pending":return{icon:Wn,color:"e0af68"};case"failed":return{icon:Bn,color:"f7768e"};case"skipped":return{icon:Fn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function dp(e){return e==="success"?"passing":e==="failed"?"failing":e}function up(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(o=>[o.path,o.status])),n=pp(t.fileRows,e.collapsedFileTreePaths),s=e.selectedFileTreePath??t.selectedFilePath;return n.map(o=>{let i=o.kind==="file"?r.get(o.path):void 0,l=i==="A"?"9ece6a":i==="M"?"e0af68":i==="D"?"f7768e":i==="??"?"565f89":void 0,c=o.kind==="directory"?e.collapsedFileTreePaths.includes(o.path)?fi:mi:pi(o.label),d=o.kind==="directory"?"7aa2f7":wi(o.label),u=" ".repeat(o.depth),g=d?{text:c,style:{fg:d}}:{text:c},w=o.kind==="directory"?{text:o.label,style:{fg:"7aa2f7"}}:l?{text:o.label,style:{fg:l}}:{text:o.label},R=[{text:u},g,w];return{id:o.path,text:`${u}${c}${o.label}`,selected:o.path===s,focused:o.path===s&&e.focusedRegion==="inspector",segments:R}})}function pp(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 fp(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(mp(t))return gp(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=>ea(o,e,t))))}return r}function mp(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function gp(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(l=>l.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let l of["branch","staged","unstaged","untracked"]){let c=o.filter(d=>d.group===l);c.length!==0&&(r.push({id:`repo-diff:${s}:${l}`,text:` ${l}`,muted:!0}),r.push(...c.map(d=>ea(d,e,t,s.length+1))))}}return r}function ea(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",l=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${l} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function hp(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:S.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:At.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 kp(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function wp(e,t){return{name:S.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}var dr={width:120,height:36},ge={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function je(e,t){return{width:Math.max(e??dr.width,dr.width),height:Math.max(t??dr.height,dr.height)}}import{spawn as Bp}from"node:child_process";import{createHash as Up}from"node:crypto";import{createServer as qp,createConnection as ca}from"node:net";import{openSync as Kp}from"node:fs";import{mkdir as Vp,readFile as rs,rm as He,writeFile as Gp}from"node:fs/promises";import{tmpdir as Hp}from"node:os";import at from"node:path";import{createRequire as vp}from"node:module";import Rp from"@xterm/headless";var Tp=1e3,yp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function ra(e){return new Rp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:Tp,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function na(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Jn(e,t){return new Promise(r=>{e.write(t,r)})}function sa(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 l=0;l<e.rows;l+=1){let c=r.getLine(i+l);if(!c){n.push({segments:[]});continue}let d=[];for(let u=0;u<e.cols;u+=1){let g=c.getCell(u,s);!g||g.getWidth()===0||d.push({text:g.getChars()||" ",style:Sp(g,i+l===o&&u===r.cursorX)})}n.push({segments:Pp(bp(d))})}return n}function Pp(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&xp(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};oa(r.style)||(s.style=r.style),t.push(s)}return t}function bp(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!oa(r.style))break;t-=1}return e.slice(0,t)}function Sp(e,t){let r={},n=ta(e,"fg"),s=ta(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 ta(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"):yp[s]??Ip(s)}function Ip(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(Cp).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 Cp(e){return e===0?0:55+e*40}function xp(e,t){return Qn(e)===Qn(t)}function Qn(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function oa(e){return Qn(e)===""}var Ep=vp(import.meta.url),Ap=/^CTRL_([A-Z])$/,Dp="\x1B[6n",$p="\x1B[c",Lp="\x1B[?u",jp={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
143
|
-
|
|
144
|
-
|
|
125
|
+
`);default:return $d(e)}}function Dd(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 jd(e){return e.checks.status}function Ld(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 zf}from"node:module";import{readFile as Md,stat as Od}from"node:fs/promises";import ln from"node:path";var Fd=200*1024,Nd=500*1024,Wt="100000";async function So(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return Wd(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([Bt(e.worktreePath,n),s?cn(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 Wd(e,t,r){let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([Co(e,n),(async()=>{if(!s)return q("No diff selected","No local changes found.","empty");let l=_t(e,s),c=l?await pt(l.target.worktreePath).catch(()=>null):null;return vo(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function Io(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return _d(e,t);try{await N(e);let r=await pt(e.worktreePath),[n,s]=await Promise.all([Eo(e.worktreePath),xo(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([Bt(e.worktreePath,i),a?cn(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:$o(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 _d(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,P]=await Promise.all([Eo(f.worktreePath).catch(()=>[]),xo(f.worktreePath,u).catch(()=>[])]);return{target:f,baseRef:u,targetFiles:w,targetDiffRows:P}})),s=[],o=[];for(let{target:f,targetFiles:u,targetDiffRows:w}of n)s.push(...u.map(P=>`${f.repoId}/${P}`)),o.push(...w.map(P=>({...P,path:`${f.repoId}/${P.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([Co(e,a),(async()=>{if(!l)return q("No diff selected","No local changes found.","empty");let f=_t(e,l),u=f?n.find(w=>w.target.repoId===f.target.repoId):null;return vo(e,l,o,u?.baseRef??null)})()]),p=l?{[l]:d}:{};return{taskId:e.id,fileRows:$o(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:p,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function Co(e,t){let r=_t(e,t);if(!r)return q("No file selected","No Git-visible files found.","empty");let n=await Bt(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function vo(e,t,r,n=null){let s=_t(e,t);return s?{...await cn(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 _t(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 Eo(e){let t=await T("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return jo(t.stdout)}async function xo(e,t){let[r,n,s,o]=await Promise.all([Bd(e,t),bo(e,"staged"),bo(e,"unstaged"),qd(e)]);return[...r,...n,...s,...o]}async function Bd(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=Ao(r.stdout),o=Do(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 bo(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=Ao(n.stdout),i=Do(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 qd(e){let t=await T("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=jo(t.stdout);return await Promise.all(r.map(async s=>{let o=await Bt(e,s),i=o.status==="ready"?Ud(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function Ao(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 Do(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 Bt(e,t){if(!t)return q("No file selected","No Git-visible files found.","empty");let r=Kd(e,t);try{let n=await Od(r);if(n.size>Fd)return q(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Md(r);return Vd(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 cn(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=${Wt}`,`${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=${Wt}`,"--",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=${Wt}`,"--",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=${Wt}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
|
|
132
|
+
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
133
|
+
|
|
134
|
+
`);return i.length>Nd?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 $o(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 Ud(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function jo(e){return[...new Set(e.split(`
|
|
136
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Kd(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 Vd(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 Gd=["tasks","center","inspector","actions"],Wo=["agent","terminal"],_o=[],I="inspection",cR=[...Wo,..._o],Bo=["commit","push","refresh-checks","close-task"],Hd=["refresh-checks","close-task"],qo=["task","checks","pr","setup-run","actions","next-action"],Uo=["diff","files","review"];function Ko(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=cu(e?.openInspectionKind)??r,s=g.runners.getEnabled(t);return{inputMode:uu(e?.inputMode),focusedRegion:au(e?.focusedRegion),selectedRepoId:ce(e?.selectedRepoId),selectedWorkspaceId:ce(e?.selectedWorkspaceId),selectedTaskId:ce(e?.selectedTaskId),selectedPtyTabId:ce(e?.selectedPtyTabId),selectedLeftItemId:Ru(ce(e?.selectedTaskId)),activeTab:r?I:ce(e?.activeTab)??"agent",preferredPtyTabKind:du(e?.preferredPtyTabKind),inspectorSection:ft(e?.inspectorSection,qo,"task"),inspectionMode:lu(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:pu(e?.selectedRunner,s,g.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,workspaceBrowser:null,terminal:zd(),centerZoomed:!1}}function zd(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Vo(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=wu(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,...mu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:su(e,t,c?.id??null),...gu(e,t,c?.id??null),selectedDiffPath:nu(e,t,c?.id??null),inspectorSection:ft(e.inspectorSection,qo,"task")}}function Go(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Yd(t)?k({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):k({state:e});if(t==="q"||t==="Q")return k({state:e,exit:!0});if(t==="ESCAPE")return k({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return k({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(un(e.selectedLeftItemId)||pn(e.selectedLeftItemId)))return k({state:{...e,selectedRunner:fn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Lo(e,1);if(t==="SHIFT_TAB"||t==="[")return Lo(e,-1);if(t==="z"||t==="Z")return k({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):Mo(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):Mo(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 k({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=fu(e,t);return k({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 k({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return k({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return k({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId)return k({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&yu(e.selectedLeftItemId)&&e.selectedWorkspaceId)return k({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&No(e.activeTab,r.ptyTabIds??[]))return k({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 Oo(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return dn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Oo(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(un(e.selectedLeftItemId)||pn(e.selectedLeftItemId))){let n=ei(e.selectedLeftItemId),s=ti(e.selectedLeftItemId);return k({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 k({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return k({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"&&No(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return k({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 k({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 k({state:eu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return k({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"?k({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?k({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):k({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?k({state:e}):e.selectedActionId==="refresh-checks"?k({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?k({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):k({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return k({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 Yd(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 Yo(e){return Qo(e)||mt(e)!==null}function Qd(e){return _o.includes(e)}function Qo(e){return Wo.includes(e)}function Jo(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var Jd=["tasks","center","inspector"];function Lo(e,t){return qt(e,"focusedRegion",Jd,t)}function dn(e,t,r){let n=qt(e,"activeTab",r&&r.length>0?r:ku(e),t);return!n.changed||Qd(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Mo(e,t,r){if(e.focusedRegion==="tasks")return Xd(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 qt(e,"selectedActionId",Hd,t)}return qt(e,"selectedActionId",Bo,t)}function Xd(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 k({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"?Fo(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):k({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return Fo(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return tu(e,t,r)}return k({state:e})}function Zd(e,t){if(e.inspectionMode===t)return k({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return k({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 Oo(e,t){return Zd(e,iu(e.inspectionMode,Uo,t))}function Xo(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return k({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 k({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return k({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 eu(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 Fo(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]?k({state:e}):k({state:{...e,[t]:i,actionMessage:null},changed:!0})}function tu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return ru(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?k({state:e}):k({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?k({state:e}):k({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?k({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?k({state:e}):k({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?k({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?k({state:e}):k({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=de(i,0,o);return c===e.diffScrollOffset?k({state:e}):k({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function ru(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=ou(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?k({state:e}):k({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function nu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function su(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function ou(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function qt(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]?k({state:e}):k({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Ut(e,t,r,n,s=!1){if(r.length===0)return k({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]?k({state:e}):k({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function iu(e,t,r){let n=t.indexOf(e);return t[de(n+r,0,t.length-1)]??e}function k(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 au(e){return e==="tabs"?"center":ft(e,Gd,"tasks")}function lu(e,t){return e==="checks"||e==="actions"||e==="review"?"review":ft(e,Uo,t)}function cu(e){return e==="file"||e==="diff"?e:null}function du(e){return e==="terminal"?"terminal":"agent"}function uu(e){return e==="terminal"?"terminal":"control"}function pu(e,t=[...x],r="codex"){return e&&g.runners.isRunnerType(e)&&t.includes(e)?e:r}function fn(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 fu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function mu(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(Qo(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 gu(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?hu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function hu(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 ku(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function No(e,t){return t.includes(e)}function wu(e,t){let r=Tu(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 Tu(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 Ru(e){return e?`task:${e}`:null}function Kt(e){return typeof e=="string"&&e.startsWith("task:")}function un(e){return typeof e=="string"&&e.startsWith("new-task:")}function pn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function yu(e){return typeof e=="string"&&e.startsWith("workspace:")}function ei(e){return un(e)?e.slice(9):null}function ti(e){return pn(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([Y.repos.listRegisteredRepos(n).then(d=>d.repos),B(n),S.listTasks(n)]),a=mn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await Io(a,l):null;return{workspaceRoot:e,workspaces:o.filter(d=>d.status==="active"),repos:s,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function mn(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 yn from"node:path";import wR from"picocolors";var Pu=[" \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 gn(){return[...Pu]}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 bu=["Start","Options","Exit"],Su=["Resume","Options","Exit"],zt=2,Yt=2,Qt=2,Iu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Cu=new RegExp("\x1B\\[(?:0)?m","g"),vu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Eu=/https?:\/\/[^\s<>"']+/g,hn="\x1B[0m",kn="\x1B]8;;\x1B\\",y={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 Tn(e,{subtitle:"crAIg is that you?",menuItems:bu,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 Tn(e,{subtitle:"Control mode is paused.",menuItems:Su,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."],xu=["Help"];function wn(e,t={}){return Tn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??xu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function li(e,t={}){let r=t.color??!0,n=y.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o=gn(),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,y.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 ci(e,t={}){let r=t.color??!0,n=y.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=ht(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 P=p[u]??J(),D=`${" ".repeat(c)}${Xt(P.text,l)}`,U=P.tone==="selected"?y.overlayMenuSelected:P.tone==="muted"?y.overlay:y.panelBg;s[w]=$(ie(D,e.width),r,U)}return s.join(`
|
|
139
|
+
`)}function di(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:y.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:y.divider,u=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:y.divider,w=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,P=$(ie(w,e.width),n,y.rail),D=Du(t,s-zt-Yt,c,n),U=$u(t,l,c,n),fe=Lu(t,o,c,n),ae=t.inputMode==="terminal",h=[];for(let je=0;je<c;je+=1){if(a){h.push(Ht(U[je]??J(),l,n,"center"));continue}let Xa=Ht(D[je]??J(),s,n,"left"),Za=$("\u2502",n,f),el=Ht(U[je]??J(),l,n,"center"),tl=$("\u2502",n,u),rl=Ht(fe[je]??J(),o,n,"right");h.push(`${Xa}${Za}${el}${tl}${rl}`)}let Qe=ae||t.modalInput?y.panelBg:y.panelMuted,Ja=Au(t.footerText,t.footerToast,e.width,n,Qe);return[P,...h,Ja].join(`
|
|
140
|
+
`)}function Au(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?Xt(o,Math.max(0,r-a-3)):o,p=Math.max(1,r-z(d)-a-2),f=t.tone==="error"?Zu(i,n,s):Ge(i,n,s),u=`${d}${" ".repeat(p)}${f} `;return $(ie(u,r),n,s)}function Tn(e,t){let r=new Array(e.height).fill($(" ".repeat(e.width),t.color,y.overlay)),n=gn(),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=fi(a[c]??"",e.width);if(c<n.length){r[l+c]=$(d,t.color,y.overlayLogo);continue}if(c===n.length+1){r[l+c]=$(d,t.color,y.overlaySubtitle);continue}let p=c-(n.length+3),u=p>=0&&p<t.menuItems.length&&p===t.menuIndex?y.overlayMenuSelected:y.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}${Rn(d,t.color,y.overlay)}`,t.color,y.overlay)}return r.join(`
|
|
141
|
+
`)}function Du(e,t,r,n){let s=Fu(e.runners),o=1,i=e.leftTree.map(l=>Ou(l,t,n));return[...ht(i,r-o),s]}function $u(e,t,r,n){let s=t-2,o=e.tabs.find(h=>h.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:Qu(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,y.panelBg):Jt(l,n,y.panelMuted)}`,d=[`${Jt(e.centerHeader.tabLabel,n,y.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),p=e.tabs.find(h=>h.active)?.id??"agent",f=e.centerHeader.tabLabel==="BROWSER"||!Yo(p)?e.centerTranscript.map(h=>({...h})):ju(e),u=Nu(e.tabs,n,e.focusedRegion==="center"),w=" engaged ",P=w.length+2,D=e.inputMode==="terminal"?Ge(`${w}\u25CF `,n,y.panelBg):"",U=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-z(u)-P)):"",ae=[{text:e.inputMode==="terminal"?`${u}${U}${D}`:u},{text:c,tone:"muted"},{text:d},J(),...f];return ht(ae,r)}function ju(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:hi(n.segments),segments:n.segments,fullBleed:!0}))}function Lu(e,t,r,n){let s=e.rightInspection?Mu(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):ht([{text:"CONTEXT"},J(),...e.rightContext.map(o=>Wu(o,n)),...e.actionMessage?[J(),{text:e.actionMessage}]:[]],r);return ht(s,r)}function Mu(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:Xu(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>si(a)),...n.slice(i,i+s).map(a=>si(a))]}function si(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 Ou(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?y.panelSelected:y.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,y.panelBg):e.panelHeader?Jt(e.text,r,y.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(P=>P.text).join("")}`,segments:u,tone:p}}return{text:`${d}${o}${i}`,tone:p}}function Fu(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:y.success.fg}}):r.push({text:s.text,style:{fg:y.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function Nu(e,t,r){return e.map(n=>n.active?r?Ge(n.label,t,y.panelBg):Jt(n.label,t,y.panelBg):Rn(n.label,t,y.panelBg)).join(" ")}function Wu(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Rn(e.value,t,y.panelBg):e.value}`}}function Ht(e,t,r,n){let s=_u(n,e.tone??"default"),o=Bu(e,r,s);if(n==="left"){if(e.fullBleed)return $(ie(o,t),r,s);let a=t-zt-Yt;if(e.rightAlign){let c=z(o),d=Math.max(0,a-c),p=`${" ".repeat(zt)}${" ".repeat(d)}${o}${" ".repeat(Yt)}`;return $(p,r,s)}let l=`${" ".repeat(zt)}${ie(o,a)}${" ".repeat(Yt)}`;return $(l,r,s)}return n==="center"&&e.fullBleed?qu(e,t,r,s):$(ie(` ${o}`,t),r,s)}function _u(e,t){return t==="selected"||t==="focused"?y.panelSelected:t==="muted"?y.panelMuted:y.panelBg}function ht(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(J());return r}function J(){return{text:""}}function Bu(e,t,r){return e.segments?e.segments.map(n=>ui(n,t,r)).join(""):e.text}function qu(e,t,r,n){let s=" ".repeat(Qt),o=Math.max(0,t-Qt*2);if(!e.segments)return $(`${s}${ie(e.text,o)}${s}`,r,n);let i=Vu(e.segments,o),a=`${s}${i.map(l=>ui(l,r,n)).join("")}${s}${r?kn:""}`;return $(a,r,n)}function ui(e,t,r){let n=e.href?`${pi(e.href)}${e.text}${kn}`:Uu(e.text);return!t||!e.style?n:`${kt(zu(e.style,r))}${Yu(e.style)}${n}${hn}${kt(r)}`}function Uu(e){return e.replace(Eu,t=>{let[r,n]=Ku(t);return`${pi(r)}${r}${kn}${n}`})}function Ku(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function pi(e){return`\x1B]8;;${e}\x1B\\`}function Vu(e,t){let r=Gu(e,t);return Hu(r,t)}function Gu(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=Xt(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function Hu(e,t){let r=z(hi(e));if(r>=t)return e;let n=e.at(-1)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function zu(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 Yu(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 Qu(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function fi(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?Ju(e,t):e+" ".repeat(t-r)}function Ju(e,t){if(t<=0)return"";if(z(e)<=t)return e;let r=gi(e);return Xt(r,Math.max(0,t-1))+"\u2026"}function z(e){let t=0;for(let r of Array.from(gi(e)))t+=mi(r);return t}function Xt(e,t){let r="",n=0;for(let s of Array.from(e)){let o=mi(s);if(n+o>t)break;r+=s,n+=o}return r}function mi(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 Xu(e,t,r){return Math.min(Math.max(e,t),r)}function gi(e){return e.replace(vu,"").replace(Iu,"")}function hi(e){return e.map(t=>t.text).join("")}function $(e,t,r){if(!t)return e;let n=kt(r),s=e.replace(Cu,`${hn}${n}`);return`${n}${s}${hn}`}function kt(e){let t=[];return e.fg&&t.push(`38;2;${oi(e.fg).join(";")}`),e.bg&&t.push(`48;2;${oi(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function oi(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 Zt(e,t,y.success.fg,r)}function Zu(e,t,r){return Zt(e,t,y.error.fg,r)}function Jt(e,t,r){return Zt(e,t,y.accent.fg,r)}function Rn(e,t,r){return Zt(e,t,y.mutedfg.fg,r)}function Zt(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${kt(s)}${e}${kt(n)}`}function ki(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"?tp(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:ep(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function ep(e,t){let r=(e??"").split(yn.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(yn.delimiter):[...r,t].join(yn.delimiter)}function tp(e){return e.command.length>0?e.command:["codex"]}function wi(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-Qt*2),rows:Math.max(5,e.height-Z.topRailHeight-5)}}function Ti(e){return e.length===1||oe(e)||e==="BACKSPACE"||e==="TAB"}function wt(e){return typeof e=="string"&&new RegExp(`:(?:agent|${x.join("|")})(?:-\\d+)?$`).test(e)}function Ri(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 Pn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function yi(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 Pi(e){return e==="\x1B[13;2u"?"SHIFT_ENTER":null}function bi(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
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 Si(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Ii(e){return e.split(`
|
|
144
|
+
`).map((t,r)=>`\x1B[${r+1};1H${t}`).join("")}import{spawn as Sp}from"node:child_process";import{createHash as Ip}from"node:crypto";import{createServer as Cp,createConnection as Li}from"node:net";import{openSync as vp}from"node:fs";import{mkdir as Ep,readFile as xn,rm as De,writeFile as xp}from"node:fs/promises";import{tmpdir as Ap}from"node:os";import He from"node:path";import{createRequire as up}from"node:module";import rp from"@xterm/headless";var np=1e3,sp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function vi(e){return new rp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:np,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Ei(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Sn(e,t){return new Promise(r=>{e.write(t,r)})}function xi(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:ap(p,i+a===o&&d===r.cursorX)})}n.push({segments:op(ip(c))})}return n}function op(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&dp(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};Ai(r.style)||(s.style=r.style),t.push(s)}return t}function ip(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Ai(r.style))break;t-=1}return e.slice(0,t)}function ap(e,t){let r={},n=Ci(e,"fg"),s=Ci(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 Ci(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"):sp[s]??lp(s)}function lp(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(cp).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 cp(e){return e===0?0:55+e*40}function dp(e,t){return bn(e)===bn(t)}function bn(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Ai(e){return bn(e)===""}var pp=up(import.meta.url),fp=/^CTRL_([A-Z])$/,mp="\x1B[6n",gp="\x1B[c",hp="\x1B[?u",kp={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:""},er=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")In(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,Di(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=wp(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&&Di(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&(In(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())In(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:xi(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??Rp().spawn,i=vi(n),a=s??this.resolveSessionSpec(t,r),l=ve({...this.env,...a.env??{}}),{executable:c,args:d}=yp(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:Pp(l)}),f={taskId:t,tabId:r,pty:p,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0};return f.disposables.push(p.onData(u=>{bp(p,u),Sn(f.terminal,u).then(()=>{this.onUpdate?.(f.tabId)})})),f.disposables.push(p.onExit(u=>{f.status="exited",Sn(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 wp(e){if(e.length===1)return e;let t=kp[e];if(t!==void 0)return t;let r=fp.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function Di(e,t){Tp(e.pty,t),Ei(e.terminal,t)}function In(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function Tp(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Rp(){return pp("node-pty")}function yp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Ee(t[0],r),...t.slice(1)].map($i).join(" ")}; exec ${$i(e)} -l`;return{executable:e,args:["-lc",s]}}function $i(e){return`'${e.replaceAll("'","'\\''")}'`}function Pp(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 bp(e,t){for(let r=0;r<Cn(t,mp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Cn(t,gp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Cn(t,hp);r+=1)e.write("\x1B[?0u")}function Cn(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 An=3;async function Mi(e){let t=Dn(e.paths);await Dp(t,e.paths,e.spawnDaemon);let r=await Bi(t.socketPath),n=new vn(r,e);return await n.ready(),n}async function Oi(e,t={}){let r=Dn(e);await Ep(e.runtimeDir,{recursive:!0}),await De(r.socketPath,{force:!0});let n=new En(e,t),s=Cp(o=>n.handleConnection(o));await Fp(s,r.socketPath),await xp(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 Fi(e){let t=Dn(e);return await rr(t.socketPath)?(await Wi(t.socketPath),!0):!1}var vn=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!==An)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)}
|
|
145
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(`
|
|
146
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(`
|
|
147
|
-
`)}}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()}},En=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new er({...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(`
|
|
148
150
|
`);for(;s!==-1;){let o=r.slice(0,s);r=r.slice(s+1),this.handleLine(t,o),s=r.indexOf(`
|
|
149
|
-
`)}}),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{
|
|
150
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
151
|
-
`)),s.once("error",
|
|
152
|
-
`);if(
|
|
153
|
-
`)}catch{}}function
|
|
154
|
-
`)}function ba(e,t={}){let r=t.color??!0,n=E.overlay,s=new Array(e.height).fill(W(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",l=t.errorLogLines??[],c=Math.max(20,e.width-8),d=Math.max(0,Math.floor((e.width-c)/2)),u=[{text:o,tone:"selected"},{text:i,tone:"muted"},ae(),...l.length>0?l.map(R=>({text:R})):[{text:"No Craig errors have been logged.",tone:"muted"}],ae(),{text:"Esc returns to Options.",tone:"muted"}],g=Dt(u,e.height-2),w=Math.max(1,Math.floor((e.height-g.length)/2));for(let R=0;R<g.length;R+=1){let I=w+R;if(I>=e.height)break;let T=g[R]??ae(),a=`${" ".repeat(d)}${Tr(T.text,c)}`,z=T.tone==="selected"?E.overlayMenuSelected:T.tone==="muted"?E.overlay:E.panelBg;s[I]=W(Te(a,e.width),r,z)}return s.join(`
|
|
155
|
-
`)
|
|
156
|
-
`)
|
|
157
|
-
`)}function pf(e,t,r,n){let s=wf(e.runners),o=1,i=e.leftTree.map(c=>kf(c,t,n));return[...Dt(i,r-o),s]}function ff(e,t,r,n){let s=t-2,o=e.tabs.find(x=>x.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:Df(e.tabs),l=e.inputMode==="terminal"?s:o.length+1,c="\u2500".repeat(Math.max(0,l)),d=`${" ".repeat(i)}${e.inputMode==="terminal"?lt(c,n,E.panelBg):Rr(c,n,E.panelMuted)}`,u=[`${Rr(e.centerHeader.tabLabel,n,E.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),g=e.tabs.find(x=>x.active)?.id??"agent",w=e.centerHeader.tabLabel==="BROWSER"||!ji(g)?e.centerTranscript.map(x=>({...x})):mf(e),R=Rf(e.tabs,n,e.focusedRegion==="center"),I=" engaged ",T=I.length+2,a=e.inputMode==="terminal"?lt(`${I}\u25CF `,n,E.panelBg):"",z=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-se(R)-T)):"",le=[{text:e.inputMode==="terminal"?`${R}${z}${a}`:R},{text:d,tone:"muted"},{text:u},ae(),...w];return Dt(le,r)}function mf(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},ae(),{text:e.terminal.error},ae(),{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:Aa(n.segments),segments:n.segments,fullBleed:!0}))}function gf(e,t,r,n){let s=e.rightInspection?hf(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):Dt([{text:"CONTEXT"},ae(),...e.rightContext.map(o=>Tf(o,n)),...e.actionMessage?[ae(),{text:e.actionMessage}]:[]],r);return Dt(s,r)}function hf(e,t){let r=e.slice(0,2),n=e.slice(2),s=Math.max(0,t-r.length),o=n.findIndex(l=>l.focused||l.selected),i=o===-1?0:Lf(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(l=>wa(l)),...n.slice(i,i+s).map(l=>wa(l))]}function wa(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 kf(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${lt("\u25CF",r,e.selected?E.panelSelected:E.panelBg)}`:"",l=e.prBadge?e.prBadge.reduce((R,I)=>R+se(I.text),0):0,c=t-se(o)-se(s)-l,d=e.selected?e.text:e.focused?lt(e.text,r,E.panelBg):e.panelHeader?Rr(e.text,r,E.panelMuted):e.text,u=Te(`${n}${d}`,Math.max(0,c)),g=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let R=[{text:`${u}${o}${i}`},...e.prBadge];return{text:`${u}${o}${e.prBadge.map(T=>T.text).join("")}`,segments:R,tone:g}}return{text:`${u}${o}${i}`,tone:g}}function wf(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:E.success.fg}}):r.push({text:s.text,style:{fg:E.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function Rf(e,t,r){return e.map(n=>n.active?r?lt(n.label,t,E.panelBg):Rr(n.label,t,E.panelBg):us(n.label,t,E.panelBg)).join(" ")}function Tf(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?us(e.value,t,E.panelBg):e.value}`}}function gr(e,t,r,n){let s=yf(n,e.tone??"default"),o=Pf(e,r,s);if(n==="left"){if(e.fullBleed)return W(Te(o,t),r,s);let l=t-hr-kr;if(e.rightAlign){let d=se(o),u=Math.max(0,l-d),g=`${" ".repeat(hr)}${" ".repeat(u)}${o}${" ".repeat(kr)}`;return W(g,r,s)}let c=`${" ".repeat(hr)}${Te(o,l)}${" ".repeat(kr)}`;return W(c,r,s)}return n==="center"&&e.fullBleed?bf(e,t,r,s):W(Te(` ${o}`,t),r,s)}function yf(e,t){return t==="selected"||t==="focused"?E.panelSelected:t==="muted"?E.panelMuted:E.panelBg}function Dt(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(ae());return r}function ae(){return{text:""}}function Pf(e,t,r){return e.segments?e.segments.map(n=>Ia(n,t,r)).join(""):e.text}function bf(e,t,r,n){let s=" ".repeat(wr),o=Math.max(0,t-wr*2);if(!e.segments)return W(`${s}${Te(e.text,o)}${s}`,r,n);let i=Cf(e.segments,o),l=`${s}${i.map(c=>Ia(c,r,n)).join("")}${s}${r?ls:""}`;return W(l,r,n)}function Ia(e,t,r){let n=e.href?`${Ca(e.href)}${e.text}${ls}`:Sf(e.text);return!t||!e.style?n:`${$t(Ef(e.style,r))}${Af(e.style)}${n}${as}${$t(r)}`}function Sf(e){return e.replace(cf,t=>{let[r,n]=If(t);return`${Ca(r)}${r}${ls}${n}`})}function If(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function Ca(e){return`\x1B]8;;${e}\x1B\\`}function Cf(e,t){let r=xf(e,t);return vf(r,t)}function xf(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=se(s.text);if(o<=n){r.push(s),n-=o;continue}let i=Tr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function vf(e,t){let r=se(Aa(e));if(r>=t)return e;let n=e.at(-1)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function Ef(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 Af(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 Df(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function xa(e,t){let r=Math.max(0,t-se(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function Te(e,t){let r=se(e);return r>=t?$f(e,t):e+" ".repeat(t-r)}function $f(e,t){if(t<=0)return"";if(se(e)<=t)return e;let r=Ea(e);return Tr(r,Math.max(0,t-1))+"\u2026"}function se(e){let t=0;for(let r of Array.from(Ea(e)))t+=va(r);return t}function Tr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=va(s);if(n+o>t)break;r+=s,n+=o}return r}function va(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 Lf(e,t,r){return Math.min(Math.max(e,t),r)}function Ea(e){return e.replace(lf,"").replace(of,"")}function Aa(e){return e.map(t=>t.text).join("")}function W(e,t,r){if(!t)return e;let n=$t(r),s=e.replace(af,`${as}${n}`);return`${n}${s}${as}`}function $t(e){let t=[];return e.fg&&t.push(`38;2;${Ra(e.fg).join(";")}`),e.bg&&t.push(`48;2;${Ra(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function Ra(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function lt(e,t,r){return yr(e,t,E.success.fg,r)}function jf(e,t,r){return yr(e,t,E.error.fg,r)}function Rr(e,t,r){return yr(e,t,E.accent.fg,r)}function us(e,t,r){return yr(e,t,E.mutedfg.fg,r)}function yr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${$t(s)}${e}${$t(n)}`}var ps=["Runners","Error Log","Help"];function fs(e,t){return N.map(r=>{let n=S.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 $a(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 La(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(ps.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:ms(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function ja(e,t,r,n){if(e.pathEdit)return Mf({...e,pathEdit:e.pathEdit},t,r);let s=fs(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 l=N[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:l,value:t.runners?.[l]?.path??""}}}}if(!ms(r))return{kind:"noop",state:e};let o=N[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",config:Of(t,o,!i),state:{...e,message:`${S.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Mf(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Da({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(ms(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save",config:Nf(t,n,s.length>0?s:null),state:Da({...e,message:s.length>0?`${S.runners.getProfile(n).displayName} executable saved.`:`${S.runners.getProfile(n).displayName} executable reset to default.`})}}return Ff(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Of(e,t,r){return{...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}}}function Nf(e,t,r){let n={...e.runners?.[t]??{},...r?{path:r}:{}};return r||delete n.path,{...e,runners:{...e.runners??{},[t]:n}}}function Da(e){let t={...e};return delete t.pathEdit,t}function ms(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
158
|
-
`}function Ff(e){return e.length===1&&e>=" "&&e!=="\x7F"}var Uf=Wf(import.meta.url),qf=Uf("terminal-kit"),Kf=qf.terminal;async function Na(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=Pe(t),n=await S.load(r),s=S.runners.getEnabled(n),o=e.uiStateFile?await J({uiStateFile:e.uiStateFile}):null,i=Promise.resolve(),l=Promise.resolve(),c=await Lt(t,void 0,s),d=ar(Ei(o,n),c);c=await Lt(t,d,s);let u=()=>{},g={workspaceRoot:t,onUpdate:()=>u(),resolveSessionSpec:(I,T)=>zf(c,T,t)},w=e.ptyRuntime??await da({...g,paths:r}),R=I=>{if(!e.uiStateFile)return;o=Ai(o,I);let T=o;i=i.then(()=>Y({uiStateFile:e.uiStateFile},T),()=>Y({uiStateFile:e.uiStateFile},T)),i.catch(()=>{})};return new Promise(I=>{let T=e.terminal??Kf,a={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:ar(d,c)},z=!1,U=!1,le=null,x=0,Me=0,Ce=null,oe=null,xe=null,he=null,ve=null,ce=null,ze=null,Sr=!1,Ir=null,hs=`Craig v${S.version.getCurrent()}`,Cr=null,xr=0,Q=!0,vr=null,y=()=>{},_=w;u=()=>{a.mode==="main"&&(a={mode:"main",shell:dt(a.shell)},xe||(xe=setTimeout(()=>{xe=null,a.mode==="main"&&y()},50)))};function dt(f){return Ge(f,_.getViewState(ks(f)))}function ks(f){let p=Ye(f);return p?p.ptyTabs.some(m=>m.id===f.activeTab)?f.activeTab:f.activeTab==="agent"||f.activeTab==="terminal"?p.ptyTabs.find(m=>m.kind===f.activeTab)?.id??f.selectedPtyTabId:f.selectedPtyTabId:f.selectedPtyTabId}function P(f){return dt(Vf(f,c))}function Ye(f){return c.tasks.find(p=>p.id===f.selectedTaskId)??null}async function ws(){let f=c.tasks.flatMap(p=>p.ptyTabs.map(m=>m.id));await _.pruneStale?.(f),await _.hydrateSessions?.(f)}function Wa(){ws().catch(()=>{}).then(()=>{a.mode==="main"&&(a={mode:"main",shell:P(a.shell)},y())})}async function _a(f){let p=P(f),m=Ye(p),h=ks(p);if(!m||!h||!m.ptyTabs.some(F=>F.id===h))return p;let k=_.getViewState(h);if(k.status!=="idle"||k.rows.length>0||k.error)return Ge(p,k);let C=await _.ensureSession(m.id,h,Mt(je(T.width,T.height)));return Ge({...p,inputMode:"control"},C)}function Rs(f,p){return he&&(clearTimeout(he),he=null),p?(he=setTimeout(()=>{he=null,!(a.mode!=="main"||a.shell.footerToast!==p)&&(a={mode:"main",shell:P({...a.shell,footerToast:null})},y())},600),{...f,footerToast:p}):{...f,footerToast:null}}function Ba(f,p){return Rs(f,p?{tone:"success",message:p}:null)}function K(f,p,m){let h=p instanceof Error?p.message:m,k=p instanceof Error?p.stack??p.message:String(p);return er.appendErrorLogBestEffort(r,{context:f,message:h,details:k}),h}function V(f,p){return Rs(f,{tone:"error",message:p})}function Oe(f){let p=l.then(f,f);return l=p.then(()=>{},()=>{}),p}function Ts(f){let p=Ye(f),m=c.inspection,h=m&&m.taskId===p?.id?m:null,k=Gf(h?.fileRows??[],f.collapsedFileTreePaths);return{leftItemIds:Hf(c),centerTabIds:Oi(p,f),ptyTabIds:p?.ptyTabs.map(C=>C.id)??[],filePathIds:h?.filePaths??[],fileTreeRowIds:k.map(C=>C.path),fileTreeFileIds:k.filter(C=>C.kind==="file").map(C=>C.path),fileTreeDirectoryIds:k.filter(C=>C.kind==="directory").map(C=>C.path),diffPathIds:h?.diffPaths??[],diffPathRanges:[],fileLineCount:h?.selectedFile.lines.length??0,diffLineCount:h?.selectedDiff.lines.length??0,reviewRowCount:Ji(f,p),pageRows:Math.max(5,je(T.width,T.height).height-ge.topRailHeight-9),enabledRunnerIds:s,projectTargetIds:p?.repoTargets?.map(C=>C.repoId)??[]}}async function Ua(f){await S.save(r,f),n=f,s=S.runners.getEnabled(n),c={...c,enabledRunnerIds:s},a.mode==="main"?a={mode:"main",shell:P({...a.shell,selectedRunner:s.includes(a.shell.selectedRunner)?a.shell.selectedRunner:S.runners.getDefault(n)})}:a={...a,shell:P({...a.shell,selectedRunner:s.includes(a.shell.selectedRunner)?a.shell.selectedRunner:S.runners.getDefault(n)})}}async function qa(f){let p=f.selectedTaskId;p&&await Oe(async()=>{let m=await pe(r,p);!m.ptyTabs.some(h=>h.id===f.activeTab)||m.selectedPtyTabId===f.activeTab||await A(r,{...m,selectedPtyTabId:f.activeTab})})}async function de(){let f=(a.mode==="main",a.shell);c=await Lt(t,f,s),a.mode==="main"?a={mode:"main",shell:P(a.shell)}:a={...a,shell:P(a.shell)}}async function ys(f){let p=++xr,m=Fa(c.tasks,f),h=c.inspection,k;if(m&&h?.taskId===m.id){let C={selectedFilePath:f.selectedFilePath,selectedDiffPath:f.selectedDiffPath},F=await ri(m,h,C);if(p!==xr)return;k={...c,inspection:F}}else if(k=await Lt(t,f,s),p!==xr)return;c=k,a.mode==="main"&&(a={mode:"main",shell:P(a.shell)},R(a.shell),y())}async function Er(f){let p=await am(f);a.mode==="main"&&(a={mode:"main",shell:P({...a.shell,workspaceBrowser:p,activeTab:a.shell.selectedPtyTabId??a.shell.activeTab,actionMessage:null})},y())}async function Ps(f){try{let p=P(f),m=Ye(p),h=p.selectedPtyTabId;if(m&&p.focusedRegion==="tasks"){let F=m.ptyTabs.find(fe=>fe.kind==="agent")??null;F?h=F.id:(m=await bs(m),await de(),h=m.selectedPtyTabId)}m&&!h&&(m=await bs(m),await de(),h=m.selectedPtyTabId);let k=P({...p,activeTab:h??p.activeTab,selectedPtyTabId:h,focusedRegion:h?"center":p.focusedRegion});if(!k.selectedTaskId||!h){a={mode:"main",shell:k},y();return}a={mode:"main",shell:Ge({...k,inputMode:"terminal"},_.getViewState(h))},R(a.shell);let C=await _.ensureSession(k.selectedTaskId,h,Mt(je(T.width,T.height)));U=gs(h),le=null,a={mode:"main",shell:Ge({...k,inputMode:"terminal"},C)},R(a.shell)}catch(p){let m=K("attach PTY",p,"Failed to start PTY.");f.selectedTaskId&&f.selectedPtyTabId&&gs(f.selectedPtyTabId)&&(await Ka(f.selectedTaskId,m).catch(()=>{}),await de().catch(()=>{})),a={mode:"main",shell:V($i(P(f),m),m)},R(a.shell)}y()}async function Ka(f,p){await Oe(async()=>{await D.markRunnerFailed(r,f,p)})}async function Va(f,p,m){let h=P(f);if(!h.selectedTaskId)throw new Error("Select a task before creating a tab.");let k=await Oe(async()=>{let C=await pe(r,h.selectedTaskId),F=p??Jf(C,h.activeTab,h.preferredPtyTabKind),fe=Ma(C,F,m??void 0,n),ut={...C,ptyTabs:[...C.ptyTabs,fe],selectedPtyTabId:fe.id};return await A(r,ut),ut});return await de(),P({...h,activeTab:k.selectedPtyTabId??h.activeTab,selectedPtyTabId:k.selectedPtyTabId,preferredPtyTabKind:k.ptyTabs.at(-1)?.kind??h.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${k.ptyTabs.at(-1)?.title??"tab"}`})}async function Ga(f){let p=P(f);if(!p.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:m,nextSelectedTab:h}=await Oe(async()=>{let k=await pe(r,p.selectedTaskId),C=k.ptyTabs.findIndex($r=>$r.id===p.activeTab);if(C===-1)throw new Error("Only PTY tabs can be closed.");let F=k.ptyTabs[C],fe=k.ptyTabs.filter($r=>$r.id!==F.id),ut=fe[Math.min(C,fe.length-1)]??fe[C-1]??null;return await A(r,{...k,ptyTabs:fe,selectedPtyTabId:ut?.id??null}),{closedTab:F,nextSelectedTab:ut}});return _.disposeSession(m.id),await de(),P({...p,activeTab:h?.id??(p.openInspectionKind?"inspection":p.activeTab),selectedPtyTabId:h?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${m.title}`})}async function Ha(f){let p=P(f);if(!p.selectedTaskId)throw new Error("Select a task before refreshing PR checks.");let m=Ye(p),h=null,k=null;if(m?.type==="project"&&m.repoTargets?.length){let C=await D.prs.discoverOrRefreshAll(r,p.selectedTaskId);await de();let F=C.synced+C.discovered+C.notFound;k=`Refreshed ${C.synced}/${F} targets`}else{let{disposition:C,task:F}=await D.prs.discoverOrRefresh(r,p.selectedTaskId);await de(),h=C==="not_found"?`No PR found for ${F.branch}`:null,C!=="not_found"&&(k=`Refreshed checks: ${O(F)?.requiredChecks.length??0} reported`)}return P({...Ba(p,k),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:h})}async function za(){if(Sr||a.mode!=="main")return;let f=c.tasks;Sr=!0;try{if(await D.prs.discoverOrRefreshMany(r,f),Ir=null,a.mode!=="main")return;c=await Lt(t,a.shell,s),a={mode:"main",shell:P(a.shell)},y()}catch(p){let m=p instanceof Error?p.message:"Background PR discovery failed.";m!==Ir&&(Ir=m,er.appendErrorLogBestEffort(r,{context:"background PR polling",message:m,details:p instanceof Error?p.stack??p.message:String(p)}))}finally{Sr=!1}}async function Ya(f){let p=P(f);if(!p.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:m,task:h}=await Oe(async()=>{let k=await pe(r,p.selectedTaskId),C=await D.closeTask(r,p.selectedTaskId);return{taskBeforeClose:k,task:C}});for(let k of m.ptyTabs)_.disposeSession(k.id);return await de(),P({...p,selectedActionId:"close-task",actionMessage:h.cleanup.preservedWorktree?`Archived task ${h.id}; worktree preserved`:`Archived task ${h.id}`})}async function Qa(f){let p=P(f);if(!p.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await D.listTasks(r,{workspaceId:p.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${p.selectedWorkspaceId} while task records still reference it.`);await re.archiveWorkspace(r,p.selectedWorkspaceId);let h=await re.removeWorkspace(r,p.selectedWorkspaceId,{listTasks:D.listTasks});return await de(),P({...p,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${h.workspaceId}`})}async function bs(f){let p=f.ptyTabs.find(k=>k.kind==="agent")??null;if(p){let k={...f,selectedPtyTabId:p.id};return await Oe(async()=>{let C=await pe(r,f.id),F=C.ptyTabs.find(fe=>fe.kind==="agent")??null;F&&await A(r,{...C,selectedPtyTabId:F.id})}),k}let m=Ma(f,"agent",void 0,n),h={...f,ptyTabs:[...f.ptyTabs,m],selectedPtyTabId:m.id};return await Oe(async()=>{let k=await pe(r,f.id),C=k.ptyTabs.find(F=>F.kind==="agent")??null;if(C){await A(r,{...k,selectedPtyTabId:C.id});return}await A(r,{...k,ptyTabs:[...k.ptyTabs,m],selectedPtyTabId:m.id})}),h}y=()=>{Ja();let f=je(T.width,T.height),p=a.mode==="main"?Sa(f,Ki(P(a.shell),c),{centerOnly:a.shell.centerZoomed,focusFlashActive:ve!==null&&Date.now()<ve}):a.variant==="boot"?Ta(f,{menuIndex:a.menuIndex,optionsMessage:a.optionsMessage,versionText:hs,updateText:Cr}):a.variant==="pause"?ya(f,{menuIndex:a.menuIndex,optionsMessage:a.optionsMessage,versionText:hs,updateText:Cr}):a.variant==="options"?cs(f,{menuIndex:a.menuIndex,optionsMenuItems:ps}):a.variant==="runners"?cs(f,{menuIndex:jt(a).menuIndex,optionsMenuItems:fs(n,jt(a)),optionsMessage:$a(jt(a)),optionsSubtitle:"Runners"}):a.variant==="error-log"?ba(f,{errorLogPath:a.errorLog?.path??r.errorLogFile,errorLogLines:a.errorLog?.lines??[]}):Pa(f);Q&&(T.moveTo(1,1),T.eraseDisplayBelow(),Q=!1),T.noFormat(em(p)),T.hideCursor(!0)};function Ja(){let f=a.mode==="main"&&a.shell.inputMode==="terminal"?"terminal":"control";f!==vr&&(vr=f,T.grabInput(f==="terminal"?{mouse:"button"}:!0))}let Xa=()=>{process.stdout.off("resize",vs),process.off("SIGCONT",Es),T.removeListener("key",Ss),T.removeListener("unknown",Is),T.removeListener("mouse",Cs),Ce&&(clearTimeout(Ce),Ce=null),oe&&(clearTimeout(oe),oe=null),xe&&(clearTimeout(xe),xe=null),he&&(clearTimeout(he),he=null),ce&&(clearTimeout(ce),ce=null),ze&&(clearInterval(ze),ze=null),_.disposeAll(),T.grabInput(!1),T.hideCursor(!1),T.fullscreen(!1)},Ar=f=>{Xa(),I(f)},Za=async()=>{if(a.mode!=="main"||z)return;let f=a.shell,p=f.taskPromptInput?.trim()??"";if(!f.selectedRepoId&&!f.selectedWorkspaceId){a={mode:"main",shell:P({...f,taskPromptError:"Select a workspace first."})},y();return}if(p.length===0){a={mode:"main",shell:P({...f,taskPromptError:"Task prompt cannot be empty."})},y();return}z=!0,a={mode:"main",shell:P({...f,actionMessage:`Creating ${f.selectedRunner} task in ${f.selectedWorkspaceId??f.selectedRepoId}...`})},y();let m=null;try{m=await Xf(r,f.selectedRepoId,f.selectedWorkspaceId,p,f.selectedRunner),await de();let h=P({...a.shell,selectedRepoId:m.repoId,selectedWorkspaceId:m.workspaceId,selectedTaskId:m.id,selectedPtyTabId:m.selectedPtyTabId,selectedLeftItemId:`task:${m.id}`,activeTab:m.selectedPtyTabId??"agent",inputMode:"terminal",focusedRegion:"center",taskPromptInput:null,taskPromptError:null,actionMessage:null}),k=await _.ensureSession(m.id,h.selectedPtyTabId??Zf(m,"agent"),Mt(je(T.width,T.height)));U=gs(h.selectedPtyTabId),a={mode:"main",shell:Ge(h,k)},R(a.shell)}catch(h){h instanceof Pr&&(m=h.task);let k=K("create task",h,"Failed to create task.");m&&(await A(r,{...m,status:"draft",runnerSession:{...m.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:k}).catch(()=>{}),await de().catch(()=>{})),a={mode:"main",shell:V(P({...a.shell,inputMode:"control",selectedTaskId:m?.id??a.shell.selectedTaskId,selectedPtyTabId:m?.selectedPtyTabId??a.shell.selectedPtyTabId,selectedLeftItemId:m?`task:${m.id}`:a.shell.selectedLeftItemId,activeTab:m?.selectedPtyTabId??a.shell.activeTab,taskPromptInput:m?null:"",taskPromptError:k,actionMessage:null}),k)}}finally{z=!1,y()}},el=f=>{if(a.mode!=="main")return;let p=a.shell;if(p.taskPromptInput!==null){if(f==="ESCAPE"){a={mode:"main",shell:P({...p,taskPromptInput:null,taskPromptError:null,actionMessage:null})},y();return}if(Ie(f)){Za();return}if(f==="BACKSPACE"){a={mode:"main",shell:P({...p,taskPromptInput:p.taskPromptInput.slice(0,-1),taskPromptError:null})},y();return}if(f==="CTRL_R"){a={mode:"main",shell:P({...p,selectedRunner:Vn(p.selectedRunner,s),taskPromptError:null})},y();return}Li(f)&&(a={mode:"main",shell:P({...p,taskPromptInput:`${p.taskPromptInput}${f}`,taskPromptError:null})},y())}},tl=f=>{if(a.mode!=="main")return;let p=a.shell.workspaceBrowser;if(p){if(f==="ESCAPE"){a={mode:"main",shell:P({...a.shell,workspaceBrowser:null,actionMessage:null})},y();return}if(f==="UP"||f==="k"){a={mode:"main",shell:P({...a.shell,workspaceBrowser:{...p,selectedIndex:Math.max(0,p.selectedIndex-1),error:null}})},y();return}if(f==="DOWN"||f==="j"){let m=Math.max(0,p.entries.length-1);a={mode:"main",shell:P({...a.shell,workspaceBrowser:{...p,selectedIndex:Math.min(m,p.selectedIndex+1),error:null}})},y();return}if(f==="LEFT"||f==="h"){Er(ct.dirname(p.cwd)).catch(m=>{let h=K("open parent workspace directory",m,"Failed to open parent directory.");a={mode:"main",shell:V(P({...a.shell,workspaceBrowser:{...p,error:h}}),h)},y()});return}if(f==="RIGHT"||f==="l"||Ie(f)){let m=p.entries[p.selectedIndex]??null;if(!m)return;if((f==="RIGHT"||f==="l")&&(m.kind==="directory"||m.kind==="repo")){Er(m.path).catch(h=>{let k=K("open workspace directory",h,"Failed to open directory.");a={mode:"main",shell:V(P({...a.shell,workspaceBrowser:{...p,error:k}}),k)},y()});return}re.addWorkspace(r,m.path).then(async h=>{await de();let k=h.repos[0]??null;a={mode:"main",shell:P({...a.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${h.workspace.id}`,selectedWorkspaceId:h.workspace.id,selectedRepoId:k?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${h.workspace.name??h.workspace.id}`})},R(a.shell),y()}).catch(h=>{let k=K("add workspace",h,"Failed to add workspace.");a={mode:"main",shell:V(P({...a.shell,workspaceBrowser:{...p,error:k}}),k)},y()})}}},Ss=f=>{let p=typeof f=="string"?f:"";if(a.mode==="main"&&a.shell.taskPromptInput!==null){el(p);return}if(a.mode==="main"&&a.shell.workspaceBrowser!==null){tl(p);return}if(a.mode==="main"&&a.shell.inputMode==="control"){if(p==="F"){ol(),y();return}ve!==null&&(ve=null,ce&&(clearTimeout(ce),ce=null))}if(a.mode==="main"){let m=Di(a.shell,p,Ts(a.shell));if(m.exit){Ar(0);return}if(m.detachTerminal){_.detach(),a={mode:"main",shell:P(m.state)},R(a.shell),y();return}if(a.shell.inputMode==="terminal"){if(m.changed){a={mode:"main",shell:P(m.state)},R(a.shell),y();return}if(U&&Ie(p)){U=!1;return}U&&(U=!1),le=rm(p)?{key:p,at:Date.now()}:null;let h=nm(p,a.shell.terminal.scrolledBack??!1);if(h!==0){Dr(h);return}_.writeKey(p);return}if(p==="CTRL_C"){Ar(0);return}if(p==="?"&&a.shell.inputMode==="control"){a={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:a.shell},Q=!0,y();return}if(m.pause){a={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:P(m.state)},Q=!0,y();return}if(m.beginTaskPrompt){a={mode:"main",shell:P(m.state)},R(a.shell),y();return}if(m.openWorkspaceBrowser){Er(t).catch(h=>{let k=K("browse workspaces",h,"Failed to browse workspaces.");a={mode:"main",shell:V(P({...m.state,workspaceBrowser:{cwd:t,entries:[],selectedIndex:0,error:k}}),k)},y()});return}if(m.createPtyTab){Va(m.state,m.createPtyTabKind,m.createPtyTabRunner).then(h=>{Ps(h)}).catch(h=>{let k=K("create PTY tab",h,"Failed to create tab.");a={mode:"main",shell:V(P({...m.state,actionMessage:k}),k)},y()});return}if(m.closePtyTab){Ga(m.state).then(h=>{a={mode:"main",shell:h},R(a.shell),y()}).catch(h=>{let k=K("close PTY tab",h,"Failed to close tab.");a={mode:"main",shell:V(P({...m.state,actionMessage:k}),k)},y()});return}if(m.refreshPullRequestChecks){Ha(m.state).then(h=>{a={mode:"main",shell:h},R(a.shell),y()}).catch(h=>{let k=K("refresh PR checks",h,"Failed to refresh PR checks.");a={mode:"main",shell:V(P({...m.state,actionMessage:k}),k)},y()});return}if(m.openPrUrl){let h=Ye(m.state),k=h?O(h)?.url??null:null;k?lm(k).catch(C=>{let F=K("open PR URL",C,"Failed to open PR in browser.");a={mode:"main",shell:V(P(m.state),F)},y()}):(a={mode:"main",shell:V(P(m.state),"No PR URL available.")},y());return}if(m.closeTask){Ya(m.state).then(h=>{a={mode:"main",shell:h},R(a.shell),y()}).catch(h=>{let k=K("close task",h,"Failed to close task.");a={mode:"main",shell:V(P({...m.state,actionMessage:k}),k)},y()});return}if(m.removeWorkspace){Qa(m.state).then(h=>{a={mode:"main",shell:h},R(a.shell),y()}).catch(h=>{let k=K("remove workspace",h,"Failed to remove workspace.");a={mode:"main",shell:V(P({...m.state,actionMessage:k}),k)},y()});return}if(m.attachTerminal){Ps(m.state);return}if(m.refreshInspection){a={mode:"main",shell:P(m.state)},R(a.shell),y(),ys(a.shell).catch(h=>{let k=K("refresh inspection",h,"Failed to refresh inspection.");a={mode:"main",shell:V(P({...a.shell,actionMessage:k}),k)},y()});return}m.changed&&(a={mode:"main",shell:P(m.state)},qa(a.shell).catch(()=>{}),R(a.shell),y());return}if(a.variant==="help"){a.viaOptions&&a.parentVariant?a={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:a.shell,parentVariant:a.parentVariant}:a.parentVariant?a={mode:"overlay",variant:a.parentVariant,menuIndex:1,optionsMessage:null,shell:a.shell}:a={mode:"main",shell:P(a.shell)},Q=!0,y();return}if(a.variant==="options"){rl(p);return}if(a.variant==="runners"){sl(p);return}if(a.variant==="error-log"){if(p==="ESCAPE"||Ie(p)){let m=a.parentVariant;a={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:a.shell,...m!==void 0?{parentVariant:m}:{}},Q=!0,y()}return}if(a.optionsMessage){(p==="ESCAPE"||Ie(p))&&(a={...a,optionsMessage:null},y());return}if(p==="UP"||p==="k"){a={...a,menuIndex:Math.max(0,a.menuIndex-1)},y();return}if(p==="DOWN"||p==="j"){a={...a,menuIndex:Math.min(2,a.menuIndex+1)},y();return}if(p==="ESCAPE"){a.variant==="pause"&&(a={mode:"main",shell:P(a.shell)},Q=!0,y());return}if(Ie(p)){if(a.menuIndex===0){let m=a.variant==="boot";a={mode:"main",shell:P({...a.shell,inputMode:"control"})},Q=!0,y(),m?ll.then(()=>{if(a.mode!=="main")return;let h=a.shell;_a(h).then(k=>{a.mode!=="main"||a.shell!==h||(a={mode:"main",shell:k},R(a.shell),y())}).catch(k=>{if(a.mode!=="main"||a.shell!==h)return;let C=K("warm selected PTY",k,"Failed to start selected PTY.");a={mode:"main",shell:V(P(a.shell),C)},R(a.shell),y()})}):Wa();return}if(a.menuIndex===1){let m=a.variant==="boot"||a.variant==="pause"?a.variant:void 0;a={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:a.shell,...m!==void 0?{parentVariant:m}:{}},Q=!0,y();return}Ar(0)}};function rl(f){if(a.mode!=="overlay"||a.variant!=="options")return;let p=La(a.menuIndex,f);if(p.kind!=="noop"){if(p.kind==="render"){a={...a,menuIndex:p.menuIndex},y();return}if(p.kind==="back"){a.parentVariant&&(a={mode:"overlay",variant:a.parentVariant,menuIndex:1,optionsMessage:null,shell:a.shell},Q=!0,y());return}if(p.kind==="help"){let m=a.parentVariant;a={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:a.shell,viaOptions:!0,...m!==void 0?{parentVariant:m}:{}},Q=!0,y();return}if(p.kind==="runners"){let m=a.parentVariant;a={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:a.shell,...m!==void 0?{parentVariant:m}:{}},Q=!0,y();return}if(p.kind==="error-log"){let m=a.parentVariant;nl(m)}}}async function nl(f){let p;try{p=await er.readRecentErrorLines(r)}catch(m){let h=K("open error log",m,"Failed to read Craig error log.");p={path:r.errorLogFile,lines:[`Unable to read error log: ${h}`],empty:!1}}a.mode==="overlay"&&(a={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:a.shell,errorLog:p,...f!==void 0?{parentVariant:f}:{}},Q=!0,y())}function sl(f){if(a.mode!=="overlay"||a.variant!=="runners")return;let p=ja(jt(a),n,f,s);if(p.kind!=="noop"){if(p.kind==="back"){let m=a.parentVariant;a={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:a.shell,...m!==void 0?{parentVariant:m}:{}},Q=!0,y();return}if(p.kind==="render"){a={...a,runnerOptions:p.state},y();return}Ua(p.config).then(()=>{a.mode!=="overlay"||a.variant!=="runners"||(a={...a,runnerOptions:p.state},y())}).catch(m=>{if(a.mode!=="overlay"||a.variant!=="runners")return;let h=K("save runner option",m,"Failed to save runner option."),k=V(P(a.shell),h);a={...a,shell:k,runnerOptions:{...jt(a),message:h}},y()})}}function ol(){ve=Date.now()+600,ce&&clearTimeout(ce),ce=setTimeout(()=>{ve=null,ce=null,y()},600)}let Is=f=>{let p=tm(f);if(a.mode!=="main"||a.shell.inputMode!=="terminal"||p.length===0)return;if(p.includes("")){_.detach(),U=!1,le=null,a={mode:"main",shell:P({...a.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},R(a.shell),y();return}let m=sm(p);if(m!==0){Dr(m);return}let h=om(p);if(h){U=!1,le={key:h,at:Date.now()},_.writeKey(h);return}if(U&&p!=="\r"&&p!==`
|
|
159
|
-
`&&p!==`\r
|
|
160
|
-
`&&
|
|
161
|
-
|
|
162
|
-
`||r===`\r
|
|
163
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}async function am(e){let t=await _f(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=ct.join(e,n.name);r.push({name:n.name,path:s,kind:await cm(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,error:null}}async function lm(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 cm(e){let t=ct.join(e,".git");return await Bf(t).catch(()=>null)!==null}function br(){return process.cwd()}async function dm(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??br(),l=Pe(i);return await ua(l),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??br(),l=Pe(i);return await pa(l),0}let e=Ws(process.argv.slice(2)),t=br(),r=Pe(t),n={paths:r};if(e.mode==="interactive")return await Na({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await Qo(e.command,n),o=Jo(s);return o.length>0&&process.stdout.write(`${o}
|
|
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{tr(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(n);tr(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:An}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);tr(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 Np(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients)tr(n,{type:"update",tabId:t,view:r})}};function Dn(e){let t=Ip("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:He.join(Ap(),`craig-${t}.sock`),pidPath:He.join(e.runtimeDir,"pty-daemon.pid")}}async function Dp(e,t,r){if(await $p(e.socketPath,1e3))return;await rr(e.socketPath)&&(await Wi(e.socketPath),await ji(e.socketPath,1e3)),await rr(e.socketPath)&&(await Mp(e),await ji(e.socketPath,1e3)),await Lp(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=jp(n),l=vp(He.join(t.runtimeDir,"pty-daemon.log"),"a");Sp(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 Ni(e.socketPath))return;await $n(50)}let o=await xn(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 Ni(e){let t=await Op(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===An}async function $p(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Ni(e))return!0;await $n(50)}return!1}function jp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=He.resolve(He.dirname(t),"..","node_modules",".bin","tsx");return{command:Fr("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 Lp(e){let t=await xn(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&qi(r))return}await De(e.socketPath,{force:!0}),await De(e.pidPath,{force:!0})}async function rr(e){let t=await Bi(e).catch(()=>null);return t?(t.end(),!0):!1}async function Wi(e){await _i(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Mp(e){let t=await xn(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!qi(r)){await De(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await De(e.socketPath,{force:!0})}}async function Op(e){return _i(e,{id:1,type:"ping"})}function _i(e,t){return new Promise((r,n)=>{let s=Li(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
|
+
`)),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 ji(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await rr(e))return;await $n(50)}}function Bi(e){return new Promise((t,r)=>{let n=Li(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Fp(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function tr(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
155
|
+
`)}catch{}}function qi(e){try{return process.kill(e,0),!0}catch{return!1}}function $n(e){return new Promise(t=>setTimeout(t,e))}function Np(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var jn=["Runners","Error Log","Help"];function Ln(e,t){return x.map(r=>{let n=g.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 Ki(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 Vi(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(jn.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Mn(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Gi(e,t,r,n){if(e.pathEdit)return Wp({...e,pathEdit:e.pathEdit},t,r);let s=Ln(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=x[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Mn(r))return{kind:"noop",state:e};let o=x[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:`${g.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Wp(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Ui({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Mn(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Ui({...e,message:s.length>0?`${g.runners.getProfile(n).displayName} executable saved.`:`${g.runners.getProfile(n).displayName} executable reset to default.`})}}return _p(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Ui(e){let t={...e};return delete t.pathEdit,t}function Mn(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
156
|
+
`}function _p(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} ",Yi="\u{F0DCF} ",Qi="\u25CB",On="\uEA64",Ji="\uEAFE",Xi="\uEBDA",Fn="\u25CB",Nn="\u25CF",Wn="\u2713",_n="\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=Up(t,e),n=t.repos.find(P=>P.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(P=>P.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(P=>P.repoId===n.id):[],i=o.find(P=>P.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=If(t.tasks),c=Gp(e,i),d=Vp(e,i,c),p=d.find(P=>P.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,u=n?.name??"no repo",w=i?g.runners.getDisplayName(i.runner):g.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?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${n?`[${n.name}]`:"[no repo]"} \xB7 ${g.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 [${g.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 ${g.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"?"\u2191\u2193 navigate 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:Bp(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(P=>Cf(P,l[P])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:u,agent:w},centerTranscript:Kp(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Sf(n,i),rightInspection:of(e,i,f)}}function Bp(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return qp(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 [${g.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 [${g.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 qp(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"},P=oa(d);P&&(w.prBadge=P),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${g.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 Up(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 Kp(e,t,r,n,s,o=null,i=null){if(s){let l=s.entries.length===0?["No directories or git repos here."]:s.entries.map((c,d)=>{let p=d===s.selectedIndex?"\u25B8":" ",f=c.kind==="repo"?" [git repo]":"/";return`${p} ${c.name}${f}`});return te(["Browse for a workspace to register.",s.cwd,"",...l,"",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 ${g.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"?Yp(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?Qp(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 Vp(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:Hp(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:zp(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function Gp(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 Hp(e){return e.title.toUpperCase()}function zp(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 Yp(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:""},...Jp(n.lines,r,s)]}function Qp(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:""},...Xp(n.lines,r,s)]}function te(e){return e.map(t=>({text:t}))}function Jp(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}},...Bn(o,r)],tone:"default"}})}function Xp(e,t,r){let n=Zp(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>ef(o,r))}function Zp(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 ef(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?rf(Bn(e.text,t),o.bg,o.fallbackFg):Bn(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 Bn(e,t){return t==="diff"?tf(e):t==="markdown"?nf(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 tf(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 rf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function nf(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:sf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function sf(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 of(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=[af(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ca(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Rf(e,r)]}:{title:"",rows:[...i,...yf(e,r)]}}function af(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=Un(t),i=Kn(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:" "},Un(e),{text:" "},Kn(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=cf(r);return{number:-1,status:lf(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 lf(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 cf(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 Un(e){return!e||!e.number?{text:Qi,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:On,style:{fg:"565f89"}}:{text:On,style:{fg:"9ece6a"}}}function Kn(e){return e?.aggregateReadiness?ra(e.aggregateReadiness):ra(aa(e))}function ra(e){return e==="failed"?{text:_n,style:{fg:"f7768e"}}:e==="pending"?{text:Nn,style:{fg:"e0af68"}}:e==="success"?{text:Wn,style:{fg:"9ece6a"}}:{text:Fn,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":df(e)?"success":"pending":"pending"}function df(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 uf(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}),pf(n,e)}var nr=32;function uf(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=Un(i.pullRequest),p=Kn(i.pullRequest),f=`${d.text} ${p.text}`,u=nr-f.length-1,w=c.length>u?c.slice(0,u-1)+"\u2026":c,P=nr-w.length-f.length,D=w+" ".repeat(Math.max(1,P));r.push({id:`project-review:${i.repoId}`,text:D+f,selected:a,focused:l,segments:[{text:D},{...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=ff(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:mf(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(gf)):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)=>hf(p,n(`comment:${f}`))))),s}function pf(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 ff(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function mf(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 gf(e){let{icon:t,color:r}=wf(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," ")} ${Tf(e.status)}`,color:r,muted:!1}}function hf(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${pa(e.createdAt)}`:"",s=kf(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 kf(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 wf(e){switch(e){case"success":return{icon:Wn,color:"9ece6a"};case"pending":return{icon:Nn,color:"e0af68"};case"failed":return{icon:_n,color:"f7768e"};case"skipped":return{icon:Fn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Tf(e){return e==="success"?"passing":e==="failed"?"failing":e}function Rf(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(o=>[o.path,o.status])),n=Vn(t.fileRows,e.collapsedFileTreePaths),s=e.selectedFileTreePath??t.selectedFilePath;return n.map(o=>{let i=o.kind==="file"?r.get(o.path):void 0,a=i==="A"?"9ece6a":i==="M"?"e0af68":i==="D"?"f7768e":i==="??"?"565f89":void 0,l=o.kind==="directory"?e.collapsedFileTreePaths.includes(o.path)?zi:Yi:Hi(o.label),c=o.kind==="directory"?"7aa2f7":Zi(o.label),d=" ".repeat(o.depth),p=c?{text:l,style:{fg:c}}:{text:l},f=o.kind==="directory"?{text:o.label,style:{fg:"7aa2f7"}}:a?{text:o.label,style:{fg:a}}:{text:o.label},u=[{text:d},p,f];return{id:o.path,text:`${d}${l}${o.label}`,selected:o.path===s,focused:o.path===s&&e.focusedRegion==="inspector",segments:u}})}function Vn(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 yf(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(Pf(t))return bf(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 Pf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function bf(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 Sf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:g.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 If(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Cf(e,t){return{name:g.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as vf,mkdir as Ef,readFile as xf}from"node:fs/promises";import Af from"node:path";var ma=80,Gn=async(e,t)=>{await Ef(Af.dirname(e.errorLogFile),{recursive:!0}),await vf(e.errorLogFile,Df(t),"utf8")},ga=async(e,t)=>{try{await Gn(e,t)}catch{}},Hn=async(e,t=ma)=>{try{let n=(await xf(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($f(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},ha=async(e,t=ma)=>Hn(e,t);function Df(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
|
+
`).map(n=>` ${n}`))),`${r.join(`
|
|
159
|
+
`)}
|
|
160
|
+
|
|
161
|
+
`}function $f(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ze={appendErrorLog:Gn,appendErrorLogBestEffort:ga,readErrorLog:Hn,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 Q(n.paths,e.selectedTaskId),i=t??jf(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 R(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 Q(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 R(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 Q(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await R(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 Q(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await R(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 Q(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await R(t.paths,{...s,selectedPtyTabId:o.id});return}await R(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function jf(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=g.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"?g.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Ye=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Pa=async(e,t,r,n,s)=>{g.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(g.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 Ye(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}},ba=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Sa=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 Q(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=g.runners.setRunnerEnabled(r.config,e,t);return await g.save(r.paths,n),n},xa=async(e,t,r)=>{let n=g.runners.setRunnerPath(r.config,e,t);return await g.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(zn(e,t)))}function zn(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 A(e,t){if(!e.uiStateFile)return;e.runtimeState=Vo(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 Lf(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:S,workspaceService:Y,queueTaskMutation:t=>Lf(e,t)}}function Yn(e,t){let r=pe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,o=Vn(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 Qn(e,t){let r=++e.inspectionRefreshSequence,n=mn(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 So(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)},A(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,Yn(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render(),Qn(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)},A(e,e.state.shell),e.render()}},16)))}function Jn(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Xn(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){Xn(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=zn(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 Zn(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))},A(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)},A(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 Mf(e,t.selectedTaskId,n).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,Ho(m(e,t),n),n)},A(e,e.state.shell)}e.render()}async function Mf(e,t,r){await ba(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 Sa(r,W(e));for(let o of n)e.ptyRuntime.disposeSession(o);return await _(e),m(e,{...r,...s})}async function Ba(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 qa(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 S.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 S.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 _f from"node:path";import{readdir as Of,stat as Ff}from"node:fs/promises";import Ka from"node:path";async function Nf(e){let t=await Of(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 Wf(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,error:null}}async function Va(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 Nf(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 Wf(e){let t=Ka.join(e,".git");return await Ff(t).catch(()=>null)!==null}function Ga(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Bf(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)},A(e,e.state.shell)}catch(s){s instanceof Ye&&(n=s.task);let o=L(e,"create task",s,"Failed to create task.");n&&!(s instanceof Ye)?(await R(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})):n&&(await R(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 qf(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)){Bf(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:fn(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 Uf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(r){if(t==="ESCAPE"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}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,r.entries.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){ir(e,_f.dirname(r.cwd)).catch(n=>{let s=L(e,"open parent workspace directory",n,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:s}}),s)},e.render()});return}if(t==="RIGHT"||t==="l"||oe(t)){let n=r.entries[r.selectedIndex]??null;if(!n)return;if((t==="RIGHT"||t==="l")&&(n.kind==="directory"||n.kind==="repo")){ir(e,n.path).catch(o=>{let i=L(e,"open workspace directory",o,"Failed to open directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:i}}),i)},e.render()});return}let{workspaceService:s}=W(e);s.addWorkspace(e.paths,n.path).then(async o=>{await _(e);let i=o.repos[0]??null,a=m(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${o.workspace.id}`,selectedWorkspaceId:o.workspace.id,selectedRepoId:i?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${o.workspace.name??o.workspace.id}`});e.state={mode:"main",shell:a},A(e,e.state.shell),e.render()}).catch(o=>{let i=L(e,"add workspace",o,"Failed to add workspace.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:i}}),i)},e.render()})}}}function Kf(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;Vf(e,n)}}}async function Vf(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 Gf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Gi(Ga(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=g.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:g.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:{...Ga(e),message:o}},e.render()})}function Ha(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){qf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Uf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Hf(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=Go(e.state.shell,r,Yn(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)},A(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)},A(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)},A(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,error:o}}),o)},e.render()});return}if(n.createPtyTab){Na(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Zn(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},A(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},A(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?Va(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},A(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){Ba(e,n.state).then(s=>{e.state={mode:"main",shell:s},A(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){Zn(e,n.state);return}if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render(),Qn(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(()=>{}),A(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"){Kf(e,r);return}if(e.state.variant==="runners"){Gf(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},A(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)},A(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 za(e,t){let r=Si(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"})},A(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!==`
|
|
162
|
+
`&&r!==`\r
|
|
163
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),bi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function Ya(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){ja(e,Pn(t));return}let r=Pn(t);r!==0&&or(e,r)}function Hf(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var Yf=zf(import.meta.url),Qf=Yf("terminal-kit"),Jf=Qf.terminal;function es(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}async function Qa(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 g.load(r),s=g.runners.getEnabled(n),o=e.uiStateFile?await Me({uiStateFile:e.uiStateFile}):null,i=await Re(t,void 0,s),a=gt(Ko(o,n),i);i=await Re(t,a,s);let l=()=>{},c={workspaceRoot:t,onUpdate:()=>l(),resolveSessionSpec:(p,f)=>ki(i,f,t)},d=e.ptyRuntime??await Mi({...c,paths:r});return new Promise(p=>{let f=e.terminal??Jf,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,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,prPollTimer:null,prPollInFlight:!1,lastBackgroundPrPollError:null,versionText:`Craig v${g.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:h=>p(h)};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=()=>{Fa(u);let h=ee(f.width,f.height),Qe=u.state.mode==="main"?di(h,na(m(u,u.state.shell),u.model),{centerOnly:u.state.shell.centerZoomed,focusFlashActive:u.focusFlashUntil!==null&&Date.now()<u.focusFlashUntil}):u.state.variant==="boot"?ii(h,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="pause"?ai(h,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="options"?wn(h,{menuIndex:u.state.menuIndex,optionsMenuItems:jn}):u.state.variant==="runners"?wn(h,{menuIndex:es(u.state).menuIndex,optionsMenuItems:Ln(u.config,es(u.state)),optionsMessage:Ki(es(u.state)),optionsSubtitle:"Runners"}):u.state.variant==="error-log"?ci(h,{errorLogPath:u.state.errorLog?.path??r.errorLogFile,errorLogLines:u.state.errorLog?.lines??[]}):li(h);u.pendingClear&&(f.moveTo(1,1),f.eraseDisplayBelow(),u.pendingClear=!1),f.noFormat(Ii(Qe)),f.hideCursor(!0)};let w=h=>Ha(u,h),P=h=>za(u,h),D=h=>Ya(u,h),U=()=>{process.stdout.off("resize",fe),process.off("SIGCONT",ae),f.removeListener("key",w),f.removeListener("unknown",P),f.removeListener("mouse",D),u.scrollRenderTimer&&(clearTimeout(u.scrollRenderTimer),u.scrollRenderTimer=null),u.inspectionScrollRenderTimer&&(clearTimeout(u.inspectionScrollRenderTimer),u.inspectionScrollRenderTimer=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=h=>{U(),p(h)};let fe=()=>{Jn(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=()=>{Jn(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",P),f.on("mouse",D),u.prPollTimer=setInterval(()=>{qa(u)},(u.config.github?.watchIntervalSeconds??5)*1e3),g.version.checkForUpdate().then(h=>{h.updateAvailable&&h.latest&&(u.updateText=`Update available: v${h.latest}`,u.render())}),u.bootHydrationReady=Xn(u).catch(()=>{}),u.render()})}async function Xf(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Oi(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Fi(a),0}let e=ps(process.argv.slice(2)),t=process.cwd(),r=ne(t),n={paths:r};if(e.mode==="interactive")return await Qa({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await yo(e.command,n),o=Po(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 Zf=await Xf();process.exit(Zf);
|