craig-cli 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +52 -52
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await
|
|
4
|
-
`)};var
|
|
2
|
+
var Vl=Object.defineProperty;var Lt=(e,t)=>{for(var r in t)Vl(e,r,{get:t[r],enumerable:!0})};import{readFile as Ql}from"node:fs/promises";import{randomUUID as Kl}from"node:crypto";import{open as Hl,readFile as tg,rename as Gl,rm as zl}from"node:fs/promises";import xr from"node:path";async function N(e,t){let r=xr.dirname(e),n=xr.join(r,`.${xr.basename(e)}.${process.pid}.${Date.now()}.${Kl()}.tmp`),s=await Hl(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await Gl(n,e)}catch(o){throw await s.close().catch(()=>{}),await zl(n,{force:!0}).catch(()=>{}),o}}async function _e(e){try{let t=await Ql(e.uiStateFile,"utf8"),r=JSON.parse(t);return Yl(r,e.uiStateFile)}catch(t){if(Xl(t))return null;throw t}}async function Te(e,t){await N(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function jt(){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 Yl(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")||!We(e,"inputMode")||!We(e,"focusedRegion")||!We(e,"activeTab")||!We(e,"inspectorSection")||!We(e,"inspectionMode")||!Ot(e,"openInspectionKind")||!Ot(e,"selectedFileTreePath")||!Ot(e,"selectedFilePath")||!Ot(e,"selectedDiffPath")||!Jl(e,"collapsedFileTreePaths")||!We(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 We(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Ot(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Jl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function Xl(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Dr={};Lt(Dr,{RUNNER_IDS:()=>$,assertEnabled:()=>$s,buildCommand:()=>Os,getConfiguredProfile:()=>Ft,getDefault:()=>Ds,getDisplayName:()=>Ls,getEnabled:()=>Nt,getProfile:()=>Ue,isRunnerType:()=>Wt,parse:()=>Ms,setRunnerEnabled:()=>js,setRunnerPath:()=>Fs});var $=["codex","cursor","claude"];var xs={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 Ue=e=>xs[e];var Ft=(e,t={})=>{let r=Ue(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var Nt=(e={})=>$.filter(t=>e.runners?.[t]?.enabled!==!1);var Ds=(e={})=>{let t=Nt(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 $s=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var Wt=e=>$.includes(e);var Ms=e=>{if(!e||e.length===0)return"codex";if(!Wt(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${$.join(", ")}.`);return e};var Ls=e=>Ue(e).displayName;var Os=(e,t,r={})=>{let n=[Ft(e,r).executable];return t&&t.length>0&&n.push(t),n};var js=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var Fs=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};var $r={};Lt($r,{PREVIEW_FEATURE_IDS:()=>se,isEnabled:()=>Ns,setEnabled:()=>Ws});var se=["incrementalCenterPane"];function Ns(e,t){return e.previews?.[t]===!0}function Ws(e,t,r){return{...e,previews:{...e.previews,[t]:r}}}import{mkdir as Zl,readFile as ec,writeFile as tc}from"node:fs/promises";import rc from"node:path";var nc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",_s=async e=>{try{return await ec(e,"utf8")}catch(t){if(nc(t))return null;throw t}},Us=async(e,t)=>{await Zl(rc.dirname(e),{recursive:!0}),await tc(e,t,"utf8")};var _t=(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(!$.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${$.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" must be an object.`);let o=s;if(o.enabled!==void 0&&typeof o.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${n}.enabled" must be a boolean.`);if(o.path!==void 0&&(typeof o.path!="string"||o.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${n}.path" must be a non-empty string.`)}}if(r.checks!==void 0&&(typeof r.checks!="object"||r.checks===null||!Array.isArray(r.checks.commands)||!r.checks.commands.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(r.open!==void 0&&(typeof r.open!="object"||r.open===null||!Array.isArray(r.open.command)||!r.open.command.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}if(r.previews!==void 0){if(typeof r.previews!="object"||r.previews===null||Array.isArray(r.previews))throw new Error(`Craig config at ${t} is invalid. "previews" must be an object.`);for(let[n,s]of Object.entries(r.previews)){if(!se.includes(n))throw new Error(`Craig config at ${t} is invalid. "previews.${n}" is not supported. Expected one of: ${se.join(", ")}.`);if(typeof s!="boolean")throw new Error(`Craig config at ${t} is invalid. "previews.${n}" must be a boolean.`)}}return r};var Mr=async(e,t={readConfigFile:_s})=>{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 _t(n,e.configFile)};var Lr=async(e,t,r={writeConfigFile:Us})=>{_t(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var Or={};Lt(Or,{checkForUpdate:()=>qs,getCurrent:()=>Ut});var Ut=()=>{try{return"0.8.3"}catch{return"unknown"}};var sc="https://registry.npmjs.org/craig-cli/latest",oc=3600*1e3,ic={value:null},ac=(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},qs=async(e={fetch:globalThis.fetch,getCurrent:Ut,cache:ic})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<oc)return e.cache.value.result;let n=null;try{let o=await e.fetch(sc,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&ac(n,t)};return e.cache.value={result:s,cachedAt:r},s};var h={load:Mr,save:Lr,previews:$r,runners:Dr,version:Or};function Bs(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
|
|
5
5
|
|
|
6
|
-
`+
|
|
6
|
+
`+H());return{mode:"command",command:{kind:"addRepo",path:r}}}if(t.length>=3&&t[0]==="workspace"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Workspace path cannot be empty.
|
|
7
7
|
|
|
8
|
-
`+
|
|
8
|
+
`+H());return{mode:"command",command:{kind:"addWorkspace",path:r}}}if(t.length===2&&t[0]==="repo"&&t[1]==="list")return{mode:"command",command:{kind:"listRepos"}};if(t.length===3&&t[0]==="repo"&&t[1]==="remove")return{mode:"command",command:{kind:"removeRepo",repoId:t[2].trim()}};if(t.length>=2&&t.length<=3&&t[0]==="workspace"&&t[1]==="list"){let r=t[2]==="--archived";if(t.length===3&&!r)throw new Error(`Unsupported command: ${t.join(" ")}
|
|
9
9
|
|
|
10
|
-
${
|
|
10
|
+
${H()}`);return{mode:"command",command:{kind:"listWorkspaces",archived:r}}}if(t.length===3&&t[0]==="workspace"&&t[1]==="archive")return{mode:"command",command:{kind:"archiveWorkspace",workspaceId:t[2].trim()}};if(t.length===3&&t[0]==="workspace"&&t[1]==="restore")return{mode:"command",command:{kind:"restoreWorkspace",workspaceId:t[2].trim()}};if(t.length===3&&t[0]==="workspace"&&t[1]==="remove")return{mode:"command",command:{kind:"removeWorkspace",workspaceId:t[2].trim()}};if(t.length>=2&&t[0]==="task"&&t[1]==="new"){let r=t.indexOf("--repo"),n=t.indexOf("--workspace"),s=t.indexOf("--runner");if(r===-1&&n===-1)throw new Error(`Task creation now requires '--repo <repo-id>' or '--workspace <workspace-id>'.
|
|
11
11
|
|
|
12
|
-
`+
|
|
12
|
+
`+H());if(r!==-1&&n!==-1)throw new Error(`Task creation accepts either '--repo' or '--workspace', not both.
|
|
13
13
|
|
|
14
|
-
`+
|
|
14
|
+
`+H());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,u)=>u>1&&u!==r&&u!==r+1&&u!==n&&u!==n+1&&u!==s&&u!==s+1).join(" ").trim();if(o!==void 0&&o.length===0)throw new Error(`Repo id cannot be empty.
|
|
15
15
|
|
|
16
|
-
`+
|
|
16
|
+
`+H());if(i!==void 0&&i.length===0)throw new Error(`Workspace id cannot be empty.
|
|
17
17
|
|
|
18
|
-
`+
|
|
18
|
+
`+H());if(c.length===0)throw new Error(`Task prompt cannot be empty.
|
|
19
19
|
|
|
20
|
-
`+
|
|
20
|
+
`+H());return{mode:"command",command:{kind:"createTask",...o?{repoId:o}:{},...i?{workspaceId:i}:{},prompt:c,...a?{runner:a}:{}}}}if(t.length>=2&&t.length<=4&&t[0]==="task"&&t[1]==="list"){if(t.length===2)return{mode:"command",command:{kind:"listTasks"}};if(t.length===4&&t[2]==="--repo")return{mode:"command",command:{kind:"listTasks",repoId:t[3].trim()}};throw new Error(`Unsupported command: ${t.join(" ")}
|
|
21
21
|
|
|
22
|
-
${
|
|
22
|
+
${H()}`)}if(t.length===3&&t[0]==="task"&&t[1]==="attach")return{mode:"command",command:{kind:"attachTask",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="show")return{mode:"command",command:{kind:"showTask",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="logs")return{mode:"command",command:{kind:"streamTaskLogs",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="diff")return{mode:"command",command:{kind:"showTaskDiff",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="focus")return{mode:"command",command:{kind:"focusTask",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="open")return{mode:"command",command:{kind:"openTask",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="check")return{mode:"command",command:{kind:"runChecks",taskId:le(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="commit")return{mode:"command",command:{kind:"commitTask",taskId:le(t[2])}};if(t.length===4&&t[0]==="link"&&t[1]==="add")return{mode:"command",command:{kind:"addTaskLink",taskId:le(t[2]),repoId:lc(t[3])}};if(t.length===3&&t[0]==="link"&&t[1]==="list")return{mode:"command",command:{kind:"listTaskLinks",taskId:le(t[2])}};throw new Error(`Unsupported command: ${t.join(" ")}
|
|
23
23
|
|
|
24
|
-
${
|
|
24
|
+
${H()}`)}function H(){return["Craig commands:"," craig Show the Craig phase 0 placeholder"," craig repo add Register a repo in the current Craig workspace"," craig workspace add <path> Register a repo or parent-directory workspace"," craig repo list List registered repos"," craig repo remove Remove a registered repo"," craig workspace list List active workspaces"," craig workspace list --archived List archived workspaces"," craig workspace archive Archive a workspace"," craig workspace restore Restore an archived workspace"," craig workspace remove Remove an archived workspace"," craig task new --repo <repo-id> [--runner codex|cursor|claude] <prompt> Create a new Craig repo task"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude] <prompt> Create a new Craig workspace task"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task show Show details for a Craig task"," craig task logs Stream Craig-managed logs for a task"," craig task diff Show the current worktree diff for a task"," craig task attach Attach to a live task session"," craig task focus Focus the tmux pane for a task"," craig task open Open the task worktree or print its path"," craig task check Run configured checks for a task"," craig task commit Commit all task worktree changes"," craig link add Add a linked repo to a task"," craig link list List linked repos for a task"].join(`
|
|
25
25
|
`)}function le(e){let t=e.trim();if(t.length===0)throw new Error(`Task id cannot be empty.
|
|
26
26
|
|
|
27
|
-
${
|
|
27
|
+
${H()}`);return t}function lc(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
28
28
|
|
|
29
|
-
${V()}`);return t}var _=(e,t)=>{let r=xr(e);if(!Zl(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},xr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Dr(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:rc(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:ec(t.repoTargets),runnerSession:t.runnerSession??Xl(t),checks:cc(t),lastCommit:t.lastCommit??null,prs:dc(t),artifacts:fc(t),cleanup:gc(t)}},Xl=e=>{if(typeof e.title!="string")return null;let t=Dr(e.runner);return{command:h.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Zl=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"&&Ws(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||tc(t.repoTargets))&&sc(t.runnerSession)&&oc(t.prompt)&&_s(t.checks)&&qs(t.lastCommit)&&ac(t.prs)&&lc(t.artifacts)&&Bs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},ec=e=>{if(Array.isArray(e))return e.filter(Ns)},tc=e=>Array.isArray(e)&&e.every(Ns),Ns=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)&&_s(t.checks)&&qs(t.lastCommit)&&Us(t.pullRequest)&&Bs(t.cleanup)},rc=e=>{if(Ws(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 nc(e.id,e.title,t,Dr(e.runner))},nc=(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}]},Dr=e=>e&&h.runners.isRunnerType(e)?e:"codex",Ws=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"),sc=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),oc=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",_s=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",Us=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&ic(e.requiredChecks),ic=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)),ac=e=>Array.isArray(e)&&e.every(Us),lc=e=>typeof e=="object"&&e!==null&&(typeof e.logPath=="string"||e.logPath===null)&&(typeof e.checkSummaryPath=="string"||e.checkSummaryPath===null)&&(typeof e.prDraftPath=="string"||e.prDraftPath===null)&&(typeof e.prStatusPath=="string"||e.prStatusPath===null),Bs=e=>typeof e=="object"&&e!==null&&(typeof e.paneClosedAt=="string"||e.paneClosedAt===null)&&(typeof e.worktreeRemovedAt=="string"||e.worktreeRemovedAt===null)&&typeof e.preservedWorktree=="boolean"&&(typeof e.warning=="string"||e.warning===null),cc=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},dc=e=>{if(Array.isArray(e.prs))return e.prs.map(uc);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Ks(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Vs(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},uc=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:Ks(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:pc(t.reviewDecision),requiredChecks:Vs(t.requiredChecks),comments:mc(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Ks=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,pc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,mc=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}]}):[],Vs=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})):[],fc=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},gc=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as Nc}from"node:fs/promises";import{readFile as hc,readdir as wc,rm as kc}from"node:fs/promises";import Gs from"node:path";var $r=(e,t)=>Gs.join(e.workspacesDir,`${t}.json`),Tc=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"):[]}},Hs=(e,t)=>{let r=Tc(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},Ee=async(e,t)=>{let r=$r(e,t),n=await hc(r,"utf8");return Hs(JSON.parse(n),r)},Ae=async(e,t)=>{await F($r(e,t.id),{...t,updatedAt:new Date().toISOString()})},J=async e=>{let t=await wc(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Ee(e,Gs.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},zs=async(e,t)=>{await kc($r(e,t),{force:!0})};import{readFile as Rc,readdir as yc,rm as Pc}from"node:fs/promises";import Qs from"node:path";var Mr=(e,t)=>Qs.join(e.reposDir,`${t}.json`),Ys=(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},Z=async(e,t)=>{let r=Mr(e,t),n=await Rc(r,"utf8");return Ys(JSON.parse(n),r)},Lr=async(e,t)=>{await F(Mr(e,t.id),{...t,updatedAt:new Date().toISOString()})},ot=async e=>{let t=await yc(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Z(e,Qs.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Js=async(e,t)=>{await Pc(Mr(e,t),{force:!0})};import{readFile as bc}from"node:fs/promises";var Sc=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"},qt=(e,t,r)=>{if(!Sc(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},G=async e=>{let t=await bc(e.indexFile,"utf8");return qt(JSON.parse(t),e.workspaceRoot,e.indexFile)},me=async(e,t)=>{await F(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as Ac,stat as xc}from"node:fs/promises";import Ke from"node:path";import{realpath as eo}from"node:fs/promises";import to from"node:path";import{execFile as Ic}from"node:child_process";import{promisify as Cc}from"node:util";var Xs=Cc(Ic);async function y(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(Zs(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function x(e,t,r={}){try{let n=await Xs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Zs(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Zs(e){return e instanceof Error}var jr=async e=>{try{let r=(await y("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([eo(r).catch(()=>to.resolve(r)),eo(e).catch(()=>to.resolve(e))]);return n===s}catch{return!1}},Or=async e=>{let t=await x("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await y("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as de,readFile as vc}from"node:fs/promises";import H from"node:path";function ce(e){let t=H.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:H.join(t,"index.json"),reposDir:H.join(t,"repos"),workspacesDir:H.join(t,"workspaces"),sessionsDir:H.join(t,"sessions"),runtimeDir:H.join(t,"runtime"),uiStateFile:H.join(t,"runtime","ui-state.json"),tasksDir:H.join(t,"tasks"),jobsDir:H.join(t,"jobs"),logsDir:H.join(t,"logs"),errorLogFile:H.join(t,"logs","errors.log"),artifactsDir:H.join(t,"artifacts"),worktreesDir:H.join(t,"worktrees"),configFile:H.join(t,"config.json")}}var Ec=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Be=async e=>{let t=ce(e);await de(t.craigDir,{recursive:!0}),await Promise.all([de(t.reposDir,{recursive:!0}),de(t.workspacesDir,{recursive:!0}),de(t.sessionsDir,{recursive:!0}),de(t.runtimeDir,{recursive:!0}),de(t.tasksDir,{recursive:!0}),de(t.jobsDir,{recursive:!0}),de(t.logsDir,{recursive:!0}),de(t.artifactsDir,{recursive:!0}),de(t.worktreesDir,{recursive:!0})]);try{let s=await vc(t.indexFile,"utf8"),o=JSON.parse(s);return qt(o,e,t.indexFile)}catch(s){if(!Ec(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 F(t.indexFile,n),n};var ro=(e,t,r)=>{let n=new Date().toISOString();return{id:Dc(e,Ke.basename(t)),name:Ke.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},no=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},Dc=(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},$c=(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},so=async(e,t)=>{let r=await G(e);await me(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},Mc=async(e,t)=>{let r=await Ac(t,{withFileTypes:!0}),n=await ot(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ke.join(t,o.name);if(!await jr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await Or(i);s.push(a?no(a,l):ro([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},Lc=async(e,t)=>{let r=await Or(t),n=await ot(e),s=n.find(u=>u.rootPath===t)??null,o=s?no(s,r):ro(n,t,r),i=`workspace_${o.id}`,l=(await J(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await Lr(e,o),l||await Ae(e,d),await so(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},jc=async(e,t)=>{let r=await Mc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await J(e),s=$c(n,Ke.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:Ke.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=>Lr(e,c))),await Ae(e,l),await so(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},it=async(e,t)=>{await Be(e.workspaceRoot);let r=Ke.resolve(e.workspaceRoot,t);if(!(await xc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await jr(r)?Lc(e,r):jc(e,r)};var Fr=async(e,t,r={listWorkspaceRecords:J,ensureCraigState:Be})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Nr=async(e,t,r={readWorkspace:Ee,writeWorkspace:Ae})=>{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 Wr=async(e,t)=>{let n={...await Ee(e,t),status:"active",archivedAt:null};await Ae(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 xe=async(e,t,r={deleteWorkspace:zs,readCraigIndex:G,writeCraigIndex:me})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var _r=async(e,t,r)=>{let n=await Ee(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 xe(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var qr={};Mt(qr,{addRepo:()=>oo,listRegisteredRepos:()=>io,removeRepo:()=>ao});import Oc from"node:path";import{stat as Fc}from"node:fs/promises";var oo=async(e,t)=>{let r=Oc.resolve(e.workspaceRoot,t);if(!(await Fc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await it(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 io=async(e,t={listRepos:ot,ensureCraigState:Be})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var ao=async(e,t,r)=>{let n=await Z(e,t),o=(await J(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=>xe(e,c.id))),await Js(e,t);let l=await G(e);return await me(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var z={addWorkspace:it,listWorkspaces:Fr,archiveWorkspace:Nr,restoreWorkspace:Wr,removeWorkspace:_r,removeWorkspaceRecord:xe,repos:qr};var Q=async(e,t)=>{let r=await Nc(Br(e,t),"utf8");return JSON.parse(r)},X=async(e,t)=>{let r=await Q(e,t);return _(r,Br(e,t))},P=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await F(Br(e,t.id),r)},Ur=async(e,t)=>{let r=await G(e);r.taskIds.includes(t)||await me(e,{...r,taskIds:[...r.taskIds,t]})},Br=(e,t)=>`${e.tasksDir}/${t}.json`;var D=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,Re=e=>e.status==="merged"||e.status==="closed",Ve=(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}},at=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Bt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Bt=e=>e.mergeable&&!Wc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),Wc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Kr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),lt=(e,t)=>{let r=e.isDraft??!1,n=_c(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:qc(e.reviewDecision??null),requiredChecks:ct(e.statusCheckRollup),comments:Vc(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}},_c=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,qc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,ct=e=>{let t=e.map(n=>Uc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||Bc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},Uc=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:co(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:Kc(t)}:null},Bc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Ut(e)&&!Ut(t)?!0:!Ut(e)&&Ut(t)?!1:lo(t.status)>=lo(e.status),Ut=e=>e.conclusion?.toUpperCase()==="CANCELLED",lo=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},Kc=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},Vc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Gc).filter(r=>r!==null).slice(-4):[]},Gc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=Hc(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},Hc=e=>e.replace(/\s+/g," ").trim(),co=(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?co(n,n):"unknown"};import{access as zc}from"node:fs/promises";import uo from"node:path";var I=async(e,t,r={readRawTask:Q,validateTaskRecord:_})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Zc(n)?new Error(`Craig task "${t}" was not found.`):n}},q=async e=>{if(!await Vr(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},Ge=(e,t)=>t.artifacts.logPath?uo.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:uo.join(e.workspaceRoot,t.artifacts.logPath):null,dt=async(e,t)=>{let r=await Vr(t.worktreePath),n=Ge(e,t),s=n?await Vr(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Qc(t),lastCommitSummary:Yc(t),prSummary:Jc(t),cleanupSummary:Xc(t)}},Vr=async e=>{try{return await zc(e),!0}catch{return!1}},Qc=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",Jc=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
29
|
+
${H()}`);return t}var U=(e,t)=>{let r=jr(e);if(!dc(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},jr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Fr(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:mc(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:uc(t.repoTargets),runnerSession:t.runnerSession??cc(t),checks:Rc(t),lastCommit:t.lastCommit??null,prs:yc(t),artifacts:Ic(t),cleanup:Cc(t)}},cc=e=>{if(typeof e.title!="string")return null;let t=Fr(e.runner);return{command:h.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},dc=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"&&Ks(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||pc(t.repoTargets))&&gc(t.runnerSession)&&hc(t.prompt)&&Hs(t.checks)&&Gs(t.lastCommit)&&kc(t.prs)&&Tc(t.artifacts)&&Qs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},uc=e=>{if(Array.isArray(e))return e.filter(Vs)},pc=e=>Array.isArray(e)&&e.every(Vs),Vs=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)&&Hs(t.checks)&&Gs(t.lastCommit)&&zs(t.pullRequest)&&Qs(t.cleanup)},mc=e=>{if(Ks(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 fc(e.id,e.title,t,Fr(e.runner))},fc=(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}]},Fr=e=>e&&h.runners.isRunnerType(e)?e:"codex",Ks=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"),gc=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),hc=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Hs=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"),Gs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",zs=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&wc(e.requiredChecks),wc=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)),kc=e=>Array.isArray(e)&&e.every(zs),Tc=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),Qs=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),Rc=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},yc=e=>{if(Array.isArray(e.prs))return e.prs.map(bc);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:Js(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},bc=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:Pc(t.reviewDecision),requiredChecks:Js(t.requiredChecks),comments:Sc(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,Pc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Sc=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}]}):[],Js=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})):[],Ic=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Cc=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as Qc}from"node:fs/promises";import{readFile as vc,readdir as Ec,rm as Ac}from"node:fs/promises";import Xs from"node:path";var Nr=(e,t)=>Xs.join(e.workspacesDir,`${t}.json`),xc=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"):[]}},Zs=(e,t)=>{let r=xc(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},ve=async(e,t)=>{let r=Nr(e,t),n=await vc(r,"utf8");return Zs(JSON.parse(n),r)},Ee=async(e,t)=>{await N(Nr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Z=async e=>{let t=await Ec(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>ve(e,Xs.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},eo=async(e,t)=>{await Ac(Nr(e,t),{force:!0})};import{readFile as Dc,readdir as $c,rm as Mc}from"node:fs/promises";import to from"node:path";var Wr=(e,t)=>to.join(e.reposDir,`${t}.json`),ro=(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},te=async(e,t)=>{let r=Wr(e,t),n=await Dc(r,"utf8");return ro(JSON.parse(n),r)},_r=async(e,t)=>{await N(Wr(e,t.id),{...t,updatedAt:new Date().toISOString()})},nt=async e=>{let t=await $c(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>te(e,to.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},no=async(e,t)=>{await Mc(Wr(e,t),{force:!0})};import{readFile as Lc}from"node:fs/promises";var Oc=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"},qt=(e,t,r)=>{if(!Oc(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},G=async e=>{let t=await Lc(e.indexFile,"utf8");return qt(JSON.parse(t),e.workspaceRoot,e.indexFile)},pe=async(e,t)=>{await N(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as _c,stat as Uc}from"node:fs/promises";import Be from"node:path";import{realpath as io}from"node:fs/promises";import ao from"node:path";import{execFile as jc}from"node:child_process";import{promisify as Fc}from"node:util";var so=Fc(jc);async function y(e,t,r={}){try{let n=await so(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(oo(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function x(e,t,r={}){try{let n=await so(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(oo(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function oo(e){return e instanceof Error}var Ur=async e=>{try{let r=(await y("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([io(r).catch(()=>ao.resolve(r)),io(e).catch(()=>ao.resolve(e))]);return n===s}catch{return!1}},qr=async e=>{let t=await x("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await y("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as de,readFile as Nc}from"node:fs/promises";import z from"node:path";function ce(e){let t=z.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:z.join(t,"index.json"),reposDir:z.join(t,"repos"),workspacesDir:z.join(t,"workspaces"),sessionsDir:z.join(t,"sessions"),runtimeDir:z.join(t,"runtime"),uiStateFile:z.join(t,"runtime","ui-state.json"),tasksDir:z.join(t,"tasks"),jobsDir:z.join(t,"jobs"),logsDir:z.join(t,"logs"),errorLogFile:z.join(t,"logs","errors.log"),artifactsDir:z.join(t,"artifacts"),worktreesDir:z.join(t,"worktrees"),configFile:z.join(t,"config.json")}}var Wc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",qe=async e=>{let t=ce(e);await de(t.craigDir,{recursive:!0}),await Promise.all([de(t.reposDir,{recursive:!0}),de(t.workspacesDir,{recursive:!0}),de(t.sessionsDir,{recursive:!0}),de(t.runtimeDir,{recursive:!0}),de(t.tasksDir,{recursive:!0}),de(t.jobsDir,{recursive:!0}),de(t.logsDir,{recursive:!0}),de(t.artifactsDir,{recursive:!0}),de(t.worktreesDir,{recursive:!0})]);try{let s=await Nc(t.indexFile,"utf8"),o=JSON.parse(s);return qt(o,e,t.indexFile)}catch(s){if(!Wc(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 N(t.indexFile,n),n};var lo=(e,t,r)=>{let n=new Date().toISOString();return{id:qc(e,Be.basename(t)),name:Be.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},co=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},qc=(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},Bc=(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},uo=async(e,t)=>{let r=await G(e);await pe(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},Vc=async(e,t)=>{let r=await _c(t,{withFileTypes:!0}),n=await nt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Be.join(t,o.name);if(!await Ur(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await qr(i);s.push(a?co(a,l):lo([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},Kc=async(e,t)=>{let r=await qr(t),n=await nt(e),s=n.find(u=>u.rootPath===t)??null,o=s?co(s,r):lo(n,t,r),i=`workspace_${o.id}`,l=(await Z(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await _r(e,o),l||await Ee(e,d),await uo(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},Hc=async(e,t)=>{let r=await Vc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Z(e),s=Bc(n,Be.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:Be.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=>_r(e,c))),await Ee(e,l),await uo(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},st=async(e,t)=>{await qe(e.workspaceRoot);let r=Be.resolve(e.workspaceRoot,t);if(!(await Uc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Ur(r)?Kc(e,r):Hc(e,r)};var Br=async(e,t,r={listWorkspaceRecords:Z,ensureCraigState:qe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Vr=async(e,t,r={readWorkspace:ve,writeWorkspace:Ee})=>{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 Kr=async(e,t)=>{let n={...await ve(e,t),status:"active",archivedAt:null};await Ee(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 Ae=async(e,t,r={deleteWorkspace:eo,readCraigIndex:G,writeCraigIndex:pe})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Hr=async(e,t,r)=>{let n=await ve(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await Ae(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Gr={};Lt(Gr,{addRepo:()=>po,listRegisteredRepos:()=>mo,removeRepo:()=>fo});import Gc from"node:path";import{stat as zc}from"node:fs/promises";var po=async(e,t)=>{let r=Gc.resolve(e.workspaceRoot,t);if(!(await zc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await st(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 mo=async(e,t={listRepos:nt,ensureCraigState:qe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var fo=async(e,t,r)=>{let n=await te(e,t),o=(await Z(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=>Ae(e,c.id))),await no(e,t);let l=await G(e);return await pe(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Q={addWorkspace:st,listWorkspaces:Br,archiveWorkspace:Vr,restoreWorkspace:Kr,removeWorkspace:Hr,removeWorkspaceRecord:Ae,repos:Gr};var Y=async(e,t)=>{let r=await Qc(Qr(e,t),"utf8");return JSON.parse(r)},ee=async(e,t)=>{let r=await Y(e,t);return U(r,Qr(e,t))},b=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await N(Qr(e,t.id),r)},zr=async(e,t)=>{let r=await G(e);r.taskIds.includes(t)||await pe(e,{...r,taskIds:[...r.taskIds,t]})},Qr=(e,t)=>`${e.tasksDir}/${t}.json`;var D=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,Re=e=>e.status==="merged"||e.status==="closed",Ve=(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}},ot=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Vt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Vt=e=>e.mergeable&&!Yc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),Yc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Yr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),it=(e,t)=>{let r=e.isDraft??!1,n=Jc(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:Xc(e.reviewDecision??null),requiredChecks:at(e.statusCheckRollup),comments:rd(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}},Jc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Xc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,at=e=>{let t=e.map(n=>Zc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||ed(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},Zc=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:ho(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:td(t)}:null},ed=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Bt(e)&&!Bt(t)?!0:!Bt(e)&&Bt(t)?!1:go(t.status)>=go(e.status),Bt=e=>e.conclusion?.toUpperCase()==="CANCELLED",go=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},td=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},rd=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(nd).filter(r=>r!==null).slice(-4):[]},nd=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=sd(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},sd=e=>e.replace(/\s+/g," ").trim(),ho=(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?ho(n,n):"unknown"};import{access as od}from"node:fs/promises";import wo from"node:path";var I=async(e,t,r={readRawTask:Y,validateTaskRecord:U})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw dd(n)?new Error(`Craig task "${t}" was not found.`):n}},q=async e=>{if(!await Jr(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},Ke=(e,t)=>t.artifacts.logPath?wo.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:wo.join(e.workspaceRoot,t.artifacts.logPath):null,lt=async(e,t)=>{let r=await Jr(t.worktreePath),n=Ke(e,t),s=n?await Jr(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:id(t),lastCommitSummary:ad(t),prSummary:ld(t),cleanupSummary:cd(t)}},Jr=async e=>{try{return await od(e),!0}catch{return!1}},id=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}`},ad=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",ld=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=D(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},
|
|
32
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},
|
|
31
|
+
`)}`}let t=D(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})`},cd=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",dd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var ko=async(e,t)=>{let r=await x("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 x("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 ud(e,s);await y("git",["worktree","add","-b",t,r,i],{cwd:e})},ud=async(e,t)=>(await x("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await x("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await x("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,Kt=async e=>{let t=await x("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},To=async e=>{await y("git",["add","-A"],{cwd:e})},Ro=async(e,t)=>{await y("git",["commit","-m",t],{cwd:e})},yo=async e=>{let t=await y("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}},bo=async e=>{let t=await x("git",["branch","--show-current"],{cwd:e});if(t.exitCode!==0)return null;let r=t.stdout.trim();return r.length>0?r:null};var Po=async(e,t)=>{await y("git",["worktree","remove","--force",t],{cwd:e})};var Zr=async e=>He(e,e.repoRoot),He=async(e,t)=>{let r=await G(e),n=So(new Date),s=Io(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await ko(t,i))return o;s+=1}},ct=async e=>{let t=await G(e),r=So(new Date),n=Io(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},So=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},Io=(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 en=async(e,t,r={readRawTask:Y,validateTaskRecord:U})=>{let n=await G(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(pd(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}},pd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Co=["merge_ready","pr_open","checked","review","running","draft"],tn=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),rn=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(md)[0]?.id??null,md=(e,t)=>{let r=vo(e.status),n=vo(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},vo=e=>{let t=Co.indexOf(e);return t>=0?t:Co.length};import Eo from"node:path";var xe=(e,t)=>t?Eo.isAbsolute(t)?t:Eo.join(e.repoRoot,t):null;import{mkdir as dt,rm as fd,writeFile as Ht}from"node:fs/promises";import E from"node:path";var xo=["AGENTS","md"].join("."),Ge=async(e,t,r,n={})=>{let s=await te(e,t),o=await Td(e,s.id),i=await He(e,s.rootPath),a=n.sessionId??null,l=`craig/${i}`,c=E.join(e.worktreesDir,s.id,i),d=E.join(e.logsDir,`${i}.log`),u=E.join(e.artifactsDir,i);await dt(E.dirname(c),{recursive:!0}),await dt(u,{recursive:!0}),await Ht(d,"","utf8");let p=gd(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 b(e,p),await zr(e,i),await Xr(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:p}},ut=async(e,t,r,n={})=>{let s=(await Z(e)).find(S=>S.id===t&&S.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 S=await Ge(e,s.primaryRepoId,r,n);return{...S,bundlePath:S.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await ct(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,u=E.join(e.craigDir,"task-bundles",i),p=E.join(e.logsDir,`${i}.log`),m=E.join(e.artifactsDir,i);await dt(u,{recursive:!0}),await dt(m,{recursive:!0}),await Ht(p,"","utf8");let k=await Promise.all(o.map(S=>te(e,S))),R=wd(k),A=await Promise.all(k.map(S=>hd(e,S,i,d,E.join(u,R.get(S.id))))),K=A.find(S=>S.status==="ready")??A[0];if(!A.some(S=>S.status==="ready"))throw await fd(u,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${A.map(S=>`${S.repoId}: ${S.failureReason??"unknown error"}`).join("; ")}`);await Ht(E.join(u,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:A.map(S=>({repoId:S.repoId,repoName:k.find(ne=>ne.id===S.repoId)?.name??S.repoId,path:E.relative(u,S.worktreePath),status:S.status,worktreePath:S.worktreePath,failureReason:S.failureReason}))},null,2),"utf8"),await Ht(E.join(u,xo),kd({taskId:i,workspaceId:t,prompt:r,repos:k,repoTargets:A,bundlePath:u}),"utf8");let f=pt(i,r,a,l,n.config??{}),we={id:i,title:r,slug:Do(r),type:"project",status:"draft",runner:l,repoId:K.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:f[0]?.id??null,linkedRepoIds:o.filter(S=>S!==K.repoId),repoRoot:u,worktreePath:u,branch:d,bundlePath:u,selectedRepoTargetId:K.repoId,repoTargets:A,ptyTabs:f,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:K.checks,lastCommit:null,prs:[],artifacts:{logPath:E.relative(e.workspaceRoot,p),checkSummaryPath:E.relative(e.workspaceRoot,E.join(m,"check-summary.json")),prDraftPath:null,prStatusPath:E.relative(e.workspaceRoot,E.join(m,"pr-status.json"))},cleanup:Gt(),lastFailureReason:A.every(S=>S.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await b(e,we),await zr(e,i),{repoId:K.repoId,repoRoot:u,sessionId:c,workspaceId:s.id,task:we,bundlePath:u,repoTargets:A}},pt=(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}]},gd=(e,t)=>{let r=new Date().toISOString(),n=pt(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:Do(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:{...nn(E.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:E.relative(e.workspaceRoot,E.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:E.relative(e.workspaceRoot,E.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:E.relative(e.workspaceRoot,E.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:Gt(),lastFailureReason:null,createdAt:r,updatedAt:r}},hd=async(e,t,r,n,s)=>{await dt(E.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:nn(E.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Ao(),cleanup:Gt()}}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:nn(E.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Ao(),cleanup:Gt()}}},wd=e=>{let t=new Set(["manifest.json",xo]),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},kd=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=E.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
|
-
`)},Jr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),bo=()=>({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}),Gt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),ld=async(e,t)=>{let n=(await J(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},Io=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import Oo from"node:path";import{readFile as cd,rm as nk}from"node:fs/promises";import dd from"node:path";var ye=async(e,t)=>{let r=await cd(Xr(e,t),"utf8"),n=JSON.parse(r);return ud(n,Xr(e,t))},$e=async(e,t)=>{await F(Xr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Xr=(e,t)=>dd.join(e.sessionsDir,`${t}.json`);function ud(e,t){let r=fd(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")||!md(r.attach)||!pd(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 pd(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 md(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 fd(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 gd}from"node:child_process";import{createHash as hd}from"node:crypto";import wd from"node:path";function Ht(e){return`'${e.replace(/'/g,"'\\''")}'`}var kd="craig",Co=async(e,t,r)=>{let n=Zr(e,t),s=Rd(),o=await y("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Pd(o.stdout);return await Td(e,n),i};var Td=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 y("tmux",n,{cwd:e})},vo=async(e,t,r)=>{await y("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},Eo=async(e,t,r)=>{await y("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var Ao=async(e,t,r)=>{await y("tmux",["pipe-pane","-o","-t",e,`cat >> ${Ht(t)}`],{cwd:r})},zt=async(e,t,r,n)=>{let s=n??Do(e);if(r?await y("tmux",["select-window","-t",r],{cwd:e}):await y("tmux",["select-window","-t",t],{cwd:e}),await y("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await y("tmux",["switch-client","-t",s],{cwd:e});return}await Sd(e,["attach-session","-t",s])};var xo=async(e,t)=>{await y("tmux",["kill-session","-t",t],{cwd:e})};var Do=e=>{let r=wd.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=hd("sha1").update(e).digest("hex").slice(0,8);return`${kd}-${r}-${n}`},Zr=(e,t)=>`${Do(e)}-${t.toLowerCase()}`,Rd=()=>{let e=yd();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},yd=()=>{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},Pd=e=>{let t=bd(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]}},bd=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Sd=async(e,t)=>{await new Promise((r,n)=>{let s=gd("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 Id,constants as Cd}from"node:fs";import{homedir as $o}from"node:os";import Pe from"node:path";var vd=[Pe.join($o(),".local","bin"),Pe.join($o(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function Lo(e=process.env){return Ed([...(e.PATH??"").split(Pe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:vd])}function Me(e=process.env){return{...e,PATH:Lo(e).join(Pe.delimiter)}}function en(e,t={}){if(e.includes(Pe.sep)){let r=Pe.isAbsolute(e)?e:Pe.resolve(t.cwd??process.cwd(),e);return Mo(r)?r:null}for(let r of Lo(t.env)){let n=Pe.join(r,e);if(Mo(n))return n}return null}function Le(e,t={}){let r=en(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 Mo(e){try{return Id(e,Cd.X_OK),!0}catch{return!1}}function Ed(e){return[...new Set(e)]}var gt={async create(e,t){let r=await Co(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Ao(r.paneId,t.logPath,t.repoRoot);let n=await jo({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||Zr(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 $e(e,s),s},async attach(e,t,r){let n=await gt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await zt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await $e(e,s),s},async resize(e,t,r,n){await vo(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await $e(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 $e(e,n),n},async snapshot(e,t){return Ad(e,t)}},tn={async prepare(e,t){let n=e.runnerSession.command[0],s=Me();await y(Le(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Le(r[0],{cwd:e.worktreePath,env:Me()});await Eo(t.session.paneId,[n,...r.slice(1)].map(s=>Ht(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},Ad=async(e,t)=>{let r=await x("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return jo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},jo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var rn=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 mt(e,n.workspaceId,s,{runner:i,config:o}):await ze(e,t,s,{runner:i,config:o}),l=a.task,c=h.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?Oo.resolve(e.workspaceRoot,l.artifacts.logPath):Oo.join(e.logsDir,`${l.id}.log`);try{await tn.prepare(l,{repoRoot:a.repoRoot});let p=await gt.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await tn.launch(l,{repoRoot:a.repoRoot,session:p});let f=new Date().toISOString();p={...p,status:"running",startedAt:f,command:c};let k={...l,status:"running",runner:i,sessionId:p.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:p.command,pid:null,startedAt:f,lastKnownState:"running",exitCode:null,exitedAt:null}};return await P(e,k),await $e(e,p),{kind:"createTask",taskId:k.id,repoId:k.repoId,workspaceId:k.workspaceId,sessionId:p.id,status:k.status,branch:k.branch,worktreePath:k.worktreePath,runner:k.runner}}catch(p){let f={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:p instanceof Error?p.message:"Unknown Craig error"};throw await P(e,f),p}};import{mkdir as Wd}from"node:fs/promises";import _d from"node:path";var Fo=3,xd=1e3,Dd=1e4,Qe=async e=>{let t=await x("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var No=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await y("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Qt=async(e,t)=>{let r=await y("gh",qo(e),{cwd:t});return JSON.parse(r.stdout)},Ye=async(e,t)=>{let r=await x("gh",qo(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Wo=async(e,t,r)=>{if(r.length===0)return[];let n=Fd(r),s=await $d(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=Nd(c);return{id:a.id,found:d!==null,view:d}})},_o=async e=>{let t=await x("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:Od(t.stdout.trim())},$d=async(e,t)=>{let r;for(let n=0;n<=Fo;n+=1)try{return await y("gh",t,{cwd:e})}catch(s){if(r=s,n===Fo||!Md(s))throw s;await jd(Ld(n))}throw r},Md=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")},Ld=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||xd,r=Math.min(t*2**e,Dd),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},jd=e=>new Promise(t=>setTimeout(t,e)),qo=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],Od=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
|
+
`)},nn=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Ao=()=>({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}),Gt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),Td=async(e,t)=>{let n=(await Z(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},Do=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import qo from"node:path";import{readFile as Rd,rm as Tk}from"node:fs/promises";import yd from"node:path";var ye=async(e,t)=>{let r=await Rd(sn(e,t),"utf8"),n=JSON.parse(r);return bd(n,sn(e,t))},De=async(e,t)=>{await N(sn(e,t.id),{...t,updatedAt:new Date().toISOString()})};var sn=(e,t)=>yd.join(e.sessionsDir,`${t}.json`);function bd(e,t){let r=Id(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")||!Sd(r.attach)||!Pd(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 Pd(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 Sd(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 Id(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 Cd}from"node:child_process";import{createHash as vd}from"node:crypto";import Ed from"node:path";function zt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Ad="craig",$o=async(e,t,r)=>{let n=on(e,t),s=Dd(),o=await y("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Md(o.stdout);return await xd(e,n),i};var xd=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 y("tmux",n,{cwd:e})},Mo=async(e,t,r)=>{await y("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},Lo=async(e,t,r)=>{await y("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var Oo=async(e,t,r)=>{await y("tmux",["pipe-pane","-o","-t",e,`cat >> ${zt(t)}`],{cwd:r})},Qt=async(e,t,r,n)=>{let s=n??Fo(e);if(r?await y("tmux",["select-window","-t",r],{cwd:e}):await y("tmux",["select-window","-t",t],{cwd:e}),await y("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await y("tmux",["switch-client","-t",s],{cwd:e});return}await Od(e,["attach-session","-t",s])};var jo=async(e,t)=>{await y("tmux",["kill-session","-t",t],{cwd:e})};var Fo=e=>{let r=Ed.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=vd("sha1").update(e).digest("hex").slice(0,8);return`${Ad}-${r}-${n}`},on=(e,t)=>`${Fo(e)}-${t.toLowerCase()}`,Dd=()=>{let e=$d();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},$d=()=>{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},Md=e=>{let t=Ld(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]}},Ld=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Od=async(e,t)=>{await new Promise((r,n)=>{let s=Cd("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 jd,constants as Fd}from"node:fs";import{homedir as No}from"node:os";import be from"node:path";var Nd=[be.join(No(),".local","bin"),be.join(No(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function _o(e=process.env){return Wd([...(e.PATH??"").split(be.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Nd])}function $e(e=process.env){return{...e,PATH:_o(e).join(be.delimiter)}}function an(e,t={}){if(e.includes(be.sep)){let r=be.isAbsolute(e)?e:be.resolve(t.cwd??process.cwd(),e);return Wo(r)?r:null}for(let r of _o(t.env)){let n=be.join(r,e);if(Wo(n))return n}return null}function Me(e,t={}){let r=an(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 Wo(e){try{return jd(e,Fd.X_OK),!0}catch{return!1}}function Wd(e){return[...new Set(e)]}var mt={async create(e,t){let r=await $o(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Oo(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||on(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 De(e,s),s},async attach(e,t,r){let n=await mt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Qt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await De(e,s),s},async resize(e,t,r,n){await Mo(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await De(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 De(e,n),n},async snapshot(e,t){return _d(e,t)}},ln={async prepare(e,t){let n=e.runnerSession.command[0],s=$e();await y(Me(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Me(r[0],{cwd:e.worktreePath,env:$e()});await Lo(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(){}},_d=async(e,t)=>{let r=await x("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 cn=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 ut(e,n.workspaceId,s,{runner:i,config:o}):await Ge(e,t,s,{runner:i,config:o}),l=a.task,c=h.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?qo.resolve(e.workspaceRoot,l.artifacts.logPath):qo.join(e.logsDir,`${l.id}.log`);try{await ln.prepare(l,{repoRoot:a.repoRoot});let p=await mt.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await ln.launch(l,{repoRoot:a.repoRoot,session:p});let m=new Date().toISOString();p={...p,status:"running",startedAt:m,command:c};let k={...l,status:"running",runner:i,sessionId:p.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:p.command,pid:null,startedAt:m,lastKnownState:"running",exitCode:null,exitedAt:null}};return await b(e,k),await De(e,p),{kind:"createTask",taskId:k.id,repoId:k.repoId,workspaceId:k.workspaceId,sessionId:p.id,status:k.status,branch:k.branch,worktreePath:k.worktreePath,runner:k.runner}}catch(p){let m={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:p instanceof Error?p.message:"Unknown Craig error"};throw await b(e,m),p}};import{mkdir as Yd}from"node:fs/promises";import Jd from"node:path";var Bo=3,Ud=1e3,qd=1e4,ze=async e=>{let t=await x("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Vo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await y("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Yt=async(e,t)=>{let r=await y("gh",Go(e),{cwd:t});return JSON.parse(r.stdout)},Qe=async(e,t)=>{let r=await x("gh",Go(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Ko=async(e,t,r)=>{if(r.length===0)return[];let n=zd(r),s=await Bd(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=Qd(c);return{id:a.id,found:d!==null,view:d}})},Ho=async e=>{let t=await x("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:Gd(t.stdout.trim())},Bd=async(e,t)=>{let r;for(let n=0;n<=Bo;n+=1)try{return await y("gh",t,{cwd:e})}catch(s){if(r=s,n===Bo||!Vd(s))throw s;await Hd(Kd(n))}throw r},Vd=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")},Kd=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||Ud,r=Math.min(t*2**e,qd),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},Hd=e=>new Promise(t=>setTimeout(t,e)),Go=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],Gd=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},zd=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,57 +110,57 @@ fragment PrFields on PullRequest {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
`,
|
|
113
|
+
`,Qd=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 Le=async(e,t)=>{let r=xe(e,t.artifacts.prStatusPath);r&&(await Yd(Jd.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,prs:t.prs}))},ft=async(e,t,r,n,s={readRawTask:Y,validateTaskRecord:U,writeTask:b,writePrStatusArtifact:Le})=>{let o=it(r,n),i=Ve(t,o),a=ot(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`),u=d.status==="closed"?d.status:a,p=Ve({...d,status:u},o);return await s.writeTask(e,p),p},gt=async(e,t)=>{let r=D(t),n=r?.number?String(r.number):t.branch,s=await Yt(n,t.worktreePath);return ft(e,t,s,r)},ht=async(e,t)=>{for(let r of await dn(t)){let n=await Qe(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await ft(e,t,n,null)}}return{discovered:!1,task:t}},dn=async e=>{let t=await bo(e.worktreePath).catch(()=>null);return[...new Set([t,e.branch].filter(r=>!!r))]};var Ye=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await Yt(n,r.worktreePath),a=Qo(i);return r.pullRequest=a,await zo(e,t,r.repoId,a),"synced"}let s=await Qe(n,r.worktreePath);if(!s)return"not_found";let o=Qo(s);return r.pullRequest=o,await zo(e,t,r.repoId,o),"discovered"},zo=async(e,t,r,n)=>{let s=await Y(e,t.id),o=U(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 b(e,a),a},Qo=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Xd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Zd(e.reviewDecision??null),requiredChecks:at(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),Xd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Zd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var wt=async(e,t)=>{let r=await I(e,t),n=D(r);return n?.number?(await ze(r.worktreePath),Re(n)?(await ht(e,r)).task:gt(e,r)):r},pn=async(e,t)=>{let r=await I(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Je(e,t),I(e,t);let n=D(r);if(await q(r),await ze(r.worktreePath),!n?.number||Re(n)){let o=await ht(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await Le(e,o.task),o.task}let s=await gt(e,r);return await Le(e,s),s},Je=async(e,t)=>{let r=await I(e,t),n=(r.repoTargets??[]).filter(a=>a.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let a of n){await ze(a.worktreePath);let l=a.pullRequest.number?await Ye(e,r,a):await Ye(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await Y(e,r.id),i=U(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=Jo(i),await b(e,i)),s},mn=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=un(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let d of s.repoTargets.filter(u=>u.status==="ready")){let u={id:`${s.id}:${d.repoId}`,task:s,targetRepoId:d.repoId,worktreePath:d.worktreePath,selector:d.pullRequest.number?String(d.pullRequest.number):d.branch,mode:d.pullRequest.number?"number":"head",fallbackSelectors:[]};await Yo(n,u).catch(async()=>{try{let p=d.pullRequest.number?await Ye(e,s,d):await Ye(e,s,d).catch(()=>"not_found");Jt(o,p,d.pullRequest.number??null,d.pullRequest.url??null)}catch{}})}continue}let i=D(s),a=i?.number&&!Re(i),l=a?[]:await dn(s),c={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):l[0]??s.branch,mode:a?"number":"head",fallbackSelectors:a?[]:l.slice(1)};await Yo(n,c).catch(async()=>{try{let{disposition:d,task:u}=await Xt(e,s.id),p=D(u);Jt(o,d,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await ze(s.worktreePath);let o=await Ko(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=un(r,a.task),d=i.get(a.id)?.view??await su(s.worktreePath,a);if(!d){Jt(l,"not_found",null,null);continue}if(a.targetRepoId){let u=await Y(e,a.task.id),p=U(u,`${e.tasksDir}/${a.task.id}.json`);await eu(e,p,a.targetRepoId,d)}else{let u=await Y(e,a.task.id),p=U(u,`${e.tasksDir}/${a.task.id}.json`);await ft(e,p,d,a.mode==="number"?D(p):null)}Jt(l,a.mode==="number"?"synced":"discovered",d.number,d.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await Y(e,s.id),i=U(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=Jo(i),await b(e,i))}return t.map(s=>un(r,s))},Xt=async(e,t)=>{let r=await I(e,t);await q(r),await ze(r.worktreePath);let n=D(r);if(n?.number&&!Re(n))return{disposition:"synced",task:await gt(e,r)};let s=await ht(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},Jo=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(ou)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},eu=async(e,t,r,n)=>{let s=tu(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await b(e,i),i},tu=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:ru(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:nu(e.reviewDecision??null),requiredChecks:at(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),ru=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,nu=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,su=async(e,t)=>{if(t.mode!=="head")return null;for(let r of t.fallbackSelectors){let n=await Qe(r,e);if(n)return n}return null},Yo=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]})},un=(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):!!D(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},Jt=(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},ou=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 fn=async(e,t)=>{let r=await I(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Je(e,t),r=await I(e,t)):r.prs.some(o=>o.number)&&(r=await wt(e,t))}catch{}let n=await lt(e,r),s=r.sessionId?await ye(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var gn=async(e,t)=>{let r=await I(e,t);if(await q(r),(await y("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await iu(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},iu=async e=>{let t=[],r=await y("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await au(e);for(let s of n){let o=await x("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 Jd}from"node:child_process";import{access as Xd}from"node:fs/promises";var dn=async(e,t)=>{let r=await I(e,t),n=Ge(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}},un=async e=>{await new Promise((t,r)=>{let n=!1,s=Jd("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 Zd}from"node:fs/promises";import eu from"node:path";var pn=async(e,t)=>{let r=await I(e,t);if(await q(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 Kt(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 P(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await x("sh",["-lc",i],{cwd:r.worktreePath}),c=new Date().toISOString(),d=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:c,exitCode:d}),d!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=c,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await Go(e,r),await P(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}return r.checks.results=o,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await Go(e,r),await P(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Go=async(e,t)=>{let r=De(e,t.artifacts.checkSummaryPath);r&&(await Zd(eu.dirname(r),{recursive:!0}),await F(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var mn=async(e,t)=>{let r=await I(e,t);await q(r);let n=await Kt(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 mo(r.worktreePath),await fo(r.worktreePath,s);let o=await go(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await P(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as tu}from"node:fs/promises";var fn=async(e,t)=>{let r=await I(e,t),n=await ru(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await P(e,s),s},ru=async e=>{try{return await tu(e),!0}catch{return!1}};var gn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await ye(e,t.sessionId);await xo(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 wo(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(s){n.push(s instanceof Error?s.message:"Failed to remove worktree.")}t.cleanup.warning=n.length>0?n.join(" "):null,await P(e,t)};var hn=async(e,t,r)=>{let[n,s]=await Promise.all([I(e,t),Z(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await P(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},wn=async(e,t)=>{let r=await I(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>Z(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var kn=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([Z(e,r.repoId),ye(e,r.sessionId)]),o=await gt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var Tn=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await ye(e,r.sessionId).catch(s=>{throw nu(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 zt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},nu=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as su}from"node:child_process";var Rn=async(e,t)=>{let r=await I(e,t);await q(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 ou(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},ou=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=su(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 yn=async(e,t,r)=>{let n=await X(e,t);await P(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},Pn=async(e,t,r)=>{let n=await X(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await P(e,s),s},bn=async(e,t)=>{let r=await X(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await P(e,s),s};var Sn=async(e,t,r="merge",n)=>{let s=await I(e,t),o=n??D(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await No(s.worktreePath,o,r)};var C={listTasks:zr,getTask:I,provisionTask:ze,provisionProjectTask:mt,createTask:rn,showTask:ln,showTaskDiff:cn,prepareTaskLogs:dn,streamTaskLogs:un,runChecks:pn,commitTask:mn,closeTask:fn,cleanupTask:gn,addTaskLink:hn,listTaskLinks:wn,sortTasksForDisplay:Qr,resolveSelectedTaskId:Yr,allocateTaskId:Hr,allocateTaskIdForRepo:He,allocateProjectTaskId:ut,createDefaultTaskPtyTabs:ft,assertTaskWorktreeExists:q,resolveTaskLogPath:Ge,buildTaskInspection:dt,resolveArtifactPath:De,attachTask:kn,focusTask:Tn,openTask:Rn,markRunnerFailed:yn,recordStartupFailure:Pn,markTaskStarted:bn,prs:{refresh:Tt,refreshChecks:on,discoverOrRefresh:Jt,discoverOrRefreshAll:Xe,discoverOrRefreshMany:an,merge:Sn,getPrimaryPr:D,isPrTerminal:Re,isMergeReady:Bt,deriveTaskStatus:at,upsertPr:Ve,normalizePr:lt,summarizeRequiredChecks:Kr,writePrStatusArtifact:je}};async function Ho(e,t){switch(e.kind){case"addWorkspace":{let r=await z.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await In(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await z.repos.addRepo(t.paths,e.path);return await In(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return z.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await qe({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await J(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await z.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return z.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await z.archiveWorkspace(t.paths,e.workspaceId);return await iu(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await z.restoreWorkspace(t.paths,e.workspaceId);return await In(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return z.removeWorkspace(t.paths,e.workspaceId,{listTasks:C.listTasks});case"createTask":return C.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?C.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):C.listTasks(t.paths);case"attachTask":return C.attachTask(t.paths,e.taskId);case"addTaskLink":return C.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return C.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return C.showTask(t.paths,e.taskId);case"showSelectedTask":return C.showTask(t.paths,Oe(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,Oe(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,Oe(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,Oe(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,Oe(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,Oe(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,Oe(t,"commit"));case"help":return{kind:"help",text:V()};case"exit":return{kind:"exit"};default:return au(e)}}async function In(e,t,r){let n=await qe({uiStateFile:e.uiStateFile})??jt();await Te({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function iu(e,t){let r=await qe({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Te({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function au(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Oe(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 zo(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
|
+
`)},au=async e=>(await y("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
116
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as lu}from"node:child_process";import{access as cu}from"node:fs/promises";var hn=async(e,t)=>{let r=await I(e,t),n=Ke(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await cu(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},wn=async e=>{await new Promise((t,r)=>{let n=!1,s=lu("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 du}from"node:fs/promises";import uu from"node:path";var kn=async(e,t)=>{let r=await I(e,t);if(await q(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 Kt(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 b(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await x("sh",["-lc",i],{cwd:r.worktreePath}),c=new Date().toISOString(),d=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:c,exitCode:d}),d!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=c,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await Xo(e,r),await b(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 Xo(e,r),await b(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Xo=async(e,t)=>{let r=xe(e,t.artifacts.checkSummaryPath);r&&(await du(uu.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var Tn=async(e,t)=>{let r=await I(e,t);await q(r);let n=await Kt(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 To(r.worktreePath),await Ro(r.worktreePath,s);let o=await yo(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await b(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as pu}from"node:fs/promises";var Rn=async(e,t)=>{let r=await I(e,t),n=await mu(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await b(e,s),s},mu=async e=>{try{return await pu(e),!0}catch{return!1}};var yn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await ye(e,t.sessionId);await jo(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 Po(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 b(e,t)};var bn=async(e,t,r)=>{let[n,s]=await Promise.all([I(e,t),te(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 b(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Pn=async(e,t)=>{let r=await I(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>te(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Sn=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([te(e,r.repoId),ye(e,r.sessionId)]),o=await mt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var In=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await ye(e,r.sessionId).catch(s=>{throw fu(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 Qt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},fu=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as gu}from"node:child_process";var Cn=async(e,t)=>{let r=await I(e,t);await q(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 hu(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},hu=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=gu(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 vn=async(e,t,r)=>{let n=await ee(e,t);await b(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},En=async(e,t,r)=>{let n=await ee(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await b(e,s),s},An=async(e,t)=>{let r=await ee(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 b(e,s),s};var xn=async(e,t,r="merge",n)=>{let s=await I(e,t),o=n??D(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Vo(s.worktreePath,o,r)};var C={listTasks:en,getTask:I,provisionTask:Ge,provisionProjectTask:ut,createTask:cn,showTask:fn,showTaskDiff:gn,prepareTaskLogs:hn,streamTaskLogs:wn,runChecks:kn,commitTask:Tn,closeTask:Rn,cleanupTask:yn,addTaskLink:bn,listTaskLinks:Pn,sortTasksForDisplay:tn,resolveSelectedTaskId:rn,allocateTaskId:Zr,allocateTaskIdForRepo:He,allocateProjectTaskId:ct,createDefaultTaskPtyTabs:pt,assertTaskWorktreeExists:q,resolveTaskLogPath:Ke,buildTaskInspection:lt,resolveArtifactPath:xe,attachTask:Sn,focusTask:In,openTask:Cn,markRunnerFailed:vn,recordStartupFailure:En,markTaskStarted:An,prs:{refresh:wt,refreshChecks:pn,discoverOrRefresh:Xt,discoverOrRefreshAll:Je,discoverOrRefreshMany:mn,merge:xn,getPrimaryPr:D,isPrTerminal:Re,isMergeReady:Vt,deriveTaskStatus:ot,upsertPr:Ve,normalizePr:it,summarizeRequiredChecks:Yr,writePrStatusArtifact:Le}};async function Zo(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 Dn(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Q.repos.addRepo(t.paths,e.path);return await Dn(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Q.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await _e({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Z(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Q.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Te({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 wu(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Q.restoreWorkspace(t.paths,e.workspaceId);return await Dn(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Q.removeWorkspace(t.paths,e.workspaceId,{listTasks:C.listTasks});case"createTask":return C.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?C.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):C.listTasks(t.paths);case"attachTask":return C.attachTask(t.paths,e.taskId);case"addTaskLink":return C.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return C.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return C.showTask(t.paths,e.taskId);case"showSelectedTask":return C.showTask(t.paths,Oe(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,Oe(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,Oe(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,Oe(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,Oe(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,Oe(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,Oe(t,"commit"));case"help":return{kind:"help",text:H()};case"exit":return{kind:"exit"};default:return ku(e)}}async function Dn(e,t,r){let n=await _e({uiStateFile:e.uiStateFile})??jt();await Te({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function wu(e,t){let r=await _e({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Te({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function ku(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Oe(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 ei(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} ${yu(t)} ${bu(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}`,...Tu(e)].join(`
|
|
124
124
|
`);case"streamTaskLogs":return`Streaming logs for ${e.taskId} from ${e.logPath}`;case"showTaskDiff":return e.isEmpty?`Task ${e.taskId} has no uncommitted diff.`:e.diffText;case"focusTask":return`Focused task ${e.taskId} on ${e.tmuxTarget}`;case"openTask":return e.launched?`Opened task ${e.taskId} at ${e.worktreePath}`:e.worktreePath;case"runChecks":return`Checks ${e.status} for ${e.taskId}: ${e.commands.join(", ")}`;case"commitTask":return[`Committed task ${e.taskId}`,`Status: ${e.status}`,`Commit: ${e.commitSha}`,`Message: ${e.message}`].join(`
|
|
125
|
-
`);default:return
|
|
126
|
-
`).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...n]=t.split(" ");return{status:r,path:n.at(-1)??""}}).filter(t=>t.path.length>0)}function
|
|
127
|
-
`)){let n=r.trim();if(!n)continue;let[s="-",o="-",...i]=n.split(" "),a=i.join(" ");a&&t.set(a,{additions:s==="-"?null:Number(s),deletions:o==="-"?null:Number(o)})}return t}async function
|
|
128
|
-
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return
|
|
129
|
-
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await y("git",["diff","--cached","--stat","--patch",`--unified=${
|
|
130
|
-
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await y("git",["diff","--stat","--patch",`--unified=${
|
|
131
|
-
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await x("git",["diff","--no-index","--stat","--patch",`--unified=${
|
|
125
|
+
`);default:return Ru(e)}}function Tu(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 Ru(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function yu(e){return e.checks.status}function bu(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 Kf}from"node:module";import{readFile as Pu,stat as Su}from"node:fs/promises";import $n from"node:path";var Iu=200*1024,Cu=500*1024,Zt="100000";async function ri(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return vu(e,t,r);try{let n=Pe(r.selectedFilePath??null,t.filePaths),s=Pe(r.selectedDiffPath??null,t.diffPaths),o=s?await kt(e.worktreePath):null,[i,a]=await Promise.all([tr(e.worktreePath,n),s?Mn(e.worktreePath,s,t.diffRows,o):Promise.resolve(V("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 vu(e,t,r){let n=Pe(r.selectedFilePath??null,t.filePaths),s=Pe(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([si(e,n),(async()=>{if(!s)return V("No diff selected","No local changes found.","empty");let l=er(e,s),c=l?await kt(l.target.worktreePath).catch(()=>null):null;return oi(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function ni(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return Eu(e,t);try{await q(e);let r=await kt(e.worktreePath),[n,s]=await Promise.all([ii(e.worktreePath),ai(e.worktreePath,r)]),o=[...new Set(s.map(u=>u.path))],i=Pe(t.selectedFilePath??null,n),a=Pe(t.selectedDiffPath??null,o),[l,c]=await Promise.all([tr(e.worktreePath,i),a?Mn(e.worktreePath,a,s,r):Promise.resolve(V("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:di(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:V("Files unavailable",n,"error"),selectedDiff:V("Diff unavailable",n,"error"),error:n}}}async function Eu(e,t){let r=(e.repoTargets??[]).filter(p=>p.status==="ready"),n=await Promise.all(r.map(async p=>{let m=await kt(p.worktreePath).catch(()=>null),[k,R]=await Promise.all([ii(p.worktreePath).catch(()=>[]),ai(p.worktreePath,m).catch(()=>[])]);return{target:p,baseRef:m,targetFiles:k,targetDiffRows:R}})),s=[],o=[];for(let{target:p,targetFiles:m,targetDiffRows:k}of n)s.push(...m.map(R=>`${p.repoId}/${R}`)),o.push(...k.map(R=>({...R,path:`${p.repoId}/${R.path}`})));let i=[...new Set(o.map(p=>p.path))].sort(),a=Pe(t.selectedFilePath??null,s),l=Pe(t.selectedDiffPath??null,i),[c,d]=await Promise.all([si(e,a),(async()=>{if(!l)return V("No diff selected","No local changes found.","empty");let p=er(e,l),m=p?n.find(k=>k.target.repoId===p.target.repoId):null;return oi(e,l,o,m?.baseRef??null)})()]),u=l?{[l]:d}:{};return{taskId:e.id,fileRows:di(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:u,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function si(e,t){let r=er(e,t);if(!r)return V("No file selected","No Git-visible files found.","empty");let n=await tr(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function oi(e,t,r,n=null){let s=er(e,t);return s?{...await Mn(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}:V(t,"Repo target is unavailable.","error",t)}function er(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 ii(e){let t=await y("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return ui(t.stdout)}async function ai(e,t){let[r,n,s,o]=await Promise.all([Au(e,t),ti(e,"staged"),ti(e,"unstaged"),xu(e)]);return[...r,...n,...s,...o]}async function Au(e,t){if(!t)return[];let[r,n]=await Promise.all([y("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),y("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=li(r.stdout),o=ci(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 ti(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([y("git",[...r,"--name-status"],{cwd:e}),y("git",[...r,"--numstat"],{cwd:e})]),o=li(n.stdout),i=ci(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 xu(e){let t=await y("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=ui(t.stdout);return await Promise.all(r.map(async s=>{let o=await tr(e,s),i=o.status==="ready"?Du(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function li(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 ci(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 kt(e){return(await x("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await x("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function tr(e,t){if(!t)return V("No file selected","No Git-visible files found.","empty");let r=$u(e,t);try{let n=await Su(r);if(n.size>Iu)return V(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Pu(r);return Mu(s)?V(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 V(t,s,"missing",t,null)}}async function Mn(e,t,r,n=null){if(!t)return V("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 kt(e);if(a){let l=await y("git",["diff","--stat","--patch",`--unified=${Zt}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
129
|
+
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await y("git",["diff","--cached","--stat","--patch",`--unified=${Zt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
130
|
+
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await y("git",["diff","--stat","--patch",`--unified=${Zt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
|
|
131
|
+
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await x("git",["diff","--no-index","--stat","--patch",`--unified=${Zt}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
|
|
132
132
|
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
133
133
|
|
|
134
|
-
`);return i.length>
|
|
135
|
-
`):["No diff for this file."],byteLength:i.length}}function
|
|
136
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function
|
|
137
|
-
`}function
|
|
138
|
-
`)}function
|
|
139
|
-
`)}function
|
|
140
|
-
`),center:
|
|
141
|
-
`)}function
|
|
134
|
+
`);return i.length>Cu?V(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?V(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 di(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 Pe(e,t){return e&&t.includes(e)?e:t[0]??null}function Du(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function ui(e){return[...new Set(e.split(`
|
|
136
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function $u(e,t){let r=$n.resolve(e,t),n=$n.resolve(e);if(r!==n&&!r.startsWith(`${n}${$n.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Mu(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function V(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Lu=["tasks","center","inspector","actions"],pi=["agent","terminal"],mi=[],v="inspection",hy=[...pi,...mi],Ln=["commit","push","refresh-checks","close-task"],fi=["refresh-checks","close-task"],gi=["task","checks","pr","setup-run","actions","next-action"],On=["files","review"];function hi(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=_u(e?.openInspectionKind)??r,s=h.runners.getEnabled(t);return{inputMode:qu(e?.inputMode),focusedRegion:Nu(e?.focusedRegion),selectedRepoId:me(e?.selectedRepoId),selectedWorkspaceId:me(e?.selectedWorkspaceId),selectedTaskId:me(e?.selectedTaskId),selectedPtyTabId:me(e?.selectedPtyTabId),selectedLeftItemId:zu(me(e?.selectedTaskId)),activeTab:r?v:me(e?.activeTab)??"agent",preferredPtyTabKind:Uu(e?.preferredPtyTabKind),inspectorSection:Tt(e?.inspectorSection,gi,"task"),inspectionMode:Wu(e?.inspectionMode,r==="diff"?"review":"files"),openInspectionKind:n,selectedFileTreePath:me(e?.selectedFileTreePath),selectedFilePath:me(e?.selectedFilePath),selectedDiffPath:me(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:Tt(e?.selectedActionId,Ln,"commit"),selectedProjectTargetId:null,selectedRunner:Bu(e?.selectedRunner,s,h.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:Ou(),centerZoomed:!1}}function Ou(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function wi(e,t){return{...e??jt(),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 Rt(e,t,r={}){let n=Gu(e,t),s=Fn(n),o=(s?.kind==="workspace"?t.workspaces?.find(d=>d.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(d=>d.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(d=>d.id===s.id)??null:s?.kind==="task"?t.repos.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(d=>d.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(d.id))??null:null)??(o?.kind!=="project"?t.repos.find(d=>d.id===o?.primaryRepoId)??null:null)??t.repos.find(d=>d.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(d=>d.workspaceId===o.id):a?t.tasks.filter(d=>d.repoId===a):[],c=(s?.kind==="task"?l.find(d=>d.id===s.id)??null:null)??l.find(d=>d.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:c?.id??null,...Vu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:Fu(e,t,c?.id??null),...Ku(e,t,c?.id??null),selectedDiffPath:ju(e,t,c?.id??null),inspectorSection:Tt(e.inspectorSection,gi,"task")}}function fe(e,t){return{...e,terminal:t}}function ki(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Ti(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 Ri(e){return e.length===1&&e>=" "&&e!=="\x7F"}function jn(e){return bi(e)||Xe(e)!==null}function yi(e){return mi.includes(e)}function bi(e){return pi.includes(e)}function Pi(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[v]:[]]}function ju(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function Fu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function Tt(e,t,r){return t.includes(e??"")?e:r}function Nu(e){return e==="tabs"?"center":Tt(e,Lu,"tasks")}function Wu(e,t){return e==="checks"||e==="actions"||e==="diff"||e==="review"?"review":Tt(e,On,t)}function _u(e){return e==="file"||e==="diff"?e:null}function Uu(e){return e==="terminal"?"terminal":"agent"}function qu(e){return e==="terminal"?"terminal":"control"}function Bu(e,t=[...$],r="codex"){return e&&h.runners.isRunnerType(e)&&t.includes(e)?e:r}function rr(e,t=$){let r=t.length>0?t:$,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function Xe(e){let t=$.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Vu(e,t,r){if(!e)return{activeTab:t===v?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(bi(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??v,selectedPtyTabId:l?.id??null}}if(t===v)return{activeTab:v,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??v,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?Hu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function Hu(e,t){let r=new Set;if(t){let n=t.split("/");for(let s=1;s<n.length;s+=1)r.add(n.slice(0,s).join("/"))}return e.filter(n=>n.kind==="directory"&&!n.path.includes("/")&&!r.has(n.path)).map(n=>n.path).sort((n,s)=>n.localeCompare(s))}function Gu(e,t){let r=je(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 je(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 Fn(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 me(e){return typeof e=="string"?e:null}function zu(e){return e?`task:${e}`:null}function yt(e){return typeof e=="string"&&e.startsWith("task:")}function nr(e){return typeof e=="string"&&e.startsWith("new-task:")}function sr(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Si(e){return typeof e=="string"&&e.startsWith("workspace:")}function Nn(e){return nr(e)?e.slice(9):null}function Wn(e){return sr(e)?e.slice(19):null}async function Se(e,t,r){let n=ce(e),[s,o]=await Promise.all([Q.repos.listRegisteredRepos(n),Q.listWorkspaces(n,{archived:!1})]),i=await C.listTasks(n),a=_n(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await ni(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function _n(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function Ii(e,t){return Rt(e,t)}import Gn from"node:path";import Iy from"picocolors";var Qu=[" \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 Un(){return[...Qu]}var or={width:120,height:36},W={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function re(e,t){return{width:Math.max(e??or.width,or.width),height:Math.max(t??or.height,or.height)}}var Yu=["Start","Options","Exit"],Ju=["Resume","Options","Exit"],ar=2,lr=2,cr=2,Xu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Zu=new RegExp("\x1B\\[(?:0)?m","g"),ep=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),tp=/https?:\/\/[^\s<>"']+/g,qn="\x1B[0m",Bn="\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 Ei(e,t={}){return Kn(e,{subtitle:"crAIg is that you?",menuItems:Yu,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 Kn(e,{subtitle:"Control mode is paused.",menuItems:Ju,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var ir=[" 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."],rp=["Help"],np=5;function pr(e,t={}){return Kn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??rp,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function xi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o=Un(),i=Math.max(1,Math.floor((e.height-o.length-2-ir.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=L(Wi(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...ir.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<ir.length;d+=1){let u=c+d;if(u>=e.height)break;let p=ir[d]??"";s[u]=L(ue(" ".repeat(l)+p,e.width),r,n)}return s.join(`
|
|
138
|
+
`)}function Di(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".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"},ie(),...a.length>0?a.map(m=>({text:m})):[{text:"No Craig errors have been logged.",tone:"muted"}],ie(),{text:"Esc returns to Options.",tone:"muted"}],u=bt(d,e.height-2),p=Math.max(1,Math.floor((e.height-u.length)/2));for(let m=0;m<u.length;m+=1){let k=p+m;if(k>=e.height)break;let R=u[m]??ie(),A=`${" ".repeat(c)}${mr(R.text,l)}`,K=R.tone==="selected"?P.overlayMenuSelected:R.tone==="muted"?P.overlay:P.panelBg;s[k]=L(ue(A,e.width),r,K)}return s.join(`
|
|
139
|
+
`)}function $i(e,t,r={}){let n=r.color??!0,s=W.leftWidth,o=W.rightWidth,i=r.centerOnly??!1,a=e.height-W.topRailHeight-1,l=r.focusFlashActive??!1,c={bg:P.divider.bg,fg:"9ece6a"},d=l&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?c:P.divider,u=l&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?c:P.divider,p=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,m=L(ue(p,e.width),n,P.rail),k=op(t,s-ar-lr,a,n),R=Vn(e,t,{color:n,centerOnly:i}),A=lp(t,o,a,n),K=t.inputMode==="terminal",f=[];for(let ne=0;ne<a;ne+=1){if(i){f.push(R.rows[ne]??"");continue}let At=dr(k[ne]??ie(),s,n,"left"),Er=L("\u2502",n,d),xt=R.rows[ne]??"",Dt=L("\u2502",n,u),T=dr(A[ne]??ie(),o,n,"right");f.push(`${At}${Er}${xt}${Dt}${T}`)}let we=K||t.modalInput?P.panelBg:P.panelMuted,S=sp(t.footerText,t.footerToast,e.width,n,we);return{frame:[m,...f,S].join(`
|
|
140
|
+
`),center:R}}function Vn(e,t,r={}){let n=r.color??!0,s=Li(e,r.centerOnly??!1),o=ip(t,s.width,s.rowCount,n);return{row:s.row,column:s.column,width:s.width,rows:o.map(i=>dr(i,s.width,n,"center"))}}function Mi(e,t,r,n={}){let s=t.tabs.find(c=>c.active)?.id??"";if(!jn(s)||t.centerHeader.tabLabel==="BROWSER"||t.terminal.error||t.terminal.rows.length===0||r.some(c=>c<0||c>=t.terminal.rows.length))return null;let o=n.color??!0,i=Li(e,n.centerOnly??!1),a=Oi(t,i.width,o).length,l=[...new Set(r)].map(c=>({terminalIndex:c,index:a+c})).filter(({index:c})=>c<i.rowCount).map(({terminalIndex:c,index:d})=>({index:d,row:dr(ji(t.terminal.rows[c]),i.width,o,"center")}));return{...i,rows:l}}function Li(e,t){return{row:W.topRailHeight+1,column:t?1:W.leftWidth+W.dividerWidth+1,width:t?e.width:e.width-W.leftWidth-W.rightWidth-W.dividerWidth*2,rowCount:e.height-W.topRailHeight-1}}function sp(e,t,r,n,s){let o=` ${e}`;if(!t)return L(ue(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=J(i),l=J(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?mr(o,Math.max(0,r-a-3)):o,u=Math.max(1,r-J(d)-a-2),p=t.tone==="error"?vp(i,n,s):Ze(i,n,s),m=`${d}${" ".repeat(u)}${p} `;return L(ue(m,r),n,s)}function Kn(e,t){let r=new Array(e.height).fill(L(" ".repeat(e.width),t.color,P.overlay)),n=Un(),s=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c}`),o=t.optionsMessage?["",t.optionsMessage]:[],i=[...s,...o];for(;i.length<np;)i.push("");let a=[...n,"",t.subtitle,"",...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=Wi(a[c]??"",e.width);if(c<n.length){r[l+c]=L(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=L(d,t.color,P.overlaySubtitle);continue}let u=c-(n.length+3),m=u>=0&&u<t.menuItems.length&&u===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=L(d,t.color,m)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,u=" ".repeat(Math.max(0,e.width-J(d)));r[e.height-1]=L(`${u}${Hn(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
|
|
141
|
+
`)}function op(e,t,r,n){let s=up(e.runners),o=1,i=e.leftTree.map(l=>dp(l,t,n));return[...bt(i,r-o),s]}function ip(e,t,r,n){let s=e.tabs.find(i=>i.active)?.id??"agent",o=e.centerHeader.tabLabel==="BROWSER"||!jn(s)?e.centerTranscript.map(i=>({...i})):ap(e);return bt([...Oi(e,t,n),...o],r)}function Oi(e,t,r){let n=t-2,s=e.tabs.find(A=>A.active)?.label??"AGENT",o=e.inputMode==="terminal"?0:Sp(e.tabs),i=e.inputMode==="terminal"?n:s.length+1,a="\u2500".repeat(Math.max(0,i)),l=`${" ".repeat(o)}${e.inputMode==="terminal"?Ze(a,r,P.panelBg):ur(a,r,P.panelMuted)}`,c=[`${ur(e.centerHeader.tabLabel,r,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),d=pp(e.tabs,r,e.focusedRegion==="center"),u=" engaged ",p=u.length+2,m=e.inputMode==="terminal"?Ze(`${u}\u25CF `,r,P.panelBg):"",k=e.inputMode==="terminal"?" ".repeat(Math.max(0,n-J(d)-p)):"";return[{text:e.inputMode==="terminal"?`${d}${k}${m}`:d},{text:l,tone:"muted"},{text:c},ie()]}function ap(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},ie(),{text:e.terminal.error},ie(),{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(ji)}function ji(e){return{text:qi(e.segments),segments:e.segments,fullBleed:!0}}function lp(e,t,r,n){let s=e.rightInspection?cp(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):bt([{text:"CONTEXT"},ie(),...e.rightContext.map(o=>mp(o,n)),...e.actionMessage?[ie(),{text:e.actionMessage}]:[]],r);return bt(s,r)}function cp(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:Cp(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>Ci(a)),...n.slice(i,i+s).map(a=>Ci(a))]}function Ci(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 dp(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Ze("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((m,k)=>m+J(k.text),0):0,l=t-J(o)-J(s)-a,c=e.selected?e.text:e.focused?Ze(e.text,r,P.panelBg):e.panelHeader?ur(e.text,r,P.panelMuted):e.text,d=ue(`${n}${c}`,Math.max(0,l)),u=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let m=[{text:`${d}${o}${i}`},...e.prBadge];return{text:`${d}${o}${e.prBadge.map(R=>R.text).join("")}`,segments:m,tone:u}}return{text:`${d}${o}${i}`,tone:u}}function up(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 pp(e,t,r){return e.map(n=>n.active?r?Ze(n.label,t,P.panelBg):ur(n.label,t,P.panelBg):Hn(n.label,t,P.panelBg)).join(" ")}function mp(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Hn(e.value,t,P.panelBg):e.value}`}}function dr(e,t,r,n){let s=fp(n,e.tone??"default"),o=gp(e,r,s);if(n==="left"){if(e.fullBleed)return L(ue(o,t),r,s);let a=t-ar-lr;if(e.rightAlign){let c=J(o),d=Math.max(0,a-c),u=`${" ".repeat(ar)}${" ".repeat(d)}${o}${" ".repeat(lr)}`;return L(u,r,s)}let l=`${" ".repeat(ar)}${ue(o,a)}${" ".repeat(lr)}`;return L(l,r,s)}return n==="center"&&e.fullBleed?hp(e,t,r,s):L(ue(` ${o}`,t),r,s)}function fp(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function bt(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(ie());return r}function ie(){return{text:""}}function gp(e,t,r){return e.segments?e.segments.map(n=>Fi(n,t,r)).join(""):e.text}function hp(e,t,r,n){let s=" ".repeat(cr),o=Math.max(0,t-cr*2);if(!e.segments)return L(`${s}${ue(e.text,o)}${s}`,r,n);let i=Tp(e.segments,o),a=`${s}${i.map(l=>Fi(l,r,n)).join("")}${s}${r?Bn:""}`;return L(a,r,n)}function Fi(e,t,r){let n=e.href?`${Ni(e.href)}${e.text}${Bn}`:wp(e.text);return!t||!e.style?n:`${Pt(bp(e.style,r))}${Pp(e.style)}${n}${qn}${Pt(r)}`}function wp(e){return e.replace(tp,t=>{let[r,n]=kp(t);return`${Ni(r)}${r}${Bn}${n}`})}function kp(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function Ni(e){return`\x1B]8;;${e}\x1B\\`}function Tp(e,t){let r=Rp(e,t);return yp(r,t)}function Rp(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=J(s.text);if(o<=n){r.push(s),n-=o;continue}let i=mr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function yp(e,t){let r=J(qi(e));if(r>=t)return e;let n=[...e].reverse().find(s=>s.style?.bg)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function bp(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 Pp(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 Sp(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function Wi(e,t){let r=Math.max(0,t-J(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ue(e,t){let r=J(e);return r>=t?Ip(e,t):e+" ".repeat(t-r)}function Ip(e,t){if(t<=0)return"";if(J(e)<=t)return e;let r=Ui(e);return mr(r,Math.max(0,t-1))+"\u2026"}function J(e){let t=0;for(let r of Array.from(Ui(e)))t+=_i(r);return t}function mr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=_i(s);if(n+o>t)break;r+=s,n+=o}return r}function _i(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 Cp(e,t,r){return Math.min(Math.max(e,t),r)}function Ui(e){return e.replace(ep,"").replace(Xu,"")}function qi(e){return e.map(t=>t.text).join("")}function L(e,t,r){if(!t)return e;let n=Pt(r),s=e.replace(Zu,`${qn}${n}`);return`${n}${s}${qn}`}function Pt(e){let t=[];return e.fg&&t.push(`38;2;${vi(e.fg).join(";")}`),e.bg&&t.push(`48;2;${vi(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function vi(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Ze(e,t,r){return fr(e,t,P.success.fg,r)}function vp(e,t,r){return fr(e,t,P.error.fg,r)}function ur(e,t,r){return fr(e,t,P.accent.fg,r)}function Hn(e,t,r){return fr(e,t,P.mutedfg.fg,r)}function fr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${Pt(s)}${e}${Pt(n)}`}function Bi(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"?Ap(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:Ep(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function Ep(e,t){let r=(e??"").split(Gn.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(Gn.delimiter):[...r,t].join(Gn.delimiter)}function Ap(e){return e.command.length>0?e.command:["codex"]}function Vi(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 Ie(e){return{columns:Math.max(20,e.width-W.leftWidth-W.rightWidth-W.dividerWidth-cr*2),rows:Math.max(5,e.height-W.topRailHeight-5)}}function Ki(e){return e.length===1||oe(e)||e==="BACKSPACE"||e==="TAB"}function St(e){return typeof e=="string"&&new RegExp(`:(?:agent|${$.join("|")})(?:-\\d+)?$`).test(e)}function Hi(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 zn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Gi(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 It(e){return Qi.includes(e)?"SHIFT_ENTER":null}function Qn(e){return Qi.some(t=>t.startsWith(e))}function zi(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var Qi=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function Yi(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
142
142
|
`||r===`\r
|
|
143
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function
|
|
143
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Ji(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Xi(e,t=null){let r=t?.split(`
|
|
144
144
|
`)??[];return e.split(`
|
|
145
|
-
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function
|
|
146
|
-
`,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:""},
|
|
147
|
-
[process exited ${
|
|
145
|
+
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function Zi(e,t,r,n){return e.map((s,o)=>t?.[o]===s?"":`\x1B[${r+o};${n}H${s}`).join("")}import{spawn as Zp}from"node:child_process";import{createHash as em}from"node:crypto";import{createServer as tm,createConnection as la}from"node:net";import{openSync as rm}from"node:fs";import{mkdir as nm,readFile as rs,rm as Fe,writeFile as sm}from"node:fs/promises";import{tmpdir as om}from"node:os";import et from"node:path";import{createRequire as Wp}from"node:module";import xp from"@xterm/headless";var Dp=1e3,$p=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function ta(e){return new xp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:Dp,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function ra(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 na(e,t=0){let r=e.buffer.active,n=[],s=r.getNullCell(),o=r.baseY+r.cursorY,i=Math.max(0,r.baseY-t);for(let a=0;a<e.rows;a+=1){let l=r.getLine(i+a);if(!l){n.push({segments:[]});continue}let c=[];for(let d=0;d<e.cols;d+=1){let u=l.getCell(d,s);!u||u.getWidth()===0||c.push({text:u.getChars()||" ",style:Op(u,i+a===o&&d===r.cursorX)})}n.push({segments:Mp(Lp(c))})}return n}function Mp(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&Np(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};sa(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!==" "||!sa(r.style))break;t-=1}return e.slice(0,t)}function Op(e,t){let r={},n=ea(e,"fg"),s=ea(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 ea(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"):$p[s]??jp(s)}function jp(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(Fp).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 Fp(e){return e===0?0:55+e*40}function Np(e,t){return Yn(e)===Yn(t)}function Yn(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function sa(e){return Yn(e)===""}var _p=Wp(import.meta.url),Up=/^CTRL_([A-Z])$/,qp="\x1B[6n",Bp="\x1B[c",Vp="\x1B[?u",Kp={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
146
|
+
`,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:""},gr=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")Xn(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,oa(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=Hp(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&&oa(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&(Xn(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())Xn(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:Gp(r),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??Qp().spawn,i=ta(n),a=s??this.resolveSessionSpec(t,r),l=$e({...this.env,...a.env??{}}),{executable:c,args:d}=Yp(this.shell,a.command,{cwd:a.cwd,env:l}),u=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:Jp(l)}),p={taskId:t,tabId:r,pty:u,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0,rows:[],renderedScrollbackLines:null,screenDirty:!0};return p.disposables.push(u.onData(m=>{Xp(u,m),Jn(p.terminal,m).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p.disposables.push(u.onExit(m=>{p.status="exited",Jn(p.terminal,`\r
|
|
147
|
+
[process exited ${m.exitCode}]`).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function Hp(e){if(e.length===1)return e;let t=Kp[e];if(t!==void 0)return t;let r=Up.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function oa(e,t){zp(e.pty,t),ra(e.terminal,t),e.screenDirty=!0}function Gp(e){return(e.screenDirty||e.renderedScrollbackLines!==e.scrollbackLines)&&(e.rows=na(e.terminal,e.scrollbackLines),e.renderedScrollbackLines=e.scrollbackLines,e.screenDirty=!1),e.rows}function Xn(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function zp(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Qp(){return _p("node-pty")}function Yp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Me(t[0],r),...t.slice(1)].map(ia).join(" ")}; exec ${ia(e)} -l`;return{executable:e,args:["-lc",s]}}function ia(e){return`'${e.replaceAll("'","'\\''")}'`}function Jp(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 Xp(e,t){for(let r=0;r<Zn(t,qp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Zn(t,Bp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Zn(t,Vp);r+=1)e.write("\x1B[?0u")}function Zn(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 ca=5,im=new Set([4,ca]),am=16;async function da(e){let t=ns(e.paths);await um(t,e.paths,e.spawnDaemon);let r=await wa(t.socketPath),n=new es(r,e);return await n.ready(),n}async function ua(e,t={}){let r=ns(e);await nm(e.runtimeDir,{recursive:!0}),await Fe(r.socketPath,{force:!0});let n=new ts(e,t),s=tm(o=>n.handleConnection(o));await wm(s,r.socketPath),await sm(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 Fe(r.socketPath,{force:!0}),await Fe(r.pidPath,{force:!0}),n.disposeAll()}async function pa(e){let t=ns(e);return await wr(t.socketPath)?(await ga(t.socketPath),!0):!1}var es=class{constructor(t,r){this.socket=t;this.options=r,this.viewUpdateMode=r.viewUpdateMode??"snapshot",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;viewedTabId=null;subscribedTabId=null;viewUpdateMode;buffer="";closed=!1;options;async ready(){let t=await this.send({type:"ping"});if(!fa(t.protocolVersion))throw new Error("Craig PTY daemon protocol mismatch.");await this.send({type:"setViewUpdateMode",mode:this.viewUpdateMode})}async ensureSession(t,r,n){let s=await this.send({type:"ensureSession",taskId:t,tabId:r,size:n,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r,this.viewedTabId=r;let o=s.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,o),o}async hydrateSessions(t){for(let r of t)try{let n=await this.send({type:"hydrateSession",tabId:r});n.view&&this.viewCache.set(r,n.view)}catch(n){let s=n instanceof Error?n.message:String(n);this.viewCache.set(r,{status:"failed",rows:[],error:s})}}async pruneStale(t){await this.send({type:"pruneStale",keepTabIds:t})}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){let r=this.attachedTabId;this.send({type:"scrollViewport",lines:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}resize(t){let r=this.attachedTabId;this.send({type:"resize",size:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}setViewedTab(t){this.closed||(this.viewedTabId=t,this.viewUpdateMode==="incremental"&&this.subscribeToView(t))}setViewUpdateMode(t){if(this.closed||this.viewUpdateMode===t)return;this.viewUpdateMode=t,this.subscribedTabId=null;let r=this.viewedTabId;this.send({type:"setViewUpdateMode",mode:t}).then(n=>{r&&n.view&&this.viewCache.set(r,n.view),this.viewUpdateMode===t&&this.viewedTabId===r&&this.notifyFullUpdate(r),t==="incremental"&&this.viewUpdateMode===t&&(this.viewedTabId===r&&this.subscribedTabId===null?this.subscribedTabId=r:this.viewedTabId!==r&&this.subscribeToView(this.viewedTabId))}).catch(()=>{this.viewUpdateMode===t&&(this.subscribedTabId=null)})}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)}
|
|
148
148
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
149
149
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
150
|
-
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}if(r.type==="update"){if("view"in r){this.viewCache.set(r.tabId,r.view),this.
|
|
150
|
+
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}if(r.type==="update"){if("view"in r){this.viewCache.set(r.tabId,r.view),this.notifyFullUpdate(r.tabId);return}let n=this.viewCache.get(r.tabId)??{status:"idle",rows:[],error:null,scrolledBack:!1},s=dm(n,r.patch),o=n.rows.slice(0,r.patch.rowCount);for(let i of r.patch.rows)o[i.index]=i.row;this.viewCache.set(r.tabId,{status:r.patch.status,rows:o,error:r.patch.error,scrolledBack:r.patch.scrolledBack}),this.viewUpdateMode==="incremental"&&this.viewedTabId===r.tabId&&this.options.onUpdate?.(s?{tabId:r.tabId,kind:"full"}:{tabId:r.tabId,kind:"rows",rowIndices:r.patch.rows.map(i=>i.index)})}}subscribeToView(t){this.closed||this.viewUpdateMode!=="incremental"||this.subscribedTabId===t||(this.subscribedTabId=t,this.send({type:"subscribeView",tabId:t}).then(r=>{t&&r.view&&this.viewCache.set(t,r.view),this.viewUpdateMode==="incremental"&&this.viewedTabId===t&&this.subscribedTabId===t&&this.notifyFullUpdate(t)}).catch(()=>{this.subscribedTabId===t&&(this.subscribedTabId=null)}))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}notifyFullUpdate(t){t&&this.options.onUpdate?.({tabId:t,kind:"full"})}},ts=class{onShutdown=null;clients=new Set;subscriptions=new Map;updateTimers=new Map;runtime;attachedTabId=null;constructor(t,r){this.runtime=new gr({...r,workspaceRoot:t.workspaceRoot,onUpdate:n=>this.handleRuntimeUpdate(n.tabId)})}handleConnection(t){let r="";this.clients.add(t),this.subscriptions.set(t,{mode:"snapshot",tabId:null,view:null,rowKeys:[]}),t.setEncoding("utf8"),t.on("data",s=>{r+=String(s);let o=r.indexOf(`
|
|
151
151
|
`);for(;o!==-1;){let i=r.slice(0,o);r=r.slice(o+1),this.handleLine(t,i),o=r.indexOf(`
|
|
152
|
-
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t)};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{
|
|
153
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
152
|
+
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t)};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{Ct(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(t,n);Ct(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:ca}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);Ct(t,{id:n.id,ok:!1,error:o})}}handleRequest(t,r){switch(r.type){case"ping":return null;case"ensureSession":return this.attachedTabId=r.tabId,this.subscribe(t,r.tabId,this.runtime.ensureSession(r.taskId,r.tabId,r.size,r.spec));case"hydrateSession":return this.runtime.getViewState(r.tabId);case"write":return this.runtime.write(r.input),null;case"writeKey":return this.runtime.writeKey(r.key),null;case"scrollViewport":return this.runtime.scrollViewport(r.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(r.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(r.tabId),this.attachedTabId===r.tabId&&(this.attachedTabId=null),null;case"setViewUpdateMode":return this.setViewUpdateMode(t,r.mode);case"subscribeView":return this.subscribe(t,r.tabId,this.runtime.getViewState(r.tabId));case"pruneStale":{let n=new Set(r.keepTabIds);for(let s of this.runtime.sessionTabIds())n.has(s)||(this.runtime.disposeSession(s),this.attachedTabId===s&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(r.tabId);case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return km(r)}}subscribe(t,r,n){let s=this.subscriptions.get(t)?.mode??"snapshot";return this.subscriptions.set(t,{mode:s,tabId:r,view:n,rowKeys:n.rows.map(hr)}),n}setViewUpdateMode(t,r){let s=this.subscriptions.get(t)?.tabId??null,o=this.runtime.getViewState(s);return this.subscriptions.set(t,{mode:r,tabId:s,view:o,rowKeys:o.rows.map(hr)}),o}handleRuntimeUpdate(t){let r=null;for(let n of this.clients)this.subscriptions.get(n)?.mode==="snapshot"&&(r??=this.runtime.getViewState(t),Ct(n,{type:"update",tabId:t,view:r}));this.scheduleBroadcastUpdate(t)}scheduleBroadcastUpdate(t){this.updateTimers.has(t)||!this.hasViewSubscriber(t)||this.updateTimers.set(t,setTimeout(()=>{this.updateTimers.delete(t),this.broadcastUpdate(t)},am))}hasViewSubscriber(t){for(let r of this.subscriptions.values())if(r.mode==="incremental"&&r.tabId===t)return!0;return!1}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients){let s=this.subscriptions.get(n);if(!s||s.mode!=="incremental"||s.tabId!==t)continue;let o=lm(s,r),i=cm(s.view,r);s.view=r,s.rowKeys=r.rows.map(hr),(o.rows.length>0||i)&&Ct(n,{type:"update",tabId:t,patch:o})}}};function lm(e,t){let r=[];for(let n=0;n<t.rows.length;n+=1){let s=t.rows[n];e.rowKeys[n]!==hr(s)&&r.push({index:n,row:s})}return{status:t.status,error:t.error,scrolledBack:t.scrolledBack??!1,rowCount:t.rows.length,rows:r}}function cm(e,t){return!e||e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==(t.scrolledBack??!1)||e.rows.length!==t.rows.length}function dm(e,t){return e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==t.scrolledBack||e.rows.length!==t.rowCount}function hr(e){return JSON.stringify(e)}function ns(e){let t=em("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:et.join(om(),`craig-${t}.sock`),pidPath:et.join(e.runtimeDir,"pty-daemon.pid")}}async function um(e,t,r){if(await pm(e.socketPath,1e3))return;await wr(e.socketPath)&&(await ga(e.socketPath),await aa(e.socketPath,1e3)),await wr(e.socketPath)&&(await gm(e),await aa(e.socketPath,1e3)),await fm(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=mm(n),l=rm(et.join(t.runtimeDir,"pty-daemon.log"),"a");Zp(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 ma(e.socketPath))return;await ss(50)}let o=await rs(et.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
153
|
+
${o.slice(-2e3)}`:""}`)}async function ma(e){let t=await hm(e).catch(()=>null);return t?.ok===!0&&fa(t.protocolVersion)}function fa(e){return e!==void 0&&im.has(e)}async function pm(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await ma(e))return!0;await ss(50)}return!1}function mm(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=et.resolve(et.dirname(t),"..","node_modules",".bin","tsx");return{command:an("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 fm(e){let t=await rs(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&ka(r))return}await Fe(e.socketPath,{force:!0}),await Fe(e.pidPath,{force:!0})}async function wr(e){let t=await wa(e).catch(()=>null);return t?(t.end(),!0):!1}async function ga(e){await ha(e,{id:1,type:"shutdown"}).catch(()=>null)}async function gm(e){let t=await rs(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!ka(r)){await Fe(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await Fe(e.socketPath,{force:!0})}}async function hm(e){return ha(e,{id:1,type:"ping"})}function ha(e,t){return new Promise((r,n)=>{let s=la(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)}
|
|
154
154
|
`)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let c=o.indexOf(`
|
|
155
|
-
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function
|
|
156
|
-
`)}catch{}}function
|
|
157
|
-
`}function am(e){return e.length===1&&e>=" "&&e!==""}import At from"node:path";function ha(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 wa="\u{F024B} ",ka="\u{F0DCF} ",Ta="\u25CB",rs="\uEA64",Ra="\uEAFE",ya="\uEBDA",ns="\u25CB",ss="\u25CF",os="\u2713",is="\u2715";function Pa(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 kr="empty",W={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Ca(e,t){let r=dm(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,a=i?.type==="project",l=Km(t.tasks),c=mm(e,i),d=pm(e,i,c),u=d.find(T=>T.id===c)??d[0]??{id:"agent",label:"CODEX"},p=t.inspection?.taskId===i?.id?t.inspection:null,f=n?.name??"no repo",k=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`:bt(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===v?"\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 Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:At.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${At.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:k},leftTree:lm(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(T=>Vm(T,l[T])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":u.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:f,agent:k},centerTranscript:um(c,e,n,i,e.workspaceBrowser,p,r),tabs:d,rightContext:Bm(n,i),rightInspection:Cm(e,i,p)}}function lm(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return cm(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}`,u=d?"\u25B8":"\u2022",p=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,f={id:`task:${c.id}`,taskId:c.id,text:`${u} ${p}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},k=Ea(c);k&&(f.prBadge=k),r.push(f)}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(u=>u.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 cm(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 u=t.selectedLeftItemId===`task:${d.id}`,p=u?"\u25B8":"\u2022",f=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,k={id:`task:${d.id}`,taskId:d.id,text:`${p} ${f}`,indent:2,selected:u,focused:u&&t.focusedRegion==="tasks"},T=Ea(d);T&&(k.prBadge=T),e.push(k)}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 dm(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 um(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,p)=>{let f=p===s.selectedIndex?"\u25B8":" ",k=u.kind==="repo"?" [git repo]":"/";return`${f} ${u.name}${k}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return oe(["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 oe(["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 oe([`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"?oe([`${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."]):oe([`${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===v&&t.openInspectionKind==="file"?hm(n,o,t.fileScrollOffset):e===v&&t.openInspectionKind==="diff"?wm(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?oe(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):oe(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function pm(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:fm(o)}))??[];if(!t)return[{id:kr,label:"EMPTY",active:r===kr,focused:e.focusedRegion==="center"&&r===kr}];let s=e.openInspectionKind||r===v?[{id:v,label:gm(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function mm(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===v&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??v:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??v:kr}function fm(e){return e.title.toUpperCase()}function gm(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 hm(e,t,r){if(!e)return oe(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return oe(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=va(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:""},...km(n.lines,r,s)]}function wm(e,t,r){if(!e)return oe(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return oe(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=va(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:""},...Tm(n.lines,r,s)]}function oe(e){return e.map(t=>({text:t}))}function km(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:W.lineNumber}},{text:" \u2502 ",style:{fg:W.gutter}},...as(o,r)],tone:"default"}})}function Tm(e,t,r){let n=Rm(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>ym(o,r))}function Rm(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 ym(e,t){let r=ba(e.oldNumber),n=ba(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:W.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:W.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?bm(as(e.text,t),o.bg,o.fallbackFg):as(e.text,t),l=o?{fg:W.lineNumber,bg:o.bg}:{fg:W.lineNumber},c=o?{fg:W.gutter,bg:o.bg}:{fg:W.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function ba(e){return e===null?" ":String(e).padStart(4," ")}function va(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 as(e,t){return t==="diff"?Pm(e):t==="markdown"?Sm(e):t==="json"?ls(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?ls(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 Pm(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:W.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:W.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:W.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:W.diffMeta}}]:[{text:e}]}function bm(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function Sm(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:W.markup,bold:!0}}]:ls(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function ls(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:Im(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function Im(e){return e.startsWith("//")||e.startsWith("/*")?{fg:W.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:W.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:W.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:W.markup}:{fg:W.keyword}}function Cm(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"?Aa(t.repoTargets??[]):s?.pullRequest??(t?D(t):null),i=[vm(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=$a(e,t),l=cs(e,r),c=$m([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,..._m(e,r)]}:{title:"",rows:[...i,...cs(e,r)]}}function vm(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=ds(t),i=us(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Sa(e){return[{text:" "},ds(e),{text:" "},us(e)]}function Ea(e){if(e.type==="project"&&e.repoTargets?.length){let r=Aa(e.repoTargets);return r?Sa(r):null}let t=D(e);return t?.number?Sa(t):null}function Aa(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=Am(r);return{number:-1,status:Em(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 Em(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 Am(e){let t=e.map(r=>xa(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 ds(e){return!e||!e.number?{text:Ta,style:{fg:"565f89"}}:e.status==="merged"?{text:Ra,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:ya,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:rs,style:{fg:"565f89"}}:{text:rs,style:{fg:"9ece6a"}}}function us(e){return e?.aggregateReadiness?Ia(e.aggregateReadiness):Ia(xa(e))}function Ia(e){return e==="failed"?{text:is,style:{fg:"f7768e"}}:e==="pending"?{text:ss,style:{fg:"e0af68"}}:e==="success"?{text:os,style:{fg:"9ece6a"}}:{text:ns,style:{fg:"565f89"}}}function xa(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")?Da(e)?"failed":xm(e)?"success":"pending":"pending"}function xm(e){return!!(e.mergeable&&!e.draft&&!Da(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function Da(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function $a(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return Dm(e,t);let r=D(t),n=La("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var wr=32;function Dm(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,p=wr-u.length-1,f=c.length>p?c.slice(0,p-1)+"\u2026":c,k=wr-f.length-u.length;r.push({id:`project-review:${i.repoId}`,text:f+" ".repeat(Math.max(1,k))+u,selected:a,focused:l,muted:!0})}else{let d=ds(i.pullRequest),u=us(i.pullRequest),p=`${d.text} ${u.text}`,f=wr-p.length-1,k=c.length>f?c.slice(0,f-1)+"\u2026":c,T=wr-k.length-p.length,A=k+" ".repeat(Math.max(1,T));r.push({id:`project-review:${i.repoId}`,text:A+p,selected:a,focused:l,segments:[{text:A},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...La("target",o.branch,o.pullRequest))),r}function Ma(e,t,r=null){return 3+$a(e,t).length+cs(e,r).length}function La(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=Mm(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:Lm(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${ja(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(jm)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,p)=>Om(u,n(`comment:${p}`))))),s}function $m(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 Mm(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function Lm(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function ja(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 jm(e){let{icon:t,color:r}=Nm(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," ")} ${Wm(e.status)}`,color:r,muted:!1}}function Om(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${ja(e.createdAt)}`:"",s=Fm(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 Fm(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 Nm(e){switch(e){case"success":return{icon:os,color:"9ece6a"};case"pending":return{icon:ss,color:"e0af68"};case"failed":return{icon:is,color:"f7768e"};case"skipped":return{icon:ns,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Wm(e){return e==="success"?"passing":e==="failed"?"failing":e}function _m(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=ps(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?wa:ka:ha(l.label),p=l.kind==="directory"?"7aa2f7":Pa(l.label),f=" ".repeat(l.depth),k=p?{text:u,style:{fg:p}}:{text:u},T=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},A=[{text:f},k,T];return{id:l.path,text:`${f}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:A}})]}function ps(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 cs(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(qm(t))return Um(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=>Oa(o,e,t))))}return r}function qm(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Um(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=>Oa(c,e,t,s.length+1))))}}return r}function Oa(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 Bm(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: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 Km(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Vm(e,t){return{name:h.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function Fa(e,t,r,n){let s=Nn(e,t,{centerOnly:n});return Gm(r,s)?{output:Ki(s.rows,r.rows,s.row,s.column),region:s}:null}function Gm(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}import{appendFile as Hm,mkdir as zm,readFile as Qm}from"node:fs/promises";import Ym from"node:path";var Na=80,ms=async(e,t)=>{await zm(Ym.dirname(e.errorLogFile),{recursive:!0}),await Hm(e.errorLogFile,Jm(t),"utf8")},Wa=async(e,t)=>{try{await ms(e,t)}catch{}},fs=async(e,t=Na)=>{try{let n=(await Qm(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
158
|
-
`).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(
|
|
155
|
+
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function aa(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await wr(e))return;await ss(50)}}function wa(e){return new Promise((t,r)=>{let n=la(e);n.once("connect",()=>t(n)),n.once("error",r)})}function wm(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function Ct(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
156
|
+
`)}catch{}}function ka(e){try{return process.kill(e,0),!0}catch{return!1}}function ss(e){return new Promise(t=>setTimeout(t,e))}function km(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var os=["Runners","Feature Previews","Error Log","Help"],Ra={incrementalCenterPane:"Incremental center pane"};function is(e,t){return $.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 ya(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 ba(e){return se.map(t=>`${h.previews.isEnabled(e,t)?"[x]":"[ ]"} ${Ra[t]}`)}function Pa(e){return e.message??"Experimental features may change or be removed. Enter toggles."}function Sa(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(os.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:kr(t)?e===0?{kind:"runners"}:e===1?{kind:"previews"}:e===2?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Ia(e,t,r){if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(se.length-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(!kr(r))return{kind:"noop",state:e};let n=se[e.menuIndex]??se[0],s=!h.previews.isEnabled(t,n);return{kind:"save-enabled",feature:n,enabled:s,state:{...e,message:`${Ra[n]} ${s?"enabled":"disabled"}.`}}}function Ca(e,t,r,n){if(e.pathEdit)return Tm({...e,pathEdit:e.pathEdit},t,r);let s=is(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=$[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!kr(r))return{kind:"noop",state:e};let o=$[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${h.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Tm(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Ta({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(kr(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Ta({...e,message:s.length>0?`${h.runners.getProfile(n).displayName} executable saved.`:`${h.runners.getProfile(n).displayName} executable reset to default.`})}}return Rm(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Ta(e){let t={...e};return delete t.pathEdit,t}function kr(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
157
|
+
`}function Rm(e){return e.length===1&&e>=" "&&e!==""}import vt from"node:path";function va(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 Ea="\u{F024B} ",Aa="\u{F0DCF} ",xa="\u25CB",as="\uEA64",Da="\uEAFE",$a="\uEBDA",ls="\u25CB",cs="\u25CF",ds="\u2713",us="\u2715";function Ma(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 Rr="empty",_={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Fa(e,t){let r=Pm(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=nf(t.tasks),c=Cm(e,i),d=Im(e,i,c),u=d.find(R=>R.id===c)??d[0]??{id:"agent",label:"CODEX"},p=t.inspection?.taskId===i?.id?t.inspection:null,m=n?.name??"no repo",k=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`:yt(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===v?"\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 Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:vt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${vt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:k},leftTree:ym(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(R=>sf(R,l[R])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":u.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:m,agent:k},centerTranscript:Sm(c,e,n,i,e.workspaceBrowser,p,r),tabs:d,rightContext:rf(n,i),rightInspection:Wm(e,i,p)}}function ym(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return bm(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}`,u=d?"\u25B8":"\u2022",p=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,m={id:`task:${c.id}`,taskId:c.id,text:`${u} ${p}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},k=Wa(c);k&&(m.prBadge=k),r.push(m)}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(u=>u.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 bm(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 u=t.selectedLeftItemId===`task:${d.id}`,p=u?"\u25B8":"\u2022",m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,k={id:`task:${d.id}`,taskId:d.id,text:`${p} ${m}`,indent:2,selected:u,focused:u&&t.focusedRegion==="tasks"},R=Wa(d);R&&(k.prBadge=R),e.push(k)}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 Pm(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 Sm(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,p)=>{let m=p===s.selectedIndex?"\u25B8":" ",k=u.kind==="repo"?" [git repo]":"/";return`${m} ${u.name}${k}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return ae(["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 ae(["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 ae([`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"?ae([`${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."]):ae([`${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===v&&t.openInspectionKind==="file"?Am(n,o,t.fileScrollOffset):e===v&&t.openInspectionKind==="diff"?xm(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?ae(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):ae(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Im(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:vm(o)}))??[];if(!t)return[{id:Rr,label:"EMPTY",active:r===Rr,focused:e.focusedRegion==="center"&&r===Rr}];let s=e.openInspectionKind||r===v?[{id:v,label:Em(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function Cm(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===v&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??v:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??v:Rr}function vm(e){return e.title.toUpperCase()}function Em(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?vt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Am(e,t,r){if(!e)return ae(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return ae(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=Na(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:""},...Dm(n.lines,r,s)]}function xm(e,t,r){if(!e)return ae(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return ae(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=Na(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:""},...$m(n.lines,r,s)]}function ae(e){return e.map(t=>({text:t}))}function Dm(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:_.lineNumber}},{text:" \u2502 ",style:{fg:_.gutter}},...ps(o,r)],tone:"default"}})}function $m(e,t,r){let n=Mm(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>Lm(o,r))}function Mm(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 Lm(e,t){let r=La(e.oldNumber),n=La(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:_.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:_.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?jm(ps(e.text,t),o.bg,o.fallbackFg):ps(e.text,t),l=o?{fg:_.lineNumber,bg:o.bg}:{fg:_.lineNumber},c=o?{fg:_.gutter,bg:o.bg}:{fg:_.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function La(e){return e===null?" ":String(e).padStart(4," ")}function Na(e){let t=vt.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 ps(e,t){return t==="diff"?Om(e):t==="markdown"?Fm(e):t==="json"?ms(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?ms(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 Om(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:_.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:_.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:_.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:_.diffMeta}}]:[{text:e}]}function jm(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function Fm(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:_.markup,bold:!0}}]:ms(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function ms(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:Nm(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function Nm(e){return e.startsWith("//")||e.startsWith("/*")?{fg:_.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:_.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:_.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:_.markup}:{fg:_.keyword}}function Wm(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"?_a(t.repoTargets??[]):s?.pullRequest??(t?D(t):null),i=[_m(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=Ba(e,t),l=fs(e,r),c=Km([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...Zm(e,r)]}:{title:"",rows:[...i,...fs(e,r)]}}function _m(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=gs(t),i=hs(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Oa(e){return[{text:" "},gs(e),{text:" "},hs(e)]}function Wa(e){if(e.type==="project"&&e.repoTargets?.length){let r=_a(e.repoTargets);return r?Oa(r):null}let t=D(e);return t?.number?Oa(t):null}function _a(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=qm(r);return{number:-1,status:Um(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 Um(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 qm(e){let t=e.map(r=>Ua(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function gs(e){return!e||!e.number?{text:xa,style:{fg:"565f89"}}:e.status==="merged"?{text:Da,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:$a,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:as,style:{fg:"565f89"}}:{text:as,style:{fg:"9ece6a"}}}function hs(e){return e?.aggregateReadiness?ja(e.aggregateReadiness):ja(Ua(e))}function ja(e){return e==="failed"?{text:us,style:{fg:"f7768e"}}:e==="pending"?{text:cs,style:{fg:"e0af68"}}:e==="success"?{text:ds,style:{fg:"9ece6a"}}:{text:ls,style:{fg:"565f89"}}}function Ua(e){let t=e?.requiredChecks??null;return e?.status==="merged"?"success":e?.status==="closed"||!e?.number||!t||t.length===0?"none":t.some(r=>r.status==="failed")||e.reviewDecision==="CHANGES_REQUESTED"?"failed":t.every(r=>r.status==="success"||r.status==="skipped")?qa(e)?"failed":Bm(e)?"success":"pending":"pending"}function Bm(e){return!!(e.mergeable&&!e.draft&&!qa(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function qa(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function Ba(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return Vm(e,t);let r=D(t),n=Ka("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var Tr=32;function Vm(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,p=Tr-u.length-1,m=c.length>p?c.slice(0,p-1)+"\u2026":c,k=Tr-m.length-u.length;r.push({id:`project-review:${i.repoId}`,text:m+" ".repeat(Math.max(1,k))+u,selected:a,focused:l,muted:!0})}else{let d=gs(i.pullRequest),u=hs(i.pullRequest),p=`${d.text} ${u.text}`,m=Tr-p.length-1,k=c.length>m?c.slice(0,m-1)+"\u2026":c,R=Tr-k.length-p.length,A=k+" ".repeat(Math.max(1,R));r.push({id:`project-review:${i.repoId}`,text:A+p,selected:a,focused:l,segments:[{text:A},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...Ka("target",o.branch,o.pullRequest))),r}function Va(e,t,r=null){return 3+Ba(e,t).length+fs(e,r).length}function Ka(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=Hm(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:Gm(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Ha(r.lastSyncedAt)}`,muted:!0}),s.push({id:n("checks-spacer"),text:""}),s.push({id:n("checks-header"),text:"Checks"}),r.requiredChecks.length?s.push(...r.requiredChecks.map(zm)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,p)=>Qm(u,n(`comment:${p}`))))),s}function Km(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 Hm(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function Gm(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Ha(e){if(!e)return"--";let t=Date.now()-new Date(e).getTime(),r=Math.floor(t/1e3);if(r<60)return`${r}s ago`;let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let s=Math.floor(n/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function zm(e){let{icon:t,color:r}=Jm(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," ")} ${Xm(e.status)}`,color:r,muted:!1}}function Qm(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Ha(e.createdAt)}`:"",s=Ym(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 Ym(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 Jm(e){switch(e){case"success":return{icon:ds,color:"9ece6a"};case"pending":return{icon:cs,color:"e0af68"};case"failed":return{icon:us,color:"f7768e"};case"skipped":return{icon:ls,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Xm(e){return e==="success"?"passing":e==="failed"?"failing":e}function Zm(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=ws(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?Ea:Aa:va(l.label),p=l.kind==="directory"?"7aa2f7":Ma(l.label),m=" ".repeat(l.depth),k=p?{text:u,style:{fg:p}}:{text:u},R=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},A=[{text:m},k,R];return{id:l.path,text:`${m}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:A}})]}function ws(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 fs(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(ef(t))return tf(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=>Ga(o,e,t))))}return r}function ef(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function tf(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=>Ga(c,e,t,s.length+1))))}}return r}function Ga(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 rf(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:vt.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 nf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function sf(e,t){return{name:h.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function za(e,t,r,n,s=null){if(s)return of(e,t,r,n,s);let o=Vn(e,t,{centerOnly:n});return af(r,o)?{output:Zi(o.rows,r.rows,o.row,o.column),region:o}:null}function of(e,t,r,n,s){let o=Mi(e,t,s,{centerOnly:n});if(!o||!lf(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:c})=>i[l]===c?"":(i[l]=c,`\x1B[${o.row+l};${o.column}H${c}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function af(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function lf(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}import{appendFile as cf,mkdir as df,readFile as uf}from"node:fs/promises";import pf from"node:path";var Qa=80,ks=async(e,t)=>{await df(pf.dirname(e.errorLogFile),{recursive:!0}),await cf(e.errorLogFile,mf(t),"utf8")},Ya=async(e,t)=>{try{await ks(e,t)}catch{}},Ts=async(e,t=Qa)=>{try{let n=(await uf(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
158
|
+
`).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(ff(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},Ja=async(e,t=Qa)=>Ts(e,t);function mf(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(`
|
|
159
159
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
160
160
|
`)}
|
|
161
161
|
|
|
162
|
-
`}function Xm(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var rt={appendErrorLog:ms,appendErrorLogBestEffort:Wa,readErrorLog:fs,readRecentErrorLines:_a};var Zm=["tasks","center","inspector"];function ef(e,t,r){if(t==="ESCAPE")return w({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return w({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return hs(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return ks({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return w({state:{...e,fileSearchQuery:n},changed:!0})}return w({state:e})}function ks(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return mi(t)?w({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):w({state:e});if(e.fileSearchQuery!==null)return ef(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return w({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return w({state:e,exit:!0});if(t==="ESCAPE")return w({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return w({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(rr(e.selectedLeftItemId)||nr(e.selectedLeftItemId)))return w({state:{...e,selectedRunner:tr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return qa(e,1);if(t==="SHIFT_TAB"||t==="[")return qa(e,-1);if(t==="z"||t==="Z")return w({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===v?Ce(e,-1,r):hs(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===v?Ce(e,1,r):hs(e,1,r);if(t==="PAGE_UP")return Ce(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Ce(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Ce(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Ce(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??$,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return w({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=cf(e,t);return w({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return w({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&bt(e.selectedLeftItemId)&&e.selectedTaskId)return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Ti(e.selectedLeftItemId)&&e.selectedWorkspaceId)return w({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Ka(e.activeTab,r.ptyTabIds??[]))return w({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return gs(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ua(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return gs(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ua(e,1)}if(ne(t)){if(e.focusedRegion==="tasks"&&(rr(e.selectedLeftItemId)||nr(e.selectedLeftItemId))){let n=Dn(e.selectedLeftItemId),s=$n(e.selectedLeftItemId);return w({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return w({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&bt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return w({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Ze(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Ka(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return w({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Ze(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===v)return w({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return w({state:nf({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return w({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:v,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?w({state:{...e,selectedDiffPath:n,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?w({state:e}):e.selectedActionId==="refresh-checks"?w({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return w({state:e})}function Ce(e,t,r){if(t===0)return w({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?Va(e,t,r):e.inspectionMode==="review"?Ba(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):w({state:e});if(e.focusedRegion==="center"&&e.activeTab===v){if(e.openInspectionKind==="file")return Ba(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return sf(e,t,r)}return w({state:e})}function qa(e,t){return Tr(e,"focusedRegion",Zm,t)}function gs(e,t,r){let n=Tr(e,"activeTab",r&&r.length>0?r:df(e),t);return!n.changed||hi(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Ze(n.state.activeTab)??n.state.preferredPtyTabKind}}}function hs(e,t,r){if(e.focusedRegion==="tasks")return tf(e,t,r.leftItemIds);if(e.focusedRegion==="center")return gs(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Va(e,t,r);if(r.projectTargetIds?.length){let s=ws(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=ws(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:Tr(e,"selectedActionId",li,t)}return Tr(e,"selectedActionId",En,t)}function tf(e,t,r){let n=ws(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=xn(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=Dn(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=$n(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function rf(e,t){if(e.inspectionMode===t)return w({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?v:e.activeTab;return w({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Ua(e,t){return rf(e,lf(e.inspectionMode,An,t))}function Va(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return w({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=he(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return w({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return w({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?v:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function nf(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 Ba(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=he(e[t]+r,0,o);return i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function sf(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return of(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=he(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=he(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?w({state:e}):w({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:v,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?w({state:e}):w({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=he(i,0,o);return c===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function of(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=he(e.diffScrollOffset+t,0,o),a=af(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?w({state:e}):w({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function af(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Tr(e,t,r,n){let s=r.indexOf(e[t]),o=he(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function ws(e,t,r,n,s=!1){if(r.length===0)return w({state:e});let o=r.indexOf(e[t]??r[0]??""),i=he(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?w({state:e}):w({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function lf(e,t,r){let n=t.indexOf(e);return t[he(n+r,0,t.length-1)]??e}function w(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function Ka(e,t){return t.includes(e)}function cf(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Ze(e.activeTab)??e.preferredPtyTabKind}function df(e){return[e.selectedPtyTabId,e.openInspectionKind?v:null].filter(t=>typeof t=="string")}function he(e,t,r){return Math.min(r,Math.max(t,e))}var Ga=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 X(n.paths,e.selectedTaskId),i=t??uf(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 P(n.paths,l),l});return{updatedTask:s,nextShell:{activeTab:s.selectedPtyTabId??e.activeTab,selectedPtyTabId:s.selectedPtyTabId,preferredPtyTabKind:s.ptyTabs.at(-1)?.kind??e.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${s.ptyTabs.at(-1)?.title??"tab"}`}}},Ha=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 X(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await P(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},za=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await X(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await P(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Qa=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await X(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await P(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=Ya(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await X(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await P(t.paths,{...s,selectedPtyTabId:o.id});return}await P(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function uf(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(f=>f.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),p=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...p?{runner:p}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?h.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var nt=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Ja=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=Me();await y(Le(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 nt(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}},Xa=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Za=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 X(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}`}}},el=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},tl=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await rt.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var rl=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 nl=async(e,t,r)=>{let n=h.runners.setRunnerEnabled(r.config,e,t);return await h.save(r.paths,n),n},sl=async(e,t,r)=>{let n=h.runners.setRunnerPath(r.config,e,t);return await h.save(r.paths,n),n},ol=async(e,t,r)=>{let n=h.previews.setEnabled(r.config,e,t);return await h.save(r.paths,n),n};var pf=250;function we(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function We(e,t){return ge(t,e.ptyRuntime.getViewState(xt(e,t)))}function xt(e,t){let r=we(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function g(e,t){return We(e,Ri(t,e.model))}function il(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:g(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function al(e,t,r){return il(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return il(e,t,{tone:"error",message:r})}function O(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return rt.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function M(e,t){if(!e.uiStateFile)return;e.runtimeState=ui(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Te({uiStateFile:e.uiStateFile},r),()=>Te({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function mf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function U(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:z,queueTaskMutation:t=>mf(e,t)}}function Ts(e,t){let r=we(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?ps(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:Fe(e.model),centerTabIds:ki(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:Ma(t,r,s),pageRows:Math.max(5,ee(e.activeTerminal.width,e.activeTerminal.height).height-N.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function ll(e,t){await za(t,U(e))}async function B(e){e.model=await Se(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:g(e,e.state.shell)}:e.state={...e.state,shell:g(e,e.state.shell)}}async function Rr(e,t){let r=++e.inspectionRefreshSequence,n=Mn(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await Yo(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await Se(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},M(e,e.state.shell),e.render())}function cl(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&Rr(e,r).catch(n=>{let s=O(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},pf))}function dl(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=Ce(e.state.shell,r,Ts(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),Rr(e,e.state.shell).catch(s=>{let o=O(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render()}},16)))}function Rs(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function ys(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 pl(e){ys(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function ml(e,t){let r=g(e,t),n=we(e.model.tasks,r),s=xt(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 ge(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,Ie(ee(e.activeTerminal.width,e.activeTerminal.height)));return ge({...r,inputMode:"control"},i)}function fl(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 Ps(e,t){try{let r=g(e,t),n=we(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 ul(e,n),await B(e),s=n.selectedPtyTabId)}n&&!s&&(n=await ul(e,n),await B(e),s=n.selectedPtyTabId);let o=g(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:ge({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},M(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,Ie(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ct(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ge({...o,inputMode:"terminal"},i)},M(e,e.state.shell)}catch(r){let n=O(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Ct(t.selectedPtyTabId)&&(await ff(e,t.selectedTaskId,n).catch(()=>{}),await B(e).catch(()=>{})),e.state={mode:"main",shell:j(e,pi(g(e,t),n),n)},M(e,e.state.shell)}e.render()}async function ff(e,t,r){await Xa(t,r,U(e))}async function gl(e,t,r,n){let s=g(e,t),{nextShell:o}=await Ga(s,r,n,U(e));return await B(e),g(e,{...s,...o})}async function hl(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await Ha(r,U(e));return e.ptyRuntime.disposeSession(n.id),await B(e),g(e,{...r,...s})}async function wl(e,t){let r=g(e,t),n=Fe(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Za(r,U(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await B(e),g(e,{...r,...i,selectedLeftItemId:gf(n,Fe(e.model),s)})}async function kl(e,t){let r=g(e,t),{nextShell:n}=await rl(r,U(e));return await B(e),g(e,{...r,...n})}async function ul(e,t){return Qa(t,U(e))}function yr(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:We(e,e.state.shell)},e.render())},16))}function gf(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Tl(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await el(e.model.tasks,U(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Se(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:g(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,tl("background PR polling",t,U(e)))}finally{e.prPollInFlight=!1}}}async function Rl(e,t){let r=g(e,t),n=we(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await C.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await B(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await C.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await B(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${D(a)?.requiredChecks.length??0} reported`)}return g(e,{...al(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Rf from"node:path";import{readdir as hf,stat as wf}from"node:fs/promises";import yl from"node:path";async function kf(e){let t=await hf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=yl.join(e,n.name);r.push({name:n.name,path:s,kind:await Tf(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 Pl(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function bl(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 Pr(e,t){let r=await kf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Tf(e){let t=yl.join(e,".git");return await wf(t).catch(()=>null)!==null}function Sl(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Il(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function yf(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:g(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Ja(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,U(e));n=s.task,await B(e);let o=g(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??ji(n,"agent"),Ie(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ct(o.selectedPtyTabId),e.state={mode:"main",shell:ge(o,i)},M(e,e.state.shell)}catch(s){s instanceof nt&&(n=s.task);let o=O(e,"create task",s,"Failed to create task.");n&&!(s instanceof nt)?(await P(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await B(e).catch(()=>{})):n&&(await P(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await B(e).catch(()=>{})),e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function Pf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ne(t)){yf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:g(e,{...r,selectedRunner:tr(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}fi(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function bf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Pl(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){Pr(e,Rf.dirname(r.cwd)).catch(s=>{let o=O(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ne(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){Pr(e,s.path).catch(i=>{let a=O(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=U(e);o.addWorkspace(e.paths,s.path).then(async i=>{await B(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},M(e,e.state.shell),e.render()}).catch(i=>{let a=O(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function Sf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=ma(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;If(e,n)}}}async function If(e,t){let r;try{r=await rt.readRecentErrorLines(e.paths)}catch(n){let s=O(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 Cf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=ga(Sl(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"?nl(r.runner,r.enabled,U(e)):sl(r.runner,r.path,U(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:g(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=O(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,g(e,e.state.shell),o),runnerOptions:{...Sl(e),message:o}},e.render()})}function vf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=fa(Il(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}ol(r.feature,r.enabled,U(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=O(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:j(e,g(e,e.state.shell),s),previewOptions:{...Il(e),message:s}},e.render()})}}function Cl(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){Pf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){bf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Af(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=ks(e.state.shell,r,Ts(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ne(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=vt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(Ef(e,r))return;e.lastTerminalKey=Oi(r)?{key:r,at:Date.now()}:null;let o=Fi(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){yr(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){Pr(e,e.workspaceRoot).catch(s=>{let o=O(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){gl(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Ps(e,s)}).catch(s=>{let o=O(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){hl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=O(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Rl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=O(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=we(e.model.tasks,n.state),o=s?D(s)?.url??null:null;o?bl(o).catch(i=>{let a=O(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){wl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=O(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){kl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=O(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){Ps(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){cl(e,e.state.shell);return}Rr(e,e.state.shell).catch(s=>{let o=O(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},ll(e,e.state.shell).catch(()=>{}),M(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Sf(e,r);return}if(e.state.variant==="runners"){Cf(e,r);return}if(e.state.variant==="previews"){vf(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ne(r)){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render()}return}if(e.state.optionsMessage){(r==="ESCAPE"||ne(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ne(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;ml(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},M(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=O(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,g(e,e.state.shell),i)},M(e,e.state.shell),e.render()})}):pl(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 vl(e,t){let r=Ui(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=vt(o);if(i){Al(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(Bn(o)){e.pendingTerminalKeySequence.raw=o,El(e);return}br(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},M(e,e.state.shell),e.render();return}let n=Ni(r);if(n!==0){yr(e,n);return}let s=vt(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
|
+
`}function ff(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var tt={appendErrorLog:ks,appendErrorLogBestEffort:Ya,readErrorLog:Ts,readRecentErrorLines:Ja};var gf=["tasks","center","inspector"];function hf(e,t,r){if(t==="ESCAPE")return w({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return w({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return ys(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Ps({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return w({state:{...e,fileSearchQuery:n},changed:!0})}return w({state:e})}function Ps(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Ti(t)?w({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):w({state:e});if(e.fileSearchQuery!==null)return hf(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return w({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return w({state:e,exit:!0});if(t==="ESCAPE")return w({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return w({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(nr(e.selectedLeftItemId)||sr(e.selectedLeftItemId)))return w({state:{...e,selectedRunner:rr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Xa(e,1);if(t==="SHIFT_TAB"||t==="[")return Xa(e,-1);if(t==="z"||t==="Z")return w({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===v?Ce(e,-1,r):ys(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===v?Ce(e,1,r):ys(e,1,r);if(t==="PAGE_UP")return Ce(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Ce(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Ce(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Ce(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??$,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return w({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=Sf(e,t);return w({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return w({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&yt(e.selectedLeftItemId)&&e.selectedTaskId)return w({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Si(e.selectedLeftItemId)&&e.selectedWorkspaceId)return w({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&tl(e.activeTab,r.ptyTabIds??[]))return w({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Rs(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Za(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Rs(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Za(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(nr(e.selectedLeftItemId)||sr(e.selectedLeftItemId))){let n=Nn(e.selectedLeftItemId),s=Wn(e.selectedLeftItemId);return w({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return w({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&yt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return w({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Xe(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&tl(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return w({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Xe(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===v)return w({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return w({state:Tf({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return w({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:v,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?w({state:{...e,selectedDiffPath:n,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?w({state:e}):e.selectedActionId==="refresh-checks"?w({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?w({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):w({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return w({state:e})}function Ce(e,t,r){if(t===0)return w({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?rl(e,t,r):e.inspectionMode==="review"?el(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):w({state:e});if(e.focusedRegion==="center"&&e.activeTab===v){if(e.openInspectionKind==="file")return el(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return Rf(e,t,r)}return w({state:e})}function Xa(e,t){return yr(e,"focusedRegion",gf,t)}function Rs(e,t,r){let n=yr(e,"activeTab",r&&r.length>0?r:If(e),t);return!n.changed||yi(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Xe(n.state.activeTab)??n.state.preferredPtyTabKind}}}function ys(e,t,r){if(e.focusedRegion==="tasks")return wf(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Rs(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return rl(e,t,r);if(r.projectTargetIds?.length){let s=bs(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=bs(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:yr(e,"selectedActionId",fi,t)}return yr(e,"selectedActionId",Ln,t)}function wf(e,t,r){let n=bs(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Fn(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=Nn(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=Wn(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function kf(e,t){if(e.inspectionMode===t)return w({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?v:e.activeTab;return w({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Za(e,t){return kf(e,Pf(e.inspectionMode,On,t))}function rl(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return w({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=ge(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return w({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return w({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?v:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Tf(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 el(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=ge(e[t]+r,0,o);return i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Rf(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return yf(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=ge(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=ge(i,0,o);return d===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:v,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?w({state:e}):w({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?w({state:{...e,selectedDiffPath:d,activeTab:v,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?w({state:e}):w({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=ge(i,0,o);return c===e.diffScrollOffset?w({state:e}):w({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function yf(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=ge(e.diffScrollOffset+t,0,o),a=bf(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?w({state:e}):w({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function bf(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function yr(e,t,r,n){let s=r.indexOf(e[t]),o=ge(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?w({state:e}):w({state:{...e,[t]:i,actionMessage:null},changed:!0})}function bs(e,t,r,n,s=!1){if(r.length===0)return w({state:e});let o=r.indexOf(e[t]??r[0]??""),i=ge(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?w({state:e}):w({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function Pf(e,t,r){let n=t.indexOf(e);return t[ge(n+r,0,t.length-1)]??e}function w(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function tl(e,t){return t.includes(e)}function Sf(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Xe(e.activeTab)??e.preferredPtyTabKind}function If(e){return[e.selectedPtyTabId,e.openInspectionKind?v:null].filter(t=>typeof t=="string")}function ge(e,t,r){return Math.min(r,Math.max(t,e))}var nl=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 ee(n.paths,e.selectedTaskId),i=t??Cf(o,e.activeTab,e.preferredPtyTabKind),a=al(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await b(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"}`}}},sl=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 ee(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 b(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}`}}},ol=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await ee(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await b(t.paths,{...n,selectedPtyTabId:e.activeTab})})},il=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await b(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=al(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await b(t.paths,{...s,selectedPtyTabId:o.id});return}await b(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Cf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function al(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(m=>m.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),p=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...p?{runner:p}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?h.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var rt=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},ll=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=$e();await y(Me(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 rt(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}},cl=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},dl=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 ee(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}`}}},ul=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},br=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await tt.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var pl=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 ml=async(e,t,r)=>{let n=h.runners.setRunnerEnabled(r.config,e,t);return await h.save(r.paths,n),n},fl=async(e,t,r)=>{let n=h.runners.setRunnerPath(r.config,e,t);return await h.save(r.paths,n),n},gl=async(e,t,r)=>{let n=h.previews.setEnabled(r.config,e,t);return await h.save(r.paths,n),n};var vf=250;function he(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function Ne(e,t){return fe(t,e.ptyRuntime.getViewState(Et(e,t)))}function Et(e,t){let r=he(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function g(e,t){return Ne(e,Ii(t,e.model))}function hl(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:g(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function wl(e,t,r){return hl(e,t,r?{tone:"success",message:r}:null)}function O(e,t,r){return hl(e,t,{tone:"error",message:r})}function j(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return tt.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function M(e,t){if(!e.uiStateFile)return;e.runtimeState=wi(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Te({uiStateFile:e.uiStateFile},r),()=>Te({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Ef(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function F(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:Q,queueTaskMutation:t=>Ef(e,t)}}function Ss(e,t){let r=he(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?ws(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:je(e.model),centerTabIds:Pi(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:Va(t,r,s),pageRows:Math.max(5,re(e.activeTerminal.width,e.activeTerminal.height).height-W.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function kl(e,t){await ol(t,F(e))}async function B(e){e.model=await Se(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:g(e,e.state.shell)}:e.state={...e.state,shell:g(e,e.state.shell)}}async function Pr(e,t){let r=++e.inspectionRefreshSequence,n=_n(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await ri(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await Se(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},M(e,e.state.shell),e.render())}function Tl(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&Pr(e,r).catch(n=>{let s=j(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},vf))}function Rl(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=Ce(e.state.shell,r,Ss(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),Pr(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render()}},16)))}function Is(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Cs(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 bl(e){Cs(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function Pl(e,t){let r=g(e,t),n=he(e.model.tasks,r),s=Et(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 fe(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,Ie(re(e.activeTerminal.width,e.activeTerminal.height)));return fe({...r,inputMode:"control"},i)}function Sl(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 vs(e,t){try{let r=g(e,t),n=he(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 yl(e,n),await B(e),s=n.selectedPtyTabId)}n&&!s&&(n=await yl(e,n),await B(e),s=n.selectedPtyTabId);let o=g(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:fe({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},M(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,Ie(re(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=St(s),e.lastTerminalKey=null,e.state={mode:"main",shell:fe({...o,inputMode:"terminal"},i)},M(e,e.state.shell)}catch(r){let n=j(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&St(t.selectedPtyTabId)&&(await Af(e,t.selectedTaskId,n).catch(()=>{}),await B(e).catch(()=>{})),e.state={mode:"main",shell:O(e,ki(g(e,t),n),n)},M(e,e.state.shell)}e.render()}async function Af(e,t,r){await cl(t,r,F(e))}async function Il(e,t,r,n){let s=g(e,t),{nextShell:o}=await nl(s,r,n,F(e));return await B(e),g(e,{...s,...o})}async function Cl(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await sl(r,F(e));return e.ptyRuntime.disposeSession(n.id),await B(e),g(e,{...r,...s})}async function vl(e,t){let r=g(e,t),n=je(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await dl(r,F(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await B(e),g(e,{...r,...i,selectedLeftItemId:xf(n,je(e.model),s)})}async function El(e,t){let r=g(e,t),{nextShell:n}=await pl(r,F(e));return await B(e),g(e,{...r,...n})}async function yl(e,t){return il(t,F(e))}function Sr(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:Ne(e,e.state.shell)},e.render())},16))}function xf(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Al(e,t){if(!(t?.aborted||e.state.mode!=="main"))try{if(await ul(e.model.tasks,F(e)),t?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;let r=await Se(e.workspaceRoot,e.state.shell,e.enabledRunnerIds);if(t?.aborted)return;e.model=r,e.state={mode:"main",shell:g(e,e.state.shell)},e.render()}catch(r){if(t?.aborted)return;let n=r instanceof Error?r.message:"Background PR discovery failed.";n!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=n,br("background PR polling",r,F(e)))}}async function xl(e,t){let r=g(e,t),n=he(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await C.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await B(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await C.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await B(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${D(a)?.requiredChecks.length??0} reported`)}return g(e,{...wl(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Of from"node:path";import{readdir as Df,stat as $f}from"node:fs/promises";import Dl from"node:path";async function Mf(e){let t=await Df(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Dl.join(e,n.name);r.push({name:n.name,path:s,kind:await Lf(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 $l(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Ml(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 Mf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Lf(e){let t=Dl.join(e,".git");return await $f(t).catch(()=>null)!==null}function Ll(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Ol(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function jf(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:g(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await ll(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,F(e));n=s.task,await B(e);let o=g(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??Vi(n,"agent"),Ie(re(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=St(o.selectedPtyTabId),e.state={mode:"main",shell:fe(o,i)},M(e,e.state.shell)}catch(s){s instanceof rt&&(n=s.task);let o=j(e,"create task",s,"Failed to create task.");n&&!(s instanceof rt)?(await b(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await B(e).catch(()=>{})):n&&(await b(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await B(e).catch(()=>{})),e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function Ff(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(oe(t)){jf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:g(e,{...r,selectedRunner:rr(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}Ri(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Nf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=$l(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){Ir(e,Of.dirname(r.cwd)).catch(s=>{let o=j(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:O(e,g(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=j(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=F(e);o.addWorkspace(e.paths,s.path).then(async i=>{await B(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},M(e,e.state.shell),e.render()}).catch(i=>{let a=j(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function Wf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Sa(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;_f(e,n)}}}async function _f(e,t){let r;try{r=await tt.readRecentErrorLines(e.paths)}catch(n){let s=j(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function Uf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Ca(Ll(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"?ml(r.runner,r.enabled,F(e)):fl(r.runner,r.path,F(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:g(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:h.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=j(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:O(e,g(e,e.state.shell),o),runnerOptions:{...Ll(e),message:o}},e.render()})}function qf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=Ia(Ol(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}gl(r.feature,r.enabled,F(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=j(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:O(e,g(e,e.state.shell),s),previewOptions:{...Ol(e),message:s}},e.render()})}}function jl(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){Ff(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Nf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Vf(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=Ps(e.state.shell,r,Ss(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&oe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=It(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(Bf(e,r))return;e.lastTerminalKey=Ki(r)?{key:r,at:Date.now()}:null;let o=Hi(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){Sr(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){Ir(e,e.workspaceRoot).catch(s=>{let o=j(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:O(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Il(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{vs(e,s)}).catch(s=>{let o=j(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Cl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){xl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=he(e.model.tasks,n.state),o=s?D(s)?.url??null:null;o?Ml(o).catch(i=>{let a=j(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:O(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:O(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){vl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){El(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){vs(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){Tl(e,e.state.shell);return}Pr(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},kl(e,e.state.shell).catch(()=>{}),M(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Wf(e,r);return}if(e.state.variant==="runners"){Uf(e,r);return}if(e.state.variant==="previews"){qf(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:2,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:g(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:g(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;Pl(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},M(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=j(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:O(e,g(e,e.state.shell),i)},M(e,e.state.shell),e.render()})}):bl(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 Fl(e,t){let r=Ji(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=It(o);if(i){Wl(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(Qn(o)){e.pendingTerminalKeySequence.raw=o,Nl(e);return}Cr(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},M(e,e.state.shell),e.render();return}let n=Gi(r);if(n!==0){Sr(e,n);return}let s=It(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
163
163
|
`&&r!==`\r
|
|
164
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),
|
|
164
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),Yi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function Bf(e,t){if(e.pendingTerminalKeySequence){let r=zi(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=It(n);if(s)return Wl(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(Qn(n))return e.pendingTerminalKeySequence.raw=n,Nl(e),!0}return Cr(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>Cr(e),30)},!0)}function Nl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>Cr(e),30))}function Cr(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function Wl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function _l(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){Rl(e,zn(t));return}let r=zn(t);r!==0&&Sr(e,r)}function Vf(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var vr=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=Ul(t.resolutionMs??1e3,"Heartbeat resolution"),this.now=t.now??Date.now,this.onError=t.onError}register(t){if(this.jobs.has(t.id))throw new Error(`Heartbeat job "${t.id}" is already registered.`);let r={...t,intervalMs:Ul(t.intervalMs,`Heartbeat job "${t.id}" interval`),inFlight:!1,nextRunAt:this.timer?this.now()+t.intervalMs:null};this.jobs.set(t.id,r)}start(){if(this.timer)return;let t=this.now();for(let r of this.jobs.values())r.nextRunAt=t+r.intervalMs;this.abortController=new AbortController,this.timer=setInterval(()=>this.tick(),this.resolutionMs)}stop(){this.abortController?.abort(),this.abortController=null,this.timer&&(clearInterval(this.timer),this.timer=null);for(let t of this.jobs.values())t.nextRunAt=null}tick(){let t=this.abortController?.signal;if(!t)return;let r=this.now();for(let n of this.jobs.values())n.inFlight||n.nextRunAt===null||r<n.nextRunAt||(n.inFlight=!0,n.nextRunAt=r+n.intervalMs,Promise.resolve().then(()=>n.run(t)).catch(s=>{if(!t.aborted)return Promise.resolve(this.onError(n.id,s)).catch(()=>{})}).finally(()=>{n.inFlight=!1}))}};function Ul(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var Hf=Kf(import.meta.url),Gf=Hf("terminal-kit"),zf=Gf.terminal;function Es(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function ql(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Qf(e,t){return e?e.tabId!==t.tabId?{tabId:t.tabId,kind:"full"}:e.kind==="full"||t.kind==="full"?{tabId:t.tabId,kind:"full"}:{tabId:t.tabId,kind:"rows",rowIndices:[...new Set([...e.rowIndices,...t.rowIndices])]}:t}async function Bl(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ce(t),n=await h.load(r),s=h.runners.getEnabled(n),o=e.uiStateFile?await _e({uiStateFile:e.uiStateFile}):null,i=await Se(t,void 0,s),a=Rt(hi(o,n),i);i=await Se(t,a,s);let l={current:i},c=()=>{},d={workspaceRoot:t,onUpdate:p=>c(p),resolveSessionSpec:(p,m)=>Bi(l.current,m,t)},u=e.ptyRuntime??await da({...d,paths:r,viewUpdateMode:h.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot"});return new Promise(p=>{let m=e.terminal??zf,k=null,R=null,A=null,K=null,f={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Rt(a,i)},get model(){return l.current},set model(T){l.current=T},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,lastBackgroundPrPollError:null,versionText:`Craig v${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:m,ptyRuntime:u,resolve:p,render:()=>{},exit:T=>p(T)},we=new vr({onError:(T,X)=>br(`heartbeat job "${T}"`,X,F(f))});c=T=>{f.state.mode==="main"&&(K=Qf(K,T),f.ptyRenderTimer||(f.ptyRenderTimer=setTimeout(()=>{f.ptyRenderTimer=null;let X=K;if(K=null,f.state.mode==="main"){let ke=Ne(f,f.state.shell);if(f.state={mode:"main",shell:ke},!h.previews.isEnabled(f.config,"incrementalCenterPane")||!A||!R){f.render();return}let $t=re(m.width,m.height),As={...A,terminal:ke.terminal},Mt=za($t,As,R,ke.centerZoomed,X?.kind==="rows"?X.rowIndices:null);if(!Mt){f.render();return}Mt.output.length>0&&m.noFormat(Mt.output),A=As,R=Mt.region,m.hideCursor(!0)}},h.previews.isEnabled(f.config,"incrementalCenterPane")?0:50)))},f.render=()=>{Sl(f);let T=f.state;f.ptyRuntime.setViewedTab?.(T.mode==="main"?Et(f,T.shell):null);let X=re(m.width,m.height),ke;if(T.mode==="main"){let Ar=Fa(g(f,T.shell),f.model),$t=$i(X,Ar,{centerOnly:T.shell.centerZoomed,focusFlashActive:f.focusFlashUntil!==null&&Date.now()<f.focusFlashUntil});ke=$t.frame,A=Ar,R=$t.center}else ke=T.variant==="boot"?Ei(X,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:f.versionText,updateText:f.updateText}):T.variant==="pause"?Ai(X,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:f.versionText,updateText:f.updateText}):T.variant==="options"?pr(X,{menuIndex:T.menuIndex,optionsMenuItems:os}):T.variant==="runners"?pr(X,{menuIndex:Es(T).menuIndex,optionsMenuItems:is(f.config,Es(T)),optionsMessage:ya(Es(T)),optionsSubtitle:"Runners"}):T.variant==="previews"?pr(X,{menuIndex:ql(T).menuIndex,optionsMenuItems:ba(f.config),optionsMessage:Pa(ql(T)),optionsSubtitle:"Feature Previews - Experimental"}):T.variant==="error-log"?Di(X,{errorLogPath:T.errorLog?.path??r.errorLogFile,errorLogLines:T.errorLog?.lines??[]}):xi(X),A=null,R=null;f.pendingClear&&(m.moveTo(1,1),m.eraseDisplayBelow(),f.pendingClear=!1,k=null),m.noFormat(Xi(ke,k)),k=ke,m.hideCursor(!0)};let S=T=>jl(f,T),ne=T=>Fl(f,T),At=T=>_l(f,T),Er=()=>{process.stdout.off("resize",xt),process.off("SIGCONT",Dt),m.removeListener("key",S),m.removeListener("unknown",ne),m.removeListener("mouse",At),f.scrollRenderTimer&&(clearTimeout(f.scrollRenderTimer),f.scrollRenderTimer=null),f.inspectionScrollRenderTimer&&(clearTimeout(f.inspectionScrollRenderTimer),f.inspectionScrollRenderTimer=null),f.leftNavInspectionTimer&&(clearTimeout(f.leftNavInspectionTimer),f.leftNavInspectionTimer=null),f.pendingTerminalKeySequence&&(clearTimeout(f.pendingTerminalKeySequence.timer),f.pendingTerminalKeySequence=null),f.ptyRenderTimer&&(clearTimeout(f.ptyRenderTimer),f.ptyRenderTimer=null),f.footerToastTimer&&(clearTimeout(f.footerToastTimer),f.footerToastTimer=null),f.focusFlashTimer&&(clearTimeout(f.focusFlashTimer),f.focusFlashTimer=null),we.stop(),f.ptyRuntime.disposeAll(),m.grabInput(!1),m.hideCursor(!1),m.fullscreen(!1)};f.exit=T=>{Er(),p(T)};let xt=()=>{Is(f),f.state.mode==="main"&&f.state.shell.inputMode==="terminal"&&(f.ptyRuntime.resize(Ie(re(m.width,m.height))),f.state={mode:"main",shell:Ne(f,f.state.shell)}),f.render()},Dt=()=>{Is(f),f.state.mode==="main"&&f.state.shell.inputMode==="terminal"&&(f.ptyRuntime.resize(Ie(re(m.width,m.height))),f.state={mode:"main",shell:Ne(f,f.state.shell)}),f.render()};process.stdout.on("resize",xt),process.on("SIGCONT",Dt),m.grabInput(!0),f.inputCaptureMode="control",m.hideCursor(!0),m.fullscreen(!0),m.on("key",S),m.on("unknown",ne),m.on("mouse",At),we.register({id:"github.pull-requests",intervalMs:(f.config.github?.watchIntervalSeconds??5)*1e3,run:T=>Al(f,T)}),we.start(),h.version.checkForUpdate().then(T=>{T.updateAvailable&&T.latest&&(f.updateText=`Update available: v${T.latest}`,f.render())}),f.bootHydrationReady=Cs(f).catch(()=>{}),f.render()})}async function Yf(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=ce(i);return await ua(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=ce(i);return await pa(a),0}let e=Bs(process.argv.slice(2)),t=process.cwd(),r=ce(t),n={paths:r};if(e.mode==="interactive")return await Bl({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await Zo(e.command,n),o=ei(s);return o.length>0&&process.stdout.write(`${o}
|
|
165
165
|
`),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
166
|
-
`),1}}var
|
|
166
|
+
`),1}}var Jf=await Yf();process.exit(Jf);
|