craig-cli 0.7.6 → 0.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +41 -41
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var nl=Object.defineProperty;var ar=(e,t)=>{for(var r in t)nl(e,r,{get:t[r],enumerable:!0})};import{readFile as ll}from"node:fs/promises";import{randomUUID as sl}from"node:crypto";import{open as ol,readFile as nm,rename as il,rm as al}from"node:fs/promises";import lr from"node:path";async function M(e,t){let r=lr.dirname(e),n=lr.join(r,`.${lr.basename(e)}.${process.pid}.${Date.now()}.${sl()}.tmp`),s=await ol(n,"w");try{let o=`${JSON.stringify(t,null,2)}
3
- `;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await il(n,e)}catch(o){throw await s.close().catch(()=>{}),await al(n,{force:!0}).catch(()=>{}),o}}async function Me(e){try{let t=await ll(e.uiStateFile,"utf8"),r=JSON.parse(t);return cl(r,e.uiStateFile)}catch(t){if(ul(t))return null;throw t}}async function me(e,t){await M(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function yt(){return{version:1,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null,selectedPtyTabId:null,inputMode:"control",focusedRegion:"tasks",activeTab:"agent",inspectorSection:"task",inspectionMode:"files",openInspectionKind:null,selectedFileTreePath:null,selectedFilePath:null,selectedDiffPath:null,collapsedFileTreePaths:[],selectedActionId:"commit",updatedAt:new Date().toISOString()}}function cl(e,t){if(typeof e!="object"||e===null||e.version!==1||!(e.selectedRepoId===null||typeof e.selectedRepoId=="string")||!(e.selectedWorkspaceId===null||typeof e.selectedWorkspaceId=="string")||!(e.selectedTaskId===null||typeof e.selectedTaskId=="string")||!(e.selectedPtyTabId===void 0||e.selectedPtyTabId===null||typeof e.selectedPtyTabId=="string")||!Le(e,"inputMode")||!Le(e,"focusedRegion")||!Le(e,"activeTab")||!Le(e,"inspectorSection")||!Le(e,"inspectionMode")||!Rt(e,"openInspectionKind")||!Rt(e,"selectedFileTreePath")||!Rt(e,"selectedFilePath")||!Rt(e,"selectedDiffPath")||!dl(e,"collapsedFileTreePaths")||!Le(e,"selectedActionId")||typeof e.updatedAt!="string")throw new Error(`Craig UI state at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}function Le(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Rt(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function dl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function ul(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var cr={};ar(cr,{RUNNER_IDS:()=>x,assertEnabled:()=>ns,buildCommand:()=>is,getConfiguredProfile:()=>Pt,getDefault:()=>rs,getDisplayName:()=>os,getEnabled:()=>bt,getProfile:()=>Oe,isRunnerType:()=>St,parse:()=>ss,setRunnerEnabled:()=>as,setRunnerPath:()=>ls});var x=["codex","cursor","claude"];var ts={codex:{id:"codex",displayName:"Codex",executable:"codex",defaultAgentTitle:"Codex"},cursor:{id:"cursor",displayName:"Cursor",executable:"cursor-agent",defaultAgentTitle:"Cursor"},claude:{id:"claude",displayName:"Claude",executable:"claude",defaultAgentTitle:"Claude"}};var Oe=e=>ts[e];var Pt=(e,t={})=>{let r=Oe(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var bt=(e={})=>x.filter(t=>e.runners?.[t]?.enabled!==!1);var rs=(e={})=>{let t=bt(e);if(t.length===0)throw new Error("No runners are enabled. Enable at least one runner in .craig/config.json.");return t.includes("codex")?"codex":t[0]};var ns=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var St=e=>x.includes(e);var ss=e=>{if(!e||e.length===0)return"codex";if(!St(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${x.join(", ")}.`);return e};var os=e=>Oe(e).displayName;var is=(e,t,r={})=>{let n=[Pt(e,r).executable];return t&&t.length>0&&n.push(t),n};var as=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var ls=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};import{mkdir as pl,readFile as fl,writeFile as ml}from"node:fs/promises";import gl from"node:path";var hl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",cs=async e=>{try{return await fl(e,"utf8")}catch(t){if(hl(t))return null;throw t}},ds=async(e,t)=>{await pl(gl.dirname(e),{recursive:!0}),await ml(e,t,"utf8")};var It=(e,t)=>{if(typeof e!="object"||e===null)throw new Error(`Craig config at ${t} is invalid. Expected a JSON object.`);let r=e;if(r.runners!==void 0){if(typeof r.runners!="object"||r.runners===null||Array.isArray(r.runners))throw new Error(`Craig config at ${t} is invalid. "runners" must be an object.`);for(let[n,s]of Object.entries(r.runners)){if(!x.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${x.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" must be an object.`);let o=s;if(o.enabled!==void 0&&typeof o.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${n}.enabled" must be a boolean.`);if(o.path!==void 0&&(typeof o.path!="string"||o.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${n}.path" must be a non-empty string.`)}}if(r.checks!==void 0&&(typeof r.checks!="object"||r.checks===null||!Array.isArray(r.checks.commands)||!r.checks.commands.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(r.open!==void 0&&(typeof r.open!="object"||r.open===null||!Array.isArray(r.open.command)||!r.open.command.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}return r};var dr=async(e,t={readConfigFile:cs})=>{let r=await t.readConfigFile(e.configFile);if(!r)return{};if(r.trimStart()[0]!=="{")throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`);let n;try{n=JSON.parse(r)}catch{throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`)}return It(n,e.configFile)};var ur=async(e,t,r={writeConfigFile:ds})=>{It(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
4
- `)};var pr={};ar(pr,{checkForUpdate:()=>us,getCurrent:()=>Ct});var Ct=()=>{try{return"0.7.6"}catch{return"unknown"}};var kl="https://registry.npmjs.org/craig-cli/latest",wl=3600*1e3,Tl={value:null},Rl=(e,t)=>{let r=c=>c.split(".").map(Number),[n=0,s=0,o=0]=r(e),[i=0,a=0,l=0]=r(t);return n!==i?n>i:s!==a?s>a:o>l},us=async(e={fetch:globalThis.fetch,getCurrent:Ct,cache:Tl})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<wl)return e.cache.value.result;let n=null;try{let o=await e.fetch(kl,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&Rl(n,t)};return e.cache.value={result:s,cachedAt:r},s};var g={load:dr,save:ur,runners:cr,version:pr};function ps(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
2
+ var sl=Object.defineProperty;var ar=(e,t)=>{for(var r in t)sl(e,r,{get:t[r],enumerable:!0})};import{readFile as cl}from"node:fs/promises";import{randomUUID as ol}from"node:crypto";import{open as il,readFile as om,rename as al,rm as ll}from"node:fs/promises";import lr from"node:path";async function M(e,t){let r=lr.dirname(e),n=lr.join(r,`.${lr.basename(e)}.${process.pid}.${Date.now()}.${ol()}.tmp`),s=await il(n,"w");try{let o=`${JSON.stringify(t,null,2)}
3
+ `;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await al(n,e)}catch(o){throw await s.close().catch(()=>{}),await ll(n,{force:!0}).catch(()=>{}),o}}async function Me(e){try{let t=await cl(e.uiStateFile,"utf8"),r=JSON.parse(t);return dl(r,e.uiStateFile)}catch(t){if(pl(t))return null;throw t}}async function me(e,t){await M(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function yt(){return{version:1,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null,selectedPtyTabId:null,inputMode:"control",focusedRegion:"tasks",activeTab:"agent",inspectorSection:"task",inspectionMode:"files",openInspectionKind:null,selectedFileTreePath:null,selectedFilePath:null,selectedDiffPath:null,collapsedFileTreePaths:[],selectedActionId:"commit",updatedAt:new Date().toISOString()}}function dl(e,t){if(typeof e!="object"||e===null||e.version!==1||!(e.selectedRepoId===null||typeof e.selectedRepoId=="string")||!(e.selectedWorkspaceId===null||typeof e.selectedWorkspaceId=="string")||!(e.selectedTaskId===null||typeof e.selectedTaskId=="string")||!(e.selectedPtyTabId===void 0||e.selectedPtyTabId===null||typeof e.selectedPtyTabId=="string")||!Le(e,"inputMode")||!Le(e,"focusedRegion")||!Le(e,"activeTab")||!Le(e,"inspectorSection")||!Le(e,"inspectionMode")||!Rt(e,"openInspectionKind")||!Rt(e,"selectedFileTreePath")||!Rt(e,"selectedFilePath")||!Rt(e,"selectedDiffPath")||!ul(e,"collapsedFileTreePaths")||!Le(e,"selectedActionId")||typeof e.updatedAt!="string")throw new Error(`Craig UI state at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}function Le(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Rt(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function ul(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function pl(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var cr={};ar(cr,{RUNNER_IDS:()=>x,assertEnabled:()=>os,buildCommand:()=>ls,getConfiguredProfile:()=>Pt,getDefault:()=>ss,getDisplayName:()=>as,getEnabled:()=>St,getProfile:()=>Oe,isRunnerType:()=>bt,parse:()=>is,setRunnerEnabled:()=>cs,setRunnerPath:()=>ds});var x=["codex","cursor","claude"];var ns={codex:{id:"codex",displayName:"Codex",executable:"codex",defaultAgentTitle:"Codex"},cursor:{id:"cursor",displayName:"Cursor",executable:"cursor-agent",defaultAgentTitle:"Cursor"},claude:{id:"claude",displayName:"Claude",executable:"claude",defaultAgentTitle:"Claude"}};var Oe=e=>ns[e];var Pt=(e,t={})=>{let r=Oe(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var St=(e={})=>x.filter(t=>e.runners?.[t]?.enabled!==!1);var ss=(e={})=>{let t=St(e);if(t.length===0)throw new Error("No runners are enabled. Enable at least one runner in .craig/config.json.");return t.includes("codex")?"codex":t[0]};var os=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var bt=e=>x.includes(e);var is=e=>{if(!e||e.length===0)return"codex";if(!bt(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${x.join(", ")}.`);return e};var as=e=>Oe(e).displayName;var ls=(e,t,r={})=>{let n=[Pt(e,r).executable];return t&&t.length>0&&n.push(t),n};var cs=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var ds=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};import{mkdir as fl,readFile as ml,writeFile as gl}from"node:fs/promises";import hl from"node:path";var kl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",us=async e=>{try{return await ml(e,"utf8")}catch(t){if(kl(t))return null;throw t}},ps=async(e,t)=>{await fl(hl.dirname(e),{recursive:!0}),await gl(e,t,"utf8")};var It=(e,t)=>{if(typeof e!="object"||e===null)throw new Error(`Craig config at ${t} is invalid. Expected a JSON object.`);let r=e;if(r.runners!==void 0){if(typeof r.runners!="object"||r.runners===null||Array.isArray(r.runners))throw new Error(`Craig config at ${t} is invalid. "runners" must be an object.`);for(let[n,s]of Object.entries(r.runners)){if(!x.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${x.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" must be an object.`);let o=s;if(o.enabled!==void 0&&typeof o.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${n}.enabled" must be a boolean.`);if(o.path!==void 0&&(typeof o.path!="string"||o.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${n}.path" must be a non-empty string.`)}}if(r.checks!==void 0&&(typeof r.checks!="object"||r.checks===null||!Array.isArray(r.checks.commands)||!r.checks.commands.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(r.open!==void 0&&(typeof r.open!="object"||r.open===null||!Array.isArray(r.open.command)||!r.open.command.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}return r};var dr=async(e,t={readConfigFile:us})=>{let r=await t.readConfigFile(e.configFile);if(!r)return{};if(r.trimStart()[0]!=="{")throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`);let n;try{n=JSON.parse(r)}catch{throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`)}return It(n,e.configFile)};var ur=async(e,t,r={writeConfigFile:ps})=>{It(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
4
+ `)};var pr={};ar(pr,{checkForUpdate:()=>fs,getCurrent:()=>Ct});var Ct=()=>{try{return"0.7.7"}catch{return"unknown"}};var wl="https://registry.npmjs.org/craig-cli/latest",Tl=3600*1e3,Rl={value:null},yl=(e,t)=>{let r=c=>c.split(".").map(Number),[n=0,s=0,o=0]=r(e),[i=0,a=0,l=0]=r(t);return n!==i?n>i:s!==a?s>a:o>l},fs=async(e={fetch:globalThis.fetch,getCurrent:Ct,cache:Rl})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<Tl)return e.cache.value.result;let n=null;try{let o=await e.fetch(wl,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&yl(n,t)};return e.cache.value={result:s,cachedAt:r},s};var h={load:dr,save:ur,runners:cr,version:pr};function ms(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
5
5
 
6
6
  `+K());return{mode:"command",command:{kind:"addRepo",path:r}}}if(t.length>=3&&t[0]==="workspace"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Workspace path cannot be empty.
7
7
 
@@ -11,7 +11,7 @@ ${K()}`);return{mode:"command",command:{kind:"listWorkspaces",archived:r}}}if(t.
11
11
 
12
12
  `+K());if(r!==-1&&n!==-1)throw new Error(`Task creation accepts either '--repo' or '--workspace', not both.
13
13
 
14
- `+K());let o=r===-1?void 0:t[r+1]?.trim()??"",i=n===-1?void 0:t[n+1]?.trim()??"",a=s===-1?void 0:g.runners.parse(t[s+1]?.trim()??""),c=t.filter((d,p)=>p>1&&p!==r&&p!==r+1&&p!==n&&p!==n+1&&p!==s&&p!==s+1).join(" ").trim();if(o!==void 0&&o.length===0)throw new Error(`Repo id cannot be empty.
14
+ `+K());let o=r===-1?void 0:t[r+1]?.trim()??"",i=n===-1?void 0:t[n+1]?.trim()??"",a=s===-1?void 0:h.runners.parse(t[s+1]?.trim()??""),c=t.filter((d,p)=>p>1&&p!==r&&p!==r+1&&p!==n&&p!==n+1&&p!==s&&p!==s+1).join(" ").trim();if(o!==void 0&&o.length===0)throw new Error(`Repo id cannot be empty.
15
15
 
16
16
  `+K());if(i!==void 0&&i.length===0)throw new Error(`Workspace id cannot be empty.
17
17
 
@@ -19,19 +19,19 @@ ${K()}`);return{mode:"command",command:{kind:"listWorkspaces",archived:r}}}if(t.
19
19
 
20
20
  `+K());return{mode:"command",command:{kind:"createTask",...o?{repoId:o}:{},...i?{workspaceId:i}:{},prompt:c,...a?{runner:a}:{}}}}if(t.length>=2&&t.length<=4&&t[0]==="task"&&t[1]==="list"){if(t.length===2)return{mode:"command",command:{kind:"listTasks"}};if(t.length===4&&t[2]==="--repo")return{mode:"command",command:{kind:"listTasks",repoId:t[3].trim()}};throw new Error(`Unsupported command: ${t.join(" ")}
21
21
 
22
- ${K()}`)}if(t.length===3&&t[0]==="task"&&t[1]==="attach")return{mode:"command",command:{kind:"attachTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="show")return{mode:"command",command:{kind:"showTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="logs")return{mode:"command",command:{kind:"streamTaskLogs",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="diff")return{mode:"command",command:{kind:"showTaskDiff",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="focus")return{mode:"command",command:{kind:"focusTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="open")return{mode:"command",command:{kind:"openTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="check")return{mode:"command",command:{kind:"runChecks",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="commit")return{mode:"command",command:{kind:"commitTask",taskId:re(t[2])}};if(t.length===4&&t[0]==="link"&&t[1]==="add")return{mode:"command",command:{kind:"addTaskLink",taskId:re(t[2]),repoId:yl(t[3])}};if(t.length===3&&t[0]==="link"&&t[1]==="list")return{mode:"command",command:{kind:"listTaskLinks",taskId:re(t[2])}};throw new Error(`Unsupported command: ${t.join(" ")}
22
+ ${K()}`)}if(t.length===3&&t[0]==="task"&&t[1]==="attach")return{mode:"command",command:{kind:"attachTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="show")return{mode:"command",command:{kind:"showTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="logs")return{mode:"command",command:{kind:"streamTaskLogs",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="diff")return{mode:"command",command:{kind:"showTaskDiff",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="focus")return{mode:"command",command:{kind:"focusTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="open")return{mode:"command",command:{kind:"openTask",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="check")return{mode:"command",command:{kind:"runChecks",taskId:re(t[2])}};if(t.length===3&&t[0]==="task"&&t[1]==="commit")return{mode:"command",command:{kind:"commitTask",taskId:re(t[2])}};if(t.length===4&&t[0]==="link"&&t[1]==="add")return{mode:"command",command:{kind:"addTaskLink",taskId:re(t[2]),repoId:Pl(t[3])}};if(t.length===3&&t[0]==="link"&&t[1]==="list")return{mode:"command",command:{kind:"listTaskLinks",taskId:re(t[2])}};throw new Error(`Unsupported command: ${t.join(" ")}
23
23
 
24
24
  ${K()}`)}function K(){return["Craig commands:"," craig Show the Craig phase 0 placeholder"," craig repo add Register a repo in the current Craig workspace"," craig workspace add <path> Register a repo or parent-directory workspace"," craig repo list List registered repos"," craig repo remove Remove a registered repo"," craig workspace list List active workspaces"," craig workspace list --archived List archived workspaces"," craig workspace archive Archive a workspace"," craig workspace restore Restore an archived workspace"," craig workspace remove Remove an archived workspace"," craig task new --repo <repo-id> [--runner codex|cursor|claude] <prompt> Create a new Craig repo task"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude] <prompt> Create a new Craig workspace task"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task show Show details for a Craig task"," craig task logs Stream Craig-managed logs for a task"," craig task diff Show the current worktree diff for a task"," craig task attach Attach to a live task session"," craig task focus Focus the tmux pane for a task"," craig task open Open the task worktree or print its path"," craig task check Run configured checks for a task"," craig task commit Commit all task worktree changes"," craig link add Add a linked repo to a task"," craig link list List linked repos for a task"].join(`
25
25
  `)}function re(e){let t=e.trim();if(t.length===0)throw new Error(`Task id cannot be empty.
26
26
 
27
- ${K()}`);return t}function yl(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
27
+ ${K()}`);return t}function Pl(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
28
28
 
29
- ${K()}`);return t}var F=(e,t)=>{let r=fr(e);if(!bl(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},fr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:mr(t.runner),repoId:typeof t.repoId=="string"?t.repoId:"legacy_repo",workspaceId:typeof t.workspaceId=="string"?t.workspaceId:"legacy_workspace",sessionId:typeof t.sessionId=="string"||t.sessionId===null?t.sessionId:null,selectedPtyTabId:typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null?t.selectedPtyTabId:null,linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(r=>typeof r=="string"):[],ptyTabs:Cl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Sl(t.repoTargets),runnerSession:t.runnerSession??Pl(t),checks:jl(t),lastCommit:t.lastCommit??null,prs:Ll(t),artifacts:Nl(t),cleanup:Wl(t)}},Pl=e=>{if(typeof e.title!="string")return null;let t=mr(e.runner);return{command:g.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},bl=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.id=="string"&&typeof t.title=="string"&&typeof t.slug=="string"&&(t.type==="repo"||t.type==="project")&&typeof t.status=="string"&&g.runners.isRunnerType(t.runner??"")&&typeof t.repoId=="string"&&typeof t.workspaceId=="string"&&(typeof t.sessionId=="string"||t.sessionId===null)&&(typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null)&&Array.isArray(t.linkedRepoIds)&&t.linkedRepoIds.every(r=>typeof r=="string")&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&typeof t.branch=="string"&&ms(t.ptyTabs)&&(t.bundlePath===void 0||t.bundlePath===null||typeof t.bundlePath=="string")&&(t.selectedRepoTargetId===void 0||t.selectedRepoTargetId===null||typeof t.selectedRepoTargetId=="string")&&(t.repoTargets===void 0||Il(t.repoTargets))&&El(t.runnerSession)&&xl(t.prompt)&&gs(t.checks)&&hs(t.lastCommit)&&Dl(t.prs)&&$l(t.artifacts)&&ws(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Sl=e=>{if(Array.isArray(e))return e.filter(fs)},Il=e=>Array.isArray(e)&&e.every(fs),fs=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.repoId=="string"&&typeof t.branch=="string"&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&(t.status==="ready"||t.status==="unavailable"||t.status==="merged"||t.status==="closed")&&(typeof t.failureReason=="string"||t.failureReason===null)&&gs(t.checks)&&hs(t.lastCommit)&&ks(t.pullRequest)&&ws(t.cleanup)},Cl=e=>{if(ms(e.ptyTabs))return e.ptyTabs;if(typeof e.id!="string"||typeof e.title!="string")return[];let t=typeof e.updatedAt=="string"?e.updatedAt:new Date().toISOString();return vl(e.id,e.title,t,mr(e.runner))},vl=(e,t,r,n)=>{let s=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:g.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},mr=e=>e&&g.runners.isRunnerType(e)?e:"codex",ms=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.id=="string"&&(t.kind==="agent"||t.kind==="terminal")&&typeof t.title=="string"&&Array.isArray(t.command)&&t.command.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"),El=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),xl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",gs=e=>typeof e=="object"&&e!==null&&typeof e.source=="object"&&e.source!==null&&e.source.type==="repo_config"&&typeof e.source.path=="string"&&(typeof e.lastRunAt=="string"||e.lastRunAt===null)&&(e.status==="not_run"||e.status==="running"||e.status==="passed"||e.status==="failed")&&Array.isArray(e.commands)&&e.commands.every(t=>typeof t=="string")&&Array.isArray(e.results)&&e.results.every(t=>typeof t=="object"&&t!==null&&typeof t.command=="string"&&typeof t.startedAt=="string"&&typeof t.finishedAt=="string"&&typeof t.exitCode=="number"),hs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",ks=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Al(e.requiredChecks),Al=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.name=="string"&&(t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown")&&(typeof t.conclusion=="string"||t.conclusion===null)),Dl=e=>Array.isArray(e)&&e.every(ks),$l=e=>typeof e=="object"&&e!==null&&(typeof e.logPath=="string"||e.logPath===null)&&(typeof e.checkSummaryPath=="string"||e.checkSummaryPath===null)&&(typeof e.prDraftPath=="string"||e.prDraftPath===null)&&(typeof e.prStatusPath=="string"||e.prStatusPath===null),ws=e=>typeof e=="object"&&e!==null&&(typeof e.paneClosedAt=="string"||e.paneClosedAt===null)&&(typeof e.worktreeRemovedAt=="string"||e.worktreeRemovedAt===null)&&typeof e.preservedWorktree=="boolean"&&(typeof e.warning=="string"||e.warning===null),jl=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Ll=e=>{if(Array.isArray(e.prs))return e.prs.map(Ml);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Ts(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Rs(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ml=e=>{let t=e??{};return{provider:"github",owner:t.owner??null,repo:t.repo??null,number:typeof t.number=="number"?t.number:null,url:t.url??null,title:t.title??null,status:Ts(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Ol(t.reviewDecision),requiredChecks:Rs(t.requiredChecks),comments:Fl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Ts=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Ol=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Fl=e=>Array.isArray(e)?e.flatMap(t=>{if(typeof t!="object"||t===null)return[];let r=t;return typeof r.body!="string"||!r.body.trim()?[]:[{author:typeof r.author=="string"?r.author:null,body:r.body,createdAt:typeof r.createdAt=="string"?r.createdAt:null,url:typeof r.url=="string"?r.url:null}]}):[],Rs=e=>Array.isArray(e)?e.map(t=>({...t,status:t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown"?t.status:"unknown",conclusion:t.conclusion??null})):[],Nl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Wl=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as lc}from"node:fs/promises";import{readFile as _l,readdir as Bl,rm as ql}from"node:fs/promises";import ys from"node:path";var gr=(e,t)=>ys.join(e.workspacesDir,`${t}.json`),Ul=e=>{if(typeof e!="object"||e===null)return e;let t=e,r=t.repoId??t.primaryRepoId;return{...t,kind:t.kind??"repo",name:t.name??r??t.id,rootPath:t.rootPath??"",primaryRepoId:t.primaryRepoId??r??"",repoId:t.kind==="project"?t.repoId:r,discoveredRepoIds:Array.isArray(t.discoveredRepoIds)?t.discoveredRepoIds.filter(n=>typeof n=="string"):t.kind==="project"?[]:r?[r]:[],linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(n=>typeof n=="string"):[]}},Ps=(e,t)=>{let r=Ul(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Pe=async(e,t)=>{let r=gr(e,t),n=await _l(r,"utf8");return Ps(JSON.parse(n),r)},be=async(e,t)=>{await M(gr(e,t.id),{...t,updatedAt:new Date().toISOString()})},B=async e=>{let t=await Bl(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Pe(e,ys.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},bs=async(e,t)=>{await ql(gr(e,t),{force:!0})};import{readFile as Kl,readdir as Vl,rm as Gl}from"node:fs/promises";import Ss from"node:path";var hr=(e,t)=>Ss.join(e.reposDir,`${t}.json`),Is=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},X=async(e,t)=>{let r=hr(e,t),n=await Kl(r,"utf8");return Is(JSON.parse(n),r)},kr=async(e,t)=>{await M(hr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Je=async e=>{let t=await Vl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>X(e,Ss.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Cs=async(e,t)=>{await Gl(hr(e,t),{force:!0})};import{readFile as Hl}from"node:fs/promises";var zl=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},vt=(e,t,r)=>{if(!zl(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},V=async e=>{let t=await Hl(e.indexFile,"utf8");return vt(JSON.parse(t),e.workspaceRoot,e.indexFile)},le=async(e,t)=>{await M(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as Zl,stat as ec}from"node:fs/promises";import Ne from"node:path";import{realpath as xs}from"node:fs/promises";import As from"node:path";import{execFile as Yl}from"node:child_process";import{promisify as Ql}from"node:util";var vs=Ql(Yl);async function T(e,t,r={}){try{let n=await vs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Es(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function E(e,t,r={}){try{let n=await vs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Es(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Es(e){return e instanceof Error}var wr=async e=>{try{let r=(await T("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([xs(r).catch(()=>As.resolve(r)),xs(e).catch(()=>As.resolve(e))]);return n===s}catch{return!1}},Tr=async e=>{let t=await E("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await E("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await T("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as se,readFile as Jl}from"node:fs/promises";import G from"node:path";function ne(e){let t=G.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:G.join(t,"index.json"),reposDir:G.join(t,"repos"),workspacesDir:G.join(t,"workspaces"),sessionsDir:G.join(t,"sessions"),runtimeDir:G.join(t,"runtime"),uiStateFile:G.join(t,"runtime","ui-state.json"),tasksDir:G.join(t,"tasks"),jobsDir:G.join(t,"jobs"),logsDir:G.join(t,"logs"),errorLogFile:G.join(t,"logs","errors.log"),artifactsDir:G.join(t,"artifacts"),worktreesDir:G.join(t,"worktrees"),configFile:G.join(t,"config.json")}}var Xl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Fe=async e=>{let t=ne(e);await se(t.craigDir,{recursive:!0}),await Promise.all([se(t.reposDir,{recursive:!0}),se(t.workspacesDir,{recursive:!0}),se(t.sessionsDir,{recursive:!0}),se(t.runtimeDir,{recursive:!0}),se(t.tasksDir,{recursive:!0}),se(t.jobsDir,{recursive:!0}),se(t.logsDir,{recursive:!0}),se(t.artifactsDir,{recursive:!0}),se(t.worktreesDir,{recursive:!0})]);try{let s=await Jl(t.indexFile,"utf8"),o=JSON.parse(s);return vt(o,e,t.indexFile)}catch(s){if(!Xl(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await M(t.indexFile,n),n};var Ds=(e,t,r)=>{let n=new Date().toISOString();return{id:tc(e,Ne.basename(t)),name:Ne.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},$s=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},tc=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",n=`repo_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`repo_${r}_${s}`,s+=1;return n},rc=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},js=async(e,t)=>{let r=await V(e);await le(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},nc=async(e,t)=>{let r=await Zl(t,{withFileTypes:!0}),n=await Je(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ne.join(t,o.name);if(!await wr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await Tr(i);s.push(a?$s(a,l):Ds([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},sc=async(e,t)=>{let r=await Tr(t),n=await Je(e),s=n.find(p=>p.rootPath===t)??null,o=s?$s(s,r):Ds(n,t,r),i=`workspace_${o.id}`,l=(await B(e)).find(p=>p.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await kr(e,o),l||await be(e,d),await js(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},oc=async(e,t)=>{let r=await nc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await B(e),s=rc(n,Ne.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:Ne.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>kr(e,c))),await be(e,l),await js(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Xe=async(e,t)=>{await Fe(e.workspaceRoot);let r=Ne.resolve(e.workspaceRoot,t);if(!(await ec(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await wr(r)?sc(e,r):oc(e,r)};var Rr=async(e,t,r={listWorkspaceRecords:B,ensureCraigState:Fe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var yr=async(e,t,r={readWorkspace:Pe,writeWorkspace:be})=>{let s={...await r.readWorkspace(e,t),status:"archived",archivedAt:new Date().toISOString()};return await r.writeWorkspace(e,s),{kind:"archiveWorkspace",workspaceId:s.id,status:s.status,branch:s.branch}};var Pr=async(e,t)=>{let n={...await Pe(e,t),status:"active",archivedAt:null};await be(e,n);let s=n.kind==="project"?n.discoveredRepoIds?.[0]??null:n.primaryRepoId;return{kind:"restoreWorkspace",workspaceId:n.id,status:n.status,branch:n.branch,primaryRepoId:s}};var Se=async(e,t,r={deleteWorkspace:bs,readCraigIndex:V,writeCraigIndex:le})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var br=async(e,t,r)=>{let n=await Pe(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await Se(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Sr={};ar(Sr,{addRepo:()=>Ls,listRegisteredRepos:()=>Ms,removeRepo:()=>Os});import ic from"node:path";import{stat as ac}from"node:fs/promises";var Ls=async(e,t)=>{let r=ic.resolve(e.workspaceRoot,t);if(!(await ac(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Xe(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var Ms=async(e,t={listRepos:Je,ensureCraigState:Fe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Os=async(e,t,r)=>{let n=await X(e,t),o=(await B(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Se(e,c.id))),await Cs(e,t);let l=await V(e);return await le(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Y={addWorkspace:Xe,listWorkspaces:Rr,archiveWorkspace:yr,restoreWorkspace:Pr,removeWorkspace:br,removeWorkspaceRecord:Se,repos:Sr};var H=async(e,t)=>{let r=await lc(Cr(e,t),"utf8");return JSON.parse(r)},Q=async(e,t)=>{let r=await H(e,t);return F(r,Cr(e,t))},R=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await M(Cr(e,t.id),r)},Ir=async(e,t)=>{let r=await V(e);r.taskIds.includes(t)||await le(e,{...r,taskIds:[...r.taskIds,t]})},Cr=(e,t)=>`${e.tasksDir}/${t}.json`;var v=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ge=e=>e.status==="merged"||e.status==="closed",We=(e,t)=>{let r=e.prs.findIndex(s=>s.number!==null&&s.number===t.number),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},Ze=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return xt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},xt=e=>e.mergeable&&!cc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),cc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",vr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),et=(e,t)=>{let r=e.isDraft??!1,n=dc(e.state,r);return{provider:"github",owner:t?.owner??null,repo:t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:n,draft:r,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:uc(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:gc(e.comments),createdAt:e.createdAt??t?.createdAt??null,updatedAt:e.updatedAt??t?.updatedAt??null,mergedAt:e.mergedAt??t?.mergedAt??null,lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}},dc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,uc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,tt=e=>{let t=e.map(n=>pc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||fc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},pc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=t.name??t.context,n=t.state??t.status??t.conclusion;return r?{name:r,status:Ns(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:mc(t)}:null},fc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Et(e)&&!Et(t)?!0:!Et(e)&&Et(t)?!1:Fs(t.status)>=Fs(e.status),Et=e=>e.conclusion?.toUpperCase()==="CANCELLED",Fs=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},mc=e=>{let t=e.completedAt??e.startedAt??e.createdAt??null;if(!t)return null;let r=new Date(t).getTime();return Number.isFinite(r)?r:null},gc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(hc).filter(r=>r!==null).slice(-4):[]},hc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=kc(t.bodyText??t.body??"");return r?{author:typeof t.author=="string"?t.author:t.author?.login??null,body:r,createdAt:t.createdAt??null,url:t.url??null}:null},kc=e=>e.replace(/\s+/g," ").trim(),Ns=(e,t)=>{let r=e?.toUpperCase()??null,n=t?.toUpperCase()??null;return n==="SKIPPED"||r==="SKIPPED"?"skipped":r==="SUCCESS"||n==="SUCCESS"||n==="NEUTRAL"?"success":r==="PENDING"||r==="EXPECTED"||r==="IN_PROGRESS"||r==="QUEUED"||r==="REQUESTED"||r==="WAITING"?"pending":r==="FAILURE"||r==="FAILED"||r==="ERROR"||r==="TIMED_OUT"||r==="CANCELLED"||r==="ACTION_REQUIRED"||r==="STARTUP_FAILURE"||n==="FAILURE"||n==="FAILED"||n==="ERROR"||n==="TIMED_OUT"||n==="CANCELLED"||n==="ACTION_REQUIRED"||n==="STARTUP_FAILURE"?"failed":r==="COMPLETED"&&n===null?"unknown":r==="COMPLETED"&&n!==null?Ns(n,n):"unknown"};import{access as wc}from"node:fs/promises";import Ws from"node:path";var b=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw bc(n)?new Error(`Craig task "${t}" was not found.`):n}},N=async e=>{if(!await Er(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},_e=(e,t)=>t.artifacts.logPath?Ws.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Ws.join(e.workspaceRoot,t.artifacts.logPath):null,rt=async(e,t)=>{let r=await Er(t.worktreePath),n=_e(e,t),s=n?await Er(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Tc(t),lastCommitSummary:Rc(t),prSummary:yc(t),cleanupSummary:Pc(t)}},Er=async e=>{try{return await wc(e),!0}catch{return!1}},Tc=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},Rc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",yc=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
29
+ ${K()}`);return t}var F=(e,t)=>{let r=fr(e);if(!bl(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},fr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:mr(t.runner),repoId:typeof t.repoId=="string"?t.repoId:"legacy_repo",workspaceId:typeof t.workspaceId=="string"?t.workspaceId:"legacy_workspace",sessionId:typeof t.sessionId=="string"||t.sessionId===null?t.sessionId:null,selectedPtyTabId:typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null?t.selectedPtyTabId:null,linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(r=>typeof r=="string"):[],ptyTabs:vl(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Il(t.repoTargets),runnerSession:t.runnerSession??Sl(t),checks:Ll(t),lastCommit:t.lastCommit??null,prs:Ml(t),artifacts:Wl(t),cleanup:_l(t)}},Sl=e=>{if(typeof e.title!="string")return null;let t=mr(e.runner);return{command:h.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},bl=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.id=="string"&&typeof t.title=="string"&&typeof t.slug=="string"&&(t.type==="repo"||t.type==="project")&&typeof t.status=="string"&&h.runners.isRunnerType(t.runner??"")&&typeof t.repoId=="string"&&typeof t.workspaceId=="string"&&(typeof t.sessionId=="string"||t.sessionId===null)&&(typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null)&&Array.isArray(t.linkedRepoIds)&&t.linkedRepoIds.every(r=>typeof r=="string")&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&typeof t.branch=="string"&&hs(t.ptyTabs)&&(t.bundlePath===void 0||t.bundlePath===null||typeof t.bundlePath=="string")&&(t.selectedRepoTargetId===void 0||t.selectedRepoTargetId===null||typeof t.selectedRepoTargetId=="string")&&(t.repoTargets===void 0||Cl(t.repoTargets))&&xl(t.runnerSession)&&Al(t.prompt)&&ks(t.checks)&&ws(t.lastCommit)&&$l(t.prs)&&jl(t.artifacts)&&Rs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Il=e=>{if(Array.isArray(e))return e.filter(gs)},Cl=e=>Array.isArray(e)&&e.every(gs),gs=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.repoId=="string"&&typeof t.branch=="string"&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&(t.status==="ready"||t.status==="unavailable"||t.status==="merged"||t.status==="closed")&&(typeof t.failureReason=="string"||t.failureReason===null)&&ks(t.checks)&&ws(t.lastCommit)&&Ts(t.pullRequest)&&Rs(t.cleanup)},vl=e=>{if(hs(e.ptyTabs))return e.ptyTabs;if(typeof e.id!="string"||typeof e.title!="string")return[];let t=typeof e.updatedAt=="string"?e.updatedAt:new Date().toISOString();return El(e.id,e.title,t,mr(e.runner))},El=(e,t,r,n)=>{let s=h.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:h.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},mr=e=>e&&h.runners.isRunnerType(e)?e:"codex",hs=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.id=="string"&&(t.kind==="agent"||t.kind==="terminal")&&typeof t.title=="string"&&Array.isArray(t.command)&&t.command.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"),xl=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),Al=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",ks=e=>typeof e=="object"&&e!==null&&typeof e.source=="object"&&e.source!==null&&e.source.type==="repo_config"&&typeof e.source.path=="string"&&(typeof e.lastRunAt=="string"||e.lastRunAt===null)&&(e.status==="not_run"||e.status==="running"||e.status==="passed"||e.status==="failed")&&Array.isArray(e.commands)&&e.commands.every(t=>typeof t=="string")&&Array.isArray(e.results)&&e.results.every(t=>typeof t=="object"&&t!==null&&typeof t.command=="string"&&typeof t.startedAt=="string"&&typeof t.finishedAt=="string"&&typeof t.exitCode=="number"),ws=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Ts=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Dl(e.requiredChecks),Dl=e=>Array.isArray(e)&&e.every(t=>typeof t=="object"&&t!==null&&typeof t.name=="string"&&(t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown")&&(typeof t.conclusion=="string"||t.conclusion===null)),$l=e=>Array.isArray(e)&&e.every(Ts),jl=e=>typeof e=="object"&&e!==null&&(typeof e.logPath=="string"||e.logPath===null)&&(typeof e.checkSummaryPath=="string"||e.checkSummaryPath===null)&&(typeof e.prDraftPath=="string"||e.prDraftPath===null)&&(typeof e.prStatusPath=="string"||e.prStatusPath===null),Rs=e=>typeof e=="object"&&e!==null&&(typeof e.paneClosedAt=="string"||e.paneClosedAt===null)&&(typeof e.worktreeRemovedAt=="string"||e.worktreeRemovedAt===null)&&typeof e.preservedWorktree=="boolean"&&(typeof e.warning=="string"||e.warning===null),Ll=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Ml=e=>{if(Array.isArray(e.prs))return e.prs.map(Ol);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:ys(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Ps(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Ol=e=>{let t=e??{};return{provider:"github",owner:t.owner??null,repo:t.repo??null,number:typeof t.number=="number"?t.number:null,url:t.url??null,title:t.title??null,status:ys(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Fl(t.reviewDecision),requiredChecks:Ps(t.requiredChecks),comments:Nl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},ys=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Fl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Nl=e=>Array.isArray(e)?e.flatMap(t=>{if(typeof t!="object"||t===null)return[];let r=t;return typeof r.body!="string"||!r.body.trim()?[]:[{author:typeof r.author=="string"?r.author:null,body:r.body,createdAt:typeof r.createdAt=="string"?r.createdAt:null,url:typeof r.url=="string"?r.url:null}]}):[],Ps=e=>Array.isArray(e)?e.map(t=>({...t,status:t.status==="pending"||t.status==="success"||t.status==="failed"||t.status==="skipped"||t.status==="unknown"?t.status:"unknown",conclusion:t.conclusion??null})):[],Wl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},_l=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as cc}from"node:fs/promises";import{readFile as ql,readdir as Bl,rm as Ul}from"node:fs/promises";import Ss from"node:path";var gr=(e,t)=>Ss.join(e.workspacesDir,`${t}.json`),Kl=e=>{if(typeof e!="object"||e===null)return e;let t=e,r=t.repoId??t.primaryRepoId;return{...t,kind:t.kind??"repo",name:t.name??r??t.id,rootPath:t.rootPath??"",primaryRepoId:t.primaryRepoId??r??"",repoId:t.kind==="project"?t.repoId:r,discoveredRepoIds:Array.isArray(t.discoveredRepoIds)?t.discoveredRepoIds.filter(n=>typeof n=="string"):t.kind==="project"?[]:r?[r]:[],linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(n=>typeof n=="string"):[]}},bs=(e,t)=>{let r=Kl(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Pe=async(e,t)=>{let r=gr(e,t),n=await ql(r,"utf8");return bs(JSON.parse(n),r)},Se=async(e,t)=>{await M(gr(e,t.id),{...t,updatedAt:new Date().toISOString()})},q=async e=>{let t=await Bl(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Pe(e,Ss.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Is=async(e,t)=>{await Ul(gr(e,t),{force:!0})};import{readFile as Vl,readdir as Gl,rm as Hl}from"node:fs/promises";import Cs from"node:path";var hr=(e,t)=>Cs.join(e.reposDir,`${t}.json`),vs=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},X=async(e,t)=>{let r=hr(e,t),n=await Vl(r,"utf8");return vs(JSON.parse(n),r)},kr=async(e,t)=>{await M(hr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Je=async e=>{let t=await Gl(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>X(e,Cs.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Es=async(e,t)=>{await Hl(hr(e,t),{force:!0})};import{readFile as zl}from"node:fs/promises";var Ql=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},vt=(e,t,r)=>{if(!Ql(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},V=async e=>{let t=await zl(e.indexFile,"utf8");return vt(JSON.parse(t),e.workspaceRoot,e.indexFile)},le=async(e,t)=>{await M(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as ec,stat as tc}from"node:fs/promises";import Ne from"node:path";import{realpath as Ds}from"node:fs/promises";import $s from"node:path";import{execFile as Yl}from"node:child_process";import{promisify as Jl}from"node:util";var xs=Jl(Yl);async function T(e,t,r={}){try{let n=await xs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(As(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function E(e,t,r={}){try{let n=await xs(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(As(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function As(e){return e instanceof Error}var wr=async e=>{try{let r=(await T("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Ds(r).catch(()=>$s.resolve(r)),Ds(e).catch(()=>$s.resolve(e))]);return n===s}catch{return!1}},Tr=async e=>{let t=await E("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await E("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await T("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as se,readFile as Xl}from"node:fs/promises";import G from"node:path";function ne(e){let t=G.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:G.join(t,"index.json"),reposDir:G.join(t,"repos"),workspacesDir:G.join(t,"workspaces"),sessionsDir:G.join(t,"sessions"),runtimeDir:G.join(t,"runtime"),uiStateFile:G.join(t,"runtime","ui-state.json"),tasksDir:G.join(t,"tasks"),jobsDir:G.join(t,"jobs"),logsDir:G.join(t,"logs"),errorLogFile:G.join(t,"logs","errors.log"),artifactsDir:G.join(t,"artifacts"),worktreesDir:G.join(t,"worktrees"),configFile:G.join(t,"config.json")}}var Zl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Fe=async e=>{let t=ne(e);await se(t.craigDir,{recursive:!0}),await Promise.all([se(t.reposDir,{recursive:!0}),se(t.workspacesDir,{recursive:!0}),se(t.sessionsDir,{recursive:!0}),se(t.runtimeDir,{recursive:!0}),se(t.tasksDir,{recursive:!0}),se(t.jobsDir,{recursive:!0}),se(t.logsDir,{recursive:!0}),se(t.artifactsDir,{recursive:!0}),se(t.worktreesDir,{recursive:!0})]);try{let s=await Xl(t.indexFile,"utf8"),o=JSON.parse(s);return vt(o,e,t.indexFile)}catch(s){if(!Zl(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await M(t.indexFile,n),n};var js=(e,t,r)=>{let n=new Date().toISOString();return{id:rc(e,Ne.basename(t)),name:Ne.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Ls=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},rc=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",n=`repo_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`repo_${r}_${s}`,s+=1;return n},nc=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},Ms=async(e,t)=>{let r=await V(e);await le(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},sc=async(e,t)=>{let r=await ec(t,{withFileTypes:!0}),n=await Je(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ne.join(t,o.name);if(!await wr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await Tr(i);s.push(a?Ls(a,l):js([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},oc=async(e,t)=>{let r=await Tr(t),n=await Je(e),s=n.find(p=>p.rootPath===t)??null,o=s?Ls(s,r):js(n,t,r),i=`workspace_${o.id}`,l=(await q(e)).find(p=>p.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await kr(e,o),l||await Se(e,d),await Ms(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},ic=async(e,t)=>{let r=await sc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await q(e),s=nc(n,Ne.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:Ne.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>kr(e,c))),await Se(e,l),await Ms(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Xe=async(e,t)=>{await Fe(e.workspaceRoot);let r=Ne.resolve(e.workspaceRoot,t);if(!(await tc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await wr(r)?oc(e,r):ic(e,r)};var Rr=async(e,t,r={listWorkspaceRecords:q,ensureCraigState:Fe})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var yr=async(e,t,r={readWorkspace:Pe,writeWorkspace:Se})=>{let s={...await r.readWorkspace(e,t),status:"archived",archivedAt:new Date().toISOString()};return await r.writeWorkspace(e,s),{kind:"archiveWorkspace",workspaceId:s.id,status:s.status,branch:s.branch}};var Pr=async(e,t)=>{let n={...await Pe(e,t),status:"active",archivedAt:null};await Se(e,n);let s=n.kind==="project"?n.discoveredRepoIds?.[0]??null:n.primaryRepoId;return{kind:"restoreWorkspace",workspaceId:n.id,status:n.status,branch:n.branch,primaryRepoId:s}};var be=async(e,t,r={deleteWorkspace:Is,readCraigIndex:V,writeCraigIndex:le})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Sr=async(e,t,r)=>{let n=await Pe(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await be(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var br={};ar(br,{addRepo:()=>Os,listRegisteredRepos:()=>Fs,removeRepo:()=>Ns});import ac from"node:path";import{stat as lc}from"node:fs/promises";var Os=async(e,t)=>{let r=ac.resolve(e.workspaceRoot,t);if(!(await lc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Xe(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var Fs=async(e,t={listRepos:Je,ensureCraigState:Fe})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ns=async(e,t,r)=>{let n=await X(e,t),o=(await q(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>be(e,c.id))),await Es(e,t);let l=await V(e);return await le(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Q={addWorkspace:Xe,listWorkspaces:Rr,archiveWorkspace:yr,restoreWorkspace:Pr,removeWorkspace:Sr,removeWorkspaceRecord:be,repos:br};var H=async(e,t)=>{let r=await cc(Cr(e,t),"utf8");return JSON.parse(r)},Y=async(e,t)=>{let r=await H(e,t);return F(r,Cr(e,t))},y=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await M(Cr(e,t.id),r)},Ir=async(e,t)=>{let r=await V(e);r.taskIds.includes(t)||await le(e,{...r,taskIds:[...r.taskIds,t]})},Cr=(e,t)=>`${e.tasksDir}/${t}.json`;var v=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ge=e=>e.status==="merged"||e.status==="closed",We=(e,t)=>{let r=e.prs.findIndex(s=>s.number!==null&&s.number===t.number),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},Ze=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return xt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},xt=e=>e.mergeable&&!dc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),dc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",vr=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),et=(e,t)=>{let r=e.isDraft??!1,n=uc(e.state,r);return{provider:"github",owner:t?.owner??null,repo:t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:n,draft:r,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:pc(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:hc(e.comments),createdAt:e.createdAt??t?.createdAt??null,updatedAt:e.updatedAt??t?.updatedAt??null,mergedAt:e.mergedAt??t?.mergedAt??null,lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}},uc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,pc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,tt=e=>{let t=e.map(n=>fc(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||mc(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},fc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=t.name??t.context,n=t.state??t.status??t.conclusion;return r?{name:r,status:_s(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:gc(t)}:null},mc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Et(e)&&!Et(t)?!0:!Et(e)&&Et(t)?!1:Ws(t.status)>=Ws(e.status),Et=e=>e.conclusion?.toUpperCase()==="CANCELLED",Ws=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},gc=e=>{let t=e.completedAt??e.startedAt??e.createdAt??null;if(!t)return null;let r=new Date(t).getTime();return Number.isFinite(r)?r:null},hc=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(kc).filter(r=>r!==null).slice(-4):[]},kc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=wc(t.bodyText??t.body??"");return r?{author:typeof t.author=="string"?t.author:t.author?.login??null,body:r,createdAt:t.createdAt??null,url:t.url??null}:null},wc=e=>e.replace(/\s+/g," ").trim(),_s=(e,t)=>{let r=e?.toUpperCase()??null,n=t?.toUpperCase()??null;return n==="SKIPPED"||r==="SKIPPED"?"skipped":r==="SUCCESS"||n==="SUCCESS"||n==="NEUTRAL"?"success":r==="PENDING"||r==="EXPECTED"||r==="IN_PROGRESS"||r==="QUEUED"||r==="REQUESTED"||r==="WAITING"?"pending":r==="FAILURE"||r==="FAILED"||r==="ERROR"||r==="TIMED_OUT"||r==="CANCELLED"||r==="ACTION_REQUIRED"||r==="STARTUP_FAILURE"||n==="FAILURE"||n==="FAILED"||n==="ERROR"||n==="TIMED_OUT"||n==="CANCELLED"||n==="ACTION_REQUIRED"||n==="STARTUP_FAILURE"?"failed":r==="COMPLETED"&&n===null?"unknown":r==="COMPLETED"&&n!==null?_s(n,n):"unknown"};import{access as Tc}from"node:fs/promises";import qs from"node:path";var S=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw bc(n)?new Error(`Craig task "${t}" was not found.`):n}},N=async e=>{if(!await Er(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},_e=(e,t)=>t.artifacts.logPath?qs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:qs.join(e.workspaceRoot,t.artifacts.logPath):null,rt=async(e,t)=>{let r=await Er(t.worktreePath),n=_e(e,t),s=n?await Er(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Rc(t),lastCommitSummary:yc(t),prSummary:Pc(t),cleanupSummary:Sc(t)}},Er=async e=>{try{return await Tc(e),!0}catch{return!1}},Rc=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},yc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Pc=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
30
30
  ${o.join(`
31
- `)}`}let t=v(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},Pc=e=>e.status!=="merged"?"not merged":e.cleanup.warning?`warning: ${e.cleanup.warning}`:e.cleanup.preservedWorktree?"preserved worktree":e.cleanup.worktreeRemovedAt?`worktree removed at ${e.cleanup.worktreeRemovedAt}`:"cleanup pending",bc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var _s=async(e,t)=>{let r=await E("git",["show-ref","--verify","--quiet",`refs/heads/${t}`],{cwd:e});if(r.exitCode===0)return!0;if(r.exitCode===1)return!1;throw new Error(r.stderr.trim()||r.stdout.trim()||"Unable to check git branch state.")},xr=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await E("git",["show-ref","--verify","--quiet",`refs/heads/${s}`],{cwd:e})).exitCode!==0)throw new Error(`Base branch '${s}' does not exist locally.`);let i=await Sc(e,s);await T("git",["worktree","add","-b",t,r,i],{cwd:e})},Sc=async(e,t)=>(await E("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await E("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await E("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,At=async e=>{let t=await E("git",["status","--short"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"Unable to inspect git status.");return t.stdout.trim().length>0},Bs=async e=>{await T("git",["add","-A"],{cwd:e})},qs=async(e,t)=>{await T("git",["commit","-m",t],{cwd:e})},Us=async e=>{let t=await T("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",n=""]=t.stdout.trim().split(`
32
- `);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}};var Ks=async(e,t)=>{await T("git",["worktree","remove","--force",t],{cwd:e})};var Ar=async e=>Be(e,e.repoRoot),Be=async(e,t)=>{let r=await V(e),n=Vs(new Date),s=Gs(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await _s(t,i))return o;s+=1}},nt=async e=>{let t=await V(e),r=Vs(new Date),n=Gs(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},Vs=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},Gs=(e,t)=>{let r=e.filter(n=>n.startsWith(`task_${t}_`)).map(n=>Number.parseInt(n.slice(-2),10)).filter(n=>Number.isInteger(n));return r.length===0?1:Math.max(...r)+1};var Dr=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{let n=await V(e),s=[],o=[];await Promise.all(n.taskIds.map(async l=>{try{let c=await r.readRawTask(e,l);s.push(r.validateTaskRecord(c,`${e.tasksDir}/${l}.json`))}catch(c){if(Ic(c)){o.push(l);return}throw c}}));let a=(t?.includeClosed?s:s.filter(l=>l.status!=="closed")).filter(l=>!(t?.workspaceId&&l.workspaceId!==t.workspaceId||t?.repoId&&l.repoId!==t.repoId&&!(l.repoTargets??[]).some(c=>c.repoId===t.repoId)));return a.sort((l,c)=>l.id.localeCompare(c.id)),o.sort(),{kind:"listTasks",tasks:a,missingTaskIds:o,repoId:t?.repoId??null}},Ic=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Hs=["merge_ready","pr_open","checked","review","running","draft"],$r=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),jr=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(Cc)[0]?.id??null,Cc=(e,t)=>{let r=zs(e.status),n=zs(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},zs=e=>{let t=Hs.indexOf(e);return t>=0?t:Hs.length};import Ys from"node:path";var Ie=(e,t)=>t?Ys.isAbsolute(t)?t:Ys.join(e.repoRoot,t):null;import{mkdir as st,rm as vc,writeFile as Dt}from"node:fs/promises";import C from"node:path";var Js=["AGENTS","md"].join("."),qe=async(e,t,r,n={})=>{let s=await X(e,t),o=await $c(e,s.id),i=await Be(e,s.rootPath),a=n.sessionId??null,l=`craig/${i}`,c=C.join(e.worktreesDir,s.id,i),d=C.join(e.logsDir,`${i}.log`),p=C.join(e.artifactsDir,i);await st(C.dirname(c),{recursive:!0}),await st(p,{recursive:!0}),await Dt(d,"","utf8");let f=Ec(e,{taskId:i,repoId:s.id,workspaceId:o.id,sessionId:a,repoRoot:s.rootPath,prompt:r,runner:n.runner??"codex",config:n.config??{},branch:l,worktreePath:c});return await R(e,f),await Ir(e,i),await xr(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:f}},ot=async(e,t,r,n={})=>{let s=(await B(e)).find(h=>h.id===t&&h.status==="active");if(!s)throw new Error(`Workspace ${t} does not exist or is archived.`);if(s.kind!=="project"){if(!s.primaryRepoId)throw new Error(`Workspace ${t} is not task-capable.`);let h=await qe(e,s.primaryRepoId,r,n);return{...h,bundlePath:h.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await nt(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,p=C.join(e.craigDir,"task-bundles",i),f=C.join(e.logsDir,`${i}.log`),u=C.join(e.artifactsDir,i);await st(p,{recursive:!0}),await st(u,{recursive:!0}),await Dt(f,"","utf8");let w=await Promise.all(o.map(h=>X(e,h))),P=Ac(w),D=await Promise.all(w.map(h=>xc(e,h,i,d,C.join(p,P.get(h.id))))),U=D.find(h=>h.status==="ready")??D[0];if(!D.some(h=>h.status==="ready"))throw await vc(p,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${D.map(h=>`${h.repoId}: ${h.failureReason??"unknown error"}`).join("; ")}`);await Dt(C.join(p,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:D.map(h=>({repoId:h.repoId,repoName:w.find(Qe=>Qe.id===h.repoId)?.name??h.repoId,path:C.relative(p,h.worktreePath),status:h.status,worktreePath:h.worktreePath,failureReason:h.failureReason}))},null,2),"utf8"),await Dt(C.join(p,Js),Dc({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:D,bundlePath:p}),"utf8");let fe=it(i,r,a,l,n.config??{}),ae={id:i,title:r,slug:Xs(r),type:"project",status:"draft",runner:l,repoId:U.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:fe[0]?.id??null,linkedRepoIds:o.filter(h=>h!==U.repoId),repoRoot:p,worktreePath:p,branch:d,bundlePath:p,selectedRepoTargetId:U.repoId,repoTargets:D,ptyTabs:fe,runnerSession:{command:g.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:U.checks,lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,f),checkSummaryPath:C.relative(e.workspaceRoot,C.join(u,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(u,"pr-status.json"))},cleanup:$t(),lastFailureReason:D.every(h=>h.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await R(e,ae),await Ir(e,i),{repoId:U.repoId,repoRoot:p,sessionId:c,workspaceId:s.id,task:ae,bundlePath:p,repoTargets:D}},it=(e,t,r,n="codex",s={})=>{let o=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:g.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Ec=(e,t)=>{let r=new Date().toISOString(),n=it(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:Xs(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:n[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:n,runnerSession:{command:g.runners.buildCommand(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{...Lr(C.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,C.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:$t(),lastFailureReason:null,createdAt:r,updatedAt:r}},xc=async(e,t,r,n,s)=>{await st(C.dirname(s),{recursive:!0});try{return await xr(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Qs(),cleanup:$t()}}catch(o){return{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"unavailable",failureReason:o instanceof Error?o.message:"Failed to create worktree.",checks:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Qs(),cleanup:$t()}}},Ac=e=>{let t=new Set(["manifest.json",Js]),r=new Map;for(let n of e){let s=t.has(n.name)?`${n.name}-repo`:n.name,o=s,i=2;for(;t.has(o);)o=`${s}-${i}`,i+=1;t.add(o),r.set(n.id,o)}return r},Dc=e=>{let t=new Map(e.repos.map(n=>[n.id,n.name])),r=e.repoTargets.map(n=>{let s=t.get(n.repoId)??n.repoId,o=C.relative(e.bundlePath,n.worktreePath),i=n.status==="ready"?"ready":`unavailable: ${n.failureReason??"unknown error"}`;return`- \`${o}/\` - ${s} (${n.repoId}, ${i})`}).join(`
31
+ `)}`}let t=v(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},Sc=e=>e.status!=="merged"?"not merged":e.cleanup.warning?`warning: ${e.cleanup.warning}`:e.cleanup.preservedWorktree?"preserved worktree":e.cleanup.worktreeRemovedAt?`worktree removed at ${e.cleanup.worktreeRemovedAt}`:"cleanup pending",bc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Bs=async(e,t)=>{let r=await E("git",["show-ref","--verify","--quiet",`refs/heads/${t}`],{cwd:e});if(r.exitCode===0)return!0;if(r.exitCode===1)return!1;throw new Error(r.stderr.trim()||r.stdout.trim()||"Unable to check git branch state.")},xr=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await E("git",["show-ref","--verify","--quiet",`refs/heads/${s}`],{cwd:e})).exitCode!==0)throw new Error(`Base branch '${s}' does not exist locally.`);let i=await Ic(e,s);await T("git",["worktree","add","-b",t,r,i],{cwd:e})},Ic=async(e,t)=>(await E("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await E("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await E("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,At=async e=>{let t=await E("git",["status","--short"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"Unable to inspect git status.");return t.stdout.trim().length>0},Us=async e=>{await T("git",["add","-A"],{cwd:e})},Ks=async(e,t)=>{await T("git",["commit","-m",t],{cwd:e})},Vs=async e=>{let t=await T("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",n=""]=t.stdout.trim().split(`
32
+ `);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}};var Gs=async(e,t)=>{await T("git",["worktree","remove","--force",t],{cwd:e})};var Ar=async e=>qe(e,e.repoRoot),qe=async(e,t)=>{let r=await V(e),n=Hs(new Date),s=zs(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await Bs(t,i))return o;s+=1}},nt=async e=>{let t=await V(e),r=Hs(new Date),n=zs(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},Hs=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},zs=(e,t)=>{let r=e.filter(n=>n.startsWith(`task_${t}_`)).map(n=>Number.parseInt(n.slice(-2),10)).filter(n=>Number.isInteger(n));return r.length===0?1:Math.max(...r)+1};var Dr=async(e,t,r={readRawTask:H,validateTaskRecord:F})=>{let n=await V(e),s=[],o=[];await Promise.all(n.taskIds.map(async l=>{try{let c=await r.readRawTask(e,l);s.push(r.validateTaskRecord(c,`${e.tasksDir}/${l}.json`))}catch(c){if(Cc(c)){o.push(l);return}throw c}}));let a=(t?.includeClosed?s:s.filter(l=>l.status!=="closed")).filter(l=>!(t?.workspaceId&&l.workspaceId!==t.workspaceId||t?.repoId&&l.repoId!==t.repoId&&!(l.repoTargets??[]).some(c=>c.repoId===t.repoId)));return a.sort((l,c)=>l.id.localeCompare(c.id)),o.sort(),{kind:"listTasks",tasks:a,missingTaskIds:o,repoId:t?.repoId??null}},Cc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var Qs=["merge_ready","pr_open","checked","review","running","draft"],$r=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),jr=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(vc)[0]?.id??null,vc=(e,t)=>{let r=Ys(e.status),n=Ys(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},Ys=e=>{let t=Qs.indexOf(e);return t>=0?t:Qs.length};import Js from"node:path";var Ie=(e,t)=>t?Js.isAbsolute(t)?t:Js.join(e.repoRoot,t):null;import{mkdir as st,rm as Ec,writeFile as Dt}from"node:fs/promises";import C from"node:path";var Zs=["AGENTS","md"].join("."),Be=async(e,t,r,n={})=>{let s=await X(e,t),o=await jc(e,s.id),i=await qe(e,s.rootPath),a=n.sessionId??null,l=`craig/${i}`,c=C.join(e.worktreesDir,s.id,i),d=C.join(e.logsDir,`${i}.log`),p=C.join(e.artifactsDir,i);await st(C.dirname(c),{recursive:!0}),await st(p,{recursive:!0}),await Dt(d,"","utf8");let f=xc(e,{taskId:i,repoId:s.id,workspaceId:o.id,sessionId:a,repoRoot:s.rootPath,prompt:r,runner:n.runner??"codex",config:n.config??{},branch:l,worktreePath:c});return await y(e,f),await Ir(e,i),await xr(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:f}},ot=async(e,t,r,n={})=>{let s=(await q(e)).find(k=>k.id===t&&k.status==="active");if(!s)throw new Error(`Workspace ${t} does not exist or is archived.`);if(s.kind!=="project"){if(!s.primaryRepoId)throw new Error(`Workspace ${t} is not task-capable.`);let k=await Be(e,s.primaryRepoId,r,n);return{...k,bundlePath:k.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await nt(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,p=C.join(e.craigDir,"task-bundles",i),f=C.join(e.logsDir,`${i}.log`),u=C.join(e.artifactsDir,i);await st(p,{recursive:!0}),await st(u,{recursive:!0}),await Dt(f,"","utf8");let w=await Promise.all(o.map(k=>X(e,k))),R=Dc(w),A=await Promise.all(w.map(k=>Ac(e,k,i,d,C.join(p,R.get(k.id))))),U=A.find(k=>k.status==="ready")??A[0];if(!A.some(k=>k.status==="ready"))throw await Ec(p,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${A.map(k=>`${k.repoId}: ${k.failureReason??"unknown error"}`).join("; ")}`);await Dt(C.join(p,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:A.map(k=>({repoId:k.repoId,repoName:w.find(Ye=>Ye.id===k.repoId)?.name??k.repoId,path:C.relative(p,k.worktreePath),status:k.status,worktreePath:k.worktreePath,failureReason:k.failureReason}))},null,2),"utf8"),await Dt(C.join(p,Zs),$c({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:A,bundlePath:p}),"utf8");let fe=it(i,r,a,l,n.config??{}),ae={id:i,title:r,slug:eo(r),type:"project",status:"draft",runner:l,repoId:U.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:fe[0]?.id??null,linkedRepoIds:o.filter(k=>k!==U.repoId),repoRoot:p,worktreePath:p,branch:d,bundlePath:p,selectedRepoTargetId:U.repoId,repoTargets:A,ptyTabs:fe,runnerSession:{command:h.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:U.checks,lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,f),checkSummaryPath:C.relative(e.workspaceRoot,C.join(u,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(u,"pr-status.json"))},cleanup:$t(),lastFailureReason:A.every(k=>k.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await y(e,ae),await Ir(e,i),{repoId:U.repoId,repoRoot:p,sessionId:c,workspaceId:s.id,task:ae,bundlePath:p,repoTargets:A}},it=(e,t,r,n="codex",s={})=>{let o=h.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:h.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},xc=(e,t)=>{let r=new Date().toISOString(),n=it(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:eo(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:n[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:n,runnerSession:{command:h.runners.buildCommand(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{...Lr(C.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,C.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:$t(),lastFailureReason:null,createdAt:r,updatedAt:r}},Ac=async(e,t,r,n,s)=>{await st(C.dirname(s),{recursive:!0});try{return await xr(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Xs(),cleanup:$t()}}catch(o){return{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"unavailable",failureReason:o instanceof Error?o.message:"Failed to create worktree.",checks:Lr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:Xs(),cleanup:$t()}}},Dc=e=>{let t=new Set(["manifest.json",Zs]),r=new Map;for(let n of e){let s=t.has(n.name)?`${n.name}-repo`:n.name,o=s,i=2;for(;t.has(o);)o=`${s}-${i}`,i+=1;t.add(o),r.set(n.id,o)}return r},$c=e=>{let t=new Map(e.repos.map(n=>[n.id,n.name])),r=e.repoTargets.map(n=>{let s=t.get(n.repoId)??n.repoId,o=C.relative(e.bundlePath,n.worktreePath),i=n.status==="ready"?"ready":`unavailable: ${n.failureReason??"unknown error"}`;return`- \`${o}/\` - ${s} (${n.repoId}, ${i})`}).join(`
33
33
  `);return["# Craig Project Task Bundle","","This directory is a Craig project task bundle. Repo work must happen inside the child repo worktrees listed below.","","Run repo Git commands from a repo worktree directory, not from the bundle root. Use `manifest.json` as the machine-readable source of truth for this bundle.","",`Task: \`${e.taskId}\``,`Workspace: \`${e.workspaceId}\``,`Prompt: ${e.prompt}`,"","## Repo Worktrees","",r,""].join(`
34
- `)},Lr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Qs=()=>({provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}),$t=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),$c=async(e,t)=>{let n=(await B(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},Xs=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import co from"node:path";import{readFile as jc,rm as fk}from"node:fs/promises";import Lc from"node:path";var he=async(e,t)=>{let r=await jc(Mr(e,t),"utf8"),n=JSON.parse(r);return Mc(n,Mr(e,t))},Ce=async(e,t)=>{await M(Mr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Mr=(e,t)=>Lc.join(e.sessionsDir,`${t}.json`);function Mc(e,t){let r=Nc(e);if(typeof r!="object"||r===null||typeof r.id!="string"||typeof r.taskId!="string"||typeof r.repoId!="string"||typeof r.workspaceId!="string"||r.substrate!=="tmux"||typeof r.sessionName!="string"||typeof r.paneId!="string"||!(r.windowTarget===null||typeof r.windowTarget=="string")||typeof r.worktreePath!="string"||!(r.logPath===null||typeof r.logPath=="string")||!Array.isArray(r.command)||!r.command.every(n=>typeof n=="string")||!["starting","running","exited","failed"].includes(r.status)||!(r.startedAt===null||typeof r.startedAt=="string")||!(r.exitedAt===null||typeof r.exitedAt=="string")||!(r.exitCode===null||typeof r.exitCode=="number")||!(r.lastAttachedAt===null||typeof r.lastAttachedAt=="string")||!Fc(r.attach)||!Oc(r.snapshot)||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig session record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function Oc(e){return e===null||typeof e=="object"&&e!==null&&typeof e.paneId=="string"&&(typeof e.windowTarget=="string"||e.windowTarget===null)&&typeof e.alive=="boolean"&&typeof e.capturedAt=="string"}function Fc(e){return typeof e=="object"&&e!==null&&e.detachChord==="ctrl+]"&&(e.lastSize===null||typeof e.lastSize=="object"&&e.lastSize!==null&&typeof e.lastSize.columns=="number"&&typeof e.lastSize.rows=="number")}function Nc(e){let t=typeof e=="object"&&e!==null?e:{};return{id:t.id??"",taskId:t.taskId??"",repoId:t.repoId??"",workspaceId:t.workspaceId??"",substrate:t.substrate??"tmux",sessionName:t.sessionName??"",paneId:t.paneId??"",windowTarget:typeof t.windowTarget=="string"?t.windowTarget:null,worktreePath:t.worktreePath??"",logPath:typeof t.logPath=="string"?t.logPath:null,command:Array.isArray(t.command)?t.command.filter(r=>typeof r=="string"):[],status:t.status??"starting",startedAt:typeof t.startedAt=="string"?t.startedAt:null,exitedAt:typeof t.exitedAt=="string"?t.exitedAt:null,exitCode:typeof t.exitCode=="number"?t.exitCode:null,lastAttachedAt:typeof t.lastAttachedAt=="string"?t.lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:typeof t.attach=="object"&&t.attach!==null&&t.attach.lastSize&&typeof t.attach.lastSize.columns=="number"&&typeof t.attach.lastSize.rows=="number"?t.attach.lastSize:null},snapshot:t.snapshot&&typeof t.snapshot=="object"?{paneId:typeof t.snapshot.paneId=="string"?t.snapshot.paneId:t.paneId??"",windowTarget:typeof t.snapshot.windowTarget=="string"?t.snapshot.windowTarget:null,alive:!!t.snapshot.alive,capturedAt:typeof t.snapshot.capturedAt=="string"?t.snapshot.capturedAt:new Date().toISOString()}:null,createdAt:t.createdAt??"",updatedAt:t.updatedAt??""}}import{spawn as Wc}from"node:child_process";import{createHash as _c}from"node:crypto";import Bc from"node:path";function jt(e){return`'${e.replace(/'/g,"'\\''")}'`}var qc="craig",Zs=async(e,t,r)=>{let n=Or(e,t),s=Kc(),o=await T("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Gc(o.stdout);return await Uc(e,n),i};var Uc=async(e,t)=>{let r=[["set-option","-t",t,"status","off"],["set-option","-t",t,"detach-on-destroy","off"],["set-window-option","-t",t,"pane-border-status","off"],["set-window-option","-t",t,"aggressive-resize","on"]];for(let n of r)await T("tmux",n,{cwd:e})},eo=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},to=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var ro=async(e,t,r)=>{await T("tmux",["pipe-pane","-o","-t",e,`cat >> ${jt(t)}`],{cwd:r})},Lt=async(e,t,r,n)=>{let s=n??so(e);if(r?await T("tmux",["select-window","-t",r],{cwd:e}):await T("tmux",["select-window","-t",t],{cwd:e}),await T("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await T("tmux",["switch-client","-t",s],{cwd:e});return}await zc(e,["attach-session","-t",s])};var no=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var so=e=>{let r=Bc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=_c("sha1").update(e).digest("hex").slice(0,8);return`${qc}-${r}-${n}`},Or=(e,t)=>`${so(e)}-${t.toLowerCase()}`,Kc=()=>{let e=Vc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Vc=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Gc=e=>{let t=Hc(e);if(t.length<3)throw new Error("tmux did not return the expected session, window, and pane targets for the Craig task session.");return{sessionName:t[0],windowTarget:t[1],paneId:t[2]}},Hc=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),zc=async(e,t)=>{await new Promise((r,n)=>{let s=Wc("tmux",t,{cwd:e,stdio:"inherit"});s.on("error",n),s.on("exit",o=>{if(o===0){r();return}n(new Error(`tmux ${t.join(" ")} failed with exit code ${o??"unknown"}.`))})})};import{accessSync as Yc,constants as Qc}from"node:fs";import{homedir as oo}from"node:os";import ke from"node:path";var Jc=[ke.join(oo(),".local","bin"),ke.join(oo(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ao(e=process.env){return Xc([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Jc])}function ve(e=process.env){return{...e,PATH:ao(e).join(ke.delimiter)}}function Fr(e,t={}){if(e.includes(ke.sep)){let r=ke.isAbsolute(e)?e:ke.resolve(t.cwd??process.cwd(),e);return io(r)?r:null}for(let r of ao(t.env)){let n=ke.join(r,e);if(io(n))return n}return null}function Ee(e,t={}){let r=Fr(e,t);if(r)return r;throw new Error(`Command not found: ${e}. Install it or add its directory to PATH. Craig also checks ~/.local/bin, /opt/homebrew/bin, and /usr/local/bin.`)}function io(e){try{return Yc(e,Qc.X_OK),!0}catch{return!1}}function Xc(e){return[...new Set(e)]}var at={async create(e,t){let r=await Zs(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await ro(r.paneId,t.logPath,t.repoRoot);let n=await lo({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||Or(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ce(e,s),s},async attach(e,t,r){let n=await at.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Lt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ce(e,s),s},async resize(e,t,r,n){await eo(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ce(e,s),s},async write(){throw new Error("Direct session writes are owned by the terminal bridge.")},async read(){throw new Error("Direct session reads are owned by the terminal bridge.")},async terminate(e,t,r){let n={...t,status:"failed",exitedAt:new Date().toISOString(),snapshot:{...t.snapshot??{paneId:t.paneId,windowTarget:t.windowTarget,alive:!1,capturedAt:new Date().toISOString()},alive:!1,capturedAt:new Date().toISOString()},command:t.command};return await Ce(e,n),n},async snapshot(e,t){return Zc(e,t)}},Nr={async prepare(e,t){let n=e.runnerSession.command[0],s=ve();await T(Ee(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ee(r[0],{cwd:e.worktreePath,env:ve()});await to(t.session.paneId,[n,...r.slice(1)].map(s=>jt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},Zc=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return lo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},lo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Wr=async(e,t,r,n={})=>{let s=r.trim(),o=await g.load(e),i=n.runner??g.runners.getDefault(o);if(g.runners.assertEnabled(i,o),t.trim().length===0)throw new Error(n.workspaceId?"Workspace id cannot be empty.":"Repo id cannot be empty.");if(s.length===0)throw new Error("Task prompt cannot be empty.");let a=n.workspaceId?await ot(e,n.workspaceId,s,{runner:i,config:o}):await qe(e,t,s,{runner:i,config:o}),l=a.task,c=g.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?co.resolve(e.workspaceRoot,l.artifacts.logPath):co.join(e.logsDir,`${l.id}.log`);try{await Nr.prepare(l,{repoRoot:a.repoRoot});let f=await at.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Nr.launch(l,{repoRoot:a.repoRoot,session:f});let u=new Date().toISOString();f={...f,status:"running",startedAt:u,command:c};let w={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:u,lastKnownState:"running",exitCode:null,exitedAt:null}};return await R(e,w),await Ce(e,f),{kind:"createTask",taskId:w.id,repoId:w.repoId,workspaceId:w.workspaceId,sessionId:f.id,status:w.status,branch:w.branch,worktreePath:w.worktreePath,runner:w.runner}}catch(f){let u={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await R(e,u),f}};import{mkdir as cd}from"node:fs/promises";import dd from"node:path";var uo=3,ed=1e3,td=1e4,Ue=async e=>{let t=await E("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var po=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await T("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Mt=async(e,t)=>{let r=await T("gh",go(e),{cwd:t});return JSON.parse(r.stdout)},Ot=async(e,t)=>{let r=await E("gh",go(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},fo=async(e,t,r)=>{if(r.length===0)return[];let n=ad(r),s=await rd(e,["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`]),i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=ld(c);return{id:a.id,found:d!==null,view:d}})},mo=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:id(t.stdout.trim())},rd=async(e,t)=>{let r;for(let n=0;n<=uo;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===uo||!nd(s))throw s;await od(sd(n))}throw r},nd=e=>{let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("rate limit")||t.includes("secondary rate limit")||t.includes("abuse detection")||t.includes("api rate limit exceeded")||t.includes("you have exceeded")},sd=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||ed,r=Math.min(t*2**e,td),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},od=e=>new Promise(t=>setTimeout(t,e)),go=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],id=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},ad=e=>`
34
+ `)},Lr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Xs=()=>({provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}),$t=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),jc=async(e,t)=>{let n=(await q(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},eo=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import po from"node:path";import{readFile as Lc,rm as gk}from"node:fs/promises";import Mc from"node:path";var he=async(e,t)=>{let r=await Lc(Mr(e,t),"utf8"),n=JSON.parse(r);return Oc(n,Mr(e,t))},Ce=async(e,t)=>{await M(Mr(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Mr=(e,t)=>Mc.join(e.sessionsDir,`${t}.json`);function Oc(e,t){let r=Wc(e);if(typeof r!="object"||r===null||typeof r.id!="string"||typeof r.taskId!="string"||typeof r.repoId!="string"||typeof r.workspaceId!="string"||r.substrate!=="tmux"||typeof r.sessionName!="string"||typeof r.paneId!="string"||!(r.windowTarget===null||typeof r.windowTarget=="string")||typeof r.worktreePath!="string"||!(r.logPath===null||typeof r.logPath=="string")||!Array.isArray(r.command)||!r.command.every(n=>typeof n=="string")||!["starting","running","exited","failed"].includes(r.status)||!(r.startedAt===null||typeof r.startedAt=="string")||!(r.exitedAt===null||typeof r.exitedAt=="string")||!(r.exitCode===null||typeof r.exitCode=="number")||!(r.lastAttachedAt===null||typeof r.lastAttachedAt=="string")||!Nc(r.attach)||!Fc(r.snapshot)||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig session record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function Fc(e){return e===null||typeof e=="object"&&e!==null&&typeof e.paneId=="string"&&(typeof e.windowTarget=="string"||e.windowTarget===null)&&typeof e.alive=="boolean"&&typeof e.capturedAt=="string"}function Nc(e){return typeof e=="object"&&e!==null&&e.detachChord==="ctrl+]"&&(e.lastSize===null||typeof e.lastSize=="object"&&e.lastSize!==null&&typeof e.lastSize.columns=="number"&&typeof e.lastSize.rows=="number")}function Wc(e){let t=typeof e=="object"&&e!==null?e:{};return{id:t.id??"",taskId:t.taskId??"",repoId:t.repoId??"",workspaceId:t.workspaceId??"",substrate:t.substrate??"tmux",sessionName:t.sessionName??"",paneId:t.paneId??"",windowTarget:typeof t.windowTarget=="string"?t.windowTarget:null,worktreePath:t.worktreePath??"",logPath:typeof t.logPath=="string"?t.logPath:null,command:Array.isArray(t.command)?t.command.filter(r=>typeof r=="string"):[],status:t.status??"starting",startedAt:typeof t.startedAt=="string"?t.startedAt:null,exitedAt:typeof t.exitedAt=="string"?t.exitedAt:null,exitCode:typeof t.exitCode=="number"?t.exitCode:null,lastAttachedAt:typeof t.lastAttachedAt=="string"?t.lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:typeof t.attach=="object"&&t.attach!==null&&t.attach.lastSize&&typeof t.attach.lastSize.columns=="number"&&typeof t.attach.lastSize.rows=="number"?t.attach.lastSize:null},snapshot:t.snapshot&&typeof t.snapshot=="object"?{paneId:typeof t.snapshot.paneId=="string"?t.snapshot.paneId:t.paneId??"",windowTarget:typeof t.snapshot.windowTarget=="string"?t.snapshot.windowTarget:null,alive:!!t.snapshot.alive,capturedAt:typeof t.snapshot.capturedAt=="string"?t.snapshot.capturedAt:new Date().toISOString()}:null,createdAt:t.createdAt??"",updatedAt:t.updatedAt??""}}import{spawn as _c}from"node:child_process";import{createHash as qc}from"node:crypto";import Bc from"node:path";function jt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Uc="craig",to=async(e,t,r)=>{let n=Or(e,t),s=Vc(),o=await T("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Hc(o.stdout);return await Kc(e,n),i};var Kc=async(e,t)=>{let r=[["set-option","-t",t,"status","off"],["set-option","-t",t,"detach-on-destroy","off"],["set-window-option","-t",t,"pane-border-status","off"],["set-window-option","-t",t,"aggressive-resize","on"]];for(let n of r)await T("tmux",n,{cwd:e})},ro=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},no=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var so=async(e,t,r)=>{await T("tmux",["pipe-pane","-o","-t",e,`cat >> ${jt(t)}`],{cwd:r})},Lt=async(e,t,r,n)=>{let s=n??io(e);if(r?await T("tmux",["select-window","-t",r],{cwd:e}):await T("tmux",["select-window","-t",t],{cwd:e}),await T("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await T("tmux",["switch-client","-t",s],{cwd:e});return}await Qc(e,["attach-session","-t",s])};var oo=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var io=e=>{let r=Bc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=qc("sha1").update(e).digest("hex").slice(0,8);return`${Uc}-${r}-${n}`},Or=(e,t)=>`${io(e)}-${t.toLowerCase()}`,Vc=()=>{let e=Gc();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Gc=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Hc=e=>{let t=zc(e);if(t.length<3)throw new Error("tmux did not return the expected session, window, and pane targets for the Craig task session.");return{sessionName:t[0],windowTarget:t[1],paneId:t[2]}},zc=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Qc=async(e,t)=>{await new Promise((r,n)=>{let s=_c("tmux",t,{cwd:e,stdio:"inherit"});s.on("error",n),s.on("exit",o=>{if(o===0){r();return}n(new Error(`tmux ${t.join(" ")} failed with exit code ${o??"unknown"}.`))})})};import{accessSync as Yc,constants as Jc}from"node:fs";import{homedir as ao}from"node:os";import ke from"node:path";var Xc=[ke.join(ao(),".local","bin"),ke.join(ao(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function co(e=process.env){return Zc([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Xc])}function ve(e=process.env){return{...e,PATH:co(e).join(ke.delimiter)}}function Fr(e,t={}){if(e.includes(ke.sep)){let r=ke.isAbsolute(e)?e:ke.resolve(t.cwd??process.cwd(),e);return lo(r)?r:null}for(let r of co(t.env)){let n=ke.join(r,e);if(lo(n))return n}return null}function Ee(e,t={}){let r=Fr(e,t);if(r)return r;throw new Error(`Command not found: ${e}. Install it or add its directory to PATH. Craig also checks ~/.local/bin, /opt/homebrew/bin, and /usr/local/bin.`)}function lo(e){try{return Yc(e,Jc.X_OK),!0}catch{return!1}}function Zc(e){return[...new Set(e)]}var at={async create(e,t){let r=await to(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await so(r.paneId,t.logPath,t.repoRoot);let n=await uo({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||Or(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ce(e,s),s},async attach(e,t,r){let n=await at.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Lt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ce(e,s),s},async resize(e,t,r,n){await ro(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ce(e,s),s},async write(){throw new Error("Direct session writes are owned by the terminal bridge.")},async read(){throw new Error("Direct session reads are owned by the terminal bridge.")},async terminate(e,t,r){let n={...t,status:"failed",exitedAt:new Date().toISOString(),snapshot:{...t.snapshot??{paneId:t.paneId,windowTarget:t.windowTarget,alive:!1,capturedAt:new Date().toISOString()},alive:!1,capturedAt:new Date().toISOString()},command:t.command};return await Ce(e,n),n},async snapshot(e,t){return ed(e,t)}},Nr={async prepare(e,t){let n=e.runnerSession.command[0],s=ve();await T(Ee(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ee(r[0],{cwd:e.worktreePath,env:ve()});await no(t.session.paneId,[n,...r.slice(1)].map(s=>jt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},ed=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return uo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},uo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Wr=async(e,t,r,n={})=>{let s=r.trim(),o=await h.load(e),i=n.runner??h.runners.getDefault(o);if(h.runners.assertEnabled(i,o),t.trim().length===0)throw new Error(n.workspaceId?"Workspace id cannot be empty.":"Repo id cannot be empty.");if(s.length===0)throw new Error("Task prompt cannot be empty.");let a=n.workspaceId?await ot(e,n.workspaceId,s,{runner:i,config:o}):await Be(e,t,s,{runner:i,config:o}),l=a.task,c=h.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?po.resolve(e.workspaceRoot,l.artifacts.logPath):po.join(e.logsDir,`${l.id}.log`);try{await Nr.prepare(l,{repoRoot:a.repoRoot});let f=await at.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Nr.launch(l,{repoRoot:a.repoRoot,session:f});let u=new Date().toISOString();f={...f,status:"running",startedAt:u,command:c};let w={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:u,lastKnownState:"running",exitCode:null,exitedAt:null}};return await y(e,w),await Ce(e,f),{kind:"createTask",taskId:w.id,repoId:w.repoId,workspaceId:w.workspaceId,sessionId:f.id,status:w.status,branch:w.branch,worktreePath:w.worktreePath,runner:w.runner}}catch(f){let u={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await y(e,u),f}};import{mkdir as dd}from"node:fs/promises";import ud from"node:path";var fo=3,td=1e3,rd=1e4,Ue=async e=>{let t=await E("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var mo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await T("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Mt=async(e,t)=>{let r=await T("gh",ko(e),{cwd:t});return JSON.parse(r.stdout)},Ot=async(e,t)=>{let r=await E("gh",ko(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},go=async(e,t,r)=>{if(r.length===0)return[];let n=ld(r),s=await nd(e,["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`]),i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=cd(c);return{id:a.id,found:d!==null,view:d}})},ho=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:ad(t.stdout.trim())},nd=async(e,t)=>{let r;for(let n=0;n<=fo;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===fo||!sd(s))throw s;await id(od(n))}throw r},sd=e=>{let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("rate limit")||t.includes("secondary rate limit")||t.includes("abuse detection")||t.includes("api rate limit exceeded")||t.includes("you have exceeded")},od=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||td,r=Math.min(t*2**e,rd),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},id=e=>new Promise(t=>setTimeout(t,e)),ko=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],ad=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},ld=e=>`
35
35
  query CraigPullRequestBatch($owner: String!, $name: String!) {
36
36
  repository(owner: $owner, name: $name) {
37
37
  ${e.map((r,n)=>{let s=`item${n}`;return r.mode==="number"?`${s}: pullRequest(number: ${Number(r.selector)}) { ...PrFields }`:`${s}: pullRequests(headRefName: ${JSON.stringify(r.selector)}, states: OPEN, first: 1, orderBy: { field: UPDATED_AT, direction: DESC }) { nodes { ...PrFields } }`}).join(`
@@ -110,56 +110,56 @@ fragment PrFields on PullRequest {
110
110
  }
111
111
  }
112
112
  }
113
- `,ld=e=>{if(!e||typeof e!="object")return null;let t="nodes"in e?e.nodes?.[0]??null:e;if(!t||typeof t!="object")return null;let r=t,n=r.statusCheckRollup?.contexts?.nodes??r.commits?.nodes?.[0]?.commit?.statusCheckRollup?.contexts?.nodes??[];return{number:r.number,url:r.url,baseRefName:r.baseRefName,headRefName:r.headRefName,headRefOid:r.headRefOid??null,state:r.state,isDraft:r.isDraft??!1,title:r.title??null,createdAt:r.createdAt??null,updatedAt:r.updatedAt??null,mergedAt:r.mergedAt??null,mergeable:r.mergeable,mergeStateStatus:r.mergeStateStatus,reviewDecision:r.reviewDecision??null,statusCheckRollup:n,comments:r.comments?.nodes??[]}};var xe=async(e,t)=>{let r=Ie(e,t.artifacts.prStatusPath);r&&(await cd(dd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,prs:t.prs}))},lt=async(e,t,r,n,s={readRawTask:H,validateTaskRecord:F,writeTask:R,writePrStatusArtifact:xe})=>{let o=et(r,n),i=We(t,o),a=Ze(i.prs),l={...i,status:a};await s.writePrStatusArtifact(e,l);let c=await s.readRawTask(e,t.id),d=s.validateTaskRecord(c,`${e.tasksDir}/${t.id}.json`),p=d.status==="closed"?d.status:a,f=We({...d,status:p},o);return await s.writeTask(e,f),f},ct=async(e,t)=>{let r=v(t),n=r?.number?String(r.number):t.branch,s=await Mt(n,t.worktreePath);return lt(e,t,s,r)},dt=async(e,t)=>{let r=await Ot(t.branch,t.worktreePath);return r?{discovered:!0,task:await lt(e,t,r,null)}:{discovered:!1,task:t}};var Ke=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await Mt(n,r.worktreePath),a=ko(i);return r.pullRequest=a,await ho(e,t,r.repoId,a),"synced"}let s=await Ot(n,r.worktreePath);if(!s)return"not_found";let o=ko(s);return r.pullRequest=o,await ho(e,t,r.repoId,o),"discovered"},ho=async(e,t,r,n)=>{let s=await H(e,t.id),o=F(s,`${e.tasksDir}/${t.id}.json`),i=(o.repoTargets??t.repoTargets??[]).map(l=>l.repoId===r?{...l,pullRequest:n}:l),a={...o,repoTargets:i};return await R(e,a),a},ko=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:ud(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:pd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),ud=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,pd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var ut=async(e,t)=>{let r=await b(e,t),n=v(r);return n?.number?(await Ue(r.worktreePath),ge(n)?(await dt(e,r)).task:ct(e,r)):r},Br=async(e,t)=>{let r=await b(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Ve(e,t),b(e,t);let n=v(r);if(await N(r),await Ue(r.worktreePath),!n?.number||ge(n)){let o=await dt(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await xe(e,o.task),o.task}let s=await ct(e,r);return await xe(e,s),s},Ve=async(e,t)=>{let r=await b(e,t),n=(r.repoTargets??[]).filter(a=>a.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let a of n){await Ue(a.worktreePath);let l=a.pullRequest.number?await Ke(e,r,a):await Ke(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await H(e,r.id),i=F(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=To(i),await R(e,i)),s},qr=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=_r(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let c of s.repoTargets.filter(d=>d.status==="ready")){let d={id:`${s.id}:${c.repoId}`,task:s,targetRepoId:c.repoId,worktreePath:c.worktreePath,selector:c.pullRequest.number?String(c.pullRequest.number):c.branch,mode:c.pullRequest.number?"number":"head"};await wo(n,d).catch(async()=>{try{let p=c.pullRequest.number?await Ke(e,s,c):await Ke(e,s,c).catch(()=>"not_found");Ft(o,p,c.pullRequest.number??null,c.pullRequest.url??null)}catch{}})}continue}let i=v(s),a=i?.number&&!ge(i),l={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):s.branch,mode:a?"number":"head"};await wo(n,l).catch(async()=>{try{let{disposition:c,task:d}=await Nt(e,s.id),p=v(d);Ft(o,c,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await Ue(s.worktreePath);let o=await fo(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=_r(r,a.task),c=i.get(a.id);if(!c?.found||!c.view){Ft(l,"not_found",null,null);continue}if(a.targetRepoId){let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await fd(e,p,a.targetRepoId,c.view)}else{let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await lt(e,p,c.view,v(p))}Ft(l,a.mode==="number"?"synced":"discovered",c.view.number,c.view.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await H(e,s.id),i=F(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=To(i),await R(e,i))}return t.map(s=>_r(r,s))},Nt=async(e,t)=>{let r=await b(e,t);await N(r),await Ue(r.worktreePath);let n=v(r);if(n?.number&&!ge(n))return{disposition:"synced",task:await ct(e,r)};let s=await dt(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},To=e=>{let t=(e.repoTargets??[]).filter(n=>n.status==="ready"),r=t.map(n=>n.pullRequest).filter(n=>!!n.number);return r.length===0?e.status:r.every(n=>n.status==="merged")?"merged":r.length===t.length&&r.every(kd)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},fd=async(e,t,r,n)=>{let s=md(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await R(e,i),i},md=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:gd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:hd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),gd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,hd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,wo=async(e,t)=>{let r=await mo(t.worktreePath);if(!r)throw new Error("GitHub repository remote could not be parsed.");let n=`${r.owner}/${r.name}`,s=e.get(n);if(s){s.items.push(t);return}e.set(n,{worktreePath:t.worktreePath,repository:r,items:[t]})},_r=(e,t)=>{let r=e.get(t.id);if(r)return r;let n={taskId:t.id,synced:0,discovered:0,notFound:0,hadPr:t.type==="project"?!!t.repoTargets?.some(s=>s.pullRequest.number):!!v(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},Ft=(e,t,r,n)=>{if(t==="synced"){e.synced+=1;return}if(t==="discovered"){e.discovered+=1,e.firstDiscoveredPrNumber??=r,e.firstDiscoveredPrUrl??=n;return}e.notFound+=1},kd=e=>e.mergeable&&e.reviewDecision!=="REVIEW_REQUIRED"&&e.reviewDecision!=="CHANGES_REQUESTED"&&e.mergeStateStatus!=="REVIEW_REQUIRED"&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped");var Ur=async(e,t)=>{let r=await b(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Ve(e,t),r=await b(e,t)):r.prs.some(o=>o.number)&&(r=await ut(e,t))}catch{}let n=await rt(e,r),s=r.sessionId?await he(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var Kr=async(e,t)=>{let r=await b(e,t);if(await N(r),(await T("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await wd(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},wd=async e=>{let t=[],r=await T("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await Td(e);for(let s of n){let o=await E("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
113
+ `,cd=e=>{if(!e||typeof e!="object")return null;let t="nodes"in e?e.nodes?.[0]??null:e;if(!t||typeof t!="object")return null;let r=t,n=r.statusCheckRollup?.contexts?.nodes??r.commits?.nodes?.[0]?.commit?.statusCheckRollup?.contexts?.nodes??[];return{number:r.number,url:r.url,baseRefName:r.baseRefName,headRefName:r.headRefName,headRefOid:r.headRefOid??null,state:r.state,isDraft:r.isDraft??!1,title:r.title??null,createdAt:r.createdAt??null,updatedAt:r.updatedAt??null,mergedAt:r.mergedAt??null,mergeable:r.mergeable,mergeStateStatus:r.mergeStateStatus,reviewDecision:r.reviewDecision??null,statusCheckRollup:n,comments:r.comments?.nodes??[]}};var xe=async(e,t)=>{let r=Ie(e,t.artifacts.prStatusPath);r&&(await dd(ud.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,prs:t.prs}))},lt=async(e,t,r,n,s={readRawTask:H,validateTaskRecord:F,writeTask:y,writePrStatusArtifact:xe})=>{let o=et(r,n),i=We(t,o),a=Ze(i.prs),l={...i,status:a};await s.writePrStatusArtifact(e,l);let c=await s.readRawTask(e,t.id),d=s.validateTaskRecord(c,`${e.tasksDir}/${t.id}.json`),p=d.status==="closed"?d.status:a,f=We({...d,status:p},o);return await s.writeTask(e,f),f},ct=async(e,t)=>{let r=v(t),n=r?.number?String(r.number):t.branch,s=await Mt(n,t.worktreePath);return lt(e,t,s,r)},dt=async(e,t)=>{let r=await Ot(t.branch,t.worktreePath);return r?{discovered:!0,task:await lt(e,t,r,null)}:{discovered:!1,task:t}};var Ke=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await Mt(n,r.worktreePath),a=To(i);return r.pullRequest=a,await wo(e,t,r.repoId,a),"synced"}let s=await Ot(n,r.worktreePath);if(!s)return"not_found";let o=To(s);return r.pullRequest=o,await wo(e,t,r.repoId,o),"discovered"},wo=async(e,t,r,n)=>{let s=await H(e,t.id),o=F(s,`${e.tasksDir}/${t.id}.json`),i=(o.repoTargets??t.repoTargets??[]).map(l=>l.repoId===r?{...l,pullRequest:n}:l),a={...o,repoTargets:i};return await y(e,a),a},To=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:pd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:fd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),pd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,fd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var ut=async(e,t)=>{let r=await S(e,t),n=v(r);return n?.number?(await Ue(r.worktreePath),ge(n)?(await dt(e,r)).task:ct(e,r)):r},qr=async(e,t)=>{let r=await S(e,t);if(r.type==="project"&&r.repoTargets?.length)return await Ve(e,t),S(e,t);let n=v(r);if(await N(r),await Ue(r.worktreePath),!n?.number||ge(n)){let o=await dt(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await xe(e,o.task),o.task}let s=await ct(e,r);return await xe(e,s),s},Ve=async(e,t)=>{let r=await S(e,t),n=(r.repoTargets??[]).filter(a=>a.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let a of n){await Ue(a.worktreePath);let l=a.pullRequest.number?await Ke(e,r,a):await Ke(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await H(e,r.id),i=F(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=yo(i),await y(e,i)),s},Br=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=_r(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let c of s.repoTargets.filter(d=>d.status==="ready")){let d={id:`${s.id}:${c.repoId}`,task:s,targetRepoId:c.repoId,worktreePath:c.worktreePath,selector:c.pullRequest.number?String(c.pullRequest.number):c.branch,mode:c.pullRequest.number?"number":"head"};await Ro(n,d).catch(async()=>{try{let p=c.pullRequest.number?await Ke(e,s,c):await Ke(e,s,c).catch(()=>"not_found");Ft(o,p,c.pullRequest.number??null,c.pullRequest.url??null)}catch{}})}continue}let i=v(s),a=i?.number&&!ge(i),l={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):s.branch,mode:a?"number":"head"};await Ro(n,l).catch(async()=>{try{let{disposition:c,task:d}=await Nt(e,s.id),p=v(d);Ft(o,c,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await Ue(s.worktreePath);let o=await go(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=_r(r,a.task),c=i.get(a.id);if(!c?.found||!c.view){Ft(l,"not_found",null,null);continue}if(a.targetRepoId){let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await md(e,p,a.targetRepoId,c.view)}else{let d=await H(e,a.task.id),p=F(d,`${e.tasksDir}/${a.task.id}.json`);await lt(e,p,c.view,v(p))}Ft(l,a.mode==="number"?"synced":"discovered",c.view.number,c.view.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await H(e,s.id),i=F(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=yo(i),await y(e,i))}return t.map(s=>_r(r,s))},Nt=async(e,t)=>{let r=await S(e,t);await N(r),await Ue(r.worktreePath);let n=v(r);if(n?.number&&!ge(n))return{disposition:"synced",task:await ct(e,r)};let s=await dt(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},yo=e=>{let t=(e.repoTargets??[]).filter(n=>n.status==="ready"),r=t.map(n=>n.pullRequest).filter(n=>!!n.number);return r.length===0?e.status:r.every(n=>n.status==="merged")?"merged":r.length===t.length&&r.every(wd)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},md=async(e,t,r,n)=>{let s=gd(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await y(e,i),i},gd=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:hd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:kd(e.reviewDecision??null),requiredChecks:tt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),hd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,kd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Ro=async(e,t)=>{let r=await ho(t.worktreePath);if(!r)throw new Error("GitHub repository remote could not be parsed.");let n=`${r.owner}/${r.name}`,s=e.get(n);if(s){s.items.push(t);return}e.set(n,{worktreePath:t.worktreePath,repository:r,items:[t]})},_r=(e,t)=>{let r=e.get(t.id);if(r)return r;let n={taskId:t.id,synced:0,discovered:0,notFound:0,hadPr:t.type==="project"?!!t.repoTargets?.some(s=>s.pullRequest.number):!!v(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},Ft=(e,t,r,n)=>{if(t==="synced"){e.synced+=1;return}if(t==="discovered"){e.discovered+=1,e.firstDiscoveredPrNumber??=r,e.firstDiscoveredPrUrl??=n;return}e.notFound+=1},wd=e=>e.mergeable&&e.reviewDecision!=="REVIEW_REQUIRED"&&e.reviewDecision!=="CHANGES_REQUESTED"&&e.mergeStateStatus!=="REVIEW_REQUIRED"&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped");var Ur=async(e,t)=>{let r=await S(e,t);try{r.type==="project"&&r.repoTargets?.length?(await Ve(e,t),r=await S(e,t)):r.prs.some(o=>o.number)&&(r=await ut(e,t))}catch{}let n=await rt(e,r),s=r.sessionId?await he(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var Kr=async(e,t)=>{let r=await S(e,t);if(await N(r),(await T("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await Td(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},Td=async e=>{let t=[],r=await T("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await Rd(e);for(let s of n){let o=await E("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
114
114
 
115
- `)},Td=async e=>(await T("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
116
- `).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Rd}from"node:child_process";import{access as yd}from"node:fs/promises";var Vr=async(e,t)=>{let r=await b(e,t),n=_e(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await yd(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Gr=async e=>{await new Promise((t,r)=>{let n=!1,s=Rd("tail",["-n","+1","-f",e],{stdio:"inherit"}),o=()=>{n=!0,s.kill("SIGINT")};process.on("SIGINT",o),s.on("error",a=>{i(),r(a)}),s.on("exit",(a,l)=>{if(i(),n||l==="SIGINT"){t();return}if(a===0){t();return}r(new Error(`tail -n +1 -f ${e} failed with exit code ${a??"unknown"}.`))});function i(){process.off("SIGINT",o)}})};import{mkdir as Pd}from"node:fs/promises";import bd from"node:path";var Hr=async(e,t)=>{let r=await b(e,t);if(await N(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await At(r.worktreePath)&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);let s=(await g.load(e)).checks?.commands??[];if(s.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);r.checks.status="running",r.checks.commands=[...s],r.checks.results=[],await R(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await E("sh",["-lc",i],{cwd:r.worktreePath}),c=new Date().toISOString(),d=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:c,exitCode:d}),d!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=c,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await Ro(e,r),await R(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}return r.checks.results=o,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await Ro(e,r),await R(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Ro=async(e,t)=>{let r=Ie(e,t.artifacts.checkSummaryPath);r&&(await Pd(bd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var zr=async(e,t)=>{let r=await b(e,t);await N(r);let n=await At(r.worktreePath);if(r.status==="running"&&n&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!n)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let s=r.prompt.value.trim();await Bs(r.worktreePath),await qs(r.worktreePath,s);let o=await Us(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await R(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Sd}from"node:fs/promises";var Yr=async(e,t)=>{let r=await b(e,t),n=await Id(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await R(e,s),s},Id=async e=>{try{return await Sd(e),!0}catch{return!1}};var Qr=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await no(e.repoRoot,s.sessionName),t.cleanup.paneClosedAt=new Date().toISOString()}}catch(s){n.push(s instanceof Error?s.message:"Failed to close tmux session.")}if(t.cleanup.preservedWorktree=r.preserveWorktree,!r.preserveWorktree)try{await Ks(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(s){n.push(s instanceof Error?s.message:"Failed to remove worktree.")}t.cleanup.warning=n.length>0?n.join(" "):null,await R(e,t)};var Jr=async(e,t,r)=>{let[n,s]=await Promise.all([b(e,t),X(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await R(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Xr=async(e,t)=>{let r=await b(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>X(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Zr=async(e,t)=>{let r=await b(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([X(e,r.repoId),he(e,r.sessionId)]),o=await at.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var en=async(e,t)=>{let r=await b(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await he(e,r.sessionId).catch(s=>{throw Cd(s)?new Error(`Task ${r.id} does not have a Craig session.`):s});if(!n.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await Lt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Cd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as vd}from"node:child_process";var tn=async(e,t)=>{let r=await b(e,t);await N(r);let s=(await g.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await Ed(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Ed=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=vd(s,o,{cwd:t,stdio:"inherit"});i.on("error",n),i.on("exit",a=>{if(a===0){r();return}n(new Error(`${e.join(" ")} failed with exit code ${a??"unknown"}.`))})})};var rn=async(e,t,r)=>{let n=await Q(e,t);await R(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},nn=async(e,t,r)=>{let n=await Q(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await R(e,s),s},sn=async(e,t)=>{let r=await Q(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await R(e,s),s};var on=async(e,t,r="merge",n)=>{let s=await b(e,t),o=n??v(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await po(s.worktreePath,o,r)};var S={listTasks:Dr,getTask:b,provisionTask:qe,provisionProjectTask:ot,createTask:Wr,showTask:Ur,showTaskDiff:Kr,prepareTaskLogs:Vr,streamTaskLogs:Gr,runChecks:Hr,commitTask:zr,closeTask:Yr,cleanupTask:Qr,addTaskLink:Jr,listTaskLinks:Xr,sortTasksForDisplay:$r,resolveSelectedTaskId:jr,allocateTaskId:Ar,allocateTaskIdForRepo:Be,allocateProjectTaskId:nt,createDefaultTaskPtyTabs:it,assertTaskWorktreeExists:N,resolveTaskLogPath:_e,buildTaskInspection:rt,resolveArtifactPath:Ie,attachTask:Zr,focusTask:en,openTask:tn,markRunnerFailed:rn,recordStartupFailure:nn,markTaskStarted:sn,prs:{refresh:ut,refreshChecks:Br,discoverOrRefresh:Nt,discoverOrRefreshAll:Ve,discoverOrRefreshMany:qr,merge:on,getPrimaryPr:v,isPrTerminal:ge,isMergeReady:xt,deriveTaskStatus:Ze,upsertPr:We,normalizePr:et,summarizeRequiredChecks:vr,writePrStatusArtifact:xe}};async function yo(e,t){switch(e.kind){case"addWorkspace":{let r=await Y.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await an(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Y.repos.addRepo(t.paths,e.path);return await an(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Y.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Me({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await B(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Y.repos.removeRepo(t.paths,e.repoId,{listTasks:S.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return Y.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Y.archiveWorkspace(t.paths,e.workspaceId);return await xd(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Y.restoreWorkspace(t.paths,e.workspaceId);return await an(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Y.removeWorkspace(t.paths,e.workspaceId,{listTasks:S.listTasks});case"createTask":return S.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?S.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):S.listTasks(t.paths);case"attachTask":return S.attachTask(t.paths,e.taskId);case"addTaskLink":return S.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return S.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return S.showTask(t.paths,e.taskId);case"showSelectedTask":return S.showTask(t.paths,Ae(t,"show"));case"streamTaskLogs":return S.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return S.prepareTaskLogs(t.paths,Ae(t,"logs"));case"showTaskDiff":return S.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return S.showTaskDiff(t.paths,Ae(t,"diff"));case"focusTask":return S.focusTask(t.paths,e.taskId);case"focusSelectedTask":return S.focusTask(t.paths,Ae(t,"focus"));case"openTask":return S.openTask(t.paths,e.taskId);case"openSelectedTask":return S.openTask(t.paths,Ae(t,"open"));case"runChecks":return S.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return S.runChecks(t.paths,Ae(t,"check"));case"commitTask":return S.commitTask(t.paths,e.taskId);case"commitSelectedTask":return S.commitTask(t.paths,Ae(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return Ad(e)}}async function an(e,t,r){let n=await Me({uiStateFile:e.uiStateFile})??yt();await me({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function xd(e,t){let r=await Me({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await me({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Ad(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ae(e,t){if(e.selectedTaskId)return e.selectedTaskId;throw new Error(`No task selected. Create a task with 'task new --repo <repo-id> <prompt>' or use '${t} <id>'.`)}function Po(e){switch(e.kind){case"createWorkspace":return[`${e.created?"Registered":"Updated"} ${e.workspace.kind??"repo"} workspace ${e.workspace.id}`,`Path: ${e.workspace.rootPath??""}`,`Repos: ${e.repos.map(t=>t.id).join(", ")}`].join(`
115
+ `)},Rd=async e=>(await T("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
116
+ `).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as yd}from"node:child_process";import{access as Pd}from"node:fs/promises";var Vr=async(e,t)=>{let r=await S(e,t),n=_e(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await Pd(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Gr=async e=>{await new Promise((t,r)=>{let n=!1,s=yd("tail",["-n","+1","-f",e],{stdio:"inherit"}),o=()=>{n=!0,s.kill("SIGINT")};process.on("SIGINT",o),s.on("error",a=>{i(),r(a)}),s.on("exit",(a,l)=>{if(i(),n||l==="SIGINT"){t();return}if(a===0){t();return}r(new Error(`tail -n +1 -f ${e} failed with exit code ${a??"unknown"}.`))});function i(){process.off("SIGINT",o)}})};import{mkdir as Sd}from"node:fs/promises";import bd from"node:path";var Hr=async(e,t)=>{let r=await S(e,t);if(await N(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await At(r.worktreePath)&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);let s=(await h.load(e)).checks?.commands??[];if(s.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);r.checks.status="running",r.checks.commands=[...s],r.checks.results=[],await y(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await E("sh",["-lc",i],{cwd:r.worktreePath}),c=new Date().toISOString(),d=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:c,exitCode:d}),d!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=c,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await Po(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}return r.checks.results=o,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await Po(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Po=async(e,t)=>{let r=Ie(e,t.artifacts.checkSummaryPath);r&&(await Sd(bd.dirname(r),{recursive:!0}),await M(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var zr=async(e,t)=>{let r=await S(e,t);await N(r);let n=await At(r.worktreePath);if(r.status==="running"&&n&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!n)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let s=r.prompt.value.trim();await Us(r.worktreePath),await Ks(r.worktreePath,s);let o=await Vs(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await y(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Id}from"node:fs/promises";var Qr=async(e,t)=>{let r=await S(e,t),n=await Cd(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await y(e,s),s},Cd=async e=>{try{return await Id(e),!0}catch{return!1}};var Yr=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await oo(e.repoRoot,s.sessionName),t.cleanup.paneClosedAt=new Date().toISOString()}}catch(s){n.push(s instanceof Error?s.message:"Failed to close tmux session.")}if(t.cleanup.preservedWorktree=r.preserveWorktree,!r.preserveWorktree)try{await Gs(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(s){n.push(s instanceof Error?s.message:"Failed to remove worktree.")}t.cleanup.warning=n.length>0?n.join(" "):null,await y(e,t)};var Jr=async(e,t,r)=>{let[n,s]=await Promise.all([S(e,t),X(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await y(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Xr=async(e,t)=>{let r=await S(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>X(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Zr=async(e,t)=>{let r=await S(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([X(e,r.repoId),he(e,r.sessionId)]),o=await at.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var en=async(e,t)=>{let r=await S(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await he(e,r.sessionId).catch(s=>{throw vd(s)?new Error(`Task ${r.id} does not have a Craig session.`):s});if(!n.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await Lt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},vd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Ed}from"node:child_process";var tn=async(e,t)=>{let r=await S(e,t);await N(r);let s=(await h.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await xd(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},xd=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Ed(s,o,{cwd:t,stdio:"inherit"});i.on("error",n),i.on("exit",a=>{if(a===0){r();return}n(new Error(`${e.join(" ")} failed with exit code ${a??"unknown"}.`))})})};var rn=async(e,t,r)=>{let n=await Y(e,t);await y(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},nn=async(e,t,r)=>{let n=await Y(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await y(e,s),s},sn=async(e,t)=>{let r=await Y(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await y(e,s),s};var on=async(e,t,r="merge",n)=>{let s=await S(e,t),o=n??v(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await mo(s.worktreePath,o,r)};var b={listTasks:Dr,getTask:S,provisionTask:Be,provisionProjectTask:ot,createTask:Wr,showTask:Ur,showTaskDiff:Kr,prepareTaskLogs:Vr,streamTaskLogs:Gr,runChecks:Hr,commitTask:zr,closeTask:Qr,cleanupTask:Yr,addTaskLink:Jr,listTaskLinks:Xr,sortTasksForDisplay:$r,resolveSelectedTaskId:jr,allocateTaskId:Ar,allocateTaskIdForRepo:qe,allocateProjectTaskId:nt,createDefaultTaskPtyTabs:it,assertTaskWorktreeExists:N,resolveTaskLogPath:_e,buildTaskInspection:rt,resolveArtifactPath:Ie,attachTask:Zr,focusTask:en,openTask:tn,markRunnerFailed:rn,recordStartupFailure:nn,markTaskStarted:sn,prs:{refresh:ut,refreshChecks:qr,discoverOrRefresh:Nt,discoverOrRefreshAll:Ve,discoverOrRefreshMany:Br,merge:on,getPrimaryPr:v,isPrTerminal:ge,isMergeReady:xt,deriveTaskStatus:Ze,upsertPr:We,normalizePr:et,summarizeRequiredChecks:vr,writePrStatusArtifact:xe}};async function So(e,t){switch(e.kind){case"addWorkspace":{let r=await Q.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await an(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Q.repos.addRepo(t.paths,e.path);return await an(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Q.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Me({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await q(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Q.repos.removeRepo(t.paths,e.repoId,{listTasks:b.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await me({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return Q.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Q.archiveWorkspace(t.paths,e.workspaceId);return await Ad(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Q.restoreWorkspace(t.paths,e.workspaceId);return await an(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Q.removeWorkspace(t.paths,e.workspaceId,{listTasks:b.listTasks});case"createTask":return b.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?b.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):b.listTasks(t.paths);case"attachTask":return b.attachTask(t.paths,e.taskId);case"addTaskLink":return b.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return b.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return b.showTask(t.paths,e.taskId);case"showSelectedTask":return b.showTask(t.paths,Ae(t,"show"));case"streamTaskLogs":return b.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return b.prepareTaskLogs(t.paths,Ae(t,"logs"));case"showTaskDiff":return b.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return b.showTaskDiff(t.paths,Ae(t,"diff"));case"focusTask":return b.focusTask(t.paths,e.taskId);case"focusSelectedTask":return b.focusTask(t.paths,Ae(t,"focus"));case"openTask":return b.openTask(t.paths,e.taskId);case"openSelectedTask":return b.openTask(t.paths,Ae(t,"open"));case"runChecks":return b.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return b.runChecks(t.paths,Ae(t,"check"));case"commitTask":return b.commitTask(t.paths,e.taskId);case"commitSelectedTask":return b.commitTask(t.paths,Ae(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return Dd(e)}}async function an(e,t,r){let n=await Me({uiStateFile:e.uiStateFile})??yt();await me({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Ad(e,t){let r=await Me({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await me({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Dd(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ae(e,t){if(e.selectedTaskId)return e.selectedTaskId;throw new Error(`No task selected. Create a task with 'task new --repo <repo-id> <prompt>' or use '${t} <id>'.`)}function bo(e){switch(e.kind){case"createWorkspace":return[`${e.created?"Registered":"Updated"} ${e.workspace.kind??"repo"} workspace ${e.workspace.id}`,`Path: ${e.workspace.rootPath??""}`,`Repos: ${e.repos.map(t=>t.id).join(", ")}`].join(`
117
117
  `);case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
118
118
  `);case"listRepos":return e.repos.length===0?"No repos registered yet. Use 'craig repo add <path>'.":["ID NAME BRANCH PATH",...e.repos.map(t=>`${t.id} ${t.name} ${t.defaultBranch} ${t.rootPath}`)].join(`
119
119
  `);case"removeRepo":return`Removed repo ${e.repoId} (${e.rootPath})`;case"listWorkspaces":return e.workspaces.length===0?e.archivedOnly?"No archived workspaces.":"No active workspaces yet. Register one with 'craig workspace add <path>'.":["ID KIND STATUS REPOS PATH",...e.workspaces.map(t=>`${t.id} ${t.kind??"repo"} ${t.status} ${(t.discoveredRepoIds??[t.primaryRepoId]).join(",")} ${t.rootPath??""}`)].join(`
120
120
  `);case"archiveWorkspace":return`Archived workspace ${e.workspaceId} on branch ${e.branch}`;case"restoreWorkspace":return`Restored workspace ${e.workspaceId} on branch ${e.branch}`;case"removeWorkspace":return`Removed workspace ${e.workspaceId} (${e.rootPath})`;case"createTask":return[`Created task ${e.taskId}`,`Repo: ${e.repoId}`,`Workspace: ${e.workspaceId}`,`Session: ${e.sessionId}`,`Status: ${e.status}`,`Branch: ${e.branch}`,`Worktree: ${e.worktreePath}`,`Runner: ${e.runner}`].join(`
121
121
  `);case"attachTask":return`Attached to task ${e.taskId} via session ${e.sessionId}`;case"addTaskLink":return`Linked repo ${e.repoId} to task ${e.taskId}: ${e.linkedRepoIds.join(", ")}`;case"listTaskLinks":return e.repos.length===0?`Task ${e.taskId} has no linked repos.`:["ID NAME BRANCH PATH",...e.repos.map(t=>`${t.id} ${t.name} ${t.defaultBranch} ${t.rootPath}`)].join(`
122
- `);case"help":return e.text;case"exit":return"";case"listTasks":return e.tasks.length===0?`No Craig tasks yet. Use 'task new --repo <repo-id> <prompt>' to create one.${e.missingTaskIds.length>0?` (${e.missingTaskIds.length} referenced task file(s) missing from .craig/tasks)`:""}`:["ID REPO STATUS CHECKS PR TITLE",...e.tasks.map(t=>`${t.id} ${t.repoId} ${t.status} ${jd(t)} ${Ld(t)} ${t.title}`)].join(`
123
- `);case"showTask":return[`${e.task.id}: ${e.task.title}`,`Status: ${e.task.status}`,`Runner: ${e.task.runner}`,`Repo: ${e.task.repoId}`,`Workspace: ${e.task.workspaceId}`,`Branch: ${e.task.branch}`,`Worktree: ${e.task.worktreePath}`,`Session: ${e.task.sessionId??"<missing>"}`,`tmux: ${e.session?.paneId??"<missing>"}`,`Linked repos: ${e.task.linkedRepoIds.length>0?e.task.linkedRepoIds.join(", "):"none"}`,`Prompt: ${e.task.prompt.source} ${JSON.stringify(e.task.prompt.value)}`,`Runner command: ${e.inspection.runnerCommandText||"<none>"}`,`Runner state: ${e.task.runnerSession.lastKnownState}`,`Started: ${e.task.runnerSession.startedAt??"not started"}`,`Exited: ${e.task.runnerSession.exitedAt??"still running"}`,`Checks: ${e.inspection.checksSummary}`,`Last commit: ${e.inspection.lastCommitSummary}`,`PR: ${e.inspection.prSummary}`,`Cleanup: ${e.inspection.cleanupSummary}`,...Dd(e)].join(`
122
+ `);case"help":return e.text;case"exit":return"";case"listTasks":return e.tasks.length===0?`No Craig tasks yet. Use 'task new --repo <repo-id> <prompt>' to create one.${e.missingTaskIds.length>0?` (${e.missingTaskIds.length} referenced task file(s) missing from .craig/tasks)`:""}`:["ID REPO STATUS CHECKS PR TITLE",...e.tasks.map(t=>`${t.id} ${t.repoId} ${t.status} ${Ld(t)} ${Md(t)} ${t.title}`)].join(`
123
+ `);case"showTask":return[`${e.task.id}: ${e.task.title}`,`Status: ${e.task.status}`,`Runner: ${e.task.runner}`,`Repo: ${e.task.repoId}`,`Workspace: ${e.task.workspaceId}`,`Branch: ${e.task.branch}`,`Worktree: ${e.task.worktreePath}`,`Session: ${e.task.sessionId??"<missing>"}`,`tmux: ${e.session?.paneId??"<missing>"}`,`Linked repos: ${e.task.linkedRepoIds.length>0?e.task.linkedRepoIds.join(", "):"none"}`,`Prompt: ${e.task.prompt.source} ${JSON.stringify(e.task.prompt.value)}`,`Runner command: ${e.inspection.runnerCommandText||"<none>"}`,`Runner state: ${e.task.runnerSession.lastKnownState}`,`Started: ${e.task.runnerSession.startedAt??"not started"}`,`Exited: ${e.task.runnerSession.exitedAt??"still running"}`,`Checks: ${e.inspection.checksSummary}`,`Last commit: ${e.inspection.lastCommitSummary}`,`PR: ${e.inspection.prSummary}`,`Cleanup: ${e.inspection.cleanupSummary}`,...$d(e)].join(`
124
124
  `);case"streamTaskLogs":return`Streaming logs for ${e.taskId} from ${e.logPath}`;case"showTaskDiff":return e.isEmpty?`Task ${e.taskId} has no uncommitted diff.`:e.diffText;case"focusTask":return`Focused task ${e.taskId} on ${e.tmuxTarget}`;case"openTask":return e.launched?`Opened task ${e.taskId} at ${e.worktreePath}`:e.worktreePath;case"runChecks":return`Checks ${e.status} for ${e.taskId}: ${e.commands.join(", ")}`;case"commitTask":return[`Committed task ${e.taskId}`,`Status: ${e.status}`,`Commit: ${e.commitSha}`,`Message: ${e.message}`].join(`
125
- `);default:return $d(e)}}function Dd(e){let t=[];return e.inspection.worktreeExists||e.task.status==="merged"&&!e.task.cleanup.preservedWorktree&&e.task.cleanup.worktreeRemovedAt||t.push(`Warning: worktree is missing at ${e.task.worktreePath}`),e.task.cleanup.warning&&!(e.task.status==="merged"&&!e.task.cleanup.worktreeRemovedAt)&&t.push(`Cleanup warning: ${e.task.cleanup.warning}`),e.task.artifacts.logPath&&!e.inspection.logExists&&t.push(`Warning: log file is missing at ${e.task.artifacts.logPath}`),e.inspection.recentFailureReason&&t.push(`Last failure: ${e.inspection.recentFailureReason}`),t}function $d(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function jd(e){return e.checks.status}function Ld(e){if(e.type==="project"&&e.repoTargets?.length){let r=e.repoTargets.filter(s=>s.pullRequest.number);if(r.length===0)return"-";let n=r.reduce((s,o)=>{let i=o.pullRequest.status??"unknown";return s[i]=(s[i]??0)+1,s},{});return Object.entries(n).map(([s,o])=>`${o} ${s}`).join(", ")}let t=e.prs[0];return t?.number?`#${t.number}:${t.status??"unknown"}`:"-"}import{createRequire as zf}from"node:module";import{readFile as Md,stat as Od}from"node:fs/promises";import ln from"node:path";var Fd=200*1024,Nd=500*1024,Wt="100000";async function So(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return Wd(e,t,r);try{let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),o=s?await pt(e.worktreePath):null,[i,a]=await Promise.all([Bt(e.worktreePath,n),s?cn(e.worktreePath,s,t.diffRows,o):Promise.resolve(q("No diff selected","No local changes found.","empty"))]),l=s?{[s]:a}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:l,selectedFile:i,selectedDiff:a,error:null}}catch(n){let s=n instanceof Error?n.message:"Unable to inspect task worktree.";return{...t,error:s}}}async function Wd(e,t,r){let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([Co(e,n),(async()=>{if(!s)return q("No diff selected","No local changes found.","empty");let l=_t(e,s),c=l?await pt(l.target.worktreePath).catch(()=>null):null;return vo(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function Io(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return _d(e,t);try{await N(e);let r=await pt(e.worktreePath),[n,s]=await Promise.all([Eo(e.worktreePath),xo(e.worktreePath,r)]),o=[...new Set(s.map(p=>p.path))],i=we(t.selectedFilePath??null,n),a=we(t.selectedDiffPath??null,o),[l,c]=await Promise.all([Bt(e.worktreePath,i),a?cn(e.worktreePath,a,s,r):Promise.resolve(q("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:$o(n),filePaths:n,diffRows:s,diffPaths:o,diffContents:d,selectedFilePath:i,selectedDiffPath:a,selectedFile:l,selectedDiff:c,error:null}}catch(r){let n=r instanceof Error?r.message:"Unable to inspect task worktree.";return{taskId:e.id,fileRows:[],filePaths:[],diffRows:[],diffPaths:[],diffContents:{},selectedFilePath:null,selectedDiffPath:null,selectedFile:q("Files unavailable",n,"error"),selectedDiff:q("Diff unavailable",n,"error"),error:n}}}async function _d(e,t){let r=(e.repoTargets??[]).filter(f=>f.status==="ready"),n=await Promise.all(r.map(async f=>{let u=await pt(f.worktreePath).catch(()=>null),[w,P]=await Promise.all([Eo(f.worktreePath).catch(()=>[]),xo(f.worktreePath,u).catch(()=>[])]);return{target:f,baseRef:u,targetFiles:w,targetDiffRows:P}})),s=[],o=[];for(let{target:f,targetFiles:u,targetDiffRows:w}of n)s.push(...u.map(P=>`${f.repoId}/${P}`)),o.push(...w.map(P=>({...P,path:`${f.repoId}/${P.path}`})));let i=[...new Set(o.map(f=>f.path))].sort(),a=we(t.selectedFilePath??null,s),l=we(t.selectedDiffPath??null,i),[c,d]=await Promise.all([Co(e,a),(async()=>{if(!l)return q("No diff selected","No local changes found.","empty");let f=_t(e,l),u=f?n.find(w=>w.target.repoId===f.target.repoId):null;return vo(e,l,o,u?.baseRef??null)})()]),p=l?{[l]:d}:{};return{taskId:e.id,fileRows:$o(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:p,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function Co(e,t){let r=_t(e,t);if(!r)return q("No file selected","No Git-visible files found.","empty");let n=await Bt(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function vo(e,t,r,n=null){let s=_t(e,t);return s?{...await cn(s.target.worktreePath,s.relativePath,r.filter(i=>i.path.startsWith(`${s.target.repoId}/`)).map(i=>({...i,path:i.path.slice(s.target.repoId.length+1)})),n),path:t,title:t}:q(t,"Repo target is unavailable.","error",t)}function _t(e,t){if(!t)return null;let[r,...n]=t.split("/"),s=n.join("/"),o=(e.repoTargets??[]).find(i=>i.repoId===r&&i.status==="ready")??null;return!o||s.length===0?null:{target:o,relativePath:s}}async function Eo(e){let t=await T("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return jo(t.stdout)}async function xo(e,t){let[r,n,s,o]=await Promise.all([Bd(e,t),bo(e,"staged"),bo(e,"unstaged"),qd(e)]);return[...r,...n,...s,...o]}async function Bd(e,t){if(!t)return[];let[r,n]=await Promise.all([T("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),T("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=Ao(r.stdout),o=Do(n.stdout);return s.map(i=>{let a=o.get(i.path)??{additions:null,deletions:null};return{group:"branch",path:i.path,status:i.status,additions:a.additions,deletions:a.deletions}}).sort((i,a)=>i.path.localeCompare(a.path))}async function bo(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([T("git",[...r,"--name-status"],{cwd:e}),T("git",[...r,"--numstat"],{cwd:e})]),o=Ao(n.stdout),i=Do(s.stdout);return o.map(a=>{let l=i.get(a.path)??{additions:null,deletions:null};return{group:t,path:a.path,status:a.status,additions:l.additions,deletions:l.deletions}}).sort((a,l)=>a.path.localeCompare(l.path))}async function qd(e){let t=await T("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=jo(t.stdout);return await Promise.all(r.map(async s=>{let o=await Bt(e,s),i=o.status==="ready"?Ud(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function Ao(e){return e.split(`
126
- `).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...n]=t.split(" ");return{status:r,path:n.at(-1)??""}}).filter(t=>t.path.length>0)}function Do(e){let t=new Map;for(let r of e.split(`
127
- `)){let n=r.trim();if(!n)continue;let[s="-",o="-",...i]=n.split(" "),a=i.join(" ");a&&t.set(a,{additions:s==="-"?null:Number(s),deletions:o==="-"?null:Number(o)})}return t}async function pt(e){return(await E("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await E("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function Bt(e,t){if(!t)return q("No file selected","No Git-visible files found.","empty");let r=Kd(e,t);try{let n=await Od(r);if(n.size>Fd)return q(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Md(r);return Vd(s)?q(t,"Binary file preview is not available in Craig.","binary",t,s.byteLength):{path:t,status:"ready",title:t,lines:s.toString("utf8").split(`
128
- `),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return q(t,s,"missing",t,null)}}async function cn(e,t,r,n=null){if(!t)return q("No diff selected","No local changes found.","empty");let s=[],o=r.filter(a=>a.path===t).map(a=>a.group);if(o.includes("branch")){let a=n??await pt(e);if(a){let l=await T("git",["diff","--stat","--patch",`--unified=${Wt}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
125
+ `);default:return jd(e)}}function $d(e){let t=[];return e.inspection.worktreeExists||e.task.status==="merged"&&!e.task.cleanup.preservedWorktree&&e.task.cleanup.worktreeRemovedAt||t.push(`Warning: worktree is missing at ${e.task.worktreePath}`),e.task.cleanup.warning&&!(e.task.status==="merged"&&!e.task.cleanup.worktreeRemovedAt)&&t.push(`Cleanup warning: ${e.task.cleanup.warning}`),e.task.artifacts.logPath&&!e.inspection.logExists&&t.push(`Warning: log file is missing at ${e.task.artifacts.logPath}`),e.inspection.recentFailureReason&&t.push(`Last failure: ${e.inspection.recentFailureReason}`),t}function jd(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Ld(e){return e.checks.status}function Md(e){if(e.type==="project"&&e.repoTargets?.length){let r=e.repoTargets.filter(s=>s.pullRequest.number);if(r.length===0)return"-";let n=r.reduce((s,o)=>{let i=o.pullRequest.status??"unknown";return s[i]=(s[i]??0)+1,s},{});return Object.entries(n).map(([s,o])=>`${o} ${s}`).join(", ")}let t=e.prs[0];return t?.number?`#${t.number}:${t.status??"unknown"}`:"-"}import{createRequire as Yf}from"node:module";import{readFile as Od,stat as Fd}from"node:fs/promises";import ln from"node:path";var Nd=200*1024,Wd=500*1024,Wt="100000";async function Co(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return _d(e,t,r);try{let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),o=s?await pt(e.worktreePath):null,[i,a]=await Promise.all([qt(e.worktreePath,n),s?cn(e.worktreePath,s,t.diffRows,o):Promise.resolve(B("No diff selected","No local changes found.","empty"))]),l=s?{[s]:a}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:l,selectedFile:i,selectedDiff:a,error:null}}catch(n){let s=n instanceof Error?n.message:"Unable to inspect task worktree.";return{...t,error:s}}}async function _d(e,t,r){let n=we(r.selectedFilePath??null,t.filePaths),s=we(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([Eo(e,n),(async()=>{if(!s)return B("No diff selected","No local changes found.","empty");let l=_t(e,s),c=l?await pt(l.target.worktreePath).catch(()=>null):null;return xo(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function vo(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return qd(e,t);try{await N(e);let r=await pt(e.worktreePath),[n,s]=await Promise.all([Ao(e.worktreePath),Do(e.worktreePath,r)]),o=[...new Set(s.map(p=>p.path))],i=we(t.selectedFilePath??null,n),a=we(t.selectedDiffPath??null,o),[l,c]=await Promise.all([qt(e.worktreePath,i),a?cn(e.worktreePath,a,s,r):Promise.resolve(B("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:Lo(n),filePaths:n,diffRows:s,diffPaths:o,diffContents:d,selectedFilePath:i,selectedDiffPath:a,selectedFile:l,selectedDiff:c,error:null}}catch(r){let n=r instanceof Error?r.message:"Unable to inspect task worktree.";return{taskId:e.id,fileRows:[],filePaths:[],diffRows:[],diffPaths:[],diffContents:{},selectedFilePath:null,selectedDiffPath:null,selectedFile:B("Files unavailable",n,"error"),selectedDiff:B("Diff unavailable",n,"error"),error:n}}}async function qd(e,t){let r=(e.repoTargets??[]).filter(f=>f.status==="ready"),n=await Promise.all(r.map(async f=>{let u=await pt(f.worktreePath).catch(()=>null),[w,R]=await Promise.all([Ao(f.worktreePath).catch(()=>[]),Do(f.worktreePath,u).catch(()=>[])]);return{target:f,baseRef:u,targetFiles:w,targetDiffRows:R}})),s=[],o=[];for(let{target:f,targetFiles:u,targetDiffRows:w}of n)s.push(...u.map(R=>`${f.repoId}/${R}`)),o.push(...w.map(R=>({...R,path:`${f.repoId}/${R.path}`})));let i=[...new Set(o.map(f=>f.path))].sort(),a=we(t.selectedFilePath??null,s),l=we(t.selectedDiffPath??null,i),[c,d]=await Promise.all([Eo(e,a),(async()=>{if(!l)return B("No diff selected","No local changes found.","empty");let f=_t(e,l),u=f?n.find(w=>w.target.repoId===f.target.repoId):null;return xo(e,l,o,u?.baseRef??null)})()]),p=l?{[l]:d}:{};return{taskId:e.id,fileRows:Lo(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:p,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function Eo(e,t){let r=_t(e,t);if(!r)return B("No file selected","No Git-visible files found.","empty");let n=await qt(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function xo(e,t,r,n=null){let s=_t(e,t);return s?{...await cn(s.target.worktreePath,s.relativePath,r.filter(i=>i.path.startsWith(`${s.target.repoId}/`)).map(i=>({...i,path:i.path.slice(s.target.repoId.length+1)})),n),path:t,title:t}:B(t,"Repo target is unavailable.","error",t)}function _t(e,t){if(!t)return null;let[r,...n]=t.split("/"),s=n.join("/"),o=(e.repoTargets??[]).find(i=>i.repoId===r&&i.status==="ready")??null;return!o||s.length===0?null:{target:o,relativePath:s}}async function Ao(e){let t=await T("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Mo(t.stdout)}async function Do(e,t){let[r,n,s,o]=await Promise.all([Bd(e,t),Io(e,"staged"),Io(e,"unstaged"),Ud(e)]);return[...r,...n,...s,...o]}async function Bd(e,t){if(!t)return[];let[r,n]=await Promise.all([T("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),T("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=$o(r.stdout),o=jo(n.stdout);return s.map(i=>{let a=o.get(i.path)??{additions:null,deletions:null};return{group:"branch",path:i.path,status:i.status,additions:a.additions,deletions:a.deletions}}).sort((i,a)=>i.path.localeCompare(a.path))}async function Io(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([T("git",[...r,"--name-status"],{cwd:e}),T("git",[...r,"--numstat"],{cwd:e})]),o=$o(n.stdout),i=jo(s.stdout);return o.map(a=>{let l=i.get(a.path)??{additions:null,deletions:null};return{group:t,path:a.path,status:a.status,additions:l.additions,deletions:l.deletions}}).sort((a,l)=>a.path.localeCompare(l.path))}async function Ud(e){let t=await T("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Mo(t.stdout);return await Promise.all(r.map(async s=>{let o=await qt(e,s),i=o.status==="ready"?Kd(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function $o(e){return e.split(`
126
+ `).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...n]=t.split(" ");return{status:r,path:n.at(-1)??""}}).filter(t=>t.path.length>0)}function jo(e){let t=new Map;for(let r of e.split(`
127
+ `)){let n=r.trim();if(!n)continue;let[s="-",o="-",...i]=n.split(" "),a=i.join(" ");a&&t.set(a,{additions:s==="-"?null:Number(s),deletions:o==="-"?null:Number(o)})}return t}async function pt(e){return(await E("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await E("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function qt(e,t){if(!t)return B("No file selected","No Git-visible files found.","empty");let r=Vd(e,t);try{let n=await Fd(r);if(n.size>Nd)return B(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Od(r);return Gd(s)?B(t,"Binary file preview is not available in Craig.","binary",t,s.byteLength):{path:t,status:"ready",title:t,lines:s.toString("utf8").split(`
128
+ `),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return B(t,s,"missing",t,null)}}async function cn(e,t,r,n=null){if(!t)return B("No diff selected","No local changes found.","empty");let s=[],o=r.filter(a=>a.path===t).map(a=>a.group);if(o.includes("branch")){let a=n??await pt(e);if(a){let l=await T("git",["diff","--stat","--patch",`--unified=${Wt}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
129
129
  ${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await T("git",["diff","--cached","--stat","--patch",`--unified=${Wt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
130
130
  ${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await T("git",["diff","--stat","--patch",`--unified=${Wt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
131
131
  ${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await E("git",["diff","--no-index","--stat","--patch",`--unified=${Wt}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
132
132
  ${a.stdout.trimEnd()}`)}let i=s.join(`
133
133
 
134
- `);return i.length>Nd?q(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?q(t,"Binary diff preview is not available in Craig.","binary",t,i.length):{path:t,status:i.length>0?"ready":"empty",title:t,lines:i.length>0?i.split(`
135
- `):["No diff for this file."],byteLength:i.length}}function $o(e){let t=[],r=new Set;for(let n of e){let s=n.split("/");for(let o=0;o<s.length-1;o+=1){let i=s.slice(0,o+1).join("/");r.has(i)||(r.add(i),t.push({kind:"directory",path:i,depth:o,label:s[o]??i}))}t.push({kind:"file",path:n,depth:s.length-1,label:s.at(-1)??n})}return t}function we(e,t){return e&&t.includes(e)?e:t[0]??null}function Ud(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function jo(e){return[...new Set(e.split(`
136
- `).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Kd(e,t){let r=ln.resolve(e,t),n=ln.resolve(e);if(r!==n&&!r.startsWith(`${n}${ln.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Vd(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function q(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Gd=["tasks","center","inspector","actions"],Wo=["agent","terminal"],_o=[],I="inspection",cR=[...Wo,..._o],Bo=["commit","push","refresh-checks","close-task"],Hd=["refresh-checks","close-task"],qo=["task","checks","pr","setup-run","actions","next-action"],Uo=["diff","files","review"];function Ko(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=cu(e?.openInspectionKind)??r,s=g.runners.getEnabled(t);return{inputMode:uu(e?.inputMode),focusedRegion:au(e?.focusedRegion),selectedRepoId:ce(e?.selectedRepoId),selectedWorkspaceId:ce(e?.selectedWorkspaceId),selectedTaskId:ce(e?.selectedTaskId),selectedPtyTabId:ce(e?.selectedPtyTabId),selectedLeftItemId:Ru(ce(e?.selectedTaskId)),activeTab:r?I:ce(e?.activeTab)??"agent",preferredPtyTabKind:du(e?.preferredPtyTabKind),inspectorSection:ft(e?.inspectorSection,qo,"task"),inspectionMode:lu(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:ce(e?.selectedFileTreePath),selectedFilePath:ce(e?.selectedFilePath),selectedDiffPath:ce(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:ft(e?.selectedActionId,Bo,"commit"),selectedProjectTargetId:null,selectedRunner:pu(e?.selectedRunner,s,g.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,workspaceBrowser:null,terminal:zd(),centerZoomed:!1}}function zd(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Vo(e,t){return{...e??yt(),selectedRepoId:t.selectedRepoId,selectedWorkspaceId:t.selectedWorkspaceId,selectedTaskId:t.selectedTaskId,selectedPtyTabId:t.selectedPtyTabId,inputMode:t.inputMode,focusedRegion:t.focusedRegion,activeTab:t.activeTab,preferredPtyTabKind:t.preferredPtyTabKind,inspectorSection:t.inspectorSection,inspectionMode:t.inspectionMode,openInspectionKind:t.openInspectionKind,selectedFileTreePath:t.selectedFileTreePath,selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath,collapsedFileTreePaths:t.collapsedFileTreePaths,selectedActionId:t.selectedActionId,selectedRunner:t.selectedRunner}}function gt(e,t,r={}){let n=wu(e,t),s=Zo(n),o=(s?.kind==="workspace"?t.workspaces?.find(d=>d.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(d=>d.id===t.tasks.find(p=>p.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(d=>d.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(d=>d.id===s.id)??null:s?.kind==="task"?t.repos.find(d=>d.id===t.tasks.find(p=>p.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(d=>d.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(d.id))??null:null)??(o?.kind!=="project"?t.repos.find(d=>d.id===o?.primaryRepoId)??null:null)??t.repos.find(d=>d.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(d=>d.workspaceId===o.id):a?t.tasks.filter(d=>d.repoId===a):[],c=(s?.kind==="task"?l.find(d=>d.id===s.id)??null:null)??l.find(d=>d.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:c?.id??null,...mu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:su(e,t,c?.id??null),...gu(e,t,c?.id??null),selectedDiffPath:nu(e,t,c?.id??null),inspectorSection:ft(e.inspectorSection,qo,"task")}}function Go(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Yd(t)?k({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):k({state:e});if(t==="q"||t==="Q")return k({state:e,exit:!0});if(t==="ESCAPE")return k({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return k({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(un(e.selectedLeftItemId)||pn(e.selectedLeftItemId)))return k({state:{...e,selectedRunner:fn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Lo(e,1);if(t==="SHIFT_TAB"||t==="[")return Lo(e,-1);if(t==="z"||t==="Z")return k({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,-1,r):Mo(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):Mo(e,1,r);if(t==="PAGE_UP")return Te(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Te(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Te(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Te(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??x,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return k({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=fu(e,t);return k({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return k({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return k({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return k({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId)return k({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&yu(e.selectedLeftItemId)&&e.selectedWorkspaceId)return k({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&No(e.activeTab,r.ptyTabIds??[]))return k({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return dn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Oo(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return dn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Oo(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(un(e.selectedLeftItemId)||pn(e.selectedLeftItemId))){let n=ei(e.selectedLeftItemId),s=ti(e.selectedLeftItemId);return k({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return k({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return k({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:mt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&No(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return k({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:mt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===I)return k({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return k({state:eu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return k({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:I,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?k({state:{...e,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?k({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):k({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?k({state:e}):e.selectedActionId==="refresh-checks"?k({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?k({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):k({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return k({state:e})}function ue(e,t){return{...e,terminal:t}}function Ho(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Yd(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function oe(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
137
- `}function zo(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Yo(e){return Qo(e)||mt(e)!==null}function Qd(e){return _o.includes(e)}function Qo(e){return Wo.includes(e)}function Jo(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var Jd=["tasks","center","inspector"];function Lo(e,t){return qt(e,"focusedRegion",Jd,t)}function dn(e,t,r){let n=qt(e,"activeTab",r&&r.length>0?r:ku(e),t);return!n.changed||Qd(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Mo(e,t,r){if(e.focusedRegion==="tasks")return Xd(e,t,r.leftItemIds);if(e.focusedRegion==="center")return dn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:n}if(r.projectTargetIds?.length){let n=Ut(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return qt(e,"selectedActionId",Hd,t)}return qt(e,"selectedActionId",Bo,t)}function Xd(e,t,r){let n=Ut(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Zo(n.state.selectedLeftItemId);if(s?.kind==="workspace")return{...n,state:{...n.state,selectedWorkspaceId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="task")return{...n,state:{...n.state,selectedTaskId:s.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="repo")return{...n,state:{...n.state,selectedRepoId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};let o=ei(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=ti(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Te(e,t,r){if(t===0)return k({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?Fo(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):k({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return Fo(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return tu(e,t,r)}return k({state:e})}function Zd(e,t){if(e.inspectionMode===t)return k({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return k({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Oo(e,t){return Zd(e,iu(e.inspectionMode,Uo,t))}function Xo(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return k({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=de(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return k({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return k({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?I:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function eu(e){if(!e.selectedFileTreePath)return e;let t=new Set(e.collapsedFileTreePaths);return t.has(e.selectedFileTreePath)?t.delete(e.selectedFileTreePath):t.add(e.selectedFileTreePath),{...e,collapsedFileTreePaths:[...t].sort((r,n)=>r.localeCompare(n)),actionMessage:null}}function Fo(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=de(e[t]+r,0,o);return i===e[t]?k({state:e}):k({state:{...e,[t]:i,actionMessage:null},changed:!0})}function tu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return ru(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=de(i,0,o);return d===e.diffScrollOffset?k({state:e}):k({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=de(i,0,o);return d===e.diffScrollOffset?k({state:e}):k({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?k({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?k({state:e}):k({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?k({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?k({state:e}):k({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=de(i,0,o);return c===e.diffScrollOffset?k({state:e}):k({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function ru(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=de(e.diffScrollOffset+t,0,o),a=ou(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?k({state:e}):k({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function nu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function su(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function ou(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function qt(e,t,r,n){let s=r.indexOf(e[t]),o=de(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?k({state:e}):k({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Ut(e,t,r,n,s=!1){if(r.length===0)return k({state:e});let o=r.indexOf(e[t]??r[0]??""),i=de(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?k({state:e}):k({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function iu(e,t,r){let n=t.indexOf(e);return t[de(n+r,0,t.length-1)]??e}function k(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function ft(e,t,r){return t.includes(e??"")?e:r}function au(e){return e==="tabs"?"center":ft(e,Gd,"tasks")}function lu(e,t){return e==="checks"||e==="actions"||e==="review"?"review":ft(e,Uo,t)}function cu(e){return e==="file"||e==="diff"?e:null}function du(e){return e==="terminal"?"terminal":"agent"}function uu(e){return e==="terminal"?"terminal":"control"}function pu(e,t=[...x],r="codex"){return e&&g.runners.isRunnerType(e)&&t.includes(e)?e:r}function fn(e,t=x){let r=t.length>0?t:x,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function mt(e){let t=x.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function fu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function mu(e,t,r){if(!e)return{activeTab:t===I?t:"agent",selectedPtyTabId:null};let n=e.ptyTabs.find(a=>a.id===r)??null,s=e.selectedPtyTabId?e.ptyTabs.find(a=>a.id===e.selectedPtyTabId)??null:null,o=e.ptyTabs.find(a=>a.id===t)??null;if(o)return{activeTab:o.id,selectedPtyTabId:o.id};if(Qo(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??I,selectedPtyTabId:l?.id??null}}if(t===I)return{activeTab:I,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??I,selectedPtyTabId:i?.id??null}}function gu(e,t,r){if(!t.inspection||t.inspection.taskId!==r)return{selectedFileTreePath:e.selectedFileTreePath,collapsedFileTreePaths:e.collapsedFileTreePaths};let n=e.selectedFileTreePath??t.inspection.selectedFilePath,s=e.selectedFileTreePath===null&&e.collapsedFileTreePaths.length===0?hu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function hu(e,t){let r=new Set;if(t){let n=t.split("/");for(let s=1;s<n.length;s+=1)r.add(n.slice(0,s).join("/"))}return e.filter(n=>n.kind==="directory"&&!n.path.includes("/")&&!r.has(n.path)).map(n=>n.path).sort((n,s)=>n.localeCompare(s))}function ku(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function No(e,t){return t.includes(e)}function wu(e,t){let r=Tu(t);return e.selectedLeftItemId&&r.includes(e.selectedLeftItemId)?e.selectedLeftItemId:e.selectedWorkspaceId&&r.includes(`workspace:${e.selectedWorkspaceId}`)?`workspace:${e.selectedWorkspaceId}`:e.selectedTaskId&&r.includes(`task:${e.selectedTaskId}`)?`task:${e.selectedTaskId}`:e.selectedRepoId&&r.includes(`repo:${e.selectedRepoId}`)?`repo:${e.selectedRepoId}`:r[0]??null}function Tu(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let n of e.tasks.filter(s=>s.workspaceId===r.id))t.push(`task:${n.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let n of e.tasks.filter(s=>s.repoId===r.id))t.push(`task:${n.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}function Zo(e){return e?e.startsWith("workspace:")?{kind:"workspace",id:e.slice(10)}:e.startsWith("repo:")?{kind:"repo",id:e.slice(5)}:e.startsWith("task:")?{kind:"task",id:e.slice(5)}:null:null}function ce(e){return typeof e=="string"?e:null}function Ru(e){return e?`task:${e}`:null}function Kt(e){return typeof e=="string"&&e.startsWith("task:")}function un(e){return typeof e=="string"&&e.startsWith("new-task:")}function pn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function yu(e){return typeof e=="string"&&e.startsWith("workspace:")}function ei(e){return un(e)?e.slice(9):null}function ti(e){return pn(e)?e.slice(19):null}function de(e,t,r){return Math.min(r,Math.max(t,e))}async function Re(e,t,r){let n=ne(e),[s,o,i]=await Promise.all([Y.repos.listRegisteredRepos(n).then(d=>d.repos),B(n),S.listTasks(n)]),a=mn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await Io(a,l):null;return{workspaceRoot:e,workspaces:o.filter(d=>d.status==="active"),repos:s,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function mn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ri(e,t){return gt(e,t)}function ni(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let n of e.tasks.filter(s=>s.workspaceId===r.id))t.push(`task:${n.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let n of e.tasks.filter(s=>s.repoId===r.id))t.push(`task:${n.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}import yn from"node:path";import wR from"picocolors";var Pu=[" \u2584\u2588\u2588\u2588\u2588\u2584 \u2588\u2588\u2580\u2588\u2588\u2588 \u2584\u2584\u2584 \u2588\u2588\u2593 \u2584\u2588\u2588\u2588\u2588"," \u2592\u2588\u2588\u2580 \u2580\u2588 \u2593\u2588\u2588 \u2592 \u2588\u2588\u2592\u2592\u2588\u2588\u2588\u2588\u2584 \u2593\u2588\u2588\u2592 \u2588\u2588\u2592 \u2580\u2588\u2592"," \u2592\u2593\u2588 \u2584 \u2593\u2588\u2588 \u2591\u2584\u2588 \u2592\u2592\u2588\u2588 \u2580\u2588\u2584 \u2592\u2588\u2588\u2592\u2592\u2588\u2588\u2591\u2584\u2584\u2584\u2591"," \u2592\u2593\u2593\u2584 \u2584\u2588\u2588\u2592\u2592\u2588\u2588\u2580\u2580\u2588\u2584 \u2591\u2588\u2588\u2584\u2584\u2584\u2584\u2588\u2588 \u2591\u2588\u2588\u2591\u2591\u2593\u2588 \u2588\u2588\u2593"," \u2592 \u2593\u2588\u2588\u2588\u2580 \u2591\u2591\u2588\u2588\u2593 \u2592\u2588\u2588\u2592 \u2593\u2588 \u2593\u2588\u2588\u2592\u2591\u2588\u2588\u2591\u2591\u2592\u2593\u2588\u2588\u2588\u2580\u2592"," \u2591 \u2591\u2592 \u2592 \u2591\u2591 \u2592\u2593 \u2591\u2592\u2593\u2591 \u2592\u2592 \u2593\u2592\u2588\u2591\u2591\u2593 \u2591\u2592 \u2592"," \u2591 \u2592 \u2591\u2592 \u2591 \u2592\u2591 \u2592 \u2592\u2592 \u2591 \u2592 \u2591 \u2591 \u2591"," \u2591 \u2591\u2591 \u2591 \u2591 \u2592 \u2592 \u2591\u2591 \u2591 \u2591"," \u2591 \u2591 \u2591 \u2591 \u2591 \u2591 \u2591"," \u2591"];function gn(){return[...Pu]}var Vt={width:120,height:36},Z={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ee(e,t){return{width:Math.max(e??Vt.width,Vt.width),height:Math.max(t??Vt.height,Vt.height)}}var bu=["Start","Options","Exit"],Su=["Resume","Options","Exit"],zt=2,Yt=2,Qt=2,Iu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Cu=new RegExp("\x1B\\[(?:0)?m","g"),vu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Eu=/https?:\/\/[^\s<>"']+/g,hn="\x1B[0m",kn="\x1B]8;;\x1B\\",y={panelBg:{bg:"0a0a0a",fg:"c0caf5"},panelMuted:{bg:"0a0a0a",fg:"565f89"},panelSelected:{bg:"1a1b26",fg:"c0caf5"},panelFocused:{bg:"1a1b26",fg:"7aa2f7"},divider:{bg:"0a0a0a",fg:"292e42"},rail:{bg:"0a0a0a",fg:"c0caf5"},overlay:{bg:"06060f",fg:"565f89"},overlayTitle:{bg:"06060f",fg:"565f89"},overlayLogo:{bg:"06060f",fg:"9ece6a"},overlaySubtitle:{bg:"06060f",fg:"41a6b5"},overlayMenuSelected:{bg:"06060f",fg:"7aa2f7"},accent:{fg:"7aa2f7"},success:{fg:"9ece6a"},pending:{fg:"e0af68"},error:{fg:"f7768e"},mutedfg:{fg:"565f89"},disabled:{fg:"3b4261"}};function ii(e,t={}){return Tn(e,{subtitle:"crAIg is that you?",menuItems:bu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function ai(e,t={}){return Tn(e,{subtitle:"Control mode is paused.",menuItems:Su,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var Gt=[" GLOBAL CENTER PANEL INSPECTOR"," ? help \u2190\u2192 / hl switch tab \u2191\u2193 / jk navigate"," Esc pause / back + new tab \u2190\u2192 / hl switch mode"," Tab cycle panels a codex tab R sync PR"," q quit t terminal tab R sync PR"," x close tab X close task"," TASKS Enter attach PTY X close task"," \u2191\u2193 / jk navigate"," n new task TERMINAL MODE"," Enter attach Ctrl+] return to control mode"," Wheel / PgUp / PgDn scroll",""," Press Esc to return."],xu=["Help"];function wn(e,t={}){return Tn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??xu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function li(e,t={}){let r=t.color??!0,n=y.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o=gn(),i=Math.max(1,Math.floor((e.height-o.length-2-Gt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=$(fi(o[d]??"",e.width),r,y.overlayLogo);let a=Math.max(...Gt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<Gt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=Gt[d]??"";s[p]=$(ie(" ".repeat(l)+f,e.width),r,n)}return s.join(`
138
- `)}function ci(e,t={}){let r=t.color??!0,n=y.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},J(),...a.length>0?a.map(u=>({text:u})):[{text:"No Craig errors have been logged.",tone:"muted"}],J(),{text:"Esc returns to Options.",tone:"muted"}],p=ht(d,e.height-2),f=Math.max(1,Math.floor((e.height-p.length)/2));for(let u=0;u<p.length;u+=1){let w=f+u;if(w>=e.height)break;let P=p[u]??J(),D=`${" ".repeat(c)}${Xt(P.text,l)}`,U=P.tone==="selected"?y.overlayMenuSelected:P.tone==="muted"?y.overlay:y.panelBg;s[w]=$(ie(D,e.width),r,U)}return s.join(`
139
- `)}function di(e,t,r={}){let n=r.color??!0,s=Z.leftWidth,o=Z.rightWidth,i=Z.dividerWidth,a=r.centerOnly??!1,l=a?e.width:e.width-s-o-i*2,c=e.height-Z.topRailHeight-1,d=r.focusFlashActive??!1,p={bg:y.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:y.divider,u=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:y.divider,w=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,P=$(ie(w,e.width),n,y.rail),D=Du(t,s-zt-Yt,c,n),U=$u(t,l,c,n),fe=Lu(t,o,c,n),ae=t.inputMode==="terminal",h=[];for(let je=0;je<c;je+=1){if(a){h.push(Ht(U[je]??J(),l,n,"center"));continue}let Xa=Ht(D[je]??J(),s,n,"left"),Za=$("\u2502",n,f),el=Ht(U[je]??J(),l,n,"center"),tl=$("\u2502",n,u),rl=Ht(fe[je]??J(),o,n,"right");h.push(`${Xa}${Za}${el}${tl}${rl}`)}let Qe=ae||t.modalInput?y.panelBg:y.panelMuted,Ja=Au(t.footerText,t.footerToast,e.width,n,Qe);return[P,...h,Ja].join(`
140
- `)}function Au(e,t,r,n,s){let o=` ${e}`;if(!t)return $(ie(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=z(i),l=z(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?Xt(o,Math.max(0,r-a-3)):o,p=Math.max(1,r-z(d)-a-2),f=t.tone==="error"?Zu(i,n,s):Ge(i,n,s),u=`${d}${" ".repeat(p)}${f} `;return $(ie(u,r),n,s)}function Tn(e,t){let r=new Array(e.height).fill($(" ".repeat(e.width),t.color,y.overlay)),n=gn(),s=Math.max(...t.menuItems.map(c=>c.length)),o=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c.padEnd(s)}`),i=t.optionsMessage?["",t.optionsMessage]:[],a=[...n,"",t.subtitle,"",...o,...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=fi(a[c]??"",e.width);if(c<n.length){r[l+c]=$(d,t.color,y.overlayLogo);continue}if(c===n.length+1){r[l+c]=$(d,t.color,y.overlaySubtitle);continue}let p=c-(n.length+3),u=p>=0&&p<t.menuItems.length&&p===t.menuIndex?y.overlayMenuSelected:y.overlay;r[l+c]=$(d,t.color,u)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,p=" ".repeat(Math.max(0,e.width-z(d)));r[e.height-1]=$(`${p}${Rn(d,t.color,y.overlay)}`,t.color,y.overlay)}return r.join(`
141
- `)}function Du(e,t,r,n){let s=Fu(e.runners),o=1,i=e.leftTree.map(l=>Ou(l,t,n));return[...ht(i,r-o),s]}function $u(e,t,r,n){let s=t-2,o=e.tabs.find(h=>h.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:Qu(e.tabs),a=e.inputMode==="terminal"?s:o.length+1,l="\u2500".repeat(Math.max(0,a)),c=`${" ".repeat(i)}${e.inputMode==="terminal"?Ge(l,n,y.panelBg):Jt(l,n,y.panelMuted)}`,d=[`${Jt(e.centerHeader.tabLabel,n,y.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),p=e.tabs.find(h=>h.active)?.id??"agent",f=e.centerHeader.tabLabel==="BROWSER"||!Yo(p)?e.centerTranscript.map(h=>({...h})):ju(e),u=Nu(e.tabs,n,e.focusedRegion==="center"),w=" engaged ",P=w.length+2,D=e.inputMode==="terminal"?Ge(`${w}\u25CF `,n,y.panelBg):"",U=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-z(u)-P)):"",ae=[{text:e.inputMode==="terminal"?`${u}${U}${D}`:u},{text:c,tone:"muted"},{text:d},J(),...f];return ht(ae,r)}function ju(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},J(),{text:e.terminal.error},J(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(n=>n.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(n=>({text:hi(n.segments),segments:n.segments,fullBleed:!0}))}function Lu(e,t,r,n){let s=e.rightInspection?Mu(e.actionMessage?[...e.rightInspection.rows.slice(0,2),{id:"action-message",text:e.actionMessage},{id:"action-message-spacer",text:""},...e.rightInspection.rows.slice(2)]:e.rightInspection.rows,r):ht([{text:"CONTEXT"},J(),...e.rightContext.map(o=>Wu(o,n)),...e.actionMessage?[J(),{text:e.actionMessage}]:[]],r);return ht(s,r)}function Mu(e,t){let r=e.slice(0,2),n=e.slice(2),s=Math.max(0,t-r.length),o=n.findIndex(a=>a.focused||a.selected),i=o===-1?0:Xu(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>si(a)),...n.slice(i,i+s).map(a=>si(a))]}function si(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",n=`${t}${e.text}`;if(e.segments)return{text:n,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let s=e.text.indexOf(" "),o=s===-1?e.text:e.text.slice(0,s),i=s===-1?"":e.text.slice(s);return{text:n,segments:[{text:t},{text:o,style:{fg:"7aa2f7"}},{text:i}],tone:r}}return e.color?{text:n,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:n,tone:r}}function Ou(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Ge("\u25CF",r,e.selected?y.panelSelected:y.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((u,w)=>u+z(w.text),0):0,l=t-z(o)-z(s)-a,c=e.selected?e.text:e.focused?Ge(e.text,r,y.panelBg):e.panelHeader?Jt(e.text,r,y.panelMuted):e.text,d=ie(`${n}${c}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let u=[{text:`${d}${o}${i}`},...e.prBadge];return{text:`${d}${o}${e.prBadge.map(P=>P.text).join("")}`,segments:u,tone:p}}return{text:`${d}${o}${i}`,tone:p}}function Fu(e){let t=e.map(n=>{let s=n.health>=1,o=parseInt(n.count,10),i=o>1?` (${o})`:"";return{text:`${s?"\u25CF":"\u25CB"} ${n.name}${i}`,active:s}}),r=[];for(let n=0;n<t.length;n++){let s=t[n];n>0&&r.push({text:" "}),s.active?r.push({text:s.text,style:{fg:y.success.fg}}):r.push({text:s.text,style:{fg:y.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function Nu(e,t,r){return e.map(n=>n.active?r?Ge(n.label,t,y.panelBg):Jt(n.label,t,y.panelBg):Rn(n.label,t,y.panelBg)).join(" ")}function Wu(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Rn(e.value,t,y.panelBg):e.value}`}}function Ht(e,t,r,n){let s=_u(n,e.tone??"default"),o=Bu(e,r,s);if(n==="left"){if(e.fullBleed)return $(ie(o,t),r,s);let a=t-zt-Yt;if(e.rightAlign){let c=z(o),d=Math.max(0,a-c),p=`${" ".repeat(zt)}${" ".repeat(d)}${o}${" ".repeat(Yt)}`;return $(p,r,s)}let l=`${" ".repeat(zt)}${ie(o,a)}${" ".repeat(Yt)}`;return $(l,r,s)}return n==="center"&&e.fullBleed?qu(e,t,r,s):$(ie(` ${o}`,t),r,s)}function _u(e,t){return t==="selected"||t==="focused"?y.panelSelected:t==="muted"?y.panelMuted:y.panelBg}function ht(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(J());return r}function J(){return{text:""}}function Bu(e,t,r){return e.segments?e.segments.map(n=>ui(n,t,r)).join(""):e.text}function qu(e,t,r,n){let s=" ".repeat(Qt),o=Math.max(0,t-Qt*2);if(!e.segments)return $(`${s}${ie(e.text,o)}${s}`,r,n);let i=Vu(e.segments,o),a=`${s}${i.map(l=>ui(l,r,n)).join("")}${s}${r?kn:""}`;return $(a,r,n)}function ui(e,t,r){let n=e.href?`${pi(e.href)}${e.text}${kn}`:Uu(e.text);return!t||!e.style?n:`${kt(zu(e.style,r))}${Yu(e.style)}${n}${hn}${kt(r)}`}function Uu(e){return e.replace(Eu,t=>{let[r,n]=Ku(t);return`${pi(r)}${r}${kn}${n}`})}function Ku(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function pi(e){return`\x1B]8;;${e}\x1B\\`}function Vu(e,t){let r=Gu(e,t);return Hu(r,t)}function Gu(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=z(s.text);if(o<=n){r.push(s),n-=o;continue}let i=Xt(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function Hu(e,t){let r=z(hi(e));if(r>=t)return e;let n=e.at(-1)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function zu(e,t){let r=e.inverse?e.bg??t.bg:e.fg,n=e.inverse?e.fg??t.fg:e.bg,s={},o=r??t.fg,i=n??t.bg;return o&&(s.fg=o),i&&(s.bg=i),s}function Yu(e){let t=[];return e.bold&&t.push("1"),e.dim&&t.push("2"),e.italic&&t.push("3"),e.underline&&t.push("4"),t.length>0?`\x1B[${t.join(";")}m`:""}function Qu(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function fi(e,t){let r=Math.max(0,t-z(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ie(e,t){let r=z(e);return r>=t?Ju(e,t):e+" ".repeat(t-r)}function Ju(e,t){if(t<=0)return"";if(z(e)<=t)return e;let r=gi(e);return Xt(r,Math.max(0,t-1))+"\u2026"}function z(e){let t=0;for(let r of Array.from(gi(e)))t+=mi(r);return t}function Xt(e,t){let r="",n=0;for(let s of Array.from(e)){let o=mi(s);if(n+o>t)break;r+=s,n+=o}return r}function mi(e){let t=e.codePointAt(0);return t===void 0||t===0||t<32||t>=127&&t<160||t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65024&&t<=65039||t>=8203&&t<=8207||t>=8288&&t<=8292||t===65279?0:t>=4352&&(t<=4447||t===9001||t===9002||t>=11904&&t<=42191&&t!==12351||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65135||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=127744&&t<=129791||t>=131072&&t<=262141)?2:1}function Xu(e,t,r){return Math.min(Math.max(e,t),r)}function gi(e){return e.replace(vu,"").replace(Iu,"")}function hi(e){return e.map(t=>t.text).join("")}function $(e,t,r){if(!t)return e;let n=kt(r),s=e.replace(Cu,`${hn}${n}`);return`${n}${s}${hn}`}function kt(e){let t=[];return e.fg&&t.push(`38;2;${oi(e.fg).join(";")}`),e.bg&&t.push(`48;2;${oi(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function oi(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Ge(e,t,r){return Zt(e,t,y.success.fg,r)}function Zu(e,t,r){return Zt(e,t,y.error.fg,r)}function Jt(e,t,r){return Zt(e,t,y.accent.fg,r)}function Rn(e,t,r){return Zt(e,t,y.mutedfg.fg,r)}function Zt(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${kt(s)}${e}${kt(n)}`}function ki(e,t,r){let n=e.tasks.find(a=>a.ptyTabs.some(l=>l.id===t))??null,s=n?.ptyTabs.find(a=>a.id===t)??null,o=n?.worktreePath??r,i=s?.kind==="agent"?tp(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:ep(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function ep(e,t){let r=(e??"").split(yn.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(yn.delimiter):[...r,t].join(yn.delimiter)}function tp(e){return e.command.length>0?e.command:["codex"]}function wi(e,t){let r=e.ptyTabs.find(n=>n.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function ye(e){return{columns:Math.max(20,e.width-Z.leftWidth-Z.rightWidth-Z.dividerWidth-Qt*2),rows:Math.max(5,e.height-Z.topRailHeight-5)}}function Ti(e){return e.length===1||oe(e)||e==="BACKSPACE"||e==="TAB"}function wt(e){return typeof e=="string"&&new RegExp(`:(?:agent|${x.join("|")})(?:-\\d+)?$`).test(e)}function Ri(e,t){return e==="UP"&&t?-3:e==="DOWN"&&t?3:e==="PAGE_UP"?-5:e==="PAGE_DOWN"?5:e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Pn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function yi(e){let t=new RegExp("\x1B\\[<(\\d+);\\d+;\\d+[mM]").exec(e);if(!t?.[1])return 0;let r=Number.parseInt(t[1],10);return r===64?-3:r===65?3:0}function Pi(e){return e==="\x1B[13;2u"?"SHIFT_ENTER":null}function bi(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
134
+ `);return i.length>Wd?B(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?B(t,"Binary diff preview is not available in Craig.","binary",t,i.length):{path:t,status:i.length>0?"ready":"empty",title:t,lines:i.length>0?i.split(`
135
+ `):["No diff for this file."],byteLength:i.length}}function Lo(e){let t=[],r=new Set;for(let n of e){let s=n.split("/");for(let o=0;o<s.length-1;o+=1){let i=s.slice(0,o+1).join("/");r.has(i)||(r.add(i),t.push({kind:"directory",path:i,depth:o,label:s[o]??i}))}t.push({kind:"file",path:n,depth:s.length-1,label:s.at(-1)??n})}return t}function we(e,t){return e&&t.includes(e)?e:t[0]??null}function Kd(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Mo(e){return[...new Set(e.split(`
136
+ `).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Vd(e,t){let r=ln.resolve(e,t),n=ln.resolve(e);if(r!==n&&!r.startsWith(`${n}${ln.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Gd(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function B(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Hd=["tasks","center","inspector","actions"],_o=["agent","terminal"],qo=[],I="inspection",uR=[..._o,...qo],Bo=["commit","push","refresh-checks","close-task"],zd=["refresh-checks","close-task"],Uo=["task","checks","pr","setup-run","actions","next-action"],Ko=["diff","files","review"];function Vo(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=uu(e?.openInspectionKind)??r,s=h.runners.getEnabled(t);return{inputMode:fu(e?.inputMode),focusedRegion:cu(e?.focusedRegion),selectedRepoId:ce(e?.selectedRepoId),selectedWorkspaceId:ce(e?.selectedWorkspaceId),selectedTaskId:ce(e?.selectedTaskId),selectedPtyTabId:ce(e?.selectedPtyTabId),selectedLeftItemId:Pu(ce(e?.selectedTaskId)),activeTab:r?I:ce(e?.activeTab)??"agent",preferredPtyTabKind:pu(e?.preferredPtyTabKind),inspectorSection:ft(e?.inspectorSection,Uo,"task"),inspectionMode:du(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:ce(e?.selectedFileTreePath),selectedFilePath:ce(e?.selectedFilePath),selectedDiffPath:ce(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:ft(e?.selectedActionId,Bo,"commit"),selectedProjectTargetId:null,selectedRunner:mu(e?.selectedRunner,s,h.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:Qd(),centerZoomed:!1}}function Qd(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Go(e,t){return{...e??yt(),selectedRepoId:t.selectedRepoId,selectedWorkspaceId:t.selectedWorkspaceId,selectedTaskId:t.selectedTaskId,selectedPtyTabId:t.selectedPtyTabId,inputMode:t.inputMode,focusedRegion:t.focusedRegion,activeTab:t.activeTab,preferredPtyTabKind:t.preferredPtyTabKind,inspectorSection:t.inspectorSection,inspectionMode:t.inspectionMode,openInspectionKind:t.openInspectionKind,selectedFileTreePath:t.selectedFileTreePath,selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath,collapsedFileTreePaths:t.collapsedFileTreePaths,selectedActionId:t.selectedActionId,selectedRunner:t.selectedRunner}}function gt(e,t,r={}){let n=Ru(e,t),s=Zo(n),o=(s?.kind==="workspace"?t.workspaces?.find(d=>d.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(d=>d.id===t.tasks.find(p=>p.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(d=>d.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(d=>d.id===s.id)??null:s?.kind==="task"?t.repos.find(d=>d.id===t.tasks.find(p=>p.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(d=>d.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(d.id))??null:null)??(o?.kind!=="project"?t.repos.find(d=>d.id===o?.primaryRepoId)??null:null)??t.repos.find(d=>d.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(d=>d.workspaceId===o.id):a?t.tasks.filter(d=>d.repoId===a):[],c=(s?.kind==="task"?l.find(d=>d.id===s.id)??null:null)??l.find(d=>d.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:c?.id??null,...hu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:iu(e,t,c?.id??null),...ku(e,t,c?.id??null),selectedDiffPath:ou(e,t,c?.id??null),inspectorSection:ft(e.inspectorSection,Uo,"task")}}function Yd(e,t,r){if(t==="ESCAPE")return g({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return g({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return un(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return mn({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return g({state:{...e,fileSearchQuery:n},changed:!0})}return g({state:e})}function mn(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Jd(t)?g({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):g({state:e});if(e.fileSearchQuery!==null)return Yd(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return g({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return g({state:e,exit:!0});if(t==="ESCAPE")return g({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return g({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(pn(e.selectedLeftItemId)||fn(e.selectedLeftItemId)))return g({state:{...e,selectedRunner:gn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Oo(e,1);if(t==="SHIFT_TAB"||t==="[")return Oo(e,-1);if(t==="z"||t==="Z")return g({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,-1,r):un(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):un(e,1,r);if(t==="PAGE_UP")return Te(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Te(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Te(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Te(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??x,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return g({state:{...e,centerTabRunner:o,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let n=gu(e,t);return g({state:{...e,preferredPtyTabKind:n,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:n,createPtyTabRunner:n==="agent"?e.centerTabRunner:null})}if(t==="R"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return g({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId)return g({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Su(e.selectedLeftItemId)&&e.selectedWorkspaceId)return g({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Wo(e.activeTab,r.ptyTabIds??[]))return g({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return dn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fo(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return dn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fo(e,1)}if(oe(t)){if(e.focusedRegion==="tasks"&&(pn(e.selectedLeftItemId)||fn(e.selectedLeftItemId))){let n=ei(e.selectedLeftItemId),s=ti(e.selectedLeftItemId);return g({state:{...e,selectedRepoId:n??e.selectedRepoId,selectedWorkspaceId:s??e.selectedWorkspaceId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return g({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Kt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return g({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:mt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Wo(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return g({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:mt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===I)return g({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let n=e.selectedFileTreePath??e.selectedFilePath;if(n&&(r.fileTreeDirectoryIds??[]).includes(n))return g({state:ru({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return g({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:I,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?g({state:{...e,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?g({state:e}):e.selectedActionId==="refresh-checks"?g({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?g({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):g({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return g({state:e})}function ue(e,t){return{...e,terminal:t}}function Ho(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Jd(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function oe(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
137
+ `}function zo(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Qo(e){return Yo(e)||mt(e)!==null}function Xd(e){return qo.includes(e)}function Yo(e){return _o.includes(e)}function Jo(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var Zd=["tasks","center","inspector"];function Oo(e,t){return Bt(e,"focusedRegion",Zd,t)}function dn(e,t,r){let n=Bt(e,"activeTab",r&&r.length>0?r:Tu(e),t);return!n.changed||Xd(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:mt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function un(e,t,r){if(e.focusedRegion==="tasks")return eu(e,t,r.leftItemIds);if(e.focusedRegion==="center")return dn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:n}if(r.projectTargetIds?.length){let n=Ut(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return Bt(e,"selectedActionId",zd,t)}return Bt(e,"selectedActionId",Bo,t)}function eu(e,t,r){let n=Ut(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Zo(n.state.selectedLeftItemId);if(s?.kind==="workspace")return{...n,state:{...n.state,selectedWorkspaceId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="task")return{...n,state:{...n.state,selectedTaskId:s.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};if(s?.kind==="repo")return{...n,state:{...n.state,selectedRepoId:s.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0},refreshInspection:!0};let o=ei(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=ti(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Te(e,t,r){if(t===0)return g({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Xo(e,t,r);if(e.inspectionMode==="diff"){let n=Ut(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?No(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):g({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return No(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return nu(e,t,r)}return g({state:e})}function tu(e,t){if(e.inspectionMode===t)return g({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return g({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Fo(e,t){return tu(e,lu(e.inspectionMode,Ko,t))}function Xo(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return g({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=de(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return g({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return g({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?I:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function ru(e){if(!e.selectedFileTreePath)return e;let t=new Set(e.collapsedFileTreePaths);return t.has(e.selectedFileTreePath)?t.delete(e.selectedFileTreePath):t.add(e.selectedFileTreePath),{...e,collapsedFileTreePaths:[...t].sort((r,n)=>r.localeCompare(n)),actionMessage:null}}function No(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=de(e[t]+r,0,o);return i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function nu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return su(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=de(i,0,o);return d===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?g({state:e}):g({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?g({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?g({state:e}):g({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=de(i,0,o);return c===e.diffScrollOffset?g({state:e}):g({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function su(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=de(e.diffScrollOffset+t,0,o),a=au(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?g({state:e}):g({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function ou(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function iu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function au(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Bt(e,t,r,n){let s=r.indexOf(e[t]),o=de(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?g({state:e}):g({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Ut(e,t,r,n,s=!1){if(r.length===0)return g({state:e});let o=r.indexOf(e[t]??r[0]??""),i=de(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?g({state:e}):g({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function lu(e,t,r){let n=t.indexOf(e);return t[de(n+r,0,t.length-1)]??e}function g(e){return{state:e.state,changed:e.changed??!1,exit:e.exit??!1,pause:e.pause??!1,attachTerminal:e.attachTerminal??!1,detachTerminal:e.detachTerminal??!1,beginTaskPrompt:e.beginTaskPrompt??!1,openWorkspaceBrowser:e.openWorkspaceBrowser??!1,createWorkspaceTask:e.createWorkspaceTask??!1,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,closeTask:e.closeTask??!1,removeWorkspace:e.removeWorkspace??!1,refreshInspection:e.refreshInspection??!1,openPrUrl:e.openPrUrl??!1}}function ft(e,t,r){return t.includes(e??"")?e:r}function cu(e){return e==="tabs"?"center":ft(e,Hd,"tasks")}function du(e,t){return e==="checks"||e==="actions"||e==="review"?"review":ft(e,Ko,t)}function uu(e){return e==="file"||e==="diff"?e:null}function pu(e){return e==="terminal"?"terminal":"agent"}function fu(e){return e==="terminal"?"terminal":"control"}function mu(e,t=[...x],r="codex"){return e&&h.runners.isRunnerType(e)&&t.includes(e)?e:r}function gn(e,t=x){let r=t.length>0?t:x,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function mt(e){let t=x.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function gu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":mt(e.activeTab)??e.preferredPtyTabKind}function hu(e,t,r){if(!e)return{activeTab:t===I?t:"agent",selectedPtyTabId:null};let n=e.ptyTabs.find(a=>a.id===r)??null,s=e.selectedPtyTabId?e.ptyTabs.find(a=>a.id===e.selectedPtyTabId)??null:null,o=e.ptyTabs.find(a=>a.id===t)??null;if(o)return{activeTab:o.id,selectedPtyTabId:o.id};if(Yo(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??I,selectedPtyTabId:l?.id??null}}if(t===I)return{activeTab:I,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??I,selectedPtyTabId:i?.id??null}}function ku(e,t,r){if(!t.inspection||t.inspection.taskId!==r)return{selectedFileTreePath:e.selectedFileTreePath,collapsedFileTreePaths:e.collapsedFileTreePaths};let n=e.selectedFileTreePath??t.inspection.selectedFilePath,s=e.selectedFileTreePath===null&&e.collapsedFileTreePaths.length===0?wu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function wu(e,t){let r=new Set;if(t){let n=t.split("/");for(let s=1;s<n.length;s+=1)r.add(n.slice(0,s).join("/"))}return e.filter(n=>n.kind==="directory"&&!n.path.includes("/")&&!r.has(n.path)).map(n=>n.path).sort((n,s)=>n.localeCompare(s))}function Tu(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function Wo(e,t){return t.includes(e)}function Ru(e,t){let r=yu(t);return e.selectedLeftItemId&&r.includes(e.selectedLeftItemId)?e.selectedLeftItemId:e.selectedWorkspaceId&&r.includes(`workspace:${e.selectedWorkspaceId}`)?`workspace:${e.selectedWorkspaceId}`:e.selectedTaskId&&r.includes(`task:${e.selectedTaskId}`)?`task:${e.selectedTaskId}`:e.selectedRepoId&&r.includes(`repo:${e.selectedRepoId}`)?`repo:${e.selectedRepoId}`:r[0]??null}function yu(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let n of e.tasks.filter(s=>s.workspaceId===r.id))t.push(`task:${n.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let n of e.tasks.filter(s=>s.repoId===r.id))t.push(`task:${n.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}function Zo(e){return e?e.startsWith("workspace:")?{kind:"workspace",id:e.slice(10)}:e.startsWith("repo:")?{kind:"repo",id:e.slice(5)}:e.startsWith("task:")?{kind:"task",id:e.slice(5)}:null:null}function ce(e){return typeof e=="string"?e:null}function Pu(e){return e?`task:${e}`:null}function Kt(e){return typeof e=="string"&&e.startsWith("task:")}function pn(e){return typeof e=="string"&&e.startsWith("new-task:")}function fn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Su(e){return typeof e=="string"&&e.startsWith("workspace:")}function ei(e){return pn(e)?e.slice(9):null}function ti(e){return fn(e)?e.slice(19):null}function de(e,t,r){return Math.min(r,Math.max(t,e))}async function Re(e,t,r){let n=ne(e),[s,o,i]=await Promise.all([Q.repos.listRegisteredRepos(n).then(d=>d.repos),q(n),b.listTasks(n)]),a=hn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await vo(a,l):null;return{workspaceRoot:e,workspaces:o.filter(d=>d.status==="active"),repos:s,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function hn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ri(e,t){return gt(e,t)}function ni(e){let t=[];if(e.workspaces?.length)for(let r of e.workspaces){t.push(`workspace:${r.id}`);for(let n of e.tasks.filter(s=>s.workspaceId===r.id))t.push(`task:${n.id}`);r.kind==="project"&&t.push(`new-task-workspace:${r.id}`),r.kind==="repo"&&t.push(`new-task:${r.primaryRepoId}`)}else for(let r of e.repos){t.push(`repo:${r.id}`);for(let n of e.tasks.filter(s=>s.repoId===r.id))t.push(`task:${n.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}import Sn from"node:path";import RR from"picocolors";var bu=[" \u2584\u2588\u2588\u2588\u2588\u2584 \u2588\u2588\u2580\u2588\u2588\u2588 \u2584\u2584\u2584 \u2588\u2588\u2593 \u2584\u2588\u2588\u2588\u2588"," \u2592\u2588\u2588\u2580 \u2580\u2588 \u2593\u2588\u2588 \u2592 \u2588\u2588\u2592\u2592\u2588\u2588\u2588\u2588\u2584 \u2593\u2588\u2588\u2592 \u2588\u2588\u2592 \u2580\u2588\u2592"," \u2592\u2593\u2588 \u2584 \u2593\u2588\u2588 \u2591\u2584\u2588 \u2592\u2592\u2588\u2588 \u2580\u2588\u2584 \u2592\u2588\u2588\u2592\u2592\u2588\u2588\u2591\u2584\u2584\u2584\u2591"," \u2592\u2593\u2593\u2584 \u2584\u2588\u2588\u2592\u2592\u2588\u2588\u2580\u2580\u2588\u2584 \u2591\u2588\u2588\u2584\u2584\u2584\u2584\u2588\u2588 \u2591\u2588\u2588\u2591\u2591\u2593\u2588 \u2588\u2588\u2593"," \u2592 \u2593\u2588\u2588\u2588\u2580 \u2591\u2591\u2588\u2588\u2593 \u2592\u2588\u2588\u2592 \u2593\u2588 \u2593\u2588\u2588\u2592\u2591\u2588\u2588\u2591\u2591\u2592\u2593\u2588\u2588\u2588\u2580\u2592"," \u2591 \u2591\u2592 \u2592 \u2591\u2591 \u2592\u2593 \u2591\u2592\u2593\u2591 \u2592\u2592 \u2593\u2592\u2588\u2591\u2591\u2593 \u2591\u2592 \u2592"," \u2591 \u2592 \u2591\u2592 \u2591 \u2592\u2591 \u2592 \u2592\u2592 \u2591 \u2592 \u2591 \u2591 \u2591"," \u2591 \u2591\u2591 \u2591 \u2591 \u2592 \u2592 \u2591\u2591 \u2591 \u2591"," \u2591 \u2591 \u2591 \u2591 \u2591 \u2591 \u2591"," \u2591"];function kn(){return[...bu]}var Vt={width:120,height:36},Z={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ee(e,t){return{width:Math.max(e??Vt.width,Vt.width),height:Math.max(t??Vt.height,Vt.height)}}var Iu=["Start","Options","Exit"],Cu=["Resume","Options","Exit"],zt=2,Qt=2,Yt=2,vu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Eu=new RegExp("\x1B\\[(?:0)?m","g"),xu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Au=/https?:\/\/[^\s<>"']+/g,wn="\x1B[0m",Tn="\x1B]8;;\x1B\\",P={panelBg:{bg:"0a0a0a",fg:"c0caf5"},panelMuted:{bg:"0a0a0a",fg:"565f89"},panelSelected:{bg:"1a1b26",fg:"c0caf5"},panelFocused:{bg:"1a1b26",fg:"7aa2f7"},divider:{bg:"0a0a0a",fg:"292e42"},rail:{bg:"0a0a0a",fg:"c0caf5"},overlay:{bg:"06060f",fg:"565f89"},overlayTitle:{bg:"06060f",fg:"565f89"},overlayLogo:{bg:"06060f",fg:"9ece6a"},overlaySubtitle:{bg:"06060f",fg:"41a6b5"},overlayMenuSelected:{bg:"06060f",fg:"7aa2f7"},accent:{fg:"7aa2f7"},success:{fg:"9ece6a"},pending:{fg:"e0af68"},error:{fg:"f7768e"},mutedfg:{fg:"565f89"},disabled:{fg:"3b4261"}};function ii(e,t={}){return yn(e,{subtitle:"crAIg is that you?",menuItems:Iu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function ai(e,t={}){return yn(e,{subtitle:"Control mode is paused.",menuItems:Cu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var Gt=[" GLOBAL CENTER PANEL INSPECTOR"," ? help \u2190\u2192 / hl switch tab \u2191\u2193 / jk navigate"," Esc pause / back + new tab \u2190\u2192 / hl switch mode"," Tab cycle panels a codex tab R sync PR"," q quit t terminal tab R sync PR"," x close tab X close task"," TASKS Enter attach PTY X close task"," \u2191\u2193 / jk navigate"," n new task TERMINAL MODE"," Enter attach Ctrl+] return to control mode"," Wheel / PgUp / PgDn scroll",""," Press Esc to return."],Du=["Help"];function Rn(e,t={}){return yn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??Du,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function li(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o=kn(),i=Math.max(1,Math.floor((e.height-o.length-2-Gt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=$(fi(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...Gt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<Gt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=Gt[d]??"";s[p]=$(ie(" ".repeat(l)+f,e.width),r,n)}return s.join(`
138
+ `)}function ci(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill($(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},J(),...a.length>0?a.map(u=>({text:u})):[{text:"No Craig errors have been logged.",tone:"muted"}],J(),{text:"Esc returns to Options.",tone:"muted"}],p=ht(d,e.height-2),f=Math.max(1,Math.floor((e.height-p.length)/2));for(let u=0;u<p.length;u+=1){let w=f+u;if(w>=e.height)break;let R=p[u]??J(),A=`${" ".repeat(c)}${Xt(R.text,l)}`,U=R.tone==="selected"?P.overlayMenuSelected:R.tone==="muted"?P.overlay:P.panelBg;s[w]=$(ie(A,e.width),r,U)}return s.join(`
139
+ `)}function di(e,t,r={}){let n=r.color??!0,s=Z.leftWidth,o=Z.rightWidth,i=Z.dividerWidth,a=r.centerOnly??!1,l=a?e.width:e.width-s-o-i*2,c=e.height-Z.topRailHeight-1,d=r.focusFlashActive??!1,p={bg:P.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:P.divider,u=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:P.divider,w=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,R=$(ie(w,e.width),n,P.rail),A=ju(t,s-zt-Qt,c,n),U=Lu(t,l,c,n),fe=Ou(t,o,c,n),ae=t.inputMode==="terminal",k=[];for(let je=0;je<c;je+=1){if(a){k.push(Ht(U[je]??J(),l,n,"center"));continue}let Za=Ht(A[je]??J(),s,n,"left"),el=$("\u2502",n,f),tl=Ht(U[je]??J(),l,n,"center"),rl=$("\u2502",n,u),nl=Ht(fe[je]??J(),o,n,"right");k.push(`${Za}${el}${tl}${rl}${nl}`)}let Ye=ae||t.modalInput?P.panelBg:P.panelMuted,Xa=$u(t.footerText,t.footerToast,e.width,n,Ye);return[R,...k,Xa].join(`
140
+ `)}function $u(e,t,r,n,s){let o=` ${e}`;if(!t)return $(ie(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=z(i),l=z(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?Xt(o,Math.max(0,r-a-3)):o,p=Math.max(1,r-z(d)-a-2),f=t.tone==="error"?tp(i,n,s):Ge(i,n,s),u=`${d}${" ".repeat(p)}${f} `;return $(ie(u,r),n,s)}function yn(e,t){let r=new Array(e.height).fill($(" ".repeat(e.width),t.color,P.overlay)),n=kn(),s=Math.max(...t.menuItems.map(c=>c.length)),o=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c.padEnd(s)}`),i=t.optionsMessage?["",t.optionsMessage]:[],a=[...n,"",t.subtitle,"",...o,...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=fi(a[c]??"",e.width);if(c<n.length){r[l+c]=$(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=$(d,t.color,P.overlaySubtitle);continue}let p=c-(n.length+3),u=p>=0&&p<t.menuItems.length&&p===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=$(d,t.color,u)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,p=" ".repeat(Math.max(0,e.width-z(d)));r[e.height-1]=$(`${p}${Pn(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
141
+ `)}function ju(e,t,r,n){let s=Wu(e.runners),o=1,i=e.leftTree.map(l=>Nu(l,t,n));return[...ht(i,r-o),s]}function Lu(e,t,r,n){let s=t-2,o=e.tabs.find(k=>k.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:Xu(e.tabs),a=e.inputMode==="terminal"?s:o.length+1,l="\u2500".repeat(Math.max(0,a)),c=`${" ".repeat(i)}${e.inputMode==="terminal"?Ge(l,n,P.panelBg):Jt(l,n,P.panelMuted)}`,d=[`${Jt(e.centerHeader.tabLabel,n,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),p=e.tabs.find(k=>k.active)?.id??"agent",f=e.centerHeader.tabLabel==="BROWSER"||!Qo(p)?e.centerTranscript.map(k=>({...k})):Mu(e),u=_u(e.tabs,n,e.focusedRegion==="center"),w=" engaged ",R=w.length+2,A=e.inputMode==="terminal"?Ge(`${w}\u25CF `,n,P.panelBg):"",U=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-z(u)-R)):"",ae=[{text:e.inputMode==="terminal"?`${u}${U}${A}`:u},{text:c,tone:"muted"},{text:d},J(),...f];return ht(ae,r)}function Mu(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},J(),{text:e.terminal.error},J(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(n=>n.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(n=>({text:hi(n.segments),segments:n.segments,fullBleed:!0}))}function Ou(e,t,r,n){let s=e.rightInspection?Fu(e.actionMessage?[...e.rightInspection.rows.slice(0,2),{id:"action-message",text:e.actionMessage},{id:"action-message-spacer",text:""},...e.rightInspection.rows.slice(2)]:e.rightInspection.rows,r):ht([{text:"CONTEXT"},J(),...e.rightContext.map(o=>qu(o,n)),...e.actionMessage?[J(),{text:e.actionMessage}]:[]],r);return ht(s,r)}function Fu(e,t){let r=e.slice(0,2),n=e.slice(2),s=Math.max(0,t-r.length),o=n.findIndex(a=>a.focused||a.selected),i=o===-1?0:ep(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>si(a)),...n.slice(i,i+s).map(a=>si(a))]}function si(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",n=`${t}${e.text}`;if(e.segments)return{text:n,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let s=e.text.indexOf(" "),o=s===-1?e.text:e.text.slice(0,s),i=s===-1?"":e.text.slice(s);return{text:n,segments:[{text:t},{text:o,style:{fg:"7aa2f7"}},{text:i}],tone:r}}return e.color?{text:n,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:n,tone:r}}function Nu(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Ge("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((u,w)=>u+z(w.text),0):0,l=t-z(o)-z(s)-a,c=e.selected?e.text:e.focused?Ge(e.text,r,P.panelBg):e.panelHeader?Jt(e.text,r,P.panelMuted):e.text,d=ie(`${n}${c}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let u=[{text:`${d}${o}${i}`},...e.prBadge];return{text:`${d}${o}${e.prBadge.map(R=>R.text).join("")}`,segments:u,tone:p}}return{text:`${d}${o}${i}`,tone:p}}function Wu(e){let t=e.map(n=>{let s=n.health>=1,o=parseInt(n.count,10),i=o>1?` (${o})`:"";return{text:`${s?"\u25CF":"\u25CB"} ${n.name}${i}`,active:s}}),r=[];for(let n=0;n<t.length;n++){let s=t[n];n>0&&r.push({text:" "}),s.active?r.push({text:s.text,style:{fg:P.success.fg}}):r.push({text:s.text,style:{fg:P.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function _u(e,t,r){return e.map(n=>n.active?r?Ge(n.label,t,P.panelBg):Jt(n.label,t,P.panelBg):Pn(n.label,t,P.panelBg)).join(" ")}function qu(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Pn(e.value,t,P.panelBg):e.value}`}}function Ht(e,t,r,n){let s=Bu(n,e.tone??"default"),o=Uu(e,r,s);if(n==="left"){if(e.fullBleed)return $(ie(o,t),r,s);let a=t-zt-Qt;if(e.rightAlign){let c=z(o),d=Math.max(0,a-c),p=`${" ".repeat(zt)}${" ".repeat(d)}${o}${" ".repeat(Qt)}`;return $(p,r,s)}let l=`${" ".repeat(zt)}${ie(o,a)}${" ".repeat(Qt)}`;return $(l,r,s)}return n==="center"&&e.fullBleed?Ku(e,t,r,s):$(ie(` ${o}`,t),r,s)}function Bu(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function ht(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(J());return r}function J(){return{text:""}}function Uu(e,t,r){return e.segments?e.segments.map(n=>ui(n,t,r)).join(""):e.text}function Ku(e,t,r,n){let s=" ".repeat(Yt),o=Math.max(0,t-Yt*2);if(!e.segments)return $(`${s}${ie(e.text,o)}${s}`,r,n);let i=Hu(e.segments,o),a=`${s}${i.map(l=>ui(l,r,n)).join("")}${s}${r?Tn:""}`;return $(a,r,n)}function ui(e,t,r){let n=e.href?`${pi(e.href)}${e.text}${Tn}`:Vu(e.text);return!t||!e.style?n:`${kt(Yu(e.style,r))}${Ju(e.style)}${n}${wn}${kt(r)}`}function Vu(e){return e.replace(Au,t=>{let[r,n]=Gu(t);return`${pi(r)}${r}${Tn}${n}`})}function Gu(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function pi(e){return`\x1B]8;;${e}\x1B\\`}function Hu(e,t){let r=zu(e,t);return Qu(r,t)}function zu(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=z(s.text);if(o<=n){r.push(s),n-=o;continue}let i=Xt(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function Qu(e,t){let r=z(hi(e));if(r>=t)return e;let n=e.at(-1)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function Yu(e,t){let r=e.inverse?e.bg??t.bg:e.fg,n=e.inverse?e.fg??t.fg:e.bg,s={},o=r??t.fg,i=n??t.bg;return o&&(s.fg=o),i&&(s.bg=i),s}function Ju(e){let t=[];return e.bold&&t.push("1"),e.dim&&t.push("2"),e.italic&&t.push("3"),e.underline&&t.push("4"),t.length>0?`\x1B[${t.join(";")}m`:""}function Xu(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function fi(e,t){let r=Math.max(0,t-z(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ie(e,t){let r=z(e);return r>=t?Zu(e,t):e+" ".repeat(t-r)}function Zu(e,t){if(t<=0)return"";if(z(e)<=t)return e;let r=gi(e);return Xt(r,Math.max(0,t-1))+"\u2026"}function z(e){let t=0;for(let r of Array.from(gi(e)))t+=mi(r);return t}function Xt(e,t){let r="",n=0;for(let s of Array.from(e)){let o=mi(s);if(n+o>t)break;r+=s,n+=o}return r}function mi(e){let t=e.codePointAt(0);return t===void 0||t===0||t<32||t>=127&&t<160||t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65024&&t<=65039||t>=8203&&t<=8207||t>=8288&&t<=8292||t===65279?0:t>=4352&&(t<=4447||t===9001||t===9002||t>=11904&&t<=42191&&t!==12351||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65135||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=127744&&t<=129791||t>=131072&&t<=262141)?2:1}function ep(e,t,r){return Math.min(Math.max(e,t),r)}function gi(e){return e.replace(xu,"").replace(vu,"")}function hi(e){return e.map(t=>t.text).join("")}function $(e,t,r){if(!t)return e;let n=kt(r),s=e.replace(Eu,`${wn}${n}`);return`${n}${s}${wn}`}function kt(e){let t=[];return e.fg&&t.push(`38;2;${oi(e.fg).join(";")}`),e.bg&&t.push(`48;2;${oi(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function oi(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Ge(e,t,r){return Zt(e,t,P.success.fg,r)}function tp(e,t,r){return Zt(e,t,P.error.fg,r)}function Jt(e,t,r){return Zt(e,t,P.accent.fg,r)}function Pn(e,t,r){return Zt(e,t,P.mutedfg.fg,r)}function Zt(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${kt(s)}${e}${kt(n)}`}function ki(e,t,r){let n=e.tasks.find(a=>a.ptyTabs.some(l=>l.id===t))??null,s=n?.ptyTabs.find(a=>a.id===t)??null,o=n?.worktreePath??r,i=s?.kind==="agent"?np(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:rp(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function rp(e,t){let r=(e??"").split(Sn.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(Sn.delimiter):[...r,t].join(Sn.delimiter)}function np(e){return e.command.length>0?e.command:["codex"]}function wi(e,t){let r=e.ptyTabs.find(n=>n.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function ye(e){return{columns:Math.max(20,e.width-Z.leftWidth-Z.rightWidth-Z.dividerWidth-Yt*2),rows:Math.max(5,e.height-Z.topRailHeight-5)}}function Ti(e){return e.length===1||oe(e)||e==="BACKSPACE"||e==="TAB"}function wt(e){return typeof e=="string"&&new RegExp(`:(?:agent|${x.join("|")})(?:-\\d+)?$`).test(e)}function Ri(e,t){return e==="UP"&&t?-3:e==="DOWN"&&t?3:e==="PAGE_UP"?-5:e==="PAGE_DOWN"?5:e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function bn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function yi(e){let t=new RegExp("\x1B\\[<(\\d+);\\d+;\\d+[mM]").exec(e);if(!t?.[1])return 0;let r=Number.parseInt(t[1],10);return r===64?-3:r===65?3:0}function Pi(e){return e==="\x1B[13;2u"?"SHIFT_ENTER":null}function Si(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
142
142
  `||r===`\r
143
- `)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Si(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Ii(e){return e.split(`
144
- `).map((t,r)=>`\x1B[${r+1};1H${t}`).join("")}import{spawn as Sp}from"node:child_process";import{createHash as Ip}from"node:crypto";import{createServer as Cp,createConnection as Li}from"node:net";import{openSync as vp}from"node:fs";import{mkdir as Ep,readFile as xn,rm as De,writeFile as xp}from"node:fs/promises";import{tmpdir as Ap}from"node:os";import He from"node:path";import{createRequire as up}from"node:module";import rp from"@xterm/headless";var np=1e3,sp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function vi(e){return new rp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:np,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Ei(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Sn(e,t){return new Promise(r=>{e.write(t,r)})}function xi(e,t=0){let r=e.buffer.active,n=[],s=r.getNullCell(),o=r.baseY+r.cursorY,i=Math.max(0,r.baseY-t);for(let a=0;a<e.rows;a+=1){let l=r.getLine(i+a);if(!l){n.push({segments:[]});continue}let c=[];for(let d=0;d<e.cols;d+=1){let p=l.getCell(d,s);!p||p.getWidth()===0||c.push({text:p.getChars()||" ",style:ap(p,i+a===o&&d===r.cursorX)})}n.push({segments:op(ip(c))})}return n}function op(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&dp(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};Ai(r.style)||(s.style=r.style),t.push(s)}return t}function ip(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Ai(r.style))break;t-=1}return e.slice(0,t)}function ap(e,t){let r={},n=Ci(e,"fg"),s=Ci(e,"bg");return n&&(r.fg=n),s&&(r.bg=s),e.isBold()&&(r.bold=!0),e.isDim()&&(r.dim=!0),e.isItalic()&&(r.italic=!0),e.isUnderline()&&(r.underline=!0),(e.isInverse()||t)&&(r.inverse=!0),r}function Ci(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let n=t==="fg"?e.isFgRGB():e.isBgRGB(),s=t==="fg"?e.getFgColor():e.getBgColor();return n?s.toString(16).padStart(6,"0"):sp[s]??lp(s)}function lp(e){if(e>=16&&e<=231){let t=e-16,r=Math.floor(t/36),n=Math.floor(t%36/6),s=t%6;return[r,n,s].map(cp).map(o=>o.toString(16).padStart(2,"0")).join("")}if(e>=232&&e<=255){let t=8+(e-232)*10;return[t,t,t].map(r=>r.toString(16).padStart(2,"0")).join("")}return"e6e6e6"}function cp(e){return e===0?0:55+e*40}function dp(e,t){return bn(e)===bn(t)}function bn(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Ai(e){return bn(e)===""}var pp=up(import.meta.url),fp=/^CTRL_([A-Z])$/,mp="\x1B[6n",gp="\x1B[c",hp="\x1B[?u",kp={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
145
- `,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""},er=class{sessions=new Map;shell;env;spawn;onUpdate;resolveSessionSpec;attachedTabId=null;constructor(t){this.shell=t.shell??process.env.SHELL??"/bin/zsh",this.env=t.env??process.env,this.spawn=t.spawn,this.onUpdate=t.onUpdate,this.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,n,s){let o=this.sessions.get(r);if(o)if(o.status!=="running")In(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,Di(o,n),this.getViewState(r);let i=this.createSession(t,r,n,s);return this.sessions.set(r,i),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||r.pty.write(t)}writeKey(t){let r=wp(t);r!==null&&this.write(r)}scrollViewport(t){let r=this.getAttachedSession();if(!r||t===0)return;let n=r.terminal.buffer.active.baseY;r.scrollbackLines=Math.max(0,Math.min(n,r.scrollbackLines-t))}resize(t){let r=this.getAttachedSession();r&&Di(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&(In(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())In(t);this.sessions.clear(),this.attachedTabId=null}getViewState(t){if(!t)return{status:"idle",rows:[],error:null,scrolledBack:!1};let r=this.sessions.get(t);return r?{status:r.status,rows:xi(r.terminal,r.scrollbackLines),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??Rp().spawn,i=vi(n),a=s??this.resolveSessionSpec(t,r),l=ve({...this.env,...a.env??{}}),{executable:c,args:d}=yp(this.shell,a.command,{cwd:a.cwd,env:l}),p=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:Pp(l)}),f={taskId:t,tabId:r,pty:p,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0};return f.disposables.push(p.onData(u=>{bp(p,u),Sn(f.terminal,u).then(()=>{this.onUpdate?.(f.tabId)})})),f.disposables.push(p.onExit(u=>{f.status="exited",Sn(f.terminal,`\r
146
- [process exited ${u.exitCode}]`).then(()=>{this.onUpdate?.(f.tabId)})})),f}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function wp(e){if(e.length===1)return e;let t=kp[e];if(t!==void 0)return t;let r=fp.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function Di(e,t){Tp(e.pty,t),Ei(e.terminal,t)}function In(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function Tp(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Rp(){return pp("node-pty")}function yp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Ee(t[0],r),...t.slice(1)].map($i).join(" ")}; exec ${$i(e)} -l`;return{executable:e,args:["-lc",s]}}function $i(e){return`'${e.replaceAll("'","'\\''")}'`}function Pp(e){let t={};for(let[r,n]of Object.entries(e))typeof n=="string"&&(t[r]=n);return t.TERM=t.TERM??"xterm-256color",t}function bp(e,t){for(let r=0;r<Cn(t,mp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Cn(t,gp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Cn(t,hp);r+=1)e.write("\x1B[?0u")}function Cn(e,t){if(t.length===0)return 0;let r=0,n=e.indexOf(t);for(;n!==-1;)r+=1,n=e.indexOf(t,n+t.length);return r}var An=3;async function Mi(e){let t=Dn(e.paths);await Dp(t,e.paths,e.spawnDaemon);let r=await Bi(t.socketPath),n=new vn(r,e);return await n.ready(),n}async function Oi(e,t={}){let r=Dn(e);await Ep(e.runtimeDir,{recursive:!0}),await De(r.socketPath,{force:!0});let n=new En(e,t),s=Cp(o=>n.handleConnection(o));await Fp(s,r.socketPath),await xp(r.pidPath,String(process.pid),"utf8"),await new Promise(o=>{let i=()=>{n.closeClients(),s.close(()=>o())};n.onShutdown=i,process.once("SIGTERM",i),process.once("SIGINT",i)}),await De(r.socketPath,{force:!0}),await De(r.pidPath,{force:!0}),n.disposeAll()}async function Fi(e){let t=Dn(e);return await rr(t.socketPath)?(await Wi(t.socketPath),!0):!1}var vn=class{constructor(t,r){this.socket=t;this.options=r,t.setEncoding("utf8"),t.on("data",n=>this.handleData(String(n))),t.on("error",n=>this.rejectAll(n instanceof Error?n:new Error(String(n)))),t.on("close",()=>{this.closed=!0,this.rejectAll(new Error("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;attachedTabId=null;buffer="";closed=!1;options;async ready(){if((await this.send({type:"ping"})).protocolVersion!==An)throw new Error("Craig PTY daemon protocol mismatch.")}async ensureSession(t,r,n){let s=await this.send({type:"ensureSession",taskId:t,tabId:r,size:n,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r;let o=s.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,o),o}async hydrateSessions(t){for(let r of t)try{let n=await this.send({type:"hydrateSession",tabId:r});n.view&&this.viewCache.set(r,n.view)}catch(n){let s=n instanceof Error?n.message:String(n);this.viewCache.set(r,{status:"failed",rows:[],error:s})}}async pruneStale(t){await this.send({type:"pruneStale",keepTabIds:t})}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){this.send({type:"scrollViewport",lines:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}resize(t){this.send({type:"resize",size:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}disposeSession(t){this.viewCache.delete(t),this.attachedTabId===t&&(this.attachedTabId=null),this.send({type:"disposeSession",tabId:t}).catch(()=>{})}disposeAll(){this.attachedTabId=null,!this.closed&&(this.socket.end(),this.closed=!0)}getViewState(t){return t?this.viewCache.get(t)??{status:"idle",rows:[],error:null,scrolledBack:!1}:{status:"idle",rows:[],error:null,scrolledBack:!1}}async requestShutdown(){await this.send({type:"shutdown"})}async send(t){if(this.closed)throw new Error("Craig PTY daemon connection is closed.");let r=this.nextRequestId;this.nextRequestId+=1;let n={...t,id:r},s=new Promise((i,a)=>{this.pending.set(r,{resolve:i,reject:a})});if(this.socket.destroyed)throw this.pending.delete(r),new Error("Craig PTY daemon connection is closed.");this.socket.write(`${JSON.stringify(n)}
143
+ `)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function bi(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Ii(e){return e.split(`
144
+ `).map((t,r)=>`\x1B[${r+1};1H${t}`).join("")}import{spawn as Cp}from"node:child_process";import{createHash as vp}from"node:crypto";import{createServer as Ep,createConnection as Li}from"node:net";import{openSync as xp}from"node:fs";import{mkdir as Ap,readFile as Dn,rm as De,writeFile as Dp}from"node:fs/promises";import{tmpdir as $p}from"node:os";import He from"node:path";import{createRequire as fp}from"node:module";import sp from"@xterm/headless";var op=1e3,ip=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function vi(e){return new sp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:op,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Ei(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Cn(e,t){return new Promise(r=>{e.write(t,r)})}function xi(e,t=0){let r=e.buffer.active,n=[],s=r.getNullCell(),o=r.baseY+r.cursorY,i=Math.max(0,r.baseY-t);for(let a=0;a<e.rows;a+=1){let l=r.getLine(i+a);if(!l){n.push({segments:[]});continue}let c=[];for(let d=0;d<e.cols;d+=1){let p=l.getCell(d,s);!p||p.getWidth()===0||c.push({text:p.getChars()||" ",style:cp(p,i+a===o&&d===r.cursorX)})}n.push({segments:ap(lp(c))})}return n}function ap(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&pp(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};Ai(r.style)||(s.style=r.style),t.push(s)}return t}function lp(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Ai(r.style))break;t-=1}return e.slice(0,t)}function cp(e,t){let r={},n=Ci(e,"fg"),s=Ci(e,"bg");return n&&(r.fg=n),s&&(r.bg=s),e.isBold()&&(r.bold=!0),e.isDim()&&(r.dim=!0),e.isItalic()&&(r.italic=!0),e.isUnderline()&&(r.underline=!0),(e.isInverse()||t)&&(r.inverse=!0),r}function Ci(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let n=t==="fg"?e.isFgRGB():e.isBgRGB(),s=t==="fg"?e.getFgColor():e.getBgColor();return n?s.toString(16).padStart(6,"0"):ip[s]??dp(s)}function dp(e){if(e>=16&&e<=231){let t=e-16,r=Math.floor(t/36),n=Math.floor(t%36/6),s=t%6;return[r,n,s].map(up).map(o=>o.toString(16).padStart(2,"0")).join("")}if(e>=232&&e<=255){let t=8+(e-232)*10;return[t,t,t].map(r=>r.toString(16).padStart(2,"0")).join("")}return"e6e6e6"}function up(e){return e===0?0:55+e*40}function pp(e,t){return In(e)===In(t)}function In(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Ai(e){return In(e)===""}var mp=fp(import.meta.url),gp=/^CTRL_([A-Z])$/,hp="\x1B[6n",kp="\x1B[c",wp="\x1B[?u",Tp={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
145
+ `,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""},er=class{sessions=new Map;shell;env;spawn;onUpdate;resolveSessionSpec;attachedTabId=null;constructor(t){this.shell=t.shell??process.env.SHELL??"/bin/zsh",this.env=t.env??process.env,this.spawn=t.spawn,this.onUpdate=t.onUpdate,this.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,n,s){let o=this.sessions.get(r);if(o)if(o.status!=="running")vn(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,Di(o,n),this.getViewState(r);let i=this.createSession(t,r,n,s);return this.sessions.set(r,i),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||r.pty.write(t)}writeKey(t){let r=Rp(t);r!==null&&this.write(r)}scrollViewport(t){let r=this.getAttachedSession();if(!r||t===0)return;let n=r.terminal.buffer.active.baseY;r.scrollbackLines=Math.max(0,Math.min(n,r.scrollbackLines-t))}resize(t){let r=this.getAttachedSession();r&&Di(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&(vn(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())vn(t);this.sessions.clear(),this.attachedTabId=null}getViewState(t){if(!t)return{status:"idle",rows:[],error:null,scrolledBack:!1};let r=this.sessions.get(t);return r?{status:r.status,rows:xi(r.terminal,r.scrollbackLines),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??Pp().spawn,i=vi(n),a=s??this.resolveSessionSpec(t,r),l=ve({...this.env,...a.env??{}}),{executable:c,args:d}=Sp(this.shell,a.command,{cwd:a.cwd,env:l}),p=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:bp(l)}),f={taskId:t,tabId:r,pty:p,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0};return f.disposables.push(p.onData(u=>{Ip(p,u),Cn(f.terminal,u).then(()=>{this.onUpdate?.(f.tabId)})})),f.disposables.push(p.onExit(u=>{f.status="exited",Cn(f.terminal,`\r
146
+ [process exited ${u.exitCode}]`).then(()=>{this.onUpdate?.(f.tabId)})})),f}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function Rp(e){if(e.length===1)return e;let t=Tp[e];if(t!==void 0)return t;let r=gp.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function Di(e,t){yp(e.pty,t),Ei(e.terminal,t)}function vn(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function yp(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Pp(){return mp("node-pty")}function Sp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Ee(t[0],r),...t.slice(1)].map($i).join(" ")}; exec ${$i(e)} -l`;return{executable:e,args:["-lc",s]}}function $i(e){return`'${e.replaceAll("'","'\\''")}'`}function bp(e){let t={};for(let[r,n]of Object.entries(e))typeof n=="string"&&(t[r]=n);return t.TERM=t.TERM??"xterm-256color",t}function Ip(e,t){for(let r=0;r<En(t,hp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<En(t,kp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<En(t,wp);r+=1)e.write("\x1B[?0u")}function En(e,t){if(t.length===0)return 0;let r=0,n=e.indexOf(t);for(;n!==-1;)r+=1,n=e.indexOf(t,n+t.length);return r}var $n=3;async function Mi(e){let t=jn(e.paths);await jp(t,e.paths,e.spawnDaemon);let r=await qi(t.socketPath),n=new xn(r,e);return await n.ready(),n}async function Oi(e,t={}){let r=jn(e);await Ap(e.runtimeDir,{recursive:!0}),await De(r.socketPath,{force:!0});let n=new An(e,t),s=Ep(o=>n.handleConnection(o));await Wp(s,r.socketPath),await Dp(r.pidPath,String(process.pid),"utf8"),await new Promise(o=>{let i=()=>{n.closeClients(),s.close(()=>o())};n.onShutdown=i,process.once("SIGTERM",i),process.once("SIGINT",i)}),await De(r.socketPath,{force:!0}),await De(r.pidPath,{force:!0}),n.disposeAll()}async function Fi(e){let t=jn(e);return await rr(t.socketPath)?(await Wi(t.socketPath),!0):!1}var xn=class{constructor(t,r){this.socket=t;this.options=r,t.setEncoding("utf8"),t.on("data",n=>this.handleData(String(n))),t.on("error",n=>this.rejectAll(n instanceof Error?n:new Error(String(n)))),t.on("close",()=>{this.closed=!0,this.rejectAll(new Error("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;attachedTabId=null;buffer="";closed=!1;options;async ready(){if((await this.send({type:"ping"})).protocolVersion!==$n)throw new Error("Craig PTY daemon protocol mismatch.")}async ensureSession(t,r,n){let s=await this.send({type:"ensureSession",taskId:t,tabId:r,size:n,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r;let o=s.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,o),o}async hydrateSessions(t){for(let r of t)try{let n=await this.send({type:"hydrateSession",tabId:r});n.view&&this.viewCache.set(r,n.view)}catch(n){let s=n instanceof Error?n.message:String(n);this.viewCache.set(r,{status:"failed",rows:[],error:s})}}async pruneStale(t){await this.send({type:"pruneStale",keepTabIds:t})}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){this.send({type:"scrollViewport",lines:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}resize(t){this.send({type:"resize",size:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}disposeSession(t){this.viewCache.delete(t),this.attachedTabId===t&&(this.attachedTabId=null),this.send({type:"disposeSession",tabId:t}).catch(()=>{})}disposeAll(){this.attachedTabId=null,!this.closed&&(this.socket.end(),this.closed=!0)}getViewState(t){return t?this.viewCache.get(t)??{status:"idle",rows:[],error:null,scrolledBack:!1}:{status:"idle",rows:[],error:null,scrolledBack:!1}}async requestShutdown(){await this.send({type:"shutdown"})}async send(t){if(this.closed)throw new Error("Craig PTY daemon connection is closed.");let r=this.nextRequestId;this.nextRequestId+=1;let n={...t,id:r},s=new Promise((i,a)=>{this.pending.set(r,{resolve:i,reject:a})});if(this.socket.destroyed)throw this.pending.delete(r),new Error("Craig PTY daemon connection is closed.");this.socket.write(`${JSON.stringify(n)}
147
147
  `);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
148
148
  `);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
149
- `)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},En=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new er({...r,workspaceRoot:t.workspaceRoot,onUpdate:n=>this.broadcastUpdate(n)})}handleConnection(t){let r="";this.clients.add(t),t.setEncoding("utf8"),t.on("data",n=>{r+=String(n);let s=r.indexOf(`
149
+ `)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},An=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new er({...r,workspaceRoot:t.workspaceRoot,onUpdate:n=>this.broadcastUpdate(n)})}handleConnection(t){let r="";this.clients.add(t),t.setEncoding("utf8"),t.on("data",n=>{r+=String(n);let s=r.indexOf(`
150
150
  `);for(;s!==-1;){let o=r.slice(0,s);r=r.slice(s+1),this.handleLine(t,o),s=r.indexOf(`
151
- `)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{tr(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(n);tr(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:An}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);tr(t,{id:n.id,ok:!1,error:o})}}handleRequest(t){switch(t.type){case"ping":return null;case"ensureSession":return this.attachedTabId=t.tabId,this.runtime.ensureSession(t.taskId,t.tabId,t.size,t.spec);case"hydrateSession":return this.runtime.getViewState(t.tabId);case"write":return this.runtime.write(t.input),null;case"writeKey":return this.runtime.writeKey(t.key),null;case"scrollViewport":return this.runtime.scrollViewport(t.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(t.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(t.tabId),this.attachedTabId===t.tabId&&(this.attachedTabId=null),null;case"pruneStale":{let r=new Set(t.keepTabIds);for(let n of this.runtime.sessionTabIds())r.has(n)||(this.runtime.disposeSession(n),this.attachedTabId===n&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(t.tabId);case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return Np(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients)tr(n,{type:"update",tabId:t,view:r})}};function Dn(e){let t=Ip("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:He.join(Ap(),`craig-${t}.sock`),pidPath:He.join(e.runtimeDir,"pty-daemon.pid")}}async function Dp(e,t,r){if(await $p(e.socketPath,1e3))return;await rr(e.socketPath)&&(await Wi(e.socketPath),await ji(e.socketPath,1e3)),await rr(e.socketPath)&&(await Mp(e),await ji(e.socketPath,1e3)),await Lp(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=jp(n),l=vp(He.join(t.runtimeDir,"pty-daemon.log"),"a");Sp(i,a,{cwd:n,detached:!0,stdio:["ignore",l,l],env:process.env}).unref()}let s=Date.now();for(;Date.now()-s<5e3;){if(await Ni(e.socketPath))return;await $n(50)}let o=await xn(He.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
152
- ${o.slice(-2e3)}`:""}`)}async function Ni(e){let t=await Op(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===An}async function $p(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Ni(e))return!0;await $n(50)}return!1}function jp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=He.resolve(He.dirname(t),"..","node_modules",".bin","tsx");return{command:Fr("tsx")??n,args:[t,"__craig-daemon",e]}}let r=process.argv.slice(1);return{command:process.execPath,args:[...process.execArgv,...r,"__craig-daemon",e]}}async function Lp(e){let t=await xn(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&qi(r))return}await De(e.socketPath,{force:!0}),await De(e.pidPath,{force:!0})}async function rr(e){let t=await Bi(e).catch(()=>null);return t?(t.end(),!0):!1}async function Wi(e){await _i(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Mp(e){let t=await xn(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!qi(r)){await De(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await De(e.socketPath,{force:!0})}}async function Op(e){return _i(e,{id:1,type:"ping"})}function _i(e,t){return new Promise((r,n)=>{let s=Li(e),o="",i=setTimeout(()=>{s.destroy(),n(new Error("Craig PTY daemon request timed out."))},500),a=()=>clearTimeout(i);s.setEncoding("utf8"),s.once("connect",()=>s.write(`${JSON.stringify(t)}
151
+ `)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{tr(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(n);tr(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:$n}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);tr(t,{id:n.id,ok:!1,error:o})}}handleRequest(t){switch(t.type){case"ping":return null;case"ensureSession":return this.attachedTabId=t.tabId,this.runtime.ensureSession(t.taskId,t.tabId,t.size,t.spec);case"hydrateSession":return this.runtime.getViewState(t.tabId);case"write":return this.runtime.write(t.input),null;case"writeKey":return this.runtime.writeKey(t.key),null;case"scrollViewport":return this.runtime.scrollViewport(t.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(t.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(t.tabId),this.attachedTabId===t.tabId&&(this.attachedTabId=null),null;case"pruneStale":{let r=new Set(t.keepTabIds);for(let n of this.runtime.sessionTabIds())r.has(n)||(this.runtime.disposeSession(n),this.attachedTabId===n&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(t.tabId);case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return _p(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients)tr(n,{type:"update",tabId:t,view:r})}};function jn(e){let t=vp("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:He.join($p(),`craig-${t}.sock`),pidPath:He.join(e.runtimeDir,"pty-daemon.pid")}}async function jp(e,t,r){if(await Lp(e.socketPath,1e3))return;await rr(e.socketPath)&&(await Wi(e.socketPath),await ji(e.socketPath,1e3)),await rr(e.socketPath)&&(await Fp(e),await ji(e.socketPath,1e3)),await Op(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=Mp(n),l=xp(He.join(t.runtimeDir,"pty-daemon.log"),"a");Cp(i,a,{cwd:n,detached:!0,stdio:["ignore",l,l],env:process.env}).unref()}let s=Date.now();for(;Date.now()-s<5e3;){if(await Ni(e.socketPath))return;await Ln(50)}let o=await Dn(He.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
152
+ ${o.slice(-2e3)}`:""}`)}async function Ni(e){let t=await Np(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===$n}async function Lp(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Ni(e))return!0;await Ln(50)}return!1}function Mp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=He.resolve(He.dirname(t),"..","node_modules",".bin","tsx");return{command:Fr("tsx")??n,args:[t,"__craig-daemon",e]}}let r=process.argv.slice(1);return{command:process.execPath,args:[...process.execArgv,...r,"__craig-daemon",e]}}async function Op(e){let t=await Dn(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Bi(r))return}await De(e.socketPath,{force:!0}),await De(e.pidPath,{force:!0})}async function rr(e){let t=await qi(e).catch(()=>null);return t?(t.end(),!0):!1}async function Wi(e){await _i(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Fp(e){let t=await Dn(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!Bi(r)){await De(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await De(e.socketPath,{force:!0})}}async function Np(e){return _i(e,{id:1,type:"ping"})}function _i(e,t){return new Promise((r,n)=>{let s=Li(e),o="",i=setTimeout(()=>{s.destroy(),n(new Error("Craig PTY daemon request timed out."))},500),a=()=>clearTimeout(i);s.setEncoding("utf8"),s.once("connect",()=>s.write(`${JSON.stringify(t)}
153
153
  `)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let c=o.indexOf(`
154
- `);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(p){n(p instanceof Error?p:new Error(String(p)))}}),s.once("close",()=>a())})}async function ji(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await rr(e))return;await $n(50)}}function Bi(e){return new Promise((t,r)=>{let n=Li(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Fp(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function tr(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
155
- `)}catch{}}function qi(e){try{return process.kill(e,0),!0}catch{return!1}}function $n(e){return new Promise(t=>setTimeout(t,e))}function Np(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var jn=["Runners","Error Log","Help"];function Ln(e,t){return x.map(r=>{let n=g.runners.getProfile(r),s=e.runners?.[r]?.enabled!==!1,o=e.runners?.[r]?.path?.trim(),i=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:o&&o.length>0?o:`default (${n.executable})`;return`${n.displayName} ${s?"enabled":"disabled"} ${i}`})}function Ki(e){return e.message?e.message:e.pathEdit?"Type an executable path. Enter saves. Empty resets to default. Esc cancels.":"Enter toggles. E edits the executable path."}function Vi(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(jn.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Mn(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Gi(e,t,r,n){if(e.pathEdit)return Wp({...e,pathEdit:e.pathEdit},t,r);let s=Ln(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(s-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let a=x[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Mn(r))return{kind:"noop",state:e};let o=x[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${g.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Wp(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Ui({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Mn(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Ui({...e,message:s.length>0?`${g.runners.getProfile(n).displayName} executable saved.`:`${g.runners.getProfile(n).displayName} executable reset to default.`})}}return _p(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Ui(e){let t={...e};return delete t.pathEdit,t}function Mn(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
156
- `}function _p(e){return e.length===1&&e>=" "&&e!==""}import Tt from"node:path";function Hi(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"\u{F06E6} ";case"js":case"jsx":case"mjs":case"cjs":return"\u{F031E} ";case"json":case"jsonc":return"\u{F0871} ";case"md":case"mdx":return"\u{F0354} ";case"yaml":case"yml":return"\u{F0B10} ";case"sh":case"bash":case"zsh":return"\u{F018D} ";case"css":case"scss":case"sass":return"\u{F031C} ";case"html":case"htm":return"\u{F031D} ";case"py":return"\u{F0320} ";case"go":return"\u{F07D3} ";case"rs":return"\u{F1617} ";case"lock":return"\u{F033E} ";case"png":case"jpg":case"jpeg":case"gif":case"svg":case"webp":return"\u{F02E9} ";default:return"\u{F0214} "}}var zi="\u{F024B} ",Yi="\u{F0DCF} ",Qi="\u25CB",On="\uEA64",Ji="\uEAFE",Xi="\uEBDA",Fn="\u25CB",Nn="\u25CF",Wn="\u2713",_n="\u2715";function Zi(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"4fc1ff";case"js":case"jsx":case"mjs":case"cjs":return"f7df1e";case"json":case"jsonc":return"fbc02d";case"md":case"mdx":return"519aba";case"yaml":case"yml":return"e06c75";case"sh":case"bash":case"zsh":return"89e051";case"css":case"scss":case"sass":return"c792ea";case"html":case"htm":return"e06c75";case"py":return"3572a5";case"go":return"00add8";case"rs":return"dea584";case"lock":return"565f89";default:return}}var sr="empty",O={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function na(e,t){let r=Up(t,e),n=t.repos.find(P=>P.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(P=>P.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(P=>P.repoId===n.id):[],i=o.find(P=>P.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=If(t.tasks),c=Gp(e,i),d=Vp(e,i,c),p=d.find(P=>P.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,u=n?.name??"no repo",w=i?g.runners.getDisplayName(i.runner):g.runners.getDisplayName(e.selectedRunner);return{inputMode:e.inputMode,modalInput:e.taskPromptInput!==null||e.workspaceBrowser!==null,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,footerToast:e.footerToast,terminal:e.terminal,footerText:e.workspaceBrowser!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${n?`[${n.name}]`:"[no repo]"} \xB7 ${g.runners.getDisplayName(e.selectedRunner)} Ctrl+R switch runner Enter create Esc cancel \u203A ${e.taskPromptInput}${e.taskPromptError?` \u2717 ${e.taskPromptError}`:""}`:e.inputMode==="terminal"?"TERMINAL \u2191\u2193/PgUp/PgDn scroll Ctrl+] return to control":e.focusedRegion==="tasks"?e.selectedLeftItemId?.startsWith("new-task:")||e.selectedLeftItemId?.startsWith("new-task-workspace:")?`r runner [${g.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Kt(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":e.selectedLeftItemId?.startsWith("workspace:")?"n new task Enter select X remove workspace Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?i===null?"n new task Tab tasks Esc pause ? help":c===I?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${g.runners.getDisplayName(e.centerTabRunner??i?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?a?"\u2191\u2193 targets Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?"\u2191\u2193 navigate Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:Tt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Tt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Bp(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(P=>Cf(P,l[P])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:u,agent:w},centerTranscript:Kp(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Sf(n,i),rightInspection:of(e,i,f)}}function Bp(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return qp(r,e,t.repos,t.tasks);let n=t.workspaces;if(n.length===0)r.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let o of n){let i=e.selectedLeftItemId===`workspace:${o.id}`;r.push({id:`workspace:${o.id}`,text:`${o.kind==="project"?"\u2261":"\u2013"} ${o.name??o.id}`,selected:i,focused:i&&e.focusedRegion==="tasks"});let a=o.kind==="project"?o.discoveredRepoIds??[]:[o.primaryRepoId],l=t.tasks.filter(c=>c.workspaceId===o.id);if(l.length===0)r.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of l){let d=e.selectedLeftItemId===`task:${c.id}`,p=d?"\u25B8":"\u2022",f=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,u={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},w=oa(c);w&&(u.prBadge=w),r.push(u)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${g.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}if(o.kind==="repo"){let c=`new-task:${o.primaryRepoId}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Task [${g.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}else{r.push({text:` Repos (${a.length})`,indent:0,muted:!0});for(let c of a.slice(0,6)){let d=t.repos.find(p=>p.id===c);r.push({text:` \xB7 ${d?.name??c}`,indent:0,muted:!0})}a.length>6&&r.push({text:` \xB7 ${a.length-6} more`,indent:0,muted:!0})}}let s=e.selectedLeftItemId==="new-workspace";return r.push({text:"",muted:!0}),r.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&e.focusedRegion==="tasks"}),r}function qp(e,t,r,n){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let o of r){let i=t.selectedLeftItemId===`repo:${o.id}`;e.push({id:`repo:${o.id}`,text:`\u2013 ${o.name}`,selected:i,focused:i&&t.focusedRegion==="tasks"});let a=n.filter(d=>d.repoId===o.id);if(a.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of a){let p=t.selectedLeftItemId===`task:${d.id}`,f=p?"\u25B8":"\u2022",u=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,w={id:`task:${d.id}`,taskId:d.id,text:`${f} ${u}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},P=oa(d);P&&(w.prBadge=P),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${g.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let s=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&t.focusedRegion==="tasks"}),e}function Up(e,t){let r=e.workspaces??[];if(!e.workspaces)return null;let n=e.tasks.find(s=>s.id===t.selectedTaskId)??null;return n?r.find(s=>s.id===n.workspaceId)??null:t.selectedWorkspaceId?r.find(s=>s.id===t.selectedWorkspaceId)??null:r[0]??null}function Kp(e,t,r,n,s,o=null,i=null){if(s){let l=s.entries.length===0?["No directories or git repos here."]:s.entries.map((c,d)=>{let p=d===s.selectedIndex?"\u25B8":" ",f=c.kind==="repo"?" [git repo]":"/";return`${p} ${c.name}${f}`});return te(["Browse for a workspace to register.",s.cwd,"",...l,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return te(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return te([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${g.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?te([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this PTY-backed agent session.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):te([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this plain task shell.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):e===I&&t.openInspectionKind==="file"?Yp(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?Qp(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?te(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):te(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Vp(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:Hp(o)}))??[];if(!t)return[{id:sr,label:"EMPTY",active:r===sr,focused:e.focusedRegion==="center"&&r===sr}];let s=e.openInspectionKind||r===I?[{id:I,label:zp(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function Gp(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===I&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??I:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??I:sr}function Hp(e){return e.title.toUpperCase()}function zp(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Tt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Yp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return te(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=sa(n.path??n.title);return[{text:n.title},{text:`${n.byteLength===null?"size unknown":`${n.byteLength} bytes`} \xB7 ${n.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...Jp(n.lines,r,s)]}function Qp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return te(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=sa(n.path??n.title);return[{text:n.title},{text:`${t.diffPaths.length} changed files \xB7 ${n.lines.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...Xp(n.lines,r,s)]}function te(e){return e.map(t=>({text:t}))}function Jp(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:O.lineNumber}},{text:" \u2502 ",style:{fg:O.gutter}},...Bn(o,r)],tone:"default"}})}function Xp(e,t,r){let n=Zp(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>ef(o,r))}function Zp(e){let t=[],r=0,n=0;for(let s of e){let o=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(s);if(o){r=Number.parseInt(o[1]??"0",10),n=Number.parseInt(o[2]??"0",10);continue}if(!(s.startsWith("diff --git")||s.startsWith("index ")||s.startsWith("+++ ")||s.startsWith("--- "))&&!(s==="staged"||s==="unstaged"||s==="untracked")){if(s.startsWith("-")&&!s.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:s.slice(1),kind:"delete"}),r+=1;continue}if(s.startsWith("+")&&!s.startsWith("+++")){t.push({oldNumber:null,newNumber:n,marker:"+",text:s.slice(1),kind:"add"}),n+=1;continue}if(s.startsWith(" ")){if(r===0&&n===0)continue;t.push({oldNumber:r,newNumber:n,marker:" ",text:s.slice(1),kind:"context"}),r+=1,n+=1;continue}}}return t}function ef(e,t){let r=ea(e.oldNumber),n=ea(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:O.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:O.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?rf(Bn(e.text,t),o.bg,o.fallbackFg):Bn(e.text,t),l=o?{fg:O.lineNumber,bg:o.bg}:{fg:O.lineNumber},c=o?{fg:O.gutter,bg:o.bg}:{fg:O.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function ea(e){return e===null?" ":String(e).padStart(4," ")}function sa(e){let t=Tt.extname(e).toLowerCase();return[".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(t)?"javascript":[".json",".jsonc"].includes(t)?"json":[".md",".mdx"].includes(t)?"markdown":[".css",".scss"].includes(t)?"css":"plain"}function Bn(e,t){return t==="diff"?tf(e):t==="markdown"?nf(e):t==="json"?qn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?qn(e,/("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)|\/\/.*$|\/\*.*?\*\/|\b(const|let|var|function|return|if|else|for|while|class|interface|type|import|export|from|async|await|new|extends|implements|switch|case|break|continue|try|catch|throw|true|false|null|undefined)\b|-?\b\d+(?:\.\d+)?\b/g):[{text:e}]}function tf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:O.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:O.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:O.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:O.diffMeta}}]:[{text:e}]}function rf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function nf(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:O.markup,bold:!0}}]:qn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function qn(e,t){let r=[],n=0;for(let s of e.matchAll(t)){let o=s[0],i=s.index??0;i>n&&r.push({text:e.slice(n,i)}),r.push({text:o,style:sf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function sf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:O.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:O.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:O.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:O.markup}:{fg:O.keyword}}function of(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?ia(t.repoTargets??[]):s?.pullRequest??(t?v(t):null),i=[af(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ca(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Rf(e,r)]}:{title:"",rows:[...i,...yf(e,r)]}}function af(e,t){let r=e.inspectionMode,n=[{label:"CHANGES",active:r==="diff"},{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=Un(t),i=Kn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function ta(e){return[{text:" "},Un(e),{text:" "},Kn(e)]}function oa(e){if(e.type==="project"&&e.repoTargets?.length){let r=ia(e.repoTargets);return r?ta(r):null}let t=v(e);return t?.number?ta(t):null}function ia(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=cf(r);return{number:-1,status:lf(r),draft:r.some(s=>s.draft),mergeable:r.length===t.length&&r.every(s=>s.mergeable),mergeStateStatus:null,reviewDecision:r.some(s=>s.reviewDecision==="CHANGES_REQUESTED")?"CHANGES_REQUESTED":r.some(s=>s.reviewDecision==="REVIEW_REQUIRED")?"REVIEW_REQUIRED":r.every(s=>s.reviewDecision==="APPROVED")?"APPROVED":null,requiredChecks:r.flatMap(s=>s.requiredChecks),aggregateReadiness:n}}function lf(e){return e.some(t=>t.status==="open")?"open":e.every(t=>t.status==="merged")?"merged":e.some(t=>t.status==="closed")?"closed":e[0]?.status??null}function cf(e){let t=e.map(r=>aa(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function Un(e){return!e||!e.number?{text:Qi,style:{fg:"565f89"}}:e.status==="merged"?{text:Ji,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Xi,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:On,style:{fg:"565f89"}}:{text:On,style:{fg:"9ece6a"}}}function Kn(e){return e?.aggregateReadiness?ra(e.aggregateReadiness):ra(aa(e))}function ra(e){return e==="failed"?{text:_n,style:{fg:"f7768e"}}:e==="pending"?{text:Nn,style:{fg:"e0af68"}}:e==="success"?{text:Wn,style:{fg:"9ece6a"}}:{text:Fn,style:{fg:"565f89"}}}function aa(e){let t=e?.requiredChecks??null;return e?.status==="merged"?"success":e?.status==="closed"||!e?.number||!t||t.length===0?"none":t.some(r=>r.status==="failed")||e.reviewDecision==="CHANGES_REQUESTED"?"failed":t.every(r=>r.status==="success"||r.status==="skipped")?la(e)?"failed":df(e)?"success":"pending":"pending"}function df(e){return!!(e.mergeable&&!e.draft&&!la(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function la(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function ca(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return uf(e,t);let r=v(t),n=ua("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),pf(n,e)}var nr=32;function uf(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let p=i.failureReason?i.failureReason.slice(0,14):i.status,f=nr-p.length-1,u=c.length>f?c.slice(0,f-1)+"\u2026":c,w=nr-u.length-p.length;r.push({id:`project-review:${i.repoId}`,text:u+" ".repeat(Math.max(1,w))+p,selected:a,focused:l,muted:!0})}else{let d=Un(i.pullRequest),p=Kn(i.pullRequest),f=`${d.text} ${p.text}`,u=nr-f.length-1,w=c.length>u?c.slice(0,u-1)+"\u2026":c,P=nr-w.length-f.length,D=w+" ".repeat(Math.max(1,P));r.push({id:`project-review:${i.repoId}`,text:D+f,selected:a,focused:l,segments:[{text:D},{...d,text:d.text},{text:" "},{...p,text:p.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...ua("target",o.branch,o.pullRequest))),r}function da(e,t){return ca(e,t).length}function ua(e,t,r){let n=p=>`${e}-${p}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=ff(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:mf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${pa(r.lastSyncedAt)}`,muted:!0}),s.push({id:n("checks-spacer"),text:""}),s.push({id:n("checks-header"),text:"Checks"}),r.requiredChecks.length?s.push(...r.requiredChecks.map(gf)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((p,f)=>hf(p,n(`comment:${f}`))))),s}function pf(e,t){if(t.focusedRegion!=="inspector"||t.inspectionMode!=="review"||e.length===0)return e;let r=Math.max(0,Math.min(t.reviewScrollOffset,e.length-1));return e.map((n,s)=>({...n,selected:t.reviewScrollOffset===0&&n.selected||s===r,focused:t.reviewScrollOffset===0&&n.focused||s===r}))}function ff(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function mf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function pa(e){if(!e)return"--";let t=Date.now()-new Date(e).getTime(),r=Math.floor(t/1e3);if(r<60)return`${r}s ago`;let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let s=Math.floor(n/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function gf(e){let{icon:t,color:r}=wf(e.status),n=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${n.padEnd(16," ")} ${Tf(e.status)}`,color:r,muted:!1}}function hf(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${pa(e.createdAt)}`:"",s=kf(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function kf(e,t){let r=e.split(/\s+/).filter(Boolean);if(r.length===0)return[];let n=[],s="";for(let o of r){if(!s){s=o;continue}`${s} ${o}`.length<=t?s=`${s} ${o}`:(n.push(s),s=o)}return s&&n.push(s),n}function wf(e){switch(e){case"success":return{icon:Wn,color:"9ece6a"};case"pending":return{icon:Nn,color:"e0af68"};case"failed":return{icon:_n,color:"f7768e"};case"skipped":return{icon:Fn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Tf(e){return e==="success"?"passing":e==="failed"?"failing":e}function Rf(e,t){if(!t)return[{id:"empty",text:"No file index. Select a task with local changes.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.fileRows.length===0)return[{id:"empty",text:"No Git-visible files.",muted:!0}];let r=new Map(t.diffRows.map(o=>[o.path,o.status])),n=Vn(t.fileRows,e.collapsedFileTreePaths),s=e.selectedFileTreePath??t.selectedFilePath;return n.map(o=>{let i=o.kind==="file"?r.get(o.path):void 0,a=i==="A"?"9ece6a":i==="M"?"e0af68":i==="D"?"f7768e":i==="??"?"565f89":void 0,l=o.kind==="directory"?e.collapsedFileTreePaths.includes(o.path)?zi:Yi:Hi(o.label),c=o.kind==="directory"?"7aa2f7":Zi(o.label),d=" ".repeat(o.depth),p=c?{text:l,style:{fg:c}}:{text:l},f=o.kind==="directory"?{text:o.label,style:{fg:"7aa2f7"}}:a?{text:o.label,style:{fg:a}}:{text:o.label},u=[{text:d},p,f];return{id:o.path,text:`${d}${l}${o.label}`,selected:o.path===s,focused:o.path===s&&e.focusedRegion==="inspector",segments:u}})}function Vn(e,t){let r=new Set(t);return e.filter(n=>{let s=n.path.split("/");for(let o=1;o<s.length;o+=1)if(r.has(s.slice(0,o).join("/")))return!1;return!0})}function yf(e,t){if(!t)return[{id:"empty",text:"No task diff index.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.diffRows.length===0)return[{id:"empty",text:t.filePaths.some(s=>s.startsWith("repo_"))?"No changes in project task worktrees. Edits in the original repos are outside this task.":"No local changes.",muted:!0}];if(Pf(t))return bf(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>fa(o,e,t))))}return r}function Pf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function bf(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>fa(c,e,t,s.length+1))))}}return r}function fa(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Sf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:g.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Tt.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function If(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Cf(e,t){return{name:g.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as vf,mkdir as Ef,readFile as xf}from"node:fs/promises";import Af from"node:path";var ma=80,Gn=async(e,t)=>{await Ef(Af.dirname(e.errorLogFile),{recursive:!0}),await vf(e.errorLogFile,Df(t),"utf8")},ga=async(e,t)=>{try{await Gn(e,t)}catch{}},Hn=async(e,t=ma)=>{try{let n=(await xf(e.errorLogFile,"utf8")).trimEnd().split(`
157
- `).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if($f(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},ha=async(e,t=ma)=>Hn(e,t);function Df(e){let r=[`[${new Date().toISOString()}] ${e.context}`,`message: ${e.message}`];return e.details&&e.details.trim().length>0&&(r.push("details:"),r.push(...e.details.trimEnd().split(`
154
+ `);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(p){n(p instanceof Error?p:new Error(String(p)))}}),s.once("close",()=>a())})}async function ji(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await rr(e))return;await Ln(50)}}function qi(e){return new Promise((t,r)=>{let n=Li(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Wp(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function tr(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
155
+ `)}catch{}}function Bi(e){try{return process.kill(e,0),!0}catch{return!1}}function Ln(e){return new Promise(t=>setTimeout(t,e))}function _p(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var Mn=["Runners","Error Log","Help"];function On(e,t){return x.map(r=>{let n=h.runners.getProfile(r),s=e.runners?.[r]?.enabled!==!1,o=e.runners?.[r]?.path?.trim(),i=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:o&&o.length>0?o:`default (${n.executable})`;return`${n.displayName} ${s?"enabled":"disabled"} ${i}`})}function Ki(e){return e.message?e.message:e.pathEdit?"Type an executable path. Enter saves. Empty resets to default. Esc cancels.":"Enter toggles. E edits the executable path."}function Vi(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(Mn.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Fn(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Gi(e,t,r,n){if(e.pathEdit)return qp({...e,pathEdit:e.pathEdit},t,r);let s=On(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(s-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let a=x[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Fn(r))return{kind:"noop",state:e};let o=x[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${h.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function qp(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Ui({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Fn(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Ui({...e,message:s.length>0?`${h.runners.getProfile(n).displayName} executable saved.`:`${h.runners.getProfile(n).displayName} executable reset to default.`})}}return Bp(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Ui(e){let t={...e};return delete t.pathEdit,t}function Fn(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
156
+ `}function Bp(e){return e.length===1&&e>=" "&&e!==""}import Tt from"node:path";function Hi(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"\u{F06E6} ";case"js":case"jsx":case"mjs":case"cjs":return"\u{F031E} ";case"json":case"jsonc":return"\u{F0871} ";case"md":case"mdx":return"\u{F0354} ";case"yaml":case"yml":return"\u{F0B10} ";case"sh":case"bash":case"zsh":return"\u{F018D} ";case"css":case"scss":case"sass":return"\u{F031C} ";case"html":case"htm":return"\u{F031D} ";case"py":return"\u{F0320} ";case"go":return"\u{F07D3} ";case"rs":return"\u{F1617} ";case"lock":return"\u{F033E} ";case"png":case"jpg":case"jpeg":case"gif":case"svg":case"webp":return"\u{F02E9} ";default:return"\u{F0214} "}}var zi="\u{F024B} ",Qi="\u{F0DCF} ",Yi="\u25CB",Nn="\uEA64",Ji="\uEAFE",Xi="\uEBDA",Wn="\u25CB",_n="\u25CF",qn="\u2713",Bn="\u2715";function Zi(e){switch(e.toLowerCase().split(".").pop()??""){case"ts":case"tsx":return"4fc1ff";case"js":case"jsx":case"mjs":case"cjs":return"f7df1e";case"json":case"jsonc":return"fbc02d";case"md":case"mdx":return"519aba";case"yaml":case"yml":return"e06c75";case"sh":case"bash":case"zsh":return"89e051";case"css":case"scss":case"sass":return"c792ea";case"html":case"htm":return"e06c75";case"py":return"3572a5";case"go":return"00add8";case"rs":return"dea584";case"lock":return"565f89";default:return}}var sr="empty",O={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function na(e,t){let r=Vp(t,e),n=t.repos.find(R=>R.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(R=>R.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(R=>R.repoId===n.id):[],i=o.find(R=>R.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=vf(t.tasks),c=zp(e,i),d=Hp(e,i,c),p=d.find(R=>R.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,u=n?.name??"no repo",w=i?h.runners.getDisplayName(i.runner):h.runners.getDisplayName(e.selectedRunner);return{inputMode:e.inputMode,modalInput:e.taskPromptInput!==null||e.workspaceBrowser!==null,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,footerToast:e.footerToast,terminal:e.terminal,footerText:e.workspaceBrowser!==null?e.workspaceBrowser.query!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} Search: ${e.workspaceBrowser.query} \u2191\u2193 move Enter select Esc clear search`:`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up / search Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${n?`[${n.name}]`:"[no repo]"} \xB7 ${h.runners.getDisplayName(e.selectedRunner)} Ctrl+R switch runner Enter create Esc cancel \u203A ${e.taskPromptInput}${e.taskPromptError?` \u2717 ${e.taskPromptError}`:""}`:e.inputMode==="terminal"?"TERMINAL \u2191\u2193/PgUp/PgDn scroll Ctrl+] return to control":e.focusedRegion==="tasks"?e.selectedLeftItemId?.startsWith("new-task:")||e.selectedLeftItemId?.startsWith("new-task-workspace:")?`r runner [${h.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Kt(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":e.selectedLeftItemId?.startsWith("workspace:")?"n new task Enter select X remove workspace Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?i===null?"n new task Tab tasks Esc pause ? help":c===I?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${h.runners.getDisplayName(e.centerTabRunner??i?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?a?"\u2191\u2193 targets Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:Tt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Tt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Up(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(R=>Ef(R,l[R])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:u,agent:w},centerTranscript:Gp(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Cf(n,i),rightInspection:lf(e,i,f)}}function Up(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Kp(r,e,t.repos,t.tasks);let n=t.workspaces;if(n.length===0)r.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let o of n){let i=e.selectedLeftItemId===`workspace:${o.id}`;r.push({id:`workspace:${o.id}`,text:`${o.kind==="project"?"\u2261":"\u2013"} ${o.name??o.id}`,selected:i,focused:i&&e.focusedRegion==="tasks"});let a=o.kind==="project"?o.discoveredRepoIds??[]:[o.primaryRepoId],l=t.tasks.filter(c=>c.workspaceId===o.id);if(l.length===0)r.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of l){let d=e.selectedLeftItemId===`task:${c.id}`,p=d?"\u25B8":"\u2022",f=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,u={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},w=oa(c);w&&(u.prBadge=w),r.push(u)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}if(o.kind==="repo"){let c=`new-task:${o.primaryRepoId}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Task [${h.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks",muted:!d})}else{r.push({text:` Repos (${a.length})`,indent:0,muted:!0});for(let c of a.slice(0,6)){let d=t.repos.find(p=>p.id===c);r.push({text:` \xB7 ${d?.name??c}`,indent:0,muted:!0})}a.length>6&&r.push({text:` \xB7 ${a.length-6} more`,indent:0,muted:!0})}}let s=e.selectedLeftItemId==="new-workspace";return r.push({text:"",muted:!0}),r.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&e.focusedRegion==="tasks"}),r}function Kp(e,t,r,n){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let o of r){let i=t.selectedLeftItemId===`repo:${o.id}`;e.push({id:`repo:${o.id}`,text:`\u2013 ${o.name}`,selected:i,focused:i&&t.focusedRegion==="tasks"});let a=n.filter(d=>d.repoId===o.id);if(a.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of a){let p=t.selectedLeftItemId===`task:${d.id}`,f=p?"\u25B8":"\u2022",u=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,w={id:`task:${d.id}`,taskId:d.id,text:`${f} ${u}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},R=oa(d);R&&(w.prBadge=R),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${h.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let s=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:s,focused:s&&t.focusedRegion==="tasks"}),e}function Vp(e,t){let r=e.workspaces??[];if(!e.workspaces)return null;let n=e.tasks.find(s=>s.id===t.selectedTaskId)??null;return n?r.find(s=>s.id===n.workspaceId)??null:t.selectedWorkspaceId?r.find(s=>s.id===t.selectedWorkspaceId)??null:r[0]??null}function Gp(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(p=>p.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((p,f)=>{let u=f===s.selectedIndex?"\u25B8":" ",w=p.kind==="repo"?" [git repo]":"/";return`${u} ${p.name}${w}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return te(["Browse for a workspace to register.",s.cwd,...d?[d]:[],"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return te(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return te([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${h.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?te([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this PTY-backed agent session.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):te([`${a.title} tab ready for ${n.id}.`,"","Press Enter to attach this plain task shell.","Use + to create another task tab, a/t for a specific kind, or x to close this tab."]):e===I&&t.openInspectionKind==="file"?Jp(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?Xp(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?te(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):te(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Hp(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:Qp(o)}))??[];if(!t)return[{id:sr,label:"EMPTY",active:r===sr,focused:e.focusedRegion==="center"&&r===sr}];let s=e.openInspectionKind||r===I?[{id:I,label:Yp(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function zp(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===I&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??I:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??I:sr}function Qp(e){return e.title.toUpperCase()}function Yp(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Tt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Jp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return te(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=sa(n.path??n.title);return[{text:n.title},{text:`${n.byteLength===null?"size unknown":`${n.byteLength} bytes`} \xB7 ${n.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...Zp(n.lines,r,s)]}function Xp(e,t,r){if(!e)return te(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return te(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=sa(n.path??n.title);return[{text:n.title},{text:`${t.diffPaths.length} changed files \xB7 ${n.lines.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...ef(n.lines,r,s)]}function te(e){return e.map(t=>({text:t}))}function Zp(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:O.lineNumber}},{text:" \u2502 ",style:{fg:O.gutter}},...Un(o,r)],tone:"default"}})}function ef(e,t,r){let n=tf(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>rf(o,r))}function tf(e){let t=[],r=0,n=0;for(let s of e){let o=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(s);if(o){r=Number.parseInt(o[1]??"0",10),n=Number.parseInt(o[2]??"0",10);continue}if(!(s.startsWith("diff --git")||s.startsWith("index ")||s.startsWith("+++ ")||s.startsWith("--- "))&&!(s==="staged"||s==="unstaged"||s==="untracked")){if(s.startsWith("-")&&!s.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:s.slice(1),kind:"delete"}),r+=1;continue}if(s.startsWith("+")&&!s.startsWith("+++")){t.push({oldNumber:null,newNumber:n,marker:"+",text:s.slice(1),kind:"add"}),n+=1;continue}if(s.startsWith(" ")){if(r===0&&n===0)continue;t.push({oldNumber:r,newNumber:n,marker:" ",text:s.slice(1),kind:"context"}),r+=1,n+=1;continue}}}return t}function rf(e,t){let r=ea(e.oldNumber),n=ea(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:O.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:O.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?sf(Un(e.text,t),o.bg,o.fallbackFg):Un(e.text,t),l=o?{fg:O.lineNumber,bg:o.bg}:{fg:O.lineNumber},c=o?{fg:O.gutter,bg:o.bg}:{fg:O.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function ea(e){return e===null?" ":String(e).padStart(4," ")}function sa(e){let t=Tt.extname(e).toLowerCase();return[".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(t)?"javascript":[".json",".jsonc"].includes(t)?"json":[".md",".mdx"].includes(t)?"markdown":[".css",".scss"].includes(t)?"css":"plain"}function Un(e,t){return t==="diff"?nf(e):t==="markdown"?of(e):t==="json"?Kn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Kn(e,/("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)|\/\/.*$|\/\*.*?\*\/|\b(const|let|var|function|return|if|else|for|while|class|interface|type|import|export|from|async|await|new|extends|implements|switch|case|break|continue|try|catch|throw|true|false|null|undefined)\b|-?\b\d+(?:\.\d+)?\b/g):[{text:e}]}function nf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:O.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:O.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:O.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:O.diffMeta}}]:[{text:e}]}function sf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function of(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:O.markup,bold:!0}}]:Kn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Kn(e,t){let r=[],n=0;for(let s of e.matchAll(t)){let o=s[0],i=s.index??0;i>n&&r.push({text:e.slice(n,i)}),r.push({text:o,style:af(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function af(e){return e.startsWith("//")||e.startsWith("/*")?{fg:O.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:O.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:O.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:O.markup}:{fg:O.keyword}}function lf(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?ia(t.repoTargets??[]):s?.pullRequest??(t?v(t):null),i=[cf(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ca(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Pf(e,r)]}:{title:"",rows:[...i,...Sf(e,r)]}}function cf(e,t){let r=e.inspectionMode,n=[{label:"CHANGES",active:r==="diff"},{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=Vn(t),i=Gn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function ta(e){return[{text:" "},Vn(e),{text:" "},Gn(e)]}function oa(e){if(e.type==="project"&&e.repoTargets?.length){let r=ia(e.repoTargets);return r?ta(r):null}let t=v(e);return t?.number?ta(t):null}function ia(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=uf(r);return{number:-1,status:df(r),draft:r.some(s=>s.draft),mergeable:r.length===t.length&&r.every(s=>s.mergeable),mergeStateStatus:null,reviewDecision:r.some(s=>s.reviewDecision==="CHANGES_REQUESTED")?"CHANGES_REQUESTED":r.some(s=>s.reviewDecision==="REVIEW_REQUIRED")?"REVIEW_REQUIRED":r.every(s=>s.reviewDecision==="APPROVED")?"APPROVED":null,requiredChecks:r.flatMap(s=>s.requiredChecks),aggregateReadiness:n}}function df(e){return e.some(t=>t.status==="open")?"open":e.every(t=>t.status==="merged")?"merged":e.some(t=>t.status==="closed")?"closed":e[0]?.status??null}function uf(e){let t=e.map(r=>aa(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function Vn(e){return!e||!e.number?{text:Yi,style:{fg:"565f89"}}:e.status==="merged"?{text:Ji,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Xi,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Nn,style:{fg:"565f89"}}:{text:Nn,style:{fg:"9ece6a"}}}function Gn(e){return e?.aggregateReadiness?ra(e.aggregateReadiness):ra(aa(e))}function ra(e){return e==="failed"?{text:Bn,style:{fg:"f7768e"}}:e==="pending"?{text:_n,style:{fg:"e0af68"}}:e==="success"?{text:qn,style:{fg:"9ece6a"}}:{text:Wn,style:{fg:"565f89"}}}function aa(e){let t=e?.requiredChecks??null;return e?.status==="merged"?"success":e?.status==="closed"||!e?.number||!t||t.length===0?"none":t.some(r=>r.status==="failed")||e.reviewDecision==="CHANGES_REQUESTED"?"failed":t.every(r=>r.status==="success"||r.status==="skipped")?la(e)?"failed":pf(e)?"success":"pending":"pending"}function pf(e){return!!(e.mergeable&&!e.draft&&!la(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function la(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function ca(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return ff(e,t);let r=v(t),n=ua("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),mf(n,e)}var nr=32;function ff(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let p=i.failureReason?i.failureReason.slice(0,14):i.status,f=nr-p.length-1,u=c.length>f?c.slice(0,f-1)+"\u2026":c,w=nr-u.length-p.length;r.push({id:`project-review:${i.repoId}`,text:u+" ".repeat(Math.max(1,w))+p,selected:a,focused:l,muted:!0})}else{let d=Vn(i.pullRequest),p=Gn(i.pullRequest),f=`${d.text} ${p.text}`,u=nr-f.length-1,w=c.length>u?c.slice(0,u-1)+"\u2026":c,R=nr-w.length-f.length,A=w+" ".repeat(Math.max(1,R));r.push({id:`project-review:${i.repoId}`,text:A+f,selected:a,focused:l,segments:[{text:A},{...d,text:d.text},{text:" "},{...p,text:p.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...ua("target",o.branch,o.pullRequest))),r}function da(e,t){return ca(e,t).length}function ua(e,t,r){let n=p=>`${e}-${p}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=gf(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:hf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${pa(r.lastSyncedAt)}`,muted:!0}),s.push({id:n("checks-spacer"),text:""}),s.push({id:n("checks-header"),text:"Checks"}),r.requiredChecks.length?s.push(...r.requiredChecks.map(kf)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((p,f)=>wf(p,n(`comment:${f}`))))),s}function mf(e,t){if(t.focusedRegion!=="inspector"||t.inspectionMode!=="review"||e.length===0)return e;let r=Math.max(0,Math.min(t.reviewScrollOffset,e.length-1));return e.map((n,s)=>({...n,selected:t.reviewScrollOffset===0&&n.selected||s===r,focused:t.reviewScrollOffset===0&&n.focused||s===r}))}function gf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function hf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function pa(e){if(!e)return"--";let t=Date.now()-new Date(e).getTime(),r=Math.floor(t/1e3);if(r<60)return`${r}s ago`;let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let s=Math.floor(n/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function kf(e){let{icon:t,color:r}=Rf(e.status),n=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${n.padEnd(16," ")} ${yf(e.status)}`,color:r,muted:!1}}function wf(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${pa(e.createdAt)}`:"",s=Tf(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function Tf(e,t){let r=e.split(/\s+/).filter(Boolean);if(r.length===0)return[];let n=[],s="";for(let o of r){if(!s){s=o;continue}`${s} ${o}`.length<=t?s=`${s} ${o}`:(n.push(s),s=o)}return s&&n.push(s),n}function Rf(e){switch(e){case"success":return{icon:qn,color:"9ece6a"};case"pending":return{icon:_n,color:"e0af68"};case"failed":return{icon:Bn,color:"f7768e"};case"skipped":return{icon:Wn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function yf(e){return e==="success"?"passing":e==="failed"?"failing":e}function Pf(e,t){if(!t)return[{id:"empty",text:"No file index. Select a task with local changes.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.fileRows.length===0)return[{id:"empty",text:"No Git-visible files.",muted:!0}];let r=new Map(t.diffRows.map(l=>[l.path,l.status])),n=Hn(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,p=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?zi:Qi:Hi(l.label),f=l.kind==="directory"?"7aa2f7":Zi(l.label),u=" ".repeat(l.depth),w=f?{text:p,style:{fg:f}}:{text:p},R=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},A=[{text:u},w,R];return{id:l.path,text:`${u}${p}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:A}})]}function Hn(e,t){let r=new Set(t);return e.filter(n=>{let s=n.path.split("/");for(let o=1;o<s.length;o+=1)if(r.has(s.slice(0,o).join("/")))return!1;return!0})}function Sf(e,t){if(!t)return[{id:"empty",text:"No task diff index.",muted:!0}];if(t.error)return[{id:"error",text:t.error,muted:!0}];if(t.diffRows.length===0)return[{id:"empty",text:t.filePaths.some(s=>s.startsWith("repo_"))?"No changes in project task worktrees. Edits in the original repos are outside this task.":"No local changes.",muted:!0}];if(bf(t))return If(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>fa(o,e,t))))}return r}function bf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function If(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>fa(c,e,t,s.length+1))))}}return r}function fa(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Cf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:h.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Tt.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function vf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Ef(e,t){return{name:h.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as xf,mkdir as Af,readFile as Df}from"node:fs/promises";import $f from"node:path";var ma=80,zn=async(e,t)=>{await Af($f.dirname(e.errorLogFile),{recursive:!0}),await xf(e.errorLogFile,jf(t),"utf8")},ga=async(e,t)=>{try{await zn(e,t)}catch{}},Qn=async(e,t=ma)=>{try{let n=(await Df(e.errorLogFile,"utf8")).trimEnd().split(`
157
+ `).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if(Lf(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},ha=async(e,t=ma)=>Qn(e,t);function jf(e){let r=[`[${new Date().toISOString()}] ${e.context}`,`message: ${e.message}`];return e.details&&e.details.trim().length>0&&(r.push("details:"),r.push(...e.details.trimEnd().split(`
158
158
  `).map(n=>` ${n}`))),`${r.join(`
159
159
  `)}
160
160
 
161
- `}function $f(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ze={appendErrorLog:Gn,appendErrorLogBestEffort:ga,readErrorLog:Hn,readRecentErrorLines:ha};var ka=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await Q(n.paths,e.selectedTaskId),i=t??jf(o,e.activeTab,e.preferredPtyTabKind),a=ya(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await R(n.paths,l),l});return{updatedTask:s,nextShell:{activeTab:s.selectedPtyTabId??e.activeTab,selectedPtyTabId:s.selectedPtyTabId,preferredPtyTabKind:s.ptyTabs.at(-1)?.kind??e.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${s.ptyTabs.at(-1)?.title??"tab"}`}}},wa=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await Q(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await R(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},Ta=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await Q(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await R(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Ra=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await Q(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await R(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=ya(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await Q(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await R(t.paths,{...s,selectedPtyTabId:o.id});return}await R(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function jf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function ya(e,t,r,n={}){let s=r??e.runner,o=g.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(u=>u.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let p=new Date().toISOString(),f=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...f?{runner:f}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?g.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Ye=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Pa=async(e,t,r,n,s)=>{g.runners.assertEnabled(n,s.config);let o=t?await s.taskService.provisionProjectTask(s.paths,t,r,{runner:n,config:s.config}):await s.taskService.provisionTask(s.paths,e??"",r,{runner:n,config:s.config});try{let l=ve();await T(Ee(g.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new Ye(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},ba=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Sa=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await Q(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},Ia=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Ca=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await ze.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var va=async(e,t)=>{if(!e.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await t.taskService.listTasks(t.paths,{workspaceId:e.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${e.selectedWorkspaceId} while task records still reference it.`);return await t.workspaceService.archiveWorkspace(t.paths,e.selectedWorkspaceId),{nextShell:{selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${(await t.workspaceService.removeWorkspace(t.paths,e.selectedWorkspaceId,{listTasks:t.taskService.listTasks})).workspaceId}`}}};var Ea=async(e,t,r)=>{let n=g.runners.setRunnerEnabled(r.config,e,t);return await g.save(r.paths,n),n},xa=async(e,t,r)=>{let n=g.runners.setRunnerPath(r.config,e,t);return await g.save(r.paths,n),n};function pe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function $e(e,t){return ue(t,e.ptyRuntime.getViewState(zn(e,t)))}function zn(e,t){let r=pe(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function m(e,t){return $e(e,ri(t,e.model))}function Aa(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:m(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Da(e,t,r){return Aa(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return Aa(e,t,{tone:"error",message:r})}function L(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return ze.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function A(e,t){if(!e.uiStateFile)return;e.runtimeState=Vo(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>me({uiStateFile:e.uiStateFile},r),()=>me({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Lf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function W(e){return{paths:e.paths,config:e.config,taskService:S,workspaceService:Y,queueTaskMutation:t=>Lf(e,t)}}function Yn(e,t){let r=pe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,o=Vn(s?.fileRows??[],t.collapsedFileTreePaths);return{leftItemIds:ni(e.model),centerTabIds:Jo(r,t),ptyTabIds:r?.ptyTabs.map(i=>i.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:o.map(i=>i.path),fileTreeFileIds:o.filter(i=>i.kind==="file").map(i=>i.path),fileTreeDirectoryIds:o.filter(i=>i.kind==="directory").map(i=>i.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:da(t,r),pageRows:Math.max(5,ee(e.activeTerminal.width,e.activeTerminal.height).height-Z.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(i=>i.repoId)??[]}}async function $a(e,t){await Ta(t,W(e))}async function _(e){e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:m(e,e.state.shell)}:e.state={...e.state,shell:m(e,e.state.shell)}}async function Qn(e,t){let r=++e.inspectionRefreshSequence,n=mn(e.model.tasks,t),s=e.model.inspection,o;if(n&&s?.taskId===n.id){let i={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},a=await So(n,s,i);if(r!==e.inspectionRefreshSequence)return;o={...e.model,inspection:a}}else if(o=await Re(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=o,e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},A(e,e.state.shell),e.render())}function ja(e,t){t!==0&&(e.pendingInspectionScrollLines+=t,!e.inspectionScrollRenderTimer&&(e.inspectionScrollRenderTimer=setTimeout(()=>{e.inspectionScrollRenderTimer=null;let r=e.pendingInspectionScrollLines;if(e.pendingInspectionScrollLines=0,r===0||e.state.mode!=="main"||e.state.shell.inputMode!=="control")return;let n=Te(e.state.shell,r,Yn(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render(),Qn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render()}},16)))}function Jn(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Xn(e){let t=e.model.tasks.flatMap(r=>r.ptyTabs.map(n=>n.id));await e.ptyRuntime.pruneStale?.(t),await e.ptyRuntime.hydrateSessions?.(t)}function Ma(e){Xn(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.render())})}async function Oa(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=zn(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return ue(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));return ue({...r,inputMode:"control"},i)}function Fa(e){let t=e.state.mode==="main"&&e.state.shell.inputMode==="terminal"?"terminal":"control";t!==e.inputCaptureMode&&(e.inputCaptureMode=t,e.activeTerminal.grabInput(t==="terminal"?{mouse:"button"}:!0))}async function Zn(e,t){try{let r=m(e,t),n=pe(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await La(e,n),await _(e),s=n.selectedPtyTabId)}n&&!s&&(n=await La(e,n),await _(e),s=n.selectedPtyTabId);let o=m(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},A(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},i)},A(e,e.state.shell)}catch(r){let n=L(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&wt(t.selectedPtyTabId)&&(await Mf(e,t.selectedTaskId,n).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,Ho(m(e,t),n),n)},A(e,e.state.shell)}e.render()}async function Mf(e,t,r){await ba(t,r,W(e))}async function Na(e,t,r,n){let s=m(e,t),{nextShell:o}=await ka(s,r,n,W(e));return await _(e),m(e,{...s,...o})}async function Wa(e,t){let r=m(e,t),{closedTab:n,nextShell:s}=await wa(r,W(e));return e.ptyRuntime.disposeSession(n.id),await _(e),m(e,{...r,...s})}async function _a(e,t){let r=m(e,t),{closedTabIds:n,nextShell:s}=await Sa(r,W(e));for(let o of n)e.ptyRuntime.disposeSession(o);return await _(e),m(e,{...r,...s})}async function Ba(e,t){let r=m(e,t),{nextShell:n}=await va(r,W(e));return await _(e),m(e,{...r,...n})}async function La(e,t){return Ra(t,W(e))}function or(e,t){e.pendingScrollLines+=t,!e.scrollRenderTimer&&(e.scrollRenderTimer=setTimeout(()=>{e.scrollRenderTimer=null;let r=e.pendingScrollLines;e.pendingScrollLines=0,r!==0&&(e.ptyRuntime.scrollViewport(r),e.state={mode:"main",shell:$e(e,e.state.shell)},e.render())},16))}async function qa(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await Ia(e.model.tasks,W(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:m(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,Ca("background PR polling",t,W(e)))}finally{e.prPollInFlight=!1}}}async function Ua(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await S.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await _(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await S.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await _(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${v(a)?.requiredChecks.length??0} reported`)}return m(e,{...Da(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import _f from"node:path";import{readdir as Of,stat as Ff}from"node:fs/promises";import Ka from"node:path";async function Nf(e){let t=await Of(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Ka.join(e,n.name);r.push({name:n.name,path:s,kind:await Wf(s)?"repo":"directory"})}return r.sort((n,s)=>n.kind!==s.kind?n.kind==="repo"?-1:1:n.name.localeCompare(s.name)),{cwd:e,entries:r,selectedIndex:0,error:null}}async function Va(e){let{spawn:t}=await import("node:child_process"),r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await new Promise((n,s)=>{let o=t(r,[e],{stdio:"ignore",detached:!0});o.unref(),o.on("error",s),o.on("spawn",n)})}async function ir(e,t){let r=await Nf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Wf(e){let t=Ka.join(e,".git");return await Ff(t).catch(()=>null)!==null}function Ga(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Bf(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:m(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Pa(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,W(e));n=s.task,await _(e);let o=m(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??wi(n,"agent"),ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(o.selectedPtyTabId),e.state={mode:"main",shell:ue(o,i)},A(e,e.state.shell)}catch(s){s instanceof Ye&&(n=s.task);let o=L(e,"create task",s,"Failed to create task.");n&&!(s instanceof Ye)?(await R(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})):n&&(await R(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function qf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(oe(t)){Bf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:m(e,{...r,selectedRunner:fn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}zo(t)&&(e.state={mode:"main",shell:m(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Uf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(r){if(t==="ESCAPE"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="UP"||t==="k"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,r.entries.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){ir(e,_f.dirname(r.cwd)).catch(n=>{let s=L(e,"open parent workspace directory",n,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:s}}),s)},e.render()});return}if(t==="RIGHT"||t==="l"||oe(t)){let n=r.entries[r.selectedIndex]??null;if(!n)return;if((t==="RIGHT"||t==="l")&&(n.kind==="directory"||n.kind==="repo")){ir(e,n.path).catch(o=>{let i=L(e,"open workspace directory",o,"Failed to open directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:i}}),i)},e.render()});return}let{workspaceService:s}=W(e);s.addWorkspace(e.paths,n.path).then(async o=>{await _(e);let i=o.repos[0]??null,a=m(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${o.workspace.id}`,selectedWorkspaceId:o.workspace.id,selectedRepoId:i?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${o.workspace.name??o.workspace.id}`});e.state={mode:"main",shell:a},A(e,e.state.shell),e.render()}).catch(o=>{let i=L(e,"add workspace",o,"Failed to add workspace.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:i}}),i)},e.render()})}}}function Kf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Vi(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;Vf(e,n)}}}async function Vf(e,t){let r;try{r=await ze.readRecentErrorLines(e.paths)}catch(n){let s=L(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function Gf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Gi(Ga(e),e.config,t,e.enabledRunnerIds);if(r.kind==="noop")return;if(r.kind==="back"){let s=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...s!==void 0?{parentVariant:s}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,runnerOptions:r.state},e.render();return}(r.kind==="save-enabled"?Ea(r.runner,r.enabled,W(e)):xa(r.runner,r.path,W(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=g.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:m(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:g.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=L(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,m(e,e.state.shell),o),runnerOptions:{...Ga(e),message:o}},e.render()})}function Ha(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){qf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Uf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Hf(e),e.render();return}e.focusFlashUntil!==null&&(e.focusFlashUntil=null,e.focusFlashTimer&&(clearTimeout(e.focusFlashTimer),e.focusFlashTimer=null))}if(e.state.mode==="main"){let n=Go(e.state.shell,r,Yn(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&oe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1),e.lastTerminalKey=Ti(r)?{key:r,at:Date.now()}:null;let s=Ri(r,e.state.shell.terminal.scrolledBack??!1);if(s!==0){or(e,s);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:m(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){ir(e,e.workspaceRoot).catch(s=>{let o=L(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,m(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,error:o}}),o)},e.render()});return}if(n.createPtyTab){Na(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Zn(e,s)}).catch(s=>{let o=L(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Wa(e,n.state).then(s=>{e.state={mode:"main",shell:s},A(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ua(e,n.state).then(s=>{e.state={mode:"main",shell:s},A(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=pe(e.model.tasks,n.state),o=s?v(s)?.url??null:null;o?Va(o).catch(i=>{let a=L(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,m(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,m(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){_a(e,n.state).then(s=>{e.state={mode:"main",shell:s},A(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Ba(e,n.state).then(s=>{e.state={mode:"main",shell:s},A(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){Zn(e,n.state);return}if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},A(e,e.state.shell),e.render(),Qn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:m(e,n.state)},$a(e,e.state.shell).catch(()=>{}),A(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:m(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Kf(e,r);return}if(e.state.variant==="runners"){Gf(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||oe(r)){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render()}return}if(e.state.optionsMessage){(r==="ESCAPE"||oe(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(oe(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;Oa(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},A(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=L(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,m(e,e.state.shell),i)},A(e,e.state.shell),e.render()})}):Ma(e);return}if(e.state.menuIndex===1){let n=e.state.variant==="boot"||e.state.variant==="pause"?e.state.variant:void 0;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}e.exit(0)}}function za(e,t){let r=Si(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},A(e,e.state.shell),e.render();return}let n=yi(r);if(n!==0){or(e,n);return}let s=Pi(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
161
+ `}function Lf(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ze={appendErrorLog:zn,appendErrorLogBestEffort:ga,readErrorLog:Qn,readRecentErrorLines:ha};var ka=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await Y(n.paths,e.selectedTaskId),i=t??Mf(o,e.activeTab,e.preferredPtyTabKind),a=ya(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await y(n.paths,l),l});return{updatedTask:s,nextShell:{activeTab:s.selectedPtyTabId??e.activeTab,selectedPtyTabId:s.selectedPtyTabId,preferredPtyTabKind:s.ptyTabs.at(-1)?.kind??e.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${s.ptyTabs.at(-1)?.title??"tab"}`}}},wa=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await y(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},Ta=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await Y(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await y(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Ra=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await y(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=ya(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await y(t.paths,{...s,selectedPtyTabId:o.id});return}await y(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Mf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function ya(e,t,r,n={}){let s=r??e.runner,o=h.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(u=>u.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let p=new Date().toISOString(),f=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...f?{runner:f}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?h.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Qe=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Pa=async(e,t,r,n,s)=>{h.runners.assertEnabled(n,s.config);let o=t?await s.taskService.provisionProjectTask(s.paths,t,r,{runner:n,config:s.config}):await s.taskService.provisionTask(s.paths,e??"",r,{runner:n,config:s.config});try{let l=ve();await T(Ee(h.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new Qe(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},Sa=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},ba=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await Y(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},Ia=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Ca=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await ze.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var va=async(e,t)=>{if(!e.selectedWorkspaceId)throw new Error("Select a workspace before removing it.");if((await t.taskService.listTasks(t.paths,{workspaceId:e.selectedWorkspaceId,includeClosed:!0})).tasks.length>0)throw new Error(`Cannot remove workspace ${e.selectedWorkspaceId} while task records still reference it.`);return await t.workspaceService.archiveWorkspace(t.paths,e.selectedWorkspaceId),{nextShell:{selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null,selectedPtyTabId:null,selectedLeftItemId:null,actionMessage:`Removed workspace ${(await t.workspaceService.removeWorkspace(t.paths,e.selectedWorkspaceId,{listTasks:t.taskService.listTasks})).workspaceId}`}}};var Ea=async(e,t,r)=>{let n=h.runners.setRunnerEnabled(r.config,e,t);return await h.save(r.paths,n),n},xa=async(e,t,r)=>{let n=h.runners.setRunnerPath(r.config,e,t);return await h.save(r.paths,n),n};function pe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function $e(e,t){return ue(t,e.ptyRuntime.getViewState(Yn(e,t)))}function Yn(e,t){let r=pe(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function m(e,t){return $e(e,ri(t,e.model))}function Aa(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:m(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Da(e,t,r){return Aa(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return Aa(e,t,{tone:"error",message:r})}function L(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return ze.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function D(e,t){if(!e.uiStateFile)return;e.runtimeState=Go(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>me({uiStateFile:e.uiStateFile},r),()=>me({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Of(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function W(e){return{paths:e.paths,config:e.config,taskService:b,workspaceService:Q,queueTaskMutation:t=>Of(e,t)}}function Jn(e,t){let r=pe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,o=Hn(s?.fileRows??[],t.collapsedFileTreePaths);return{leftItemIds:ni(e.model),centerTabIds:Jo(r,t),ptyTabIds:r?.ptyTabs.map(i=>i.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:o.map(i=>i.path),fileTreeFileIds:o.filter(i=>i.kind==="file").map(i=>i.path),fileTreeDirectoryIds:o.filter(i=>i.kind==="directory").map(i=>i.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:da(t,r),pageRows:Math.max(5,ee(e.activeTerminal.width,e.activeTerminal.height).height-Z.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(i=>i.repoId)??[]}}async function $a(e,t){await Ta(t,W(e))}async function _(e){e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:m(e,e.state.shell)}:e.state={...e.state,shell:m(e,e.state.shell)}}async function Xn(e,t){let r=++e.inspectionRefreshSequence,n=hn(e.model.tasks,t),s=e.model.inspection,o;if(n&&s?.taskId===n.id){let i={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},a=await Co(n,s,i);if(r!==e.inspectionRefreshSequence)return;o={...e.model,inspection:a}}else if(o=await Re(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=o,e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},D(e,e.state.shell),e.render())}function ja(e,t){t!==0&&(e.pendingInspectionScrollLines+=t,!e.inspectionScrollRenderTimer&&(e.inspectionScrollRenderTimer=setTimeout(()=>{e.inspectionScrollRenderTimer=null;let r=e.pendingInspectionScrollLines;if(e.pendingInspectionScrollLines=0,r===0||e.state.mode!=="main"||e.state.shell.inputMode!=="control")return;let n=Te(e.state.shell,r,Jn(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),Xn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render()}},16)))}function Zn(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function es(e){let t=e.model.tasks.flatMap(r=>r.ptyTabs.map(n=>n.id));await e.ptyRuntime.pruneStale?.(t),await e.ptyRuntime.hydrateSessions?.(t)}function Ma(e){es(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.render())})}async function Oa(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=Yn(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return ue(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));return ue({...r,inputMode:"control"},i)}function Fa(e){let t=e.state.mode==="main"&&e.state.shell.inputMode==="terminal"?"terminal":"control";t!==e.inputCaptureMode&&(e.inputCaptureMode=t,e.activeTerminal.grabInput(t==="terminal"?{mouse:"button"}:!0))}async function ts(e,t){try{let r=m(e,t),n=pe(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await La(e,n),await _(e),s=n.selectedPtyTabId)}n&&!s&&(n=await La(e,n),await _(e),s=n.selectedPtyTabId);let o=m(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},D(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ue({...o,inputMode:"terminal"},i)},D(e,e.state.shell)}catch(r){let n=L(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&wt(t.selectedPtyTabId)&&(await Ff(e,t.selectedTaskId,n).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,Ho(m(e,t),n),n)},D(e,e.state.shell)}e.render()}async function Ff(e,t,r){await Sa(t,r,W(e))}async function Na(e,t,r,n){let s=m(e,t),{nextShell:o}=await ka(s,r,n,W(e));return await _(e),m(e,{...s,...o})}async function Wa(e,t){let r=m(e,t),{closedTab:n,nextShell:s}=await wa(r,W(e));return e.ptyRuntime.disposeSession(n.id),await _(e),m(e,{...r,...s})}async function _a(e,t){let r=m(e,t),{closedTabIds:n,nextShell:s}=await ba(r,W(e));for(let o of n)e.ptyRuntime.disposeSession(o);return await _(e),m(e,{...r,...s})}async function qa(e,t){let r=m(e,t),{nextShell:n}=await va(r,W(e));return await _(e),m(e,{...r,...n})}async function La(e,t){return Ra(t,W(e))}function or(e,t){e.pendingScrollLines+=t,!e.scrollRenderTimer&&(e.scrollRenderTimer=setTimeout(()=>{e.scrollRenderTimer=null;let r=e.pendingScrollLines;e.pendingScrollLines=0,r!==0&&(e.ptyRuntime.scrollViewport(r),e.state={mode:"main",shell:$e(e,e.state.shell)},e.render())},16))}async function Ba(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await Ia(e.model.tasks,W(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:m(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,Ca("background PR polling",t,W(e)))}finally{e.prPollInFlight=!1}}}async function Ua(e,t){let r=m(e,t),n=pe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await b.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await _(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await b.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await _(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${v(a)?.requiredChecks.length??0} reported`)}return m(e,{...Da(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Bf from"node:path";import{readdir as Nf,stat as Wf}from"node:fs/promises";import Ka from"node:path";async function _f(e){let t=await Nf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Ka.join(e,n.name);r.push({name:n.name,path:s,kind:await qf(s)?"repo":"directory"})}return r.sort((n,s)=>n.kind!==s.kind?n.kind==="repo"?-1:1:n.name.localeCompare(s.name)),{cwd:e,entries:r,selectedIndex:0,query:null,error:null}}function Va(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Ga(e){let{spawn:t}=await import("node:child_process"),r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await new Promise((n,s)=>{let o=t(r,[e],{stdio:"ignore",detached:!0});o.unref(),o.on("error",s),o.on("spawn",n)})}async function ir(e,t){let r=await _f(t);e.state.mode==="main"&&(e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function qf(e){let t=Ka.join(e,".git");return await Wf(t).catch(()=>null)!==null}function Ha(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Uf(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:m(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:m(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Pa(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,W(e));n=s.task,await _(e);let o=m(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??wi(n,"agent"),ye(ee(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=wt(o.selectedPtyTabId),e.state={mode:"main",shell:ue(o,i)},D(e,e.state.shell)}catch(s){s instanceof Qe&&(n=s.task);let o=L(e,"create task",s,"Failed to create task.");n&&!(s instanceof Qe)?(await y(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})):n&&(await y(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await _(e).catch(()=>{})),e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function Kf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(oe(t)){Uf(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:m(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:m(e,{...r,selectedRunner:gn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}zo(t)&&(e.state={mode:"main",shell:m(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Vf(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Va(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:m(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){ir(e,Bf.dirname(r.cwd)).catch(s=>{let o=L(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||oe(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){ir(e,s.path).catch(i=>{let a=L(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=W(e);o.addWorkspace(e.paths,s.path).then(async i=>{await _(e);let a=i.repos[0]??null,l=m(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},D(e,e.state.shell),e.render()}).catch(i=>{let a=L(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function Gf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Vi(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;Hf(e,n)}}}async function Hf(e,t){let r;try{r=await ze.readRecentErrorLines(e.paths)}catch(n){let s=L(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function zf(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Gi(Ha(e),e.config,t,e.enabledRunnerIds);if(r.kind==="noop")return;if(r.kind==="back"){let s=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...s!==void 0?{parentVariant:s}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,runnerOptions:r.state},e.render();return}(r.kind==="save-enabled"?Ea(r.runner,r.enabled,W(e)):xa(r.runner,r.path,W(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=h.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:m(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:h.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=L(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,m(e,e.state.shell),o),runnerOptions:{...Ha(e),message:o}},e.render()})}function za(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){Kf(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Vf(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Qf(e),e.render();return}e.focusFlashUntil!==null&&(e.focusFlashUntil=null,e.focusFlashTimer&&(clearTimeout(e.focusFlashTimer),e.focusFlashTimer=null))}if(e.state.mode==="main"){let n=mn(e.state.shell,r,Jn(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&oe(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1),e.lastTerminalKey=Ti(r)?{key:r,at:Date.now()}:null;let s=Ri(r,e.state.shell.terminal.scrolledBack??!1);if(s!==0){or(e,s);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:m(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){ir(e,e.workspaceRoot).catch(s=>{let o=L(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,m(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Na(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{ts(e,s)}).catch(s=>{let o=L(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Wa(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ua(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=pe(e.model.tasks,n.state),o=s?v(s)?.url??null:null;o?Ga(o).catch(i=>{let a=L(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,m(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,m(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){_a(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){qa(e,n.state).then(s=>{e.state={mode:"main",shell:s},D(e,e.state.shell),e.render()}).catch(s=>{let o=L(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,m(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){ts(e,n.state);return}if(n.refreshInspection){e.state={mode:"main",shell:m(e,n.state)},D(e,e.state.shell),e.render(),Xn(e,e.state.shell).catch(s=>{let o=L(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,m(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:m(e,n.state)},$a(e,e.state.shell).catch(()=>{}),D(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:2,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:m(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Gf(e,r);return}if(e.state.variant==="runners"){zf(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||oe(r)){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render()}return}if(e.state.optionsMessage){(r==="ESCAPE"||oe(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:m(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(oe(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;Oa(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},D(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=L(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,m(e,e.state.shell),i)},D(e,e.state.shell),e.render()})}):Ma(e);return}if(e.state.menuIndex===1){let n=e.state.variant==="boot"||e.state.variant==="pause"?e.state.variant:void 0;e.state={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}e.exit(0)}}function Qa(e,t){let r=bi(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:m(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},D(e,e.state.shell),e.render();return}let n=yi(r);if(n!==0){or(e,n);return}let s=Pi(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
162
162
  `&&r!==`\r
163
- `&&(e.suppressTerminalEnterOnAttach=!1),bi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function Ya(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){ja(e,Pn(t));return}let r=Pn(t);r!==0&&or(e,r)}function Hf(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var Yf=zf(import.meta.url),Qf=Yf("terminal-kit"),Jf=Qf.terminal;function es(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}async function Qa(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ne(t),n=await g.load(r),s=g.runners.getEnabled(n),o=e.uiStateFile?await Me({uiStateFile:e.uiStateFile}):null,i=await Re(t,void 0,s),a=gt(Ko(o,n),i);i=await Re(t,a,s);let l=()=>{},c={workspaceRoot:t,onUpdate:()=>l(),resolveSessionSpec:(p,f)=>ki(i,f,t)},d=e.ptyRuntime??await Mi({...c,paths:r});return new Promise(p=>{let f=e.terminal??Jf,u={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:gt(a,i)},model:i,config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,prPollTimer:null,prPollInFlight:!1,lastBackgroundPrPollError:null,versionText:`Craig v${g.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:f,ptyRuntime:d,resolve:p,render:()=>{},exit:h=>p(h)};l=()=>{u.state.mode==="main"&&(u.state={mode:"main",shell:$e(u,u.state.shell)},u.ptyRenderTimer||(u.ptyRenderTimer=setTimeout(()=>{u.ptyRenderTimer=null,u.state.mode==="main"&&u.render()},50)))},u.render=()=>{Fa(u);let h=ee(f.width,f.height),Qe=u.state.mode==="main"?di(h,na(m(u,u.state.shell),u.model),{centerOnly:u.state.shell.centerZoomed,focusFlashActive:u.focusFlashUntil!==null&&Date.now()<u.focusFlashUntil}):u.state.variant==="boot"?ii(h,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="pause"?ai(h,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="options"?wn(h,{menuIndex:u.state.menuIndex,optionsMenuItems:jn}):u.state.variant==="runners"?wn(h,{menuIndex:es(u.state).menuIndex,optionsMenuItems:Ln(u.config,es(u.state)),optionsMessage:Ki(es(u.state)),optionsSubtitle:"Runners"}):u.state.variant==="error-log"?ci(h,{errorLogPath:u.state.errorLog?.path??r.errorLogFile,errorLogLines:u.state.errorLog?.lines??[]}):li(h);u.pendingClear&&(f.moveTo(1,1),f.eraseDisplayBelow(),u.pendingClear=!1),f.noFormat(Ii(Qe)),f.hideCursor(!0)};let w=h=>Ha(u,h),P=h=>za(u,h),D=h=>Ya(u,h),U=()=>{process.stdout.off("resize",fe),process.off("SIGCONT",ae),f.removeListener("key",w),f.removeListener("unknown",P),f.removeListener("mouse",D),u.scrollRenderTimer&&(clearTimeout(u.scrollRenderTimer),u.scrollRenderTimer=null),u.inspectionScrollRenderTimer&&(clearTimeout(u.inspectionScrollRenderTimer),u.inspectionScrollRenderTimer=null),u.ptyRenderTimer&&(clearTimeout(u.ptyRenderTimer),u.ptyRenderTimer=null),u.footerToastTimer&&(clearTimeout(u.footerToastTimer),u.footerToastTimer=null),u.focusFlashTimer&&(clearTimeout(u.focusFlashTimer),u.focusFlashTimer=null),u.prPollTimer&&(clearInterval(u.prPollTimer),u.prPollTimer=null),u.ptyRuntime.disposeAll(),f.grabInput(!1),f.hideCursor(!1),f.fullscreen(!1)};u.exit=h=>{U(),p(h)};let fe=()=>{Jn(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()},ae=()=>{Jn(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()};process.stdout.on("resize",fe),process.on("SIGCONT",ae),f.grabInput(!0),u.inputCaptureMode="control",f.hideCursor(!0),f.fullscreen(!0),f.on("key",w),f.on("unknown",P),f.on("mouse",D),u.prPollTimer=setInterval(()=>{qa(u)},(u.config.github?.watchIntervalSeconds??5)*1e3),g.version.checkForUpdate().then(h=>{h.updateAvailable&&h.latest&&(u.updateText=`Update available: v${h.latest}`,u.render())}),u.bootHydrationReady=Xn(u).catch(()=>{}),u.render()})}async function Xf(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Oi(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Fi(a),0}let e=ps(process.argv.slice(2)),t=process.cwd(),r=ne(t),n={paths:r};if(e.mode==="interactive")return await Qa({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await yo(e.command,n),o=Po(s);return o.length>0&&process.stdout.write(`${o}
163
+ `&&(e.suppressTerminalEnterOnAttach=!1),Si(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function Ya(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){ja(e,bn(t));return}let r=bn(t);r!==0&&or(e,r)}function Qf(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var Jf=Yf(import.meta.url),Xf=Jf("terminal-kit"),Zf=Xf.terminal;function rs(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}async function Ja(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ne(t),n=await h.load(r),s=h.runners.getEnabled(n),o=e.uiStateFile?await Me({uiStateFile:e.uiStateFile}):null,i=await Re(t,void 0,s),a=gt(Vo(o,n),i);i=await Re(t,a,s);let l=()=>{},c={workspaceRoot:t,onUpdate:()=>l(),resolveSessionSpec:(p,f)=>ki(i,f,t)},d=e.ptyRuntime??await Mi({...c,paths:r});return new Promise(p=>{let f=e.terminal??Zf,u={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:gt(a,i)},model:i,config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,prPollTimer:null,prPollInFlight:!1,lastBackgroundPrPollError:null,versionText:`Craig v${h.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:f,ptyRuntime:d,resolve:p,render:()=>{},exit:k=>p(k)};l=()=>{u.state.mode==="main"&&(u.state={mode:"main",shell:$e(u,u.state.shell)},u.ptyRenderTimer||(u.ptyRenderTimer=setTimeout(()=>{u.ptyRenderTimer=null,u.state.mode==="main"&&u.render()},50)))},u.render=()=>{Fa(u);let k=ee(f.width,f.height),Ye=u.state.mode==="main"?di(k,na(m(u,u.state.shell),u.model),{centerOnly:u.state.shell.centerZoomed,focusFlashActive:u.focusFlashUntil!==null&&Date.now()<u.focusFlashUntil}):u.state.variant==="boot"?ii(k,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="pause"?ai(k,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="options"?Rn(k,{menuIndex:u.state.menuIndex,optionsMenuItems:Mn}):u.state.variant==="runners"?Rn(k,{menuIndex:rs(u.state).menuIndex,optionsMenuItems:On(u.config,rs(u.state)),optionsMessage:Ki(rs(u.state)),optionsSubtitle:"Runners"}):u.state.variant==="error-log"?ci(k,{errorLogPath:u.state.errorLog?.path??r.errorLogFile,errorLogLines:u.state.errorLog?.lines??[]}):li(k);u.pendingClear&&(f.moveTo(1,1),f.eraseDisplayBelow(),u.pendingClear=!1),f.noFormat(Ii(Ye)),f.hideCursor(!0)};let w=k=>za(u,k),R=k=>Qa(u,k),A=k=>Ya(u,k),U=()=>{process.stdout.off("resize",fe),process.off("SIGCONT",ae),f.removeListener("key",w),f.removeListener("unknown",R),f.removeListener("mouse",A),u.scrollRenderTimer&&(clearTimeout(u.scrollRenderTimer),u.scrollRenderTimer=null),u.inspectionScrollRenderTimer&&(clearTimeout(u.inspectionScrollRenderTimer),u.inspectionScrollRenderTimer=null),u.ptyRenderTimer&&(clearTimeout(u.ptyRenderTimer),u.ptyRenderTimer=null),u.footerToastTimer&&(clearTimeout(u.footerToastTimer),u.footerToastTimer=null),u.focusFlashTimer&&(clearTimeout(u.focusFlashTimer),u.focusFlashTimer=null),u.prPollTimer&&(clearInterval(u.prPollTimer),u.prPollTimer=null),u.ptyRuntime.disposeAll(),f.grabInput(!1),f.hideCursor(!1),f.fullscreen(!1)};u.exit=k=>{U(),p(k)};let fe=()=>{Zn(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()},ae=()=>{Zn(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(ye(ee(f.width,f.height))),u.state={mode:"main",shell:$e(u,u.state.shell)}),u.render()};process.stdout.on("resize",fe),process.on("SIGCONT",ae),f.grabInput(!0),u.inputCaptureMode="control",f.hideCursor(!0),f.fullscreen(!0),f.on("key",w),f.on("unknown",R),f.on("mouse",A),u.prPollTimer=setInterval(()=>{Ba(u)},(u.config.github?.watchIntervalSeconds??5)*1e3),h.version.checkForUpdate().then(k=>{k.updateAvailable&&k.latest&&(u.updateText=`Update available: v${k.latest}`,u.render())}),u.bootHydrationReady=es(u).catch(()=>{}),u.render()})}async function em(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Oi(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=ne(i);return await Fi(a),0}let e=ms(process.argv.slice(2)),t=process.cwd(),r=ne(t),n={paths:r};if(e.mode==="interactive")return await Ja({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await So(e.command,n),o=bo(s);return o.length>0&&process.stdout.write(`${o}
164
164
  `),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
165
- `),1}}var Zf=await Xf();process.exit(Zf);
165
+ `),1}}var tm=await em();process.exit(tm);