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