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