craig-cli 0.7.10 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +36 -35
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var fl=Object.defineProperty;var pr=(e,t)=>{for(var r in t)fl(e,r,{get:t[r],enumerable:!0})};import{readFile as wl}from"node:fs/promises";import{randomUUID as ml}from"node:crypto";import{open as gl,readFile as
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await hl(n,e)}catch(o){throw await s.close().catch(()=>{}),await kl(n,{force:!0}).catch(()=>{}),o}}async function
|
|
4
|
-
`)};var kr={};pr(kr,{checkForUpdate:()=>Ts,getCurrent:()=>
|
|
2
|
+
var fl=Object.defineProperty;var pr=(e,t)=>{for(var r in t)fl(e,r,{get:t[r],enumerable:!0})};import{readFile as wl}from"node:fs/promises";import{randomUUID as ml}from"node:crypto";import{open as gl,readFile as Tm,rename as hl,rm as kl}from"node:fs/promises";import fr from"node:path";async function O(e,t){let r=fr.dirname(e),n=fr.join(r,`.${fr.basename(e)}.${process.pid}.${Date.now()}.${ml()}.tmp`),s=await gl(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await hl(n,e)}catch(o){throw await s.close().catch(()=>{}),await kl(n,{force:!0}).catch(()=>{}),o}}async function Fe(e){try{let t=await wl(e.uiStateFile,"utf8"),r=JSON.parse(t);return Tl(r,e.uiStateFile)}catch(t){if(yl(t))return null;throw t}}async function he(e,t){await O(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function It(){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 Tl(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")||!Oe(e,"inputMode")||!Oe(e,"focusedRegion")||!Oe(e,"activeTab")||!Oe(e,"inspectorSection")||!Oe(e,"inspectionMode")||!bt(e,"openInspectionKind")||!bt(e,"selectedFileTreePath")||!bt(e,"selectedFilePath")||!bt(e,"selectedDiffPath")||!Rl(e,"collapsedFileTreePaths")||!Oe(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 Oe(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function bt(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Rl(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function yl(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var mr={};pr(mr,{RUNNER_IDS:()=>x,assertEnabled:()=>us,buildCommand:()=>ms,getConfiguredProfile:()=>Ct,getDefault:()=>ds,getDisplayName:()=>fs,getEnabled:()=>vt,getProfile:()=>Ne,isRunnerType:()=>Et,parse:()=>ps,setRunnerEnabled:()=>gs,setRunnerPath:()=>hs});var x=["codex","cursor","claude"];var cs={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 Ne=e=>cs[e];var Ct=(e,t={})=>{let r=Ne(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var vt=(e={})=>x.filter(t=>e.runners?.[t]?.enabled!==!1);var ds=(e={})=>{let t=vt(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 us=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var Et=e=>x.includes(e);var ps=e=>{if(!e||e.length===0)return"codex";if(!Et(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${x.join(", ")}.`);return e};var fs=e=>Ne(e).displayName;var ms=(e,t,r={})=>{let n=[Ct(e,r).executable];return t&&t.length>0&&n.push(t),n};var gs=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var hs=(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 Sl,writeFile as bl}from"node:fs/promises";import Il from"node:path";var Cl=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",ks=async e=>{try{return await Sl(e,"utf8")}catch(t){if(Cl(t))return null;throw t}},ws=async(e,t)=>{await Pl(Il.dirname(e),{recursive:!0}),await bl(e,t,"utf8")};var At=(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 gr=async(e,t={readConfigFile:ks})=>{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 At(n,e.configFile)};var hr=async(e,t,r={writeConfigFile:ws})=>{At(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var kr={};pr(kr,{checkForUpdate:()=>Ts,getCurrent:()=>xt});var xt=()=>{try{return"0.7.11"}catch{return"unknown"}};var vl="https://registry.npmjs.org/craig-cli/latest",El=3600*1e3,Al={value:null},xl=(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},Ts=async(e={fetch:globalThis.fetch,getCurrent:xt,cache:Al})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<El)return e.cache.value.result;let n=null;try{let o=await e.fetch(vl,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&xl(n,t)};return e.cache.value={result:s,cachedAt:r},s};var k={load:gr,save:hr,runners:mr,version:kr};function Rs(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
|
|
|
@@ -26,12 +26,12 @@ ${K()}`)}function K(){return["Craig commands:"," craig Show the Cr
|
|
|
26
26
|
|
|
27
27
|
${K()}`);return t}function Dl(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
28
28
|
|
|
29
|
-
${K()}`);return t}var N=(e,t)=>{let r=wr(e);if(!Ll(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},wr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Tr(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:Ol(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:jl(t.repoTargets),runnerSession:t.runnerSession??$l(t),checks:Ul(t),lastCommit:t.lastCommit??null,prs:Kl(t),artifacts:zl(t),cleanup:Ql(t)}},$l=e=>{if(typeof e.title!="string")return null;let t=Tr(e.runner);return{command:k.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Ll=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"&&k.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"&&Ps(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||Ml(t.repoTargets))&&Nl(t.runnerSession)&&Wl(t.prompt)&&Ss(t.checks)&&bs(t.lastCommit)&&ql(t.prs)&&Bl(t.artifacts)&&Cs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},jl=e=>{if(Array.isArray(e))return e.filter(ys)},Ml=e=>Array.isArray(e)&&e.every(ys),ys=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)&&Ss(t.checks)&&bs(t.lastCommit)&&Is(t.pullRequest)&&Cs(t.cleanup)},Ol=e=>{if(Ps(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 Fl(e.id,e.title,t,Tr(e.runner))},Fl=(e,t,r,n)=>{let s=k.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:k.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Tr=e=>e&&k.runners.isRunnerType(e)?e:"codex",Ps=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"),Nl=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),Wl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Ss=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"),bs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Is=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&_l(e.requiredChecks),_l=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)),ql=e=>Array.isArray(e)&&e.every(Is),Bl=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),Cs=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),Ul=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Kl=e=>{if(Array.isArray(e.prs))return e.prs.map(Vl);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:vs(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Es(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Vl=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:vs(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Gl(t.reviewDecision),requiredChecks:Es(t.requiredChecks),comments:Hl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},vs=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Gl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Hl=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}]}):[],Es=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})):[],zl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Ql=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as wc}from"node:fs/promises";import{readFile as Yl,readdir as Jl,rm as Xl}from"node:fs/promises";import As from"node:path";var Rr=(e,t)=>As.join(e.workspacesDir,`${t}.json`),Zl=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"):[]}},xs=(e,t)=>{let r=Zl(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},Se=async(e,t)=>{let r=Rr(e,t),n=await Yl(r,"utf8");return xs(JSON.parse(n),r)},be=async(e,t)=>{await O(Rr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Y=async e=>{let t=await Jl(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Se(e,As.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Ds=async(e,t)=>{await Xl(Rr(e,t),{force:!0})};import{readFile as ec,readdir as tc,rm as rc}from"node:fs/promises";import $s from"node:path";var yr=(e,t)=>$s.join(e.reposDir,`${t}.json`),Ls=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},Z=async(e,t)=>{let r=yr(e,t),n=await ec(r,"utf8");return Ls(JSON.parse(n),r)},Pr=async(e,t)=>{await O(yr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Xe=async e=>{let t=await tc(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Z(e,$s.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},js=async(e,t)=>{await rc(yr(e,t),{force:!0})};import{readFile as nc}from"node:fs/promises";var sc=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},xt=(e,t,r)=>{if(!sc(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},V=async e=>{let t=await nc(e.indexFile,"utf8");return xt(JSON.parse(t),e.workspaceRoot,e.indexFile)},ce=async(e,t)=>{await O(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as cc,stat as dc}from"node:fs/promises";import We from"node:path";import{realpath as Fs}from"node:fs/promises";import Ns from"node:path";import{execFile as oc}from"node:child_process";import{promisify as ic}from"node:util";var Ms=ic(oc);async function T(e,t,r={}){try{let n=await Ms(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Os(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 Ms(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Os(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Os(e){return e instanceof Error}var Sr=async e=>{try{let r=(await T("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Fs(r).catch(()=>Ns.resolve(r)),Fs(e).catch(()=>Ns.resolve(e))]);return n===s}catch{return!1}},br=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 oe,readFile as ac}from"node:fs/promises";import G from"node:path";function se(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 lc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Ne=async e=>{let t=se(e);await oe(t.craigDir,{recursive:!0}),await Promise.all([oe(t.reposDir,{recursive:!0}),oe(t.workspacesDir,{recursive:!0}),oe(t.sessionsDir,{recursive:!0}),oe(t.runtimeDir,{recursive:!0}),oe(t.tasksDir,{recursive:!0}),oe(t.jobsDir,{recursive:!0}),oe(t.logsDir,{recursive:!0}),oe(t.artifactsDir,{recursive:!0}),oe(t.worktreesDir,{recursive:!0})]);try{let s=await ac(t.indexFile,"utf8"),o=JSON.parse(s);return xt(o,e,t.indexFile)}catch(s){if(!lc(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await O(t.indexFile,n),n};var Ws=(e,t,r)=>{let n=new Date().toISOString();return{id:uc(e,We.basename(t)),name:We.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},_s=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},uc=(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},pc=(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},qs=async(e,t)=>{let r=await V(e);await ce(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},fc=async(e,t)=>{let r=await cc(t,{withFileTypes:!0}),n=await Xe(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=We.join(t,o.name);if(!await Sr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await br(i);s.push(a?_s(a,l):Ws([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},mc=async(e,t)=>{let r=await br(t),n=await Xe(e),s=n.find(p=>p.rootPath===t)??null,o=s?_s(s,r):Ws(n,t,r),i=`workspace_${o.id}`,l=(await Y(e)).find(p=>p.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await Pr(e,o),l||await be(e,d),await qs(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},gc=async(e,t)=>{let r=await fc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Y(e),s=pc(n,We.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:We.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=>Pr(e,c))),await be(e,l),await qs(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Ze=async(e,t)=>{await Ne(e.workspaceRoot);let r=We.resolve(e.workspaceRoot,t);if(!(await dc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Sr(r)?mc(e,r):gc(e,r)};var Ir=async(e,t,r={listWorkspaceRecords:Y,ensureCraigState:Ne})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Cr=async(e,t,r={readWorkspace:Se,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 vr=async(e,t)=>{let n={...await Se(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 Ie=async(e,t,r={deleteWorkspace:Ds,readCraigIndex:V,writeCraigIndex:ce})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Er=async(e,t,r)=>{let n=await Se(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 Ie(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Ar={};pr(Ar,{addRepo:()=>Bs,listRegisteredRepos:()=>Us,removeRepo:()=>Ks});import hc from"node:path";import{stat as kc}from"node:fs/promises";var Bs=async(e,t)=>{let r=hc.resolve(e.workspaceRoot,t);if(!(await kc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Ze(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 Us=async(e,t={listRepos:Xe,ensureCraigState:Ne})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ks=async(e,t,r)=>{let n=await Z(e,t),o=(await Y(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Ie(e,c.id))),await js(e,t);let l=await V(e);return await ce(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var H={addWorkspace:Ze,listWorkspaces:Ir,archiveWorkspace:Cr,restoreWorkspace:vr,removeWorkspace:Er,removeWorkspaceRecord:Ie,repos:Ar};var z=async(e,t)=>{let r=await wc(Dr(e,t),"utf8");return JSON.parse(r)},J=async(e,t)=>{let r=await z(e,t);return N(r,Dr(e,t))},y=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await O(Dr(e,t.id),r)},xr=async(e,t)=>{let r=await V(e);r.taskIds.includes(t)||await ce(e,{...r,taskIds:[...r.taskIds,t]})},Dr=(e,t)=>`${e.tasksDir}/${t}.json`;var A=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ge=e=>e.status==="merged"||e.status==="closed",_e=(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}},et=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return $t(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},$t=e=>e.mergeable&&!Tc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),Tc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",$r=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),tt=(e,t)=>{let r=e.isDraft??!1,n=Rc(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:yc(e.reviewDecision??null),requiredChecks:rt(e.statusCheckRollup),comments:Ic(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}},Rc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,yc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,rt=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||Sc(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:Gs(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:bc(t)}:null},Sc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Dt(e)&&!Dt(t)?!0:!Dt(e)&&Dt(t)?!1:Vs(t.status)>=Vs(e.status),Dt=e=>e.conclusion?.toUpperCase()==="CANCELLED",Vs=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},bc=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},Ic=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Cc).filter(r=>r!==null).slice(-4):[]},Cc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=vc(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},vc=e=>e.replace(/\s+/g," ").trim(),Gs=(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?Gs(n,n):"unknown"};import{access as Ec}from"node:fs/promises";import Hs from"node:path";var S=async(e,t,r={readRawTask:z,validateTaskRecord:N})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Lc(n)?new Error(`Craig task "${t}" was not found.`):n}},W=async e=>{if(!await Lr(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},qe=(e,t)=>t.artifacts.logPath?Hs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Hs.join(e.workspaceRoot,t.artifacts.logPath):null,nt=async(e,t)=>{let r=await Lr(t.worktreePath),n=qe(e,t),s=n?await Lr(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Ac(t),lastCommitSummary:xc(t),prSummary:Dc(t),cleanupSummary:$c(t)}},Lr=async e=>{try{return await Ec(e),!0}catch{return!1}},Ac=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},xc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Dc=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 N=(e,t)=>{let r=wr(e);if(!Ll(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},wr=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Tr(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:Ol(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:jl(t.repoTargets),runnerSession:t.runnerSession??$l(t),checks:Ul(t),lastCommit:t.lastCommit??null,prs:Kl(t),artifacts:zl(t),cleanup:Ql(t)}},$l=e=>{if(typeof e.title!="string")return null;let t=Tr(e.runner);return{command:k.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Ll=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"&&k.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"&&Ps(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||Ml(t.repoTargets))&&Nl(t.runnerSession)&&Wl(t.prompt)&&Ss(t.checks)&&bs(t.lastCommit)&&ql(t.prs)&&Bl(t.artifacts)&&Cs(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},jl=e=>{if(Array.isArray(e))return e.filter(ys)},Ml=e=>Array.isArray(e)&&e.every(ys),ys=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)&&Ss(t.checks)&&bs(t.lastCommit)&&Is(t.pullRequest)&&Cs(t.cleanup)},Ol=e=>{if(Ps(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 Fl(e.id,e.title,t,Tr(e.runner))},Fl=(e,t,r,n)=>{let s=k.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:k.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Tr=e=>e&&k.runners.isRunnerType(e)?e:"codex",Ps=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"),Nl=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),Wl=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Ss=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"),bs=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",Is=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&_l(e.requiredChecks),_l=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)),ql=e=>Array.isArray(e)&&e.every(Is),Bl=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),Cs=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),Ul=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Kl=e=>{if(Array.isArray(e.prs))return e.prs.map(Vl);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:vs(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Es(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Vl=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:vs(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Gl(t.reviewDecision),requiredChecks:Es(t.requiredChecks),comments:Hl(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},vs=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Gl=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Hl=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}]}):[],Es=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})):[],zl=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Ql=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as wc}from"node:fs/promises";import{readFile as Yl,readdir as Jl,rm as Xl}from"node:fs/promises";import As from"node:path";var Rr=(e,t)=>As.join(e.workspacesDir,`${t}.json`),Zl=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"):[]}},xs=(e,t)=>{let r=Zl(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},be=async(e,t)=>{let r=Rr(e,t),n=await Yl(r,"utf8");return xs(JSON.parse(n),r)},Ie=async(e,t)=>{await O(Rr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Y=async e=>{let t=await Jl(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>be(e,As.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Ds=async(e,t)=>{await Xl(Rr(e,t),{force:!0})};import{readFile as ec,readdir as tc,rm as rc}from"node:fs/promises";import $s from"node:path";var yr=(e,t)=>$s.join(e.reposDir,`${t}.json`),Ls=(e,t)=>{if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.name!="string"||typeof e.rootPath!="string"||typeof e.defaultBranch!="string"||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig repo record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e},Z=async(e,t)=>{let r=yr(e,t),n=await ec(r,"utf8");return Ls(JSON.parse(n),r)},Pr=async(e,t)=>{await O(yr(e,t.id),{...t,updatedAt:new Date().toISOString()})},Ze=async e=>{let t=await tc(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Z(e,$s.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},js=async(e,t)=>{await rc(yr(e,t),{force:!0})};import{readFile as nc}from"node:fs/promises";var sc=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Dt=(e,t,r)=>{if(!sc(e))throw new Error(`Craig index at ${r} is invalid. Remove or repair the file before rerunning Craig.`);if(e.workspaceRoot!==t)throw new Error(`Craig index at ${r} belongs to ${e.workspaceRoot}, not ${t}. Remove or repair the file before rerunning Craig.`);return e},V=async e=>{let t=await nc(e.indexFile,"utf8");return Dt(JSON.parse(t),e.workspaceRoot,e.indexFile)},ce=async(e,t)=>{await O(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as cc,stat as dc}from"node:fs/promises";import _e from"node:path";import{realpath as Fs}from"node:fs/promises";import Ns from"node:path";import{execFile as oc}from"node:child_process";import{promisify as ic}from"node:util";var Ms=ic(oc);async function R(e,t,r={}){try{let n=await Ms(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Os(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function v(e,t,r={}){try{let n=await Ms(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Os(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Os(e){return e instanceof Error}var Sr=async e=>{try{let r=(await R("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Fs(r).catch(()=>Ns.resolve(r)),Fs(e).catch(()=>Ns.resolve(e))]);return n===s}catch{return!1}},br=async e=>{let t=await v("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 v("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await R("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as oe,readFile as ac}from"node:fs/promises";import G from"node:path";function se(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 lc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",We=async e=>{let t=se(e);await oe(t.craigDir,{recursive:!0}),await Promise.all([oe(t.reposDir,{recursive:!0}),oe(t.workspacesDir,{recursive:!0}),oe(t.sessionsDir,{recursive:!0}),oe(t.runtimeDir,{recursive:!0}),oe(t.tasksDir,{recursive:!0}),oe(t.jobsDir,{recursive:!0}),oe(t.logsDir,{recursive:!0}),oe(t.artifactsDir,{recursive:!0}),oe(t.worktreesDir,{recursive:!0})]);try{let s=await ac(t.indexFile,"utf8"),o=JSON.parse(s);return Dt(o,e,t.indexFile)}catch(s){if(!lc(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await O(t.indexFile,n),n};var Ws=(e,t,r)=>{let n=new Date().toISOString();return{id:uc(e,_e.basename(t)),name:_e.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},_s=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},uc=(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},pc=(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},qs=async(e,t)=>{let r=await V(e);await ce(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},fc=async(e,t)=>{let r=await cc(t,{withFileTypes:!0}),n=await Ze(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=_e.join(t,o.name);if(!await Sr(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await br(i);s.push(a?_s(a,l):Ws([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},mc=async(e,t)=>{let r=await br(t),n=await Ze(e),s=n.find(p=>p.rootPath===t)??null,o=s?_s(s,r):Ws(n,t,r),i=`workspace_${o.id}`,l=(await Y(e)).find(p=>p.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await Pr(e,o),l||await Ie(e,d),await qs(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},gc=async(e,t)=>{let r=await fc(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Y(e),s=pc(n,_e.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:_e.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=>Pr(e,c))),await Ie(e,l),await qs(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},et=async(e,t)=>{await We(e.workspaceRoot);let r=_e.resolve(e.workspaceRoot,t);if(!(await dc(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Sr(r)?mc(e,r):gc(e,r)};var Ir=async(e,t,r={listWorkspaceRecords:Y,ensureCraigState:We})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Cr=async(e,t,r={readWorkspace:be,writeWorkspace:Ie})=>{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 vr=async(e,t)=>{let n={...await be(e,t),status:"active",archivedAt:null};await Ie(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 Ce=async(e,t,r={deleteWorkspace:Ds,readCraigIndex:V,writeCraigIndex:ce})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Er=async(e,t,r)=>{let n=await be(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 Ce(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Ar={};pr(Ar,{addRepo:()=>Bs,listRegisteredRepos:()=>Us,removeRepo:()=>Ks});import hc from"node:path";import{stat as kc}from"node:fs/promises";var Bs=async(e,t)=>{let r=hc.resolve(e.workspaceRoot,t);if(!(await kc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await et(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 Us=async(e,t={listRepos:Ze,ensureCraigState:We})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ks=async(e,t,r)=>{let n=await Z(e,t),o=(await Y(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Ce(e,c.id))),await js(e,t);let l=await V(e);return await ce(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var H={addWorkspace:et,listWorkspaces:Ir,archiveWorkspace:Cr,restoreWorkspace:vr,removeWorkspace:Er,removeWorkspaceRecord:Ce,repos:Ar};var z=async(e,t)=>{let r=await wc(Dr(e,t),"utf8");return JSON.parse(r)},J=async(e,t)=>{let r=await z(e,t);return N(r,Dr(e,t))},y=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await O(Dr(e,t.id),r)},xr=async(e,t)=>{let r=await V(e);r.taskIds.includes(t)||await ce(e,{...r,taskIds:[...r.taskIds,t]})},Dr=(e,t)=>`${e.tasksDir}/${t}.json`;var E=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,ke=e=>e.status==="merged"||e.status==="closed",qe=(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}},tt=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Lt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Lt=e=>e.mergeable&&!Tc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),Tc=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",$r=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),rt=(e,t)=>{let r=e.isDraft??!1,n=Rc(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:yc(e.reviewDecision??null),requiredChecks:nt(e.statusCheckRollup),comments:Ic(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}},Rc=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,yc=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,nt=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||Sc(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:Gs(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:bc(t)}:null},Sc=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):$t(e)&&!$t(t)?!0:!$t(e)&&$t(t)?!1:Vs(t.status)>=Vs(e.status),$t=e=>e.conclusion?.toUpperCase()==="CANCELLED",Vs=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},bc=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},Ic=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Cc).filter(r=>r!==null).slice(-4):[]},Cc=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=vc(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},vc=e=>e.replace(/\s+/g," ").trim(),Gs=(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?Gs(n,n):"unknown"};import{access as Ec}from"node:fs/promises";import Hs from"node:path";var S=async(e,t,r={readRawTask:z,validateTaskRecord:N})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Lc(n)?new Error(`Craig task "${t}" was not found.`):n}},W=async e=>{if(!await Lr(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},Be=(e,t)=>t.artifacts.logPath?Hs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Hs.join(e.workspaceRoot,t.artifacts.logPath):null,st=async(e,t)=>{let r=await Lr(t.worktreePath),n=Be(e,t),s=n?await Lr(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Ac(t),lastCommitSummary:xc(t),prSummary:Dc(t),cleanupSummary:$c(t)}},Lr=async e=>{try{return await Ec(e),!0}catch{return!1}},Ac=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},xc=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Dc=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
30
30
|
${o.join(`
|
|
31
|
-
`)}`}let t=
|
|
32
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},Xs=async e=>{let t=await
|
|
31
|
+
`)}`}let t=E(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})`},$c=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",Lc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var zs=async(e,t)=>{let r=await v("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.")},jr=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await v("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 jc(e,s);await R("git",["worktree","add","-b",t,r,i],{cwd:e})},jc=async(e,t)=>(await v("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await v("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await v("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,jt=async e=>{let t=await v("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},Qs=async e=>{await R("git",["add","-A"],{cwd:e})},Ys=async(e,t)=>{await R("git",["commit","-m",t],{cwd:e})},Js=async e=>{let t=await R("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}},Xs=async e=>{let t=await v("git",["branch","--show-current"],{cwd:e});if(t.exitCode!==0)return null;let r=t.stdout.trim();return r.length>0?r:null};var Zs=async(e,t)=>{await R("git",["worktree","remove","--force",t],{cwd:e})};var Mr=async e=>Ue(e,e.repoRoot),Ue=async(e,t)=>{let r=await V(e),n=eo(new Date),s=to(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await zs(t,i))return o;s+=1}},ot=async e=>{let t=await V(e),r=eo(new Date),n=to(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},eo=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},to=(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 Or=async(e,t,r={readRawTask:z,validateTaskRecord:N})=>{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(Mc(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}},Mc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var ro=["merge_ready","pr_open","checked","review","running","draft"],Fr=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),Nr=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(Oc)[0]?.id??null,Oc=(e,t)=>{let r=no(e.status),n=no(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},no=e=>{let t=ro.indexOf(e);return t>=0?t:ro.length};import so from"node:path";var ve=(e,t)=>t?so.isAbsolute(t)?t:so.join(e.repoRoot,t):null;import{mkdir as it,rm as Fc,writeFile as Mt}from"node:fs/promises";import C from"node:path";var io=["AGENTS","md"].join("."),Ke=async(e,t,r,n={})=>{let s=await Z(e,t),o=await Bc(e,s.id),i=await Ue(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 it(C.dirname(c),{recursive:!0}),await it(p,{recursive:!0}),await Mt(d,"","utf8");let f=Nc(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 xr(e,i),await jr(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:f}},at=async(e,t,r,n={})=>{let s=(await Y(e)).find(T=>T.id===t&&T.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 T=await Ke(e,s.primaryRepoId,r,n);return{...T,bundlePath:T.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await ot(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`),m=C.join(e.artifactsDir,i);await it(p,{recursive:!0}),await it(m,{recursive:!0}),await Mt(f,"","utf8");let w=await Promise.all(o.map(T=>Z(e,T))),u=_c(w),D=await Promise.all(w.map(T=>Wc(e,T,i,d,C.join(p,u.get(T.id))))),B=D.find(T=>T.status==="ready")??D[0];if(!D.some(T=>T.status==="ready"))throw await Fc(p,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${D.map(T=>`${T.repoId}: ${T.failureReason??"unknown error"}`).join("; ")}`);await Mt(C.join(p,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:D.map(T=>({repoId:T.repoId,repoName:w.find(Me=>Me.id===T.repoId)?.name??T.repoId,path:C.relative(p,T.worktreePath),status:T.status,worktreePath:T.worktreePath,failureReason:T.failureReason}))},null,2),"utf8"),await Mt(C.join(p,io),qc({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:D,bundlePath:p}),"utf8");let me=lt(i,r,a,l,n.config??{}),ge={id:i,title:r,slug:ao(r),type:"project",status:"draft",runner:l,repoId:B.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:me[0]?.id??null,linkedRepoIds:o.filter(T=>T!==B.repoId),repoRoot:p,worktreePath:p,branch:d,bundlePath:p,selectedRepoTargetId:B.repoId,repoTargets:D,ptyTabs:me,runnerSession:{command:k.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:B.checks,lastCommit:null,prs:[],artifacts:{logPath:C.relative(e.workspaceRoot,f),checkSummaryPath:C.relative(e.workspaceRoot,C.join(m,"check-summary.json")),prDraftPath:null,prStatusPath:C.relative(e.workspaceRoot,C.join(m,"pr-status.json"))},cleanup:Ot(),lastFailureReason:D.every(T=>T.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await y(e,ge),await xr(e,i),{repoId:B.repoId,repoRoot:p,sessionId:c,workspaceId:s.id,task:ge,bundlePath:p,repoTargets:D}},lt=(e,t,r,n="codex",s={})=>{let o=k.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:k.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Nc=(e,t)=>{let r=new Date().toISOString(),n=lt(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:ao(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:k.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:{...Wr(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:Ot(),lastFailureReason:null,createdAt:r,updatedAt:r}},Wc=async(e,t,r,n,s)=>{await it(C.dirname(s),{recursive:!0});try{return await jr(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Wr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:oo(),cleanup:Ot()}}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:Wr(C.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:oo(),cleanup:Ot()}}},_c=e=>{let t=new Set(["manifest.json",io]),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},qc=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
|
-
`)},Wr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),oo=()=>({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}),Mt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),Bc=async(e,t)=>{let n=(await Y(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},ao=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import To from"node:path";import{readFile as Uc,rm as Ek}from"node:fs/promises";import Kc from"node:path";var he=async(e,t)=>{let r=await Uc(_r(e,t),"utf8"),n=JSON.parse(r);return Vc(n,_r(e,t))},ve=async(e,t)=>{await O(_r(e,t.id),{...t,updatedAt:new Date().toISOString()})};var _r=(e,t)=>Kc.join(e.sessionsDir,`${t}.json`);function Vc(e,t){let r=zc(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")||!Hc(r.attach)||!Gc(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 Gc(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 Hc(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 zc(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 Qc}from"node:child_process";import{createHash as Yc}from"node:crypto";import Jc from"node:path";function Ot(e){return`'${e.replace(/'/g,"'\\''")}'`}var Xc="craig",lo=async(e,t,r)=>{let n=qr(e,t),s=ed(),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=rd(o.stdout);return await Zc(e,n),i};var Zc=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})},co=async(e,t,r)=>{await T("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},uo=async(e,t,r)=>{await T("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var po=async(e,t,r)=>{await T("tmux",["pipe-pane","-o","-t",e,`cat >> ${Ot(t)}`],{cwd:r})},Ft=async(e,t,r,n)=>{let s=n??mo(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 sd(e,["attach-session","-t",s])};var fo=async(e,t)=>{await T("tmux",["kill-session","-t",t],{cwd:e})};var mo=e=>{let r=Jc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Yc("sha1").update(e).digest("hex").slice(0,8);return`${Xc}-${r}-${n}`},qr=(e,t)=>`${mo(e)}-${t.toLowerCase()}`,ed=()=>{let e=td();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},td=()=>{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},rd=e=>{let t=nd(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]}},nd=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),sd=async(e,t)=>{await new Promise((r,n)=>{let s=Qc("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 od,constants as id}from"node:fs";import{homedir as go}from"node:os";import ke from"node:path";var ad=[ke.join(go(),".local","bin"),ke.join(go(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ko(e=process.env){return ld([...(e.PATH??"").split(ke.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:ad])}function Ee(e=process.env){return{...e,PATH:ko(e).join(ke.delimiter)}}function Br(e,t={}){if(e.includes(ke.sep)){let r=ke.isAbsolute(e)?e:ke.resolve(t.cwd??process.cwd(),e);return ho(r)?r:null}for(let r of ko(t.env)){let n=ke.join(r,e);if(ho(n))return n}return null}function Ae(e,t={}){let r=Br(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 ho(e){try{return od(e,id.X_OK),!0}catch{return!1}}function ld(e){return[...new Set(e)]}var lt={async create(e,t){let r=await lo(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await po(r.paneId,t.logPath,t.repoRoot);let n=await wo({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||qr(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await ve(e,s),s},async attach(e,t,r){let n=await lt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Ft(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await ve(e,s),s},async resize(e,t,r,n){await co(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await ve(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 ve(e,n),n},async snapshot(e,t){return cd(e,t)}},Ur={async prepare(e,t){let n=e.runnerSession.command[0],s=Ee();await T(Ae(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Ae(r[0],{cwd:e.worktreePath,env:Ee()});await uo(t.session.paneId,[n,...r.slice(1)].map(s=>Ot(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},cd=async(e,t)=>{let r=await E("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return wo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},wo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Kr=async(e,t,r,n={})=>{let s=r.trim(),o=await k.load(e),i=n.runner??k.runners.getDefault(o);if(k.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 it(e,n.workspaceId,s,{runner:i,config:o}):await Ue(e,t,s,{runner:i,config:o}),l=a.task,c=k.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?To.resolve(e.workspaceRoot,l.artifacts.logPath):To.join(e.logsDir,`${l.id}.log`);try{await Ur.prepare(l,{repoRoot:a.repoRoot});let f=await lt.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Ur.launch(l,{repoRoot:a.repoRoot,session:f});let m=new Date().toISOString();f={...f,status:"running",startedAt:m,command:c};let u={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:m,lastKnownState:"running",exitCode:null,exitedAt:null}};return await y(e,u),await ve(e,f),{kind:"createTask",taskId:u.id,repoId:u.repoId,workspaceId:u.workspaceId,sessionId:f.id,status:u.status,branch:u.branch,worktreePath:u.worktreePath,runner:u.runner}}catch(f){let m={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await y(e,m),f}};import{mkdir as Td}from"node:fs/promises";import Rd from"node:path";var Ro=3,dd=1e3,ud=1e4,Ke=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 yo=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})},Nt=async(e,t)=>{let r=await T("gh",bo(e),{cwd:t});return JSON.parse(r.stdout)},Ve=async(e,t)=>{let r=await E("gh",bo(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Po=async(e,t,r)=>{if(r.length===0)return[];let n=kd(r),s=await pd(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=wd(c);return{id:a.id,found:d!==null,view:d}})},So=async e=>{let t=await E("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:hd(t.stdout.trim())},pd=async(e,t)=>{let r;for(let n=0;n<=Ro;n+=1)try{return await T("gh",t,{cwd:e})}catch(s){if(r=s,n===Ro||!fd(s))throw s;await gd(md(n))}throw r},fd=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")},md=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||dd,r=Math.min(t*2**e,ud),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},gd=e=>new Promise(t=>setTimeout(t,e)),bo=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],hd=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},kd=e=>`
|
|
34
|
+
`)},Wr=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),oo=()=>({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}),Ot=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),Bc=async(e,t)=>{let n=(await Y(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},ao=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import To from"node:path";import{readFile as Uc,rm as Ak}from"node:fs/promises";import Kc from"node:path";var we=async(e,t)=>{let r=await Uc(_r(e,t),"utf8"),n=JSON.parse(r);return Vc(n,_r(e,t))},Ee=async(e,t)=>{await O(_r(e,t.id),{...t,updatedAt:new Date().toISOString()})};var _r=(e,t)=>Kc.join(e.sessionsDir,`${t}.json`);function Vc(e,t){let r=zc(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")||!Hc(r.attach)||!Gc(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 Gc(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 Hc(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 zc(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 Qc}from"node:child_process";import{createHash as Yc}from"node:crypto";import Jc from"node:path";function Ft(e){return`'${e.replace(/'/g,"'\\''")}'`}var Xc="craig",lo=async(e,t,r)=>{let n=qr(e,t),s=ed(),o=await R("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=rd(o.stdout);return await Zc(e,n),i};var Zc=async(e,t)=>{let r=[["set-option","-t",t,"status","off"],["set-option","-t",t,"detach-on-destroy","off"],["set-window-option","-t",t,"pane-border-status","off"],["set-window-option","-t",t,"aggressive-resize","on"]];for(let n of r)await R("tmux",n,{cwd:e})},co=async(e,t,r)=>{await R("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},uo=async(e,t,r)=>{await R("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var po=async(e,t,r)=>{await R("tmux",["pipe-pane","-o","-t",e,`cat >> ${Ft(t)}`],{cwd:r})},Nt=async(e,t,r,n)=>{let s=n??mo(e);if(r?await R("tmux",["select-window","-t",r],{cwd:e}):await R("tmux",["select-window","-t",t],{cwd:e}),await R("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await R("tmux",["switch-client","-t",s],{cwd:e});return}await sd(e,["attach-session","-t",s])};var fo=async(e,t)=>{await R("tmux",["kill-session","-t",t],{cwd:e})};var mo=e=>{let r=Jc.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Yc("sha1").update(e).digest("hex").slice(0,8);return`${Xc}-${r}-${n}`},qr=(e,t)=>`${mo(e)}-${t.toLowerCase()}`,ed=()=>{let e=td();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},td=()=>{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},rd=e=>{let t=nd(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]}},nd=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),sd=async(e,t)=>{await new Promise((r,n)=>{let s=Qc("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 od,constants as id}from"node:fs";import{homedir as go}from"node:os";import Te from"node:path";var ad=[Te.join(go(),".local","bin"),Te.join(go(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ko(e=process.env){return ld([...(e.PATH??"").split(Te.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:ad])}function Ae(e=process.env){return{...e,PATH:ko(e).join(Te.delimiter)}}function Br(e,t={}){if(e.includes(Te.sep)){let r=Te.isAbsolute(e)?e:Te.resolve(t.cwd??process.cwd(),e);return ho(r)?r:null}for(let r of ko(t.env)){let n=Te.join(r,e);if(ho(n))return n}return null}function xe(e,t={}){let r=Br(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 ho(e){try{return od(e,id.X_OK),!0}catch{return!1}}function ld(e){return[...new Set(e)]}var ct={async create(e,t){let r=await lo(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await po(r.paneId,t.logPath,t.repoRoot);let n=await wo({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),s={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||qr(t.repoRoot,t.taskId),paneId:r.paneId,windowTarget:r.windowTarget,worktreePath:t.worktreePath,logPath:t.logPath,command:t.command,status:"starting",startedAt:null,exitedAt:null,exitCode:null,lastAttachedAt:null,attach:{detachChord:"ctrl+]",lastSize:null},snapshot:n,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ee(e,s),s},async attach(e,t,r){let n=await ct.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Nt(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ee(e,s),s},async resize(e,t,r,n){await co(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ee(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 Ee(e,n),n},async snapshot(e,t){return cd(e,t)}},Ur={async prepare(e,t){let n=e.runnerSession.command[0],s=Ae();await R(xe(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=xe(r[0],{cwd:e.worktreePath,env:Ae()});await uo(t.session.paneId,[n,...r.slice(1)].map(s=>Ft(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},cd=async(e,t)=>{let r=await v("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return wo({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},wo=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Kr=async(e,t,r,n={})=>{let s=r.trim(),o=await k.load(e),i=n.runner??k.runners.getDefault(o);if(k.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 at(e,n.workspaceId,s,{runner:i,config:o}):await Ke(e,t,s,{runner:i,config:o}),l=a.task,c=k.runners.buildCommand(i,s,o),d=`session_${l.id}`,p=l.artifacts.logPath?To.resolve(e.workspaceRoot,l.artifacts.logPath):To.join(e.logsDir,`${l.id}.log`);try{await Ur.prepare(l,{repoRoot:a.repoRoot});let f=await ct.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:p,command:c});await Ur.launch(l,{repoRoot:a.repoRoot,session:f});let m=new Date().toISOString();f={...f,status:"running",startedAt:m,command:c};let w={...l,status:"running",runner:i,sessionId:f.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:f.command,pid:null,startedAt:m,lastKnownState:"running",exitCode:null,exitedAt:null}};return await y(e,w),await Ee(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 m={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:f instanceof Error?f.message:"Unknown Craig error"};throw await y(e,m),f}};import{mkdir as Td}from"node:fs/promises";import Rd from"node:path";var Ro=3,dd=1e3,ud=1e4,Ve=async e=>{let t=await v("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var yo=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await R("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},Wt=async(e,t)=>{let r=await R("gh",bo(e),{cwd:t});return JSON.parse(r.stdout)},Ge=async(e,t)=>{let r=await v("gh",bo(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Po=async(e,t,r)=>{if(r.length===0)return[];let n=kd(r),s=await pd(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=wd(c);return{id:a.id,found:d!==null,view:d}})},So=async e=>{let t=await v("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:hd(t.stdout.trim())},pd=async(e,t)=>{let r;for(let n=0;n<=Ro;n+=1)try{return await R("gh",t,{cwd:e})}catch(s){if(r=s,n===Ro||!fd(s))throw s;await gd(md(n))}throw r},fd=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")},md=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||dd,r=Math.min(t*2**e,ud),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},gd=e=>new Promise(t=>setTimeout(t,e)),bo=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],hd=e=>{let t=e.replace(/\.git$/,""),r=t.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)$/);if(r?.[1]&&r[2])return{owner:r[1],name:r[2]};let n=t.match(/^git@github\.com:([^/]+)\/([^/]+)$/);if(n?.[1]&&n[2])return{owner:n[1],name:n[2]};let s=t.match(/^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+)$/);return s?.[1]&&s[2]?{owner:s[1],name:s[2]}:null},kd=e=>`
|
|
35
35
|
query CraigPullRequestBatch($owner: String!, $name: String!) {
|
|
36
36
|
repository(owner: $owner, name: $name) {
|
|
37
37
|
${e.map((r,n)=>{let s=`item${n}`;return r.mode==="number"?`${s}: pullRequest(number: ${Number(r.selector)}) { ...PrFields }`:`${s}: pullRequests(headRefName: ${JSON.stringify(r.selector)}, states: OPEN, first: 1, orderBy: { field: UPDATED_AT, direction: DESC }) { nodes { ...PrFields } }`}).join(`
|
|
@@ -110,10 +110,10 @@ fragment PrFields on PullRequest {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
`,wd=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
|
|
113
|
+
`,wd=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 De=async(e,t)=>{let r=ve(e,t.artifacts.prStatusPath);r&&(await Td(Rd.dirname(r),{recursive:!0}),await O(r,{taskId:t.id,prs:t.prs}))},dt=async(e,t,r,n,s={readRawTask:z,validateTaskRecord:N,writeTask:y,writePrStatusArtifact:De})=>{let o=rt(r,n),i=qe(t,o),a=tt(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=qe({...d,status:p},o);return await s.writeTask(e,f),f},ut=async(e,t)=>{let r=E(t),n=r?.number?String(r.number):t.branch,s=await Wt(n,t.worktreePath);return dt(e,t,s,r)},pt=async(e,t)=>{for(let r of await Vr(t)){let n=await Ge(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await dt(e,t,n,null)}}return{discovered:!1,task:t}},Vr=async e=>{let t=await Xs(e.worktreePath).catch(()=>null);return[...new Set([t,e.branch].filter(r=>!!r))]};var He=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await Wt(n,r.worktreePath),a=Co(i);return r.pullRequest=a,await Io(e,t,r.repoId,a),"synced"}let s=await Ge(n,r.worktreePath);if(!s)return"not_found";let o=Co(s);return r.pullRequest=o,await Io(e,t,r.repoId,o),"discovered"},Io=async(e,t,r,n)=>{let s=await z(e,t.id),o=N(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},Co=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:yd(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Pd(e.reviewDecision??null),requiredChecks:nt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),yd=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Pd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var ft=async(e,t)=>{let r=await S(e,t),n=E(r);return n?.number?(await Ve(r.worktreePath),ke(n)?(await pt(e,r)).task:ut(e,r)):r},Hr=async(e,t)=>{let r=await S(e,t);if(r.type==="project"&&r.repoTargets?.length)return await ze(e,t),S(e,t);let n=E(r);if(await W(r),await Ve(r.worktreePath),!n?.number||ke(n)){let o=await pt(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await De(e,o.task),o.task}let s=await ut(e,r);return await De(e,s),s},ze=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 Ve(a.worktreePath);let l=a.pullRequest.number?await He(e,r,a):await He(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await z(e,r.id),i=N(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=Eo(i),await y(e,i)),s},zr=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=Gr(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let d of s.repoTargets.filter(p=>p.status==="ready")){let p={id:`${s.id}:${d.repoId}`,task:s,targetRepoId:d.repoId,worktreePath:d.worktreePath,selector:d.pullRequest.number?String(d.pullRequest.number):d.branch,mode:d.pullRequest.number?"number":"head",fallbackSelectors:[]};await vo(n,p).catch(async()=>{try{let f=d.pullRequest.number?await He(e,s,d):await He(e,s,d).catch(()=>"not_found");_t(o,f,d.pullRequest.number??null,d.pullRequest.url??null)}catch{}})}continue}let i=E(s),a=i?.number&&!ke(i),l=a?[]:await Vr(s),c={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):l[0]??s.branch,mode:a?"number":"head",fallbackSelectors:a?[]:l.slice(1)};await vo(n,c).catch(async()=>{try{let{disposition:d,task:p}=await qt(e,s.id),f=E(p);_t(o,d,f?.number??null,f?.url??null)}catch{}})}for(let s of n.values())try{await Ve(s.worktreePath);let o=await Po(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=Gr(r,a.task),d=i.get(a.id)?.view??await vd(s.worktreePath,a);if(!d){_t(l,"not_found",null,null);continue}if(a.targetRepoId){let p=await z(e,a.task.id),f=N(p,`${e.tasksDir}/${a.task.id}.json`);await Sd(e,f,a.targetRepoId,d)}else{let p=await z(e,a.task.id),f=N(p,`${e.tasksDir}/${a.task.id}.json`);await dt(e,f,d,a.mode==="number"?E(f):null)}_t(l,a.mode==="number"?"synced":"discovered",d.number,d.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await z(e,s.id),i=N(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=Eo(i),await y(e,i))}return t.map(s=>Gr(r,s))},qt=async(e,t)=>{let r=await S(e,t);await W(r),await Ve(r.worktreePath);let n=E(r);if(n?.number&&!ke(n))return{disposition:"synced",task:await ut(e,r)};let s=await pt(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},Eo=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(Ed)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},Sd=async(e,t,r,n)=>{let s=bd(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await y(e,i),i},bd=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Id(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Cd(e.reviewDecision??null),requiredChecks:nt(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),Id=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Cd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,vd=async(e,t)=>{if(t.mode!=="head")return null;for(let r of t.fallbackSelectors){let n=await Ge(r,e);if(n)return n}return null},vo=async(e,t)=>{let r=await So(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]})},Gr=(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):!!E(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},_t=(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},Ed=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 Qr=async(e,t)=>{let r=await S(e,t);try{r.type==="project"&&r.repoTargets?.length?(await ze(e,t),r=await S(e,t)):r.prs.some(o=>o.number)&&(r=await ft(e,t))}catch{}let n=await st(e,r),s=r.sessionId?await we(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var Yr=async(e,t)=>{let r=await S(e,t);if(await W(r),(await R("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await Ad(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},Ad=async e=>{let t=[],r=await R("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await xd(e);for(let s of n){let o=await v("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
|
|
114
114
|
|
|
115
|
-
`)},xd=async e=>(await
|
|
116
|
-
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Dd}from"node:child_process";import{access as $d}from"node:fs/promises";var Jr=async(e,t)=>{let r=await S(e,t),n=qe(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await $d(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Xr=async e=>{await new Promise((t,r)=>{let n=!1,s=Dd("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 Ld}from"node:fs/promises";import jd from"node:path";var Zr=async(e,t)=>{let r=await S(e,t);if(await W(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await Lt(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 k.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 Ao(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 Ao(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Ao=async(e,t)=>{let r=Ce(e,t.artifacts.checkSummaryPath);r&&(await Ld(jd.dirname(r),{recursive:!0}),await O(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var en=async(e,t)=>{let r=await S(e,t);await W(r);let n=await Lt(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 Qs(r.worktreePath),await Ys(r.worktreePath,s);let o=await Js(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 Md}from"node:fs/promises";var tn=async(e,t)=>{let r=await S(e,t),n=await Od(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},Od=async e=>{try{return await Md(e),!0}catch{return!1}};var rn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await he(e,t.sessionId);await fo(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 Zs(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 nn=async(e,t,r)=>{let[n,s]=await Promise.all([S(e,t),Z(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await y(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},sn=async(e,t)=>{let r=await S(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>Z(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var on=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([Z(e,r.repoId),he(e,r.sessionId)]),o=await lt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var an=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 Fd(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 Ft(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Fd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Nd}from"node:child_process";var ln=async(e,t)=>{let r=await S(e,t);await W(r);let s=(await k.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 Wd(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Wd=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Nd(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 cn=async(e,t,r)=>{let n=await J(e,t);await y(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},dn=async(e,t,r)=>{let n=await J(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await y(e,s),s},un=async(e,t)=>{let r=await J(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await y(e,s),s};var pn=async(e,t,r="merge",n)=>{let s=await S(e,t),o=n??A(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await yo(s.worktreePath,o,r)};var b={listTasks:Or,getTask:S,provisionTask:Ue,provisionProjectTask:it,createTask:Kr,showTask:Qr,showTaskDiff:Yr,prepareTaskLogs:Jr,streamTaskLogs:Xr,runChecks:Zr,commitTask:en,closeTask:tn,cleanupTask:rn,addTaskLink:nn,listTaskLinks:sn,sortTasksForDisplay:Fr,resolveSelectedTaskId:Nr,allocateTaskId:Mr,allocateTaskIdForRepo:Be,allocateProjectTaskId:st,createDefaultTaskPtyTabs:at,assertTaskWorktreeExists:W,resolveTaskLogPath:qe,buildTaskInspection:nt,resolveArtifactPath:Ce,attachTask:on,focusTask:an,openTask:ln,markRunnerFailed:cn,recordStartupFailure:dn,markTaskStarted:un,prs:{refresh:pt,refreshChecks:Hr,discoverOrRefresh:_t,discoverOrRefreshAll:He,discoverOrRefreshMany:zr,merge:pn,getPrimaryPr:A,isPrTerminal:ge,isMergeReady:$t,deriveTaskStatus:et,upsertPr:_e,normalizePr:tt,summarizeRequiredChecks:$r,writePrStatusArtifact:xe}};async function xo(e,t){switch(e.kind){case"addWorkspace":{let r=await H.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await fn(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await H.repos.addRepo(t.paths,e.path);return await fn(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return H.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Oe({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Y(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await H.repos.removeRepo(t.paths,e.repoId,{listTasks: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 H.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await H.archiveWorkspace(t.paths,e.workspaceId);return await _d(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await H.restoreWorkspace(t.paths,e.workspaceId);return await fn(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return H.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,De(t,"show"));case"streamTaskLogs":return b.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return b.prepareTaskLogs(t.paths,De(t,"logs"));case"showTaskDiff":return b.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return b.showTaskDiff(t.paths,De(t,"diff"));case"focusTask":return b.focusTask(t.paths,e.taskId);case"focusSelectedTask":return b.focusTask(t.paths,De(t,"focus"));case"openTask":return b.openTask(t.paths,e.taskId);case"openSelectedTask":return b.openTask(t.paths,De(t,"open"));case"runChecks":return b.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return b.runChecks(t.paths,De(t,"check"));case"commitTask":return b.commitTask(t.paths,e.taskId);case"commitSelectedTask":return b.commitTask(t.paths,De(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return qd(e)}}async function fn(e,t,r){let n=await Oe({uiStateFile:e.uiStateFile})??bt();await me({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function _d(e,t){let r=await Oe({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await me({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function qd(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function De(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 Do(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
|
+
`)},xd=async e=>(await R("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
116
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Dd}from"node:child_process";import{access as $d}from"node:fs/promises";var Jr=async(e,t)=>{let r=await S(e,t),n=Be(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await $d(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Xr=async e=>{await new Promise((t,r)=>{let n=!1,s=Dd("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 Ld}from"node:fs/promises";import jd from"node:path";var Zr=async(e,t)=>{let r=await S(e,t);if(await W(r),r.status==="draft"||r.status==="merged")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);if(r.status==="running"&&await jt(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 k.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 v("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 Ao(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 Ao(e,r),await y(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Ao=async(e,t)=>{let r=ve(e,t.artifacts.checkSummaryPath);r&&(await Ld(jd.dirname(r),{recursive:!0}),await O(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var en=async(e,t)=>{let r=await S(e,t);await W(r);let n=await jt(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 Qs(r.worktreePath),await Ys(r.worktreePath,s);let o=await Js(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 Md}from"node:fs/promises";var tn=async(e,t)=>{let r=await S(e,t),n=await Od(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},Od=async e=>{try{return await Md(e),!0}catch{return!1}};var rn=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await we(e,t.sessionId);await fo(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 Zs(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 nn=async(e,t,r)=>{let[n,s]=await Promise.all([S(e,t),Z(e,r)]);if(n.repoId===s.id)throw new Error(`Repo ${s.id} is already the primary repo for task ${n.id}.`);let o=n.linkedRepoIds.includes(s.id)?n.linkedRepoIds:[...n.linkedRepoIds,s.id];return await y(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},sn=async(e,t)=>{let r=await S(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>Z(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var on=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([Z(e,r.repoId),we(e,r.sessionId)]),o=await ct.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var an=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 we(e,r.sessionId).catch(s=>{throw Fd(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 Nt(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Fd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Nd}from"node:child_process";var ln=async(e,t)=>{let r=await S(e,t);await W(r);let s=(await k.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 Wd(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Wd=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Nd(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 cn=async(e,t,r)=>{let n=await J(e,t);await y(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},dn=async(e,t,r)=>{let n=await J(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await y(e,s),s},un=async(e,t)=>{let r=await J(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await y(e,s),s};var pn=async(e,t,r="merge",n)=>{let s=await S(e,t),o=n??E(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await yo(s.worktreePath,o,r)};var b={listTasks:Or,getTask:S,provisionTask:Ke,provisionProjectTask:at,createTask:Kr,showTask:Qr,showTaskDiff:Yr,prepareTaskLogs:Jr,streamTaskLogs:Xr,runChecks:Zr,commitTask:en,closeTask:tn,cleanupTask:rn,addTaskLink:nn,listTaskLinks:sn,sortTasksForDisplay:Fr,resolveSelectedTaskId:Nr,allocateTaskId:Mr,allocateTaskIdForRepo:Ue,allocateProjectTaskId:ot,createDefaultTaskPtyTabs:lt,assertTaskWorktreeExists:W,resolveTaskLogPath:Be,buildTaskInspection:st,resolveArtifactPath:ve,attachTask:on,focusTask:an,openTask:ln,markRunnerFailed:cn,recordStartupFailure:dn,markTaskStarted:un,prs:{refresh:ft,refreshChecks:Hr,discoverOrRefresh:qt,discoverOrRefreshAll:ze,discoverOrRefreshMany:zr,merge:pn,getPrimaryPr:E,isPrTerminal:ke,isMergeReady:Lt,deriveTaskStatus:tt,upsertPr:qe,normalizePr:rt,summarizeRequiredChecks:$r,writePrStatusArtifact:De}};async function xo(e,t){switch(e.kind){case"addWorkspace":{let r=await H.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await fn(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await H.repos.addRepo(t.paths,e.path);return await fn(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return H.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await Fe({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Y(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await H.repos.removeRepo(t.paths,e.repoId,{listTasks:b.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await he({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await he({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return H.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await H.archiveWorkspace(t.paths,e.workspaceId);return await _d(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await H.restoreWorkspace(t.paths,e.workspaceId);return await fn(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return H.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,$e(t,"show"));case"streamTaskLogs":return b.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return b.prepareTaskLogs(t.paths,$e(t,"logs"));case"showTaskDiff":return b.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return b.showTaskDiff(t.paths,$e(t,"diff"));case"focusTask":return b.focusTask(t.paths,e.taskId);case"focusSelectedTask":return b.focusTask(t.paths,$e(t,"focus"));case"openTask":return b.openTask(t.paths,e.taskId);case"openSelectedTask":return b.openTask(t.paths,$e(t,"open"));case"runChecks":return b.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return b.runChecks(t.paths,$e(t,"check"));case"commitTask":return b.commitTask(t.paths,e.taskId);case"commitSelectedTask":return b.commitTask(t.paths,$e(t,"commit"));case"help":return{kind:"help",text:K()};case"exit":return{kind:"exit"};default:return qd(e)}}async function fn(e,t,r){let n=await Fe({uiStateFile:e.uiStateFile})??It();await he({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function _d(e,t){let r=await Fe({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await he({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function qd(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function $e(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 Do(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(`
|
|
@@ -122,44 +122,45 @@ fragment PrFields on PullRequest {
|
|
|
122
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} ${Kd(t)} ${Vd(t)} ${t.title}`)].join(`
|
|
123
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}`,...Bd(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 Ud(e)}}function Bd(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 Ud(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Kd(e){return e.checks.status}function Vd(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
|
|
125
|
+
`);default:return Ud(e)}}function Bd(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 Ud(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Kd(e){return e.checks.status}function Vd(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 dm}from"node:module";import{readFile as Gd,stat as Hd}from"node:fs/promises";import mn from"node:path";var zd=200*1024,Qd=500*1024,Bt="100000";async function Lo(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return Yd(e,t,r);try{let n=Re(r.selectedFilePath??null,t.filePaths),s=Re(r.selectedDiffPath??null,t.diffPaths),o=s?await mt(e.worktreePath):null,[i,a]=await Promise.all([Kt(e.worktreePath,n),s?gn(e.worktreePath,s,t.diffRows,o):Promise.resolve(U("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 Yd(e,t,r){let n=Re(r.selectedFilePath??null,t.filePaths),s=Re(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([Mo(e,n),(async()=>{if(!s)return U("No diff selected","No local changes found.","empty");let l=Ut(e,s),c=l?await mt(l.target.worktreePath).catch(()=>null):null;return Oo(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function jo(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return Jd(e,t);try{await W(e);let r=await mt(e.worktreePath),[n,s]=await Promise.all([Fo(e.worktreePath),No(e.worktreePath,r)]),o=[...new Set(s.map(p=>p.path))],i=Re(t.selectedFilePath??null,n),a=Re(t.selectedDiffPath??null,o),[l,c]=await Promise.all([Kt(e.worktreePath,i),a?gn(e.worktreePath,a,s,r):Promise.resolve(U("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:qo(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:U("Files unavailable",n,"error"),selectedDiff:U("Diff unavailable",n,"error"),error:n}}}async function Jd(e,t){let r=(e.repoTargets??[]).filter(f=>f.status==="ready"),n=await Promise.all(r.map(async f=>{let m=await mt(f.worktreePath).catch(()=>null),[w,u]=await Promise.all([Fo(f.worktreePath).catch(()=>[]),No(f.worktreePath,m).catch(()=>[])]);return{target:f,baseRef:m,targetFiles:w,targetDiffRows:u}})),s=[],o=[];for(let{target:f,targetFiles:m,targetDiffRows:w}of n)s.push(...m.map(u=>`${f.repoId}/${u}`)),o.push(...w.map(u=>({...u,path:`${f.repoId}/${u.path}`})));let i=[...new Set(o.map(f=>f.path))].sort(),a=Re(t.selectedFilePath??null,s),l=Re(t.selectedDiffPath??null,i),[c,d]=await Promise.all([Mo(e,a),(async()=>{if(!l)return U("No diff selected","No local changes found.","empty");let f=Ut(e,l),m=f?n.find(w=>w.target.repoId===f.target.repoId):null;return Oo(e,l,o,m?.baseRef??null)})()]),p=l?{[l]:d}:{};return{taskId:e.id,fileRows:qo(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:p,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function Mo(e,t){let r=Ut(e,t);if(!r)return U("No file selected","No Git-visible files found.","empty");let n=await Kt(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function Oo(e,t,r,n=null){let s=Ut(e,t);return s?{...await gn(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}:U(t,"Repo target is unavailable.","error",t)}function Ut(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 Fo(e){let t=await R("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Bo(t.stdout)}async function No(e,t){let[r,n,s,o]=await Promise.all([Xd(e,t),$o(e,"staged"),$o(e,"unstaged"),Zd(e)]);return[...r,...n,...s,...o]}async function Xd(e,t){if(!t)return[];let[r,n]=await Promise.all([R("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),R("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=Wo(r.stdout),o=_o(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 $o(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([R("git",[...r,"--name-status"],{cwd:e}),R("git",[...r,"--numstat"],{cwd:e})]),o=Wo(n.stdout),i=_o(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 Zd(e){let t=await R("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Bo(t.stdout);return await Promise.all(r.map(async s=>{let o=await Kt(e,s),i=o.status==="ready"?eu(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function Wo(e){return e.split(`
|
|
126
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 _o(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
|
|
128
|
-
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return U(t,s,"missing",t,null)}}async function gn(e,t,r,n=null){if(!t)return U("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
|
|
129
|
-
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await
|
|
130
|
-
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await
|
|
131
|
-
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await
|
|
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 mt(e){return(await v("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await v("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function Kt(e,t){if(!t)return U("No file selected","No Git-visible files found.","empty");let r=tu(e,t);try{let n=await Hd(r);if(n.size>zd)return U(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await Gd(r);return ru(s)?U(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 U(t,s,"missing",t,null)}}async function gn(e,t,r,n=null){if(!t)return U("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 mt(e);if(a){let l=await R("git",["diff","--stat","--patch",`--unified=${Bt}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
129
|
+
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await R("git",["diff","--cached","--stat","--patch",`--unified=${Bt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
130
|
+
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await R("git",["diff","--stat","--patch",`--unified=${Bt}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
|
|
131
|
+
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await v("git",["diff","--no-index","--stat","--patch",`--unified=${Bt}`,"--","/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
134
|
`);return i.length>Qd?U(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?U(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 qo(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
|
|
136
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function tu(e,t){let r=mn.resolve(e,t),n=mn.resolve(e);if(r!==n&&!r.startsWith(`${n}${mn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function ru(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function U(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var nu=["tasks","center","inspector","actions"],Ho=["agent","terminal"],zo=[],I="inspection",IR=[...Ho,...zo],Qo=["commit","push","refresh-checks","close-task"],su=["refresh-checks","close-task"],Yo=["task","checks","pr","setup-run","actions","next-action"],Jo=["diff","files","review"];function Xo(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=yu(e?.openInspectionKind)??r,s=k.runners.getEnabled(t);return{inputMode:Su(e?.inputMode),focusedRegion:Tu(e?.focusedRegion),selectedRepoId:de(e?.selectedRepoId),selectedWorkspaceId:de(e?.selectedWorkspaceId),selectedTaskId:de(e?.selectedTaskId),selectedPtyTabId:de(e?.selectedPtyTabId),selectedLeftItemId:$u(de(e?.selectedTaskId)),activeTab:r?I:de(e?.activeTab)??"agent",preferredPtyTabKind:Pu(e?.preferredPtyTabKind),inspectorSection:mt(e?.inspectorSection,Yo,"task"),inspectionMode:Ru(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:de(e?.selectedFileTreePath),selectedFilePath:de(e?.selectedFilePath),selectedDiffPath:de(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:mt(e?.selectedActionId,Qo,"commit"),selectedProjectTargetId:null,selectedRunner:bu(e?.selectedRunner,s,k.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:ou(),centerZoomed:!1}}function ou(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Zo(e,t){return{...e??bt(),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 ht(e,t,r={}){let n=xu(e,t),s=ii(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,...Cu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:hu(e,t,c?.id??null),...vu(e,t,c?.id??null),selectedDiffPath:gu(e,t,c?.id??null),inspectorSection:mt(e.inspectorSection,Yo,"task")}}function iu(e,t,r){if(t==="ESCAPE")return h({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return h({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return kn(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Rn({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return h({state:{...e,fileSearchQuery:n},changed:!0})}return h({state:e})}function Rn(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return au(t)?h({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):h({state:e});if(e.fileSearchQuery!==null)return iu(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return h({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return h({state:e,exit:!0});if(t==="ESCAPE")return h({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return h({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(wn(e.selectedLeftItemId)||Tn(e.selectedLeftItemId)))return h({state:{...e,selectedRunner:yn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Uo(e,1);if(t==="SHIFT_TAB"||t==="[")return Uo(e,-1);if(t==="z"||t==="Z")return h({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):kn(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?Te(e,1,r):kn(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 h({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=Iu(e,t);return h({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 h({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return h({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Gt(e.selectedLeftItemId)&&e.selectedTaskId)return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Lu(e.selectedLeftItemId)&&e.selectedWorkspaceId)return h({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Go(e.activeTab,r.ptyTabIds??[]))return h({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return hn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ko(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return hn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ko(e,1)}if(ie(t)){if(e.focusedRegion==="tasks"&&(wn(e.selectedLeftItemId)||Tn(e.selectedLeftItemId))){let n=ai(e.selectedLeftItemId),s=li(e.selectedLeftItemId);return h({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 h({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Gt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return h({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:gt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Go(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return h({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:gt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===I)return h({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 h({state:pu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return h({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"?h({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?h({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):h({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?h({state:e}):e.selectedActionId==="refresh-checks"?h({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?h({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):h({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return h({state:e})}function pe(e,t){return{...e,terminal:t}}function ei(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function au(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function ie(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
137
|
-
`}function ti(e){return e.length===1&&e>=" "&&e!=="\x7F"}function ri(e){return ni(e)||gt(e)!==null}function lu(e){return zo.includes(e)}function ni(e){return Ho.includes(e)}function si(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var cu=["tasks","center","inspector"];function Uo(e,t){return Kt(e,"focusedRegion",cu,t)}function hn(e,t,r){let n=Kt(e,"activeTab",r&&r.length>0?r:Au(e),t);return!n.changed||lu(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:gt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function kn(e,t,r){if(e.focusedRegion==="tasks")return du(e,t,r.leftItemIds);if(e.focusedRegion==="center")return hn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return oi(e,t,r);if(e.inspectionMode==="diff"){let n=Vt(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=Vt(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return Kt(e,"selectedActionId",su,t)}return Kt(e,"selectedActionId",Qo,t)}function du(e,t,r){let n=Vt(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=ii(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=ai(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=li(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Te(e,t,r){if(t===0)return h({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return oi(e,t,r);if(e.inspectionMode==="diff"){let n=Vt(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?Vo(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):h({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return Vo(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return fu(e,t,r)}return h({state:e})}function uu(e,t){if(e.inspectionMode===t)return h({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return h({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 Ko(e,t){return uu(e,wu(e.inspectionMode,Jo,t))}function oi(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return h({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=ue(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return h({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return h({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 pu(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 Vo(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=ue(e[t]+r,0,o);return i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function fu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return mu(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=ue(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=ue(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?h({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?h({state:e}):h({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?h({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?h({state:e}):h({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=ue(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function mu(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=ue(e.diffScrollOffset+t,0,o),a=ku(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?h({state:e}):h({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function gu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function hu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function ku(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Kt(e,t,r,n){let s=r.indexOf(e[t]),o=ue(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Vt(e,t,r,n,s=!1){if(r.length===0)return h({state:e});let o=r.indexOf(e[t]??r[0]??""),i=ue(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?h({state:e}):h({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function wu(e,t,r){let n=t.indexOf(e);return t[ue(n+r,0,t.length-1)]??e}function h(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 mt(e,t,r){return t.includes(e??"")?e:r}function Tu(e){return e==="tabs"?"center":mt(e,nu,"tasks")}function Ru(e,t){return e==="checks"||e==="actions"||e==="review"?"review":mt(e,Jo,t)}function yu(e){return e==="file"||e==="diff"?e:null}function Pu(e){return e==="terminal"?"terminal":"agent"}function Su(e){return e==="terminal"?"terminal":"control"}function bu(e,t=[...x],r="codex"){return e&&k.runners.isRunnerType(e)&&t.includes(e)?e:r}function yn(e,t=x){let r=t.length>0?t:x,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function gt(e){let t=x.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Iu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":gt(e.activeTab)??e.preferredPtyTabKind}function Cu(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(ni(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 vu(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?Eu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function Eu(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 Au(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function Go(e,t){return t.includes(e)}function xu(e,t){let r=Du(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 Du(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 ii(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 de(e){return typeof e=="string"?e:null}function $u(e){return e?`task:${e}`:null}function Gt(e){return typeof e=="string"&&e.startsWith("task:")}function wn(e){return typeof e=="string"&&e.startsWith("new-task:")}function Tn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Lu(e){return typeof e=="string"&&e.startsWith("workspace:")}function ai(e){return wn(e)?e.slice(9):null}function li(e){return Tn(e)?e.slice(19):null}function ue(e,t,r){return Math.min(r,Math.max(t,e))}async function Re(e,t,r){let n=se(e),[s,o]=await Promise.all([H.repos.listRegisteredRepos(n),H.listWorkspaces(n,{archived:!1})]),i=await b.listTasks(n),a=Pn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await jo(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function Pn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ci(e,t){return ht(e,t)}function kt(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 An from"node:path";import jR from"picocolors";var ju=[" \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 Sn(){return[...ju]}var Ht={width:120,height:36},ee={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function te(e,t){return{width:Math.max(e??Ht.width,Ht.width),height:Math.max(t??Ht.height,Ht.height)}}var Mu=["Start","Options","Exit"],Ou=["Resume","Options","Exit"],Yt=2,Jt=2,Xt=2,Fu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Nu=new RegExp("\x1B\\[(?:0)?m","g"),Wu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),_u=/https?:\/\/[^\s<>"']+/g,bn="\x1B[0m",In="\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 pi(e,t={}){return vn(e,{subtitle:"crAIg is that you?",menuItems:Mu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function fi(e,t={}){return vn(e,{subtitle:"Control mode is paused.",menuItems:Ou,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var zt=[" 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."],qu=["Help"];function Cn(e,t={}){return vn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??qu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function mi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o=Sn(),i=Math.max(1,Math.floor((e.height-o.length-2-zt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=L(Ti(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...zt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<zt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=zt[d]??"";s[p]=L(ae(" ".repeat(l)+f,e.width),r,n)}return s.join(`
|
|
138
|
-
`)}function gi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},X(),...a.length>0?a.map(m=>({text:m})):[{text:"No Craig errors have been logged.",tone:"muted"}],X(),{text:"Esc returns to Options.",tone:"muted"}],p=
|
|
139
|
-
`)}function hi(e,t,r={}){let n=r.color??!0,s=ee.leftWidth,o=ee.rightWidth,i=ee.dividerWidth,a=r.centerOnly??!1,l=a?e.width:e.width-s-o-i*2,c=e.height-ee.topRailHeight-1,d=r.focusFlashActive??!1,p={bg:P.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:P.divider,m=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:P.divider,
|
|
140
|
-
`)}function Bu(e,t,r,n,s){let o=` ${e}`;if(!t)return L(ae(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=Q(i),l=Q(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?
|
|
141
|
-
`)}function Uu(e,t,r,n){let s=Qu(e.runners),o=1,i=e.leftTree.map(l=>zu(l,t,n));return[...
|
|
135
|
+
`):["No diff for this file."],byteLength:i.length}}function qo(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 Re(e,t){return e&&t.includes(e)?e:t[0]??null}function eu(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Bo(e){return[...new Set(e.split(`
|
|
136
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function tu(e,t){let r=mn.resolve(e,t),n=mn.resolve(e);if(r!==n&&!r.startsWith(`${n}${mn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function ru(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function U(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var nu=["tasks","center","inspector","actions"],Ho=["agent","terminal"],zo=[],I="inspection",CR=[...Ho,...zo],Qo=["commit","push","refresh-checks","close-task"],su=["refresh-checks","close-task"],Yo=["task","checks","pr","setup-run","actions","next-action"],Jo=["diff","files","review"];function Xo(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=yu(e?.openInspectionKind)??r,s=k.runners.getEnabled(t);return{inputMode:Su(e?.inputMode),focusedRegion:Tu(e?.focusedRegion),selectedRepoId:de(e?.selectedRepoId),selectedWorkspaceId:de(e?.selectedWorkspaceId),selectedTaskId:de(e?.selectedTaskId),selectedPtyTabId:de(e?.selectedPtyTabId),selectedLeftItemId:$u(de(e?.selectedTaskId)),activeTab:r?I:de(e?.activeTab)??"agent",preferredPtyTabKind:Pu(e?.preferredPtyTabKind),inspectorSection:gt(e?.inspectorSection,Yo,"task"),inspectionMode:Ru(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:n,selectedFileTreePath:de(e?.selectedFileTreePath),selectedFilePath:de(e?.selectedFilePath),selectedDiffPath:de(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:gt(e?.selectedActionId,Qo,"commit"),selectedProjectTargetId:null,selectedRunner:bu(e?.selectedRunner,s,k.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:ou(),centerZoomed:!1}}function ou(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Zo(e,t){return{...e??It(),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 kt(e,t,r={}){let n=xu(e,t),s=ii(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,...Cu(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:hu(e,t,c?.id??null),...vu(e,t,c?.id??null),selectedDiffPath:gu(e,t,c?.id??null),inspectorSection:gt(e.inspectorSection,Yo,"task")}}function iu(e,t,r){if(t==="ESCAPE")return h({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return h({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return kn(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Rn({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return h({state:{...e,fileSearchQuery:n},changed:!0})}return h({state:e})}function Rn(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return au(t)?h({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):h({state:e});if(e.fileSearchQuery!==null)return iu(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return h({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return h({state:e,exit:!0});if(t==="ESCAPE")return h({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return h({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(wn(e.selectedLeftItemId)||Tn(e.selectedLeftItemId)))return h({state:{...e,selectedRunner:yn(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Uo(e,1);if(t==="SHIFT_TAB"||t==="[")return Uo(e,-1);if(t==="z"||t==="Z")return h({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===I?ye(e,-1,r):kn(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===I?ye(e,1,r):kn(e,1,r);if(t==="PAGE_UP")return ye(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return ye(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return ye(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return ye(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 h({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=Iu(e,t);return h({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 h({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return h({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Ht(e.selectedLeftItemId)&&e.selectedTaskId)return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Lu(e.selectedLeftItemId)&&e.selectedWorkspaceId)return h({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Go(e.activeTab,r.ptyTabIds??[]))return h({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return hn(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ko(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return hn(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Ko(e,1)}if(ie(t)){if(e.focusedRegion==="tasks"&&(wn(e.selectedLeftItemId)||Tn(e.selectedLeftItemId))){let n=ai(e.selectedLeftItemId),s=li(e.selectedLeftItemId);return h({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 h({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Ht(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return h({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:ht(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Go(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return h({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:ht(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===I)return h({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 h({state:pu({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return h({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"?h({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?h({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):h({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?h({state:e}):e.selectedActionId==="refresh-checks"?h({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?h({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):h({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return h({state:e})}function pe(e,t){return{...e,terminal:t}}function ei(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function au(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function ie(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
137
|
+
`}function ti(e){return e.length===1&&e>=" "&&e!=="\x7F"}function ri(e){return ni(e)||ht(e)!==null}function lu(e){return zo.includes(e)}function ni(e){return Ho.includes(e)}function si(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[I]:[]]}var cu=["tasks","center","inspector"];function Uo(e,t){return Vt(e,"focusedRegion",cu,t)}function hn(e,t,r){let n=Vt(e,"activeTab",r&&r.length>0?r:Au(e),t);return!n.changed||lu(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:ht(n.state.activeTab)??n.state.preferredPtyTabKind}}}function kn(e,t,r){if(e.focusedRegion==="tasks")return du(e,t,r.leftItemIds);if(e.focusedRegion==="center")return hn(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return oi(e,t,r);if(e.inspectionMode==="diff"){let n=Gt(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=Gt(e,"selectedProjectTargetId",r.projectTargetIds,t);return n.changed?{...n,state:{...n.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:n}return Vt(e,"selectedActionId",su,t)}return Vt(e,"selectedActionId",Qo,t)}function du(e,t,r){let n=Gt(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=ii(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=ai(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=li(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function ye(e,t,r){if(t===0)return h({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return oi(e,t,r);if(e.inspectionMode==="diff"){let n=Gt(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,diffScrollOffset:0}}:n}return e.inspectionMode==="review"?Vo(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):h({state:e})}if(e.focusedRegion==="center"&&e.activeTab===I){if(e.openInspectionKind==="file")return Vo(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return fu(e,t,r)}return h({state:e})}function uu(e,t){if(e.inspectionMode===t)return h({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,n=t==="diff"||t==="files"?I:e.activeTab;return h({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 Ko(e,t){return uu(e,wu(e.inspectionMode,Jo,t))}function oi(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return h({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=ue(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return h({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return h({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 pu(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 Vo(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=ue(e[t]+r,0,o);return i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function fu(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return mu(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=ue(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=ue(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?h({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?h({state:e}):h({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?h({state:{...e,selectedDiffPath:d,activeTab:I,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?h({state:e}):h({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=ue(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function mu(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=ue(e.diffScrollOffset+t,0,o),a=ku(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?h({state:e}):h({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function gu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function hu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function ku(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Vt(e,t,r,n){let s=r.indexOf(e[t]),o=ue(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Gt(e,t,r,n,s=!1){if(r.length===0)return h({state:e});let o=r.indexOf(e[t]??r[0]??""),i=ue(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?h({state:e}):h({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function wu(e,t,r){let n=t.indexOf(e);return t[ue(n+r,0,t.length-1)]??e}function h(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 gt(e,t,r){return t.includes(e??"")?e:r}function Tu(e){return e==="tabs"?"center":gt(e,nu,"tasks")}function Ru(e,t){return e==="checks"||e==="actions"||e==="review"?"review":gt(e,Jo,t)}function yu(e){return e==="file"||e==="diff"?e:null}function Pu(e){return e==="terminal"?"terminal":"agent"}function Su(e){return e==="terminal"?"terminal":"control"}function bu(e,t=[...x],r="codex"){return e&&k.runners.isRunnerType(e)&&t.includes(e)?e:r}function yn(e,t=x){let r=t.length>0?t:x,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function ht(e){let t=x.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Iu(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":ht(e.activeTab)??e.preferredPtyTabKind}function Cu(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(ni(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 vu(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?Eu(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function Eu(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 Au(e){return[e.selectedPtyTabId,e.openInspectionKind?I:null].filter(t=>typeof t=="string")}function Go(e,t){return t.includes(e)}function xu(e,t){let r=Du(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 Du(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 ii(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 de(e){return typeof e=="string"?e:null}function $u(e){return e?`task:${e}`:null}function Ht(e){return typeof e=="string"&&e.startsWith("task:")}function wn(e){return typeof e=="string"&&e.startsWith("new-task:")}function Tn(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Lu(e){return typeof e=="string"&&e.startsWith("workspace:")}function ai(e){return wn(e)?e.slice(9):null}function li(e){return Tn(e)?e.slice(19):null}function ue(e,t,r){return Math.min(r,Math.max(t,e))}async function Pe(e,t,r){let n=se(e),[s,o]=await Promise.all([H.repos.listRegisteredRepos(n),H.listWorkspaces(n,{archived:!1})]),i=await b.listTasks(n),a=Pn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await jo(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function Pn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ci(e,t){return kt(e,t)}function wt(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 An from"node:path";import MR from"picocolors";var ju=[" \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 Sn(){return[...ju]}var zt={width:120,height:36},ee={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function te(e,t){return{width:Math.max(e??zt.width,zt.width),height:Math.max(t??zt.height,zt.height)}}var Mu=["Start","Options","Exit"],Ou=["Resume","Options","Exit"],Jt=2,Xt=2,Zt=2,Fu=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Nu=new RegExp("\x1B\\[(?:0)?m","g"),Wu=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),_u=/https?:\/\/[^\s<>"']+/g,bn="\x1B[0m",In="\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 pi(e,t={}){return vn(e,{subtitle:"crAIg is that you?",menuItems:Mu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function fi(e,t={}){return vn(e,{subtitle:"Control mode is paused.",menuItems:Ou,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var Qt=[" 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."],qu=["Help"];function Cn(e,t={}){return vn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??qu,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function mi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o=Sn(),i=Math.max(1,Math.floor((e.height-o.length-2-Qt.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=L(Ti(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...Qt.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<Qt.length;d+=1){let p=c+d;if(p>=e.height)break;let f=Qt[d]??"";s[p]=L(ae(" ".repeat(l)+f,e.width),r,n)}return s.join(`
|
|
138
|
+
`)}function gi(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},X(),...a.length>0?a.map(m=>({text:m})):[{text:"No Craig errors have been logged.",tone:"muted"}],X(),{text:"Esc returns to Options.",tone:"muted"}],p=Tt(d,e.height-2),f=Math.max(1,Math.floor((e.height-p.length)/2));for(let m=0;m<p.length;m+=1){let w=f+m;if(w>=e.height)break;let u=p[m]??X(),D=`${" ".repeat(c)}${tr(u.text,l)}`,B=u.tone==="selected"?P.overlayMenuSelected:u.tone==="muted"?P.overlay:P.panelBg;s[w]=L(ae(D,e.width),r,B)}return s.join(`
|
|
139
|
+
`)}function hi(e,t,r={}){let n=r.color??!0,s=ee.leftWidth,o=ee.rightWidth,i=ee.dividerWidth,a=r.centerOnly??!1,l=a?e.width:e.width-s-o-i*2,c=e.height-ee.topRailHeight-1,d=r.focusFlashActive??!1,p={bg:P.divider.bg,fg:"9ece6a"},f=d&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?p:P.divider,m=d&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?p:P.divider,w=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,u=L(ae(w,e.width),n,P.rail),D=Uu(t,s-Jt-Xt,c,n),B=Ku(t,l,c,n),me=Gu(t,o,c,n),ge=t.inputMode==="terminal",T=[];for(let le=0;le<c;le+=1){if(a){T.push(Yt(B[le]??X(),l,n,"center"));continue}let ll=Yt(D[le]??X(),s,n,"left"),cl=L("\u2502",n,f),dl=Yt(B[le]??X(),l,n,"center"),ul=L("\u2502",n,m),pl=Yt(me[le]??X(),o,n,"right");T.push(`${ll}${cl}${dl}${ul}${pl}`)}let Me=ge||t.modalInput?P.panelBg:P.panelMuted,A=Bu(t.footerText,t.footerToast,e.width,n,Me);return[u,...T,A].join(`
|
|
140
|
+
`)}function Bu(e,t,r,n,s){let o=` ${e}`;if(!t)return L(ae(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=Q(i),l=Q(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?tr(o,Math.max(0,r-a-3)):o,p=Math.max(1,r-Q(d)-a-2),f=t.tone==="error"?up(i,n,s):Qe(i,n,s),m=`${d}${" ".repeat(p)}${f} `;return L(ae(m,r),n,s)}function vn(e,t){let r=new Array(e.height).fill(L(" ".repeat(e.width),t.color,P.overlay)),n=Sn(),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=Ti(a[c]??"",e.width);if(c<n.length){r[l+c]=L(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=L(d,t.color,P.overlaySubtitle);continue}let p=c-(n.length+3),m=p>=0&&p<t.menuItems.length&&p===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=L(d,t.color,m)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,p=" ".repeat(Math.max(0,e.width-Q(d)));r[e.height-1]=L(`${p}${En(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
|
|
141
|
+
`)}function Uu(e,t,r,n){let s=Qu(e.runners),o=1,i=e.leftTree.map(l=>zu(l,t,n));return[...Tt(i,r-o),s]}function Ku(e,t,r,n){let s=t-2,o=e.tabs.find(T=>T.active)?.label??"AGENT",i=e.inputMode==="terminal"?0:lp(e.tabs),a=e.inputMode==="terminal"?s:o.length+1,l="\u2500".repeat(Math.max(0,a)),c=`${" ".repeat(i)}${e.inputMode==="terminal"?Qe(l,n,P.panelBg):er(l,n,P.panelMuted)}`,d=[`${er(e.centerHeader.tabLabel,n,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),p=e.tabs.find(T=>T.active)?.id??"agent",f=e.centerHeader.tabLabel==="BROWSER"||!ri(p)?e.centerTranscript.map(T=>({...T})):Vu(e),m=Yu(e.tabs,n,e.focusedRegion==="center"),w=" engaged ",u=w.length+2,D=e.inputMode==="terminal"?Qe(`${w}\u25CF `,n,P.panelBg):"",B=e.inputMode==="terminal"?" ".repeat(Math.max(0,s-Q(m)-u)):"",ge=[{text:e.inputMode==="terminal"?`${m}${B}${D}`:m},{text:c,tone:"muted"},{text:d},X(),...f];return Tt(ge,r)}function Vu(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},X(),{text:e.terminal.error},X(),{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:Pi(n.segments),segments:n.segments,fullBleed:!0}))}function Gu(e,t,r,n){let s=e.rightInspection?Hu(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):Tt([{text:"CONTEXT"},X(),...e.rightContext.map(o=>Ju(o,n)),...e.actionMessage?[X(),{text:e.actionMessage}]:[]],r);return Tt(s,r)}function Hu(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:dp(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>di(a)),...n.slice(i,i+s).map(a=>di(a))]}function di(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 zu(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Qe("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((m,w)=>m+Q(w.text),0):0,l=t-Q(o)-Q(s)-a,c=e.selected?e.text:e.focused?Qe(e.text,r,P.panelBg):e.panelHeader?er(e.text,r,P.panelMuted):e.text,d=ae(`${n}${c}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.prBadge){let m=[{text:`${d}${o}${i}`},...e.prBadge];return{text:`${d}${o}${e.prBadge.map(u=>u.text).join("")}`,segments:m,tone:p}}return{text:`${d}${o}${i}`,tone:p}}function Qu(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 Yu(e,t,r){return e.map(n=>n.active?r?Qe(n.label,t,P.panelBg):er(n.label,t,P.panelBg):En(n.label,t,P.panelBg)).join(" ")}function Ju(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?En(e.value,t,P.panelBg):e.value}`}}function Yt(e,t,r,n){let s=Xu(n,e.tone??"default"),o=Zu(e,r,s);if(n==="left"){if(e.fullBleed)return L(ae(o,t),r,s);let a=t-Jt-Xt;if(e.rightAlign){let c=Q(o),d=Math.max(0,a-c),p=`${" ".repeat(Jt)}${" ".repeat(d)}${o}${" ".repeat(Xt)}`;return L(p,r,s)}let l=`${" ".repeat(Jt)}${ae(o,a)}${" ".repeat(Xt)}`;return L(l,r,s)}return n==="center"&&e.fullBleed?ep(e,t,r,s):L(ae(` ${o}`,t),r,s)}function Xu(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function Tt(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(X());return r}function X(){return{text:""}}function Zu(e,t,r){return e.segments?e.segments.map(n=>ki(n,t,r)).join(""):e.text}function ep(e,t,r,n){let s=" ".repeat(Zt),o=Math.max(0,t-Zt*2);if(!e.segments)return L(`${s}${ae(e.text,o)}${s}`,r,n);let i=np(e.segments,o),a=`${s}${i.map(l=>ki(l,r,n)).join("")}${s}${r?In:""}`;return L(a,r,n)}function ki(e,t,r){let n=e.href?`${wi(e.href)}${e.text}${In}`:tp(e.text);return!t||!e.style?n:`${Rt(ip(e.style,r))}${ap(e.style)}${n}${bn}${Rt(r)}`}function tp(e){return e.replace(_u,t=>{let[r,n]=rp(t);return`${wi(r)}${r}${In}${n}`})}function rp(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function wi(e){return`\x1B]8;;${e}\x1B\\`}function np(e,t){let r=sp(e,t);return op(r,t)}function sp(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=Q(s.text);if(o<=n){r.push(s),n-=o;continue}let i=tr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function op(e,t){let r=Q(Pi(e));if(r>=t)return e;let n=[...e].reverse().find(s=>s.style?.bg)?.style;return n?.bg?[...e,{text:" ".repeat(t-r),style:n}]:[...e,{text:" ".repeat(t-r)}]}function ip(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 ap(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 lp(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function Ti(e,t){let r=Math.max(0,t-Q(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ae(e,t){let r=Q(e);return r>=t?cp(e,t):e+" ".repeat(t-r)}function cp(e,t){if(t<=0)return"";if(Q(e)<=t)return e;let r=yi(e);return tr(r,Math.max(0,t-1))+"\u2026"}function Q(e){let t=0;for(let r of Array.from(yi(e)))t+=Ri(r);return t}function tr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=Ri(s);if(n+o>t)break;r+=s,n+=o}return r}function Ri(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 dp(e,t,r){return Math.min(Math.max(e,t),r)}function yi(e){return e.replace(Wu,"").replace(Fu,"")}function Pi(e){return e.map(t=>t.text).join("")}function L(e,t,r){if(!t)return e;let n=Rt(r),s=e.replace(Nu,`${bn}${n}`);return`${n}${s}${bn}`}function Rt(e){let t=[];return e.fg&&t.push(`38;2;${ui(e.fg).join(";")}`),e.bg&&t.push(`48;2;${ui(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function ui(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Qe(e,t,r){return rr(e,t,P.success.fg,r)}function up(e,t,r){return rr(e,t,P.error.fg,r)}function er(e,t,r){return rr(e,t,P.accent.fg,r)}function En(e,t,r){return rr(e,t,P.mutedfg.fg,r)}function rr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${Rt(s)}${e}${Rt(n)}`}function Si(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"?fp(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:pp(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function pp(e,t){let r=(e??"").split(An.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(An.delimiter):[...r,t].join(An.delimiter)}function fp(e){return e.command.length>0?e.command:["codex"]}function bi(e,t){let r=e.ptyTabs.find(n=>n.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function Se(e){return{columns:Math.max(20,e.width-ee.leftWidth-ee.rightWidth-ee.dividerWidth-Zt*2),rows:Math.max(5,e.height-ee.topRailHeight-5)}}function Ii(e){return e.length===1||ie(e)||e==="BACKSPACE"||e==="TAB"}function yt(e){return typeof e=="string"&&new RegExp(`:(?:agent|${x.join("|")})(?:-\\d+)?$`).test(e)}function Ci(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 xn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function vi(e){let t=new RegExp("\x1B\\[<(\\d+);\\d+;\\d+[mM]").exec(e);if(!t?.[1])return 0;let r=Number.parseInt(t[1],10);return r===64?-3:r===65?3:0}function Pt(e){return Ai.includes(e)?"SHIFT_ENTER":null}function Dn(e){return Ai.some(t=>t.startsWith(e))}function Ei(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var Ai=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function xi(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 Di(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function $i(e){
|
|
144
|
-
`)
|
|
145
|
-
|
|
146
|
-
[
|
|
143
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Di(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function $i(e,t=null){let r=t?.split(`
|
|
144
|
+
`)??[];return e.split(`
|
|
145
|
+
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}import{spawn as Fp}from"node:child_process";import{createHash as Np}from"node:crypto";import{createServer as Wp,createConnection as qi}from"node:net";import{openSync as _p}from"node:fs";import{mkdir as qp,readFile as Nn,rm as Le,writeFile as Bp}from"node:fs/promises";import{tmpdir as Up}from"node:os";import Ye from"node:path";import{createRequire as Sp}from"node:module";import mp from"@xterm/headless";var gp=1e3,hp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function ji(e){return new mp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:gp,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Mi(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Ln(e,t){return new Promise(r=>{e.write(t,r)})}function Oi(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:Tp(p,i+a===o&&d===r.cursorX)})}n.push({segments:kp(wp(c))})}return n}function kp(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};Fi(r.style)||(s.style=r.style),t.push(s)}return t}function wp(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Fi(r.style))break;t-=1}return e.slice(0,t)}function Tp(e,t){let r={},n=Li(e,"fg"),s=Li(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 Li(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"):hp[s]??Rp(s)}function Rp(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(yp).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 yp(e){return e===0?0:55+e*40}function Pp(e,t){return $n(e)===$n(t)}function $n(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Fi(e){return $n(e)===""}var bp=Sp(import.meta.url),Ip=/^CTRL_([A-Z])$/,Cp="\x1B[6n",vp="\x1B[c",Ep="\x1B[?u",Ap={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
146
|
+
`,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""},nr=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")jn(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,Ni(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=xp(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&&Ni(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}disposeSession(t){let r=this.sessions.get(t);r&&(jn(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())jn(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:Dp(r),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??Lp().spawn,i=ji(n),a=s??this.resolveSessionSpec(t,r),l=Ae({...this.env,...a.env??{}}),{executable:c,args:d}=jp(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:Mp(l)}),f={taskId:t,tabId:r,pty:p,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0,rows:[],renderedScrollbackLines:null,screenDirty:!0};return f.disposables.push(p.onData(m=>{Op(p,m),Ln(f.terminal,m).then(()=>{f.screenDirty=!0,this.onUpdate?.(f.tabId)})})),f.disposables.push(p.onExit(m=>{f.status="exited",Ln(f.terminal,`\r
|
|
147
|
+
[process exited ${m.exitCode}]`).then(()=>{f.screenDirty=!0,this.onUpdate?.(f.tabId)})})),f}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function xp(e){if(e.length===1)return e;let t=Ap[e];if(t!==void 0)return t;let r=Ip.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function Ni(e,t){$p(e.pty,t),Mi(e.terminal,t),e.screenDirty=!0}function Dp(e){return(e.screenDirty||e.renderedScrollbackLines!==e.scrollbackLines)&&(e.rows=Oi(e.terminal,e.scrollbackLines),e.renderedScrollbackLines=e.scrollbackLines,e.screenDirty=!1),e.rows}function jn(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function $p(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function Lp(){return bp("node-pty")}function jp(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[xe(t[0],r),...t.slice(1)].map(Wi).join(" ")}; exec ${Wi(e)} -l`;return{executable:e,args:["-lc",s]}}function Wi(e){return`'${e.replaceAll("'","'\\''")}'`}function Mp(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 Op(e,t){for(let r=0;r<Mn(t,Cp);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Mn(t,vp);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Mn(t,Ep);r+=1)e.write("\x1B[?0u")}function Mn(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 Wn=3;async function Bi(e){let t=_n(e.paths);await Kp(t,e.paths,e.spawnDaemon);let r=await zi(t.socketPath),n=new On(r,e);return await n.ready(),n}async function Ui(e,t={}){let r=_n(e);await qp(e.runtimeDir,{recursive:!0}),await Le(r.socketPath,{force:!0});let n=new Fn(e,t),s=Wp(o=>n.handleConnection(o));await Yp(s,r.socketPath),await Bp(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 Le(r.socketPath,{force:!0}),await Le(r.pidPath,{force:!0}),n.disposeAll()}async function Ki(e){let t=_n(e);return await or(t.socketPath)?(await Gi(t.socketPath),!0):!1}var On=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!==Wn)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
148
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
148
149
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
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()}},Fn=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new
|
|
150
|
+
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}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()}},Fn=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new nr({...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
151
|
`);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{
|
|
152
|
-
${o.slice(-2e3)}`:""}`)}async function Vi(e){let t=await Qp(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===Wn}async function Vp(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Vi(e))return!0;await qn(50)}return!1}function Gp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=
|
|
152
|
+
`)}}),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{sr(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(n);sr(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:Wn}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);sr(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 Jp(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients)sr(n,{type:"update",tabId:t,view:r})}};function _n(e){let t=Np("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:Ye.join(Up(),`craig-${t}.sock`),pidPath:Ye.join(e.runtimeDir,"pty-daemon.pid")}}async function Kp(e,t,r){if(await Vp(e.socketPath,1e3))return;await or(e.socketPath)&&(await Gi(e.socketPath),await _i(e.socketPath,1e3)),await or(e.socketPath)&&(await zp(e),await _i(e.socketPath,1e3)),await Hp(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=Gp(n),l=_p(Ye.join(t.runtimeDir,"pty-daemon.log"),"a");Fp(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 Vi(e.socketPath))return;await qn(50)}let o=await Nn(Ye.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
153
|
+
${o.slice(-2e3)}`:""}`)}async function Vi(e){let t=await Qp(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===Wn}async function Vp(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Vi(e))return!0;await qn(50)}return!1}function Gp(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=Ye.resolve(Ye.dirname(t),"..","node_modules",".bin","tsx");return{command:Br("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 Hp(e){let t=await Nn(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Qi(r))return}await Le(e.socketPath,{force:!0}),await Le(e.pidPath,{force:!0})}async function or(e){let t=await zi(e).catch(()=>null);return t?(t.end(),!0):!1}async function Gi(e){await Hi(e,{id:1,type:"shutdown"}).catch(()=>null)}async function zp(e){let t=await Nn(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!Qi(r)){await Le(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await Le(e.socketPath,{force:!0})}}async function Qp(e){return Hi(e,{id:1,type:"ping"})}function Hi(e,t){return new Promise((r,n)=>{let s=qi(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
154
|
`)),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 _i(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await
|
|
155
|
+
`);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 _i(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await or(e))return;await qn(50)}}function zi(e){return new Promise((t,r)=>{let n=qi(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Yp(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function sr(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
155
156
|
`)}catch{}}function Qi(e){try{return process.kill(e,0),!0}catch{return!1}}function qn(e){return new Promise(t=>setTimeout(t,e))}function Jp(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var Bn=["Runners","Error Log","Help"];function Un(e,t){return x.map(r=>{let n=k.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 Ji(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 Xi(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(Bn.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Kn(t)?e===0?{kind:"runners"}:e===1?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Zi(e,t,r,n){if(e.pathEdit)return Xp({...e,pathEdit:e.pathEdit},t,r);let s=Un(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(!Kn(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:`${k.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Xp(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Yi({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Kn(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:Yi({...e,message:s.length>0?`${k.runners.getProfile(n).displayName} executable saved.`:`${k.runners.getProfile(n).displayName} executable reset to default.`})}}return Zp(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function Yi(e){let t={...e};return delete t.pathEdit,t}function Kn(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
156
|
-
`}function Zp(e){return e.length===1&&e>=" "&&e!==""}import Pt from"node:path";function ea(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 ta="\u{F024B} ",ra="\u{F0DCF} ",na="\u25CB",Vn="\uEA64",sa="\uEAFE",oa="\uEBDA",Gn="\u25CB",Hn="\u25CF",zn="\u2713",Qn="\u2715";function ia(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 ir="empty",F={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function da(e,t){let r=rf(t,e),n=t.repos.find(R=>R.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(R=>R.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(R=>R.repoId===n.id):[],i=o.find(R=>R.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=Nf(t.tasks),c=of(e,i),d=sf(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,m=n?.name??"no repo",u=i?k.runners.getDisplayName(i.runner):k.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 ${k.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 [${k.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Gt(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 ${k.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:Pt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Pt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:u},leftTree:ef(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(R=>Wf(R,l[R])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:m,agent:u},centerTranscript:nf(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Ff(n,i),rightInspection:Tf(e,i,f)}}function ef(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return tf(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,m={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},u=pa(c);u&&(m.prBadge=u),r.push(m)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${k.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 [${k.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 tf(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",m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,u={id:`task:${d.id}`,taskId:d.id,text:`${f} ${m}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},R=pa(d);R&&(u.prBadge=R),e.push(u)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${k.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 rf(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 nf(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 m=f===s.selectedIndex?"\u25B8":" ",u=p.kind==="repo"?" [git repo]":"/";return`${m} ${p.name}${u}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return re(["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 re(["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 re([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${k.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?re([`${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."]):re([`${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"?cf(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?df(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?re(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):re(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function sf(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:af(o)}))??[];if(!t)return[{id:ir,label:"EMPTY",active:r===ir,focused:e.focusedRegion==="center"&&r===ir}];let s=e.openInspectionKind||r===I?[{id:I,label:lf(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function of(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:ir}function af(e){return e.title.toUpperCase()}function lf(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Pt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function cf(e,t,r){if(!e)return re(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return re(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=ua(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:""},...uf(n.lines,r,s)]}function df(e,t,r){if(!e)return re(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return re(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=ua(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:""},...pf(n.lines,r,s)]}function re(e){return e.map(t=>({text:t}))}function uf(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:F.lineNumber}},{text:" \u2502 ",style:{fg:F.gutter}},...Yn(o,r)],tone:"default"}})}function pf(e,t,r){let n=ff(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>mf(o,r))}function ff(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 mf(e,t){let r=aa(e.oldNumber),n=aa(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:F.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:F.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?hf(Yn(e.text,t),o.bg,o.fallbackFg):Yn(e.text,t),l=o?{fg:F.lineNumber,bg:o.bg}:{fg:F.lineNumber},c=o?{fg:F.gutter,bg:o.bg}:{fg:F.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function aa(e){return e===null?" ":String(e).padStart(4," ")}function ua(e){let t=Pt.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 Yn(e,t){return t==="diff"?gf(e):t==="markdown"?kf(e):t==="json"?Jn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Jn(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 gf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:F.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:F.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:F.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:F.diffMeta}}]:[{text:e}]}function hf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function kf(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:F.markup,bold:!0}}]:Jn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Jn(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:wf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function wf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:F.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:F.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:F.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:F.markup}:{fg:F.keyword}}function Tf(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?fa(t.repoTargets??[]):s?.pullRequest??(t?A(t):null),i=[Rf(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ha(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Lf(e,r)]}:{title:"",rows:[...i,...jf(e,r)]}}function Rf(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=Xn(t),i=Zn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function la(e){return[{text:" "},Xn(e),{text:" "},Zn(e)]}function pa(e){if(e.type==="project"&&e.repoTargets?.length){let r=fa(e.repoTargets);return r?la(r):null}let t=A(e);return t?.number?la(t):null}function fa(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=Pf(r);return{number:-1,status:yf(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 yf(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 Pf(e){let t=e.map(r=>ma(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 Xn(e){return!e||!e.number?{text:na,style:{fg:"565f89"}}:e.status==="merged"?{text:sa,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:oa,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Vn,style:{fg:"565f89"}}:{text:Vn,style:{fg:"9ece6a"}}}function Zn(e){return e?.aggregateReadiness?ca(e.aggregateReadiness):ca(ma(e))}function ca(e){return e==="failed"?{text:Qn,style:{fg:"f7768e"}}:e==="pending"?{text:Hn,style:{fg:"e0af68"}}:e==="success"?{text:zn,style:{fg:"9ece6a"}}:{text:Gn,style:{fg:"565f89"}}}function ma(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")?ga(e)?"failed":Sf(e)?"success":"pending":"pending"}function Sf(e){return!!(e.mergeable&&!e.draft&&!ga(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function ga(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function ha(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return bf(e,t);let r=A(t),n=wa("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}),If(n,e)}var or=32;function bf(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=or-p.length-1,m=c.length>f?c.slice(0,f-1)+"\u2026":c,u=or-m.length-p.length;r.push({id:`project-review:${i.repoId}`,text:m+" ".repeat(Math.max(1,u))+p,selected:a,focused:l,muted:!0})}else{let d=Xn(i.pullRequest),p=Zn(i.pullRequest),f=`${d.text} ${p.text}`,m=or-f.length-1,u=c.length>m?c.slice(0,m-1)+"\u2026":c,R=or-u.length-f.length,D=u+" ".repeat(Math.max(1,R));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(...wa("target",o.branch,o.pullRequest))),r}function ka(e,t){return ha(e,t).length}function wa(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=Cf(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:vf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Ta(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(Ef)):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)=>Af(p,n(`comment:${f}`))))),s}function If(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 Cf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function vf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Ta(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 Ef(e){let{icon:t,color:r}=Df(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," ")} ${$f(e.status)}`,color:r,muted:!1}}function Af(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Ta(e.createdAt)}`:"",s=xf(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 xf(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 Df(e){switch(e){case"success":return{icon:zn,color:"9ece6a"};case"pending":return{icon:Hn,color:"e0af68"};case"failed":return{icon:Qn,color:"f7768e"};case"skipped":return{icon:Gn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function $f(e){return e==="success"?"passing":e==="failed"?"failing":e}function Lf(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=es(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)?ta:ra:ea(l.label),f=l.kind==="directory"?"7aa2f7":ia(l.label),m=" ".repeat(l.depth),u=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},D=[{text:m},u,R];return{id:l.path,text:`${m}${p}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:D}})]}function es(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 jf(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(Mf(t))return Of(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=>Ra(o,e,t))))}return r}function Mf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Of(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=>Ra(c,e,t,s.length+1))))}}return r}function Ra(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 Ff(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:k.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Pt.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function Nf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Wf(e,t){return{name:k.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as _f,mkdir as qf,readFile as Bf}from"node:fs/promises";import Uf from"node:path";var ya=80,ts=async(e,t)=>{await qf(Uf.dirname(e.errorLogFile),{recursive:!0}),await _f(e.errorLogFile,Kf(t),"utf8")},Pa=async(e,t)=>{try{await ts(e,t)}catch{}},rs=async(e,t=ya)=>{try{let n=(await Bf(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
157
|
+
`}function Zp(e){return e.length===1&&e>=" "&&e!==""}import St from"node:path";function ea(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 ta="\u{F024B} ",ra="\u{F0DCF} ",na="\u25CB",Vn="\uEA64",sa="\uEAFE",oa="\uEBDA",Gn="\u25CB",Hn="\u25CF",zn="\u2713",Qn="\u2715";function ia(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 ar="empty",F={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function da(e,t){let r=rf(t,e),n=t.repos.find(u=>u.id===e.selectedRepoId)??t.repos[0]??null,s=r?t.tasks.filter(u=>u.workspaceId===r.id):t.tasks,o=r?.kind==="project"?s:n?s.filter(u=>u.repoId===n.id):[],i=o.find(u=>u.id===e.selectedTaskId)??o[0]??null,a=i?.type==="project",l=Nf(t.tasks),c=of(e,i),d=sf(e,i,c),p=d.find(u=>u.id===c)??d[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===i?.id?t.inspection:null,m=n?.name??"no repo",w=i?k.runners.getDisplayName(i.runner):k.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 ${k.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 [${k.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Ht(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 ${k.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:St.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${St.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:ef(e,t),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(u=>Wf(u,l[u])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":i?.id??"no task",repo:m,agent:w},centerTranscript:nf(c,e,n,i,e.workspaceBrowser,f,r),tabs:d,rightContext:Ff(n,i),rightInspection:Tf(e,i,f)}}function ef(e,t){let r=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return tf(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,m={id:`task:${c.id}`,taskId:c.id,text:`${p} ${f}`,indent:2,selected:d,focused:d&&e.focusedRegion==="tasks"},w=pa(c);w&&(m.prBadge=w),r.push(m)}if(o.kind==="project"){let c=`new-task-workspace:${o.id}`,d=e.selectedLeftItemId===c;r.push({id:c,text:`+ New Project Task [${k.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 [${k.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 tf(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",m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,w={id:`task:${d.id}`,taskId:d.id,text:`${f} ${m}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks"},u=pa(d);u&&(w.prBadge=u),e.push(w)}let l=`new-task:${o.id}`,c=t.selectedLeftItemId===l;e.push({id:l,text:`+ New Task [${k.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 rf(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 nf(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 m=f===s.selectedIndex?"\u25B8":" ",w=p.kind==="repo"?" [git repo]":"/";return`${m} ${p.name}${w}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return re(["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 re(["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 re([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${k.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?re([`${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."]):re([`${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"?cf(n,o,t.fileScrollOffset):e===I&&t.openInspectionKind==="diff"?df(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?re(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):re(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function sf(e,t,r){let n=t?.ptyTabs.map(o=>({id:o.id,label:af(o)}))??[];if(!t)return[{id:ar,label:"EMPTY",active:r===ar,focused:e.focusedRegion==="center"&&r===ar}];let s=e.openInspectionKind||r===I?[{id:I,label:lf(e)}]:[];return[...n,...s].map(o=>({...o,active:o.id===r,focused:e.focusedRegion==="center"&&o.id===r}))}function of(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:ar}function af(e){return e.title.toUpperCase()}function lf(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?St.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function cf(e,t,r){if(!e)return re(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return re(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=ua(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:""},...uf(n.lines,r,s)]}function df(e,t,r){if(!e)return re(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return re(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=ua(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:""},...pf(n.lines,r,s)]}function re(e){return e.map(t=>({text:t}))}function uf(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:F.lineNumber}},{text:" \u2502 ",style:{fg:F.gutter}},...Yn(o,r)],tone:"default"}})}function pf(e,t,r){let n=ff(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>mf(o,r))}function ff(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 mf(e,t){let r=aa(e.oldNumber),n=aa(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:F.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:F.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?hf(Yn(e.text,t),o.bg,o.fallbackFg):Yn(e.text,t),l=o?{fg:F.lineNumber,bg:o.bg}:{fg:F.lineNumber},c=o?{fg:F.gutter,bg:o.bg}:{fg:F.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function aa(e){return e===null?" ":String(e).padStart(4," ")}function ua(e){let t=St.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 Yn(e,t){return t==="diff"?gf(e):t==="markdown"?kf(e):t==="json"?Jn(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Jn(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 gf(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:F.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:F.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:F.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:F.diffMeta}}]:[{text:e}]}function hf(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function kf(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:F.markup,bold:!0}}]:Jn(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Jn(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:wf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function wf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:F.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:F.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:F.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:F.markup}:{fg:F.keyword}}function Tf(e,t,r){let n=e.selectedProjectTargetId??t?.repoTargets?.[0]?.repoId??null,s=t?.type==="project"&&n?t.repoTargets?.find(a=>a.repoId===n)??null:null,o=t?.type==="project"?fa(t.repoTargets??[]):s?.pullRequest??(t?E(t):null),i=[Rf(e,o),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...ha(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Lf(e,r)]}:{title:"",rows:[...i,...jf(e,r)]}}function Rf(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=Xn(t),i=Zn(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function la(e){return[{text:" "},Xn(e),{text:" "},Zn(e)]}function pa(e){if(e.type==="project"&&e.repoTargets?.length){let r=fa(e.repoTargets);return r?la(r):null}let t=E(e);return t?.number?la(t):null}function fa(e){let t=e.filter(s=>s.status==="ready"),r=t.map(s=>s.pullRequest).filter(s=>!!s.number);if(r.length===0)return null;let n=Pf(r);return{number:-1,status:yf(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 yf(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 Pf(e){let t=e.map(r=>ma(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 Xn(e){return!e||!e.number?{text:na,style:{fg:"565f89"}}:e.status==="merged"?{text:sa,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:oa,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Vn,style:{fg:"565f89"}}:{text:Vn,style:{fg:"9ece6a"}}}function Zn(e){return e?.aggregateReadiness?ca(e.aggregateReadiness):ca(ma(e))}function ca(e){return e==="failed"?{text:Qn,style:{fg:"f7768e"}}:e==="pending"?{text:Hn,style:{fg:"e0af68"}}:e==="success"?{text:zn,style:{fg:"9ece6a"}}:{text:Gn,style:{fg:"565f89"}}}function ma(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")?ga(e)?"failed":Sf(e)?"success":"pending":"pending"}function Sf(e){return!!(e.mergeable&&!e.draft&&!ga(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function ga(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function ha(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return bf(e,t);let r=E(t),n=wa("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}),If(n,e)}var ir=32;function bf(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=ir-p.length-1,m=c.length>f?c.slice(0,f-1)+"\u2026":c,w=ir-m.length-p.length;r.push({id:`project-review:${i.repoId}`,text:m+" ".repeat(Math.max(1,w))+p,selected:a,focused:l,muted:!0})}else{let d=Xn(i.pullRequest),p=Zn(i.pullRequest),f=`${d.text} ${p.text}`,m=ir-f.length-1,w=c.length>m?c.slice(0,m-1)+"\u2026":c,u=ir-w.length-f.length,D=w+" ".repeat(Math.max(1,u));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(...wa("target",o.branch,o.pullRequest))),r}function ka(e,t){return ha(e,t).length}function wa(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=Cf(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:vf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Ta(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(Ef)):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)=>Af(p,n(`comment:${f}`))))),s}function If(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 Cf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function vf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Ta(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 Ef(e){let{icon:t,color:r}=Df(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," ")} ${$f(e.status)}`,color:r,muted:!1}}function Af(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Ta(e.createdAt)}`:"",s=xf(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 xf(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 Df(e){switch(e){case"success":return{icon:zn,color:"9ece6a"};case"pending":return{icon:Hn,color:"e0af68"};case"failed":return{icon:Qn,color:"f7768e"};case"skipped":return{icon:Gn,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function $f(e){return e==="success"?"passing":e==="failed"?"failing":e}function Lf(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=es(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)?ta:ra:ea(l.label),f=l.kind==="directory"?"7aa2f7":ia(l.label),m=" ".repeat(l.depth),w=f?{text:p,style:{fg:f}}:{text:p},u=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},D=[{text:m},w,u];return{id:l.path,text:`${m}${p}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:D}})]}function es(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 jf(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(Mf(t))return Of(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=>Ra(o,e,t))))}return r}function Mf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Of(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=>Ra(c,e,t,s.length+1))))}}return r}function Ra(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 Ff(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:k.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:St.basename(t.worktreePath)}]:[{label:"Repo",value:e.name},{label:"Branch",value:e.defaultBranch},{label:"Task",value:"none",mutedValue:!0}]:[{label:"Repo",value:"none",mutedValue:!0}]}function Nf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Wf(e,t){return{name:k.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}import{appendFile as _f,mkdir as qf,readFile as Bf}from"node:fs/promises";import Uf from"node:path";var ya=80,ts=async(e,t)=>{await qf(Uf.dirname(e.errorLogFile),{recursive:!0}),await _f(e.errorLogFile,Kf(t),"utf8")},Pa=async(e,t)=>{try{await ts(e,t)}catch{}},rs=async(e,t=ya)=>{try{let n=(await Bf(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
157
158
|
`).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if(Vf(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},Sa=async(e,t=ya)=>rs(e,t);function Kf(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
159
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
159
160
|
`)}
|
|
160
161
|
|
|
161
|
-
`}function Vf(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Ye={appendErrorLog:ts,appendErrorLogBestEffort:Pa,readErrorLog:rs,readRecentErrorLines:Sa};var ba=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await J(n.paths,e.selectedTaskId),i=t??Gf(o,e.activeTab,e.preferredPtyTabKind),a=Ea(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"}`}}},Ia=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await y(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},Ca=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await J(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await y(t.paths,{...n,selectedPtyTabId:e.activeTab})})},va=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await y(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=Ea(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await y(t.paths,{...s,selectedPtyTabId:o.id});return}await y(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Gf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Ea(e,t,r,n={}){let s=r??e.runner,o=k.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(m=>m.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let 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"?k.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Je=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Aa=async(e,t,r,n,s)=>{k.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=Ee();await T(Ae(k.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 Je(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},xa=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Da=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},$a=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},La=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await Ye.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var ja=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 Ma=async(e,t,r)=>{let n=k.runners.setRunnerEnabled(r.config,e,t);return await k.save(r.paths,n),n},Oa=async(e,t,r)=>{let n=k.runners.setRunnerPath(r.config,e,t);return await k.save(r.paths,n),n};function fe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function Le(e,t){return pe(t,e.ptyRuntime.getViewState(ns(e,t)))}function ns(e,t){let r=fe(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function g(e,t){return Le(e,ci(t,e.model))}function Fa(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:g(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Na(e,t,r){return Fa(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return Fa(e,t,{tone:"error",message:r})}function M(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return Ye.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function $(e,t){if(!e.uiStateFile)return;e.runtimeState=Zo(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 Hf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function _(e){return{paths:e.paths,config:e.config,taskService:b,workspaceService:H,queueTaskMutation:t=>Hf(e,t)}}function ss(e,t){let r=fe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?es(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:kt(e.model),centerTabIds:si(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:ka(t,r),pageRows:Math.max(5,te(e.activeTerminal.width,e.activeTerminal.height).height-ee.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function Wa(e,t){await Ca(t,_(e))}async function q(e){e.model=await Re(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:g(e,e.state.shell)}:e.state={...e.state,shell:g(e,e.state.shell)}}async function ar(e,t){let r=++e.inspectionRefreshSequence,n=Pn(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 Lo(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:g(e,e.state.shell)},$(e,e.state.shell),e.render())}function _a(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&ar(e,r).catch(n=>{let s=M(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},120))}function qa(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,ss(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render(),ar(e,e.state.shell).catch(s=>{let o=M(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render()}},16)))}function os(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function is(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 Ua(e){is(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function Ka(e,t){let r=g(e,t),n=fe(e.model.tasks,r),s=ns(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return pe(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ye(te(e.activeTerminal.width,e.activeTerminal.height)));return pe({...r,inputMode:"control"},i)}function Va(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 as(e,t){try{let r=g(e,t),n=fe(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await Ba(e,n),await q(e),s=n.selectedPtyTabId)}n&&!s&&(n=await Ba(e,n),await q(e),s=n.selectedPtyTabId);let o=g(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:pe({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},$(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ye(te(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Rt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:pe({...o,inputMode:"terminal"},i)},$(e,e.state.shell)}catch(r){let n=M(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Rt(t.selectedPtyTabId)&&(await zf(e,t.selectedTaskId,n).catch(()=>{}),await q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,ei(g(e,t),n),n)},$(e,e.state.shell)}e.render()}async function zf(e,t,r){await xa(t,r,_(e))}async function Ga(e,t,r,n){let s=g(e,t),{nextShell:o}=await ba(s,r,n,_(e));return await q(e),g(e,{...s,...o})}async function Ha(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await Ia(r,_(e));return e.ptyRuntime.disposeSession(n.id),await q(e),g(e,{...r,...s})}async function za(e,t){let r=g(e,t),n=kt(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Da(r,_(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await q(e),g(e,{...r,...i,selectedLeftItemId:Qf(n,kt(e.model),s)})}async function Qa(e,t){let r=g(e,t),{nextShell:n}=await ja(r,_(e));return await q(e),g(e,{...r,...n})}async function Ba(e,t){return va(t,_(e))}function lr(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:Le(e,e.state.shell)},e.render())},16))}function Qf(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Ya(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await $a(e.model.tasks,_(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:g(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,La("background PR polling",t,_(e)))}finally{e.prPollInFlight=!1}}}async function Ja(e,t){let r=g(e,t),n=fe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await b.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await q(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await b.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await q(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${A(a)?.requiredChecks.length??0} reported`)}return g(e,{...Na(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import em from"node:path";import{readdir as Yf,stat as Jf}from"node:fs/promises";import Xa from"node:path";async function Xf(e){let t=await Yf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Xa.join(e,n.name);r.push({name:n.name,path:s,kind:await Zf(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 Za(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function el(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 cr(e,t){let r=await Xf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Zf(e){let t=Xa.join(e,".git");return await Jf(t).catch(()=>null)!==null}function tl(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function tm(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:g(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Aa(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,_(e));n=s.task,await q(e);let o=g(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??bi(n,"agent"),ye(te(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Rt(o.selectedPtyTabId),e.state={mode:"main",shell:pe(o,i)},$(e,e.state.shell)}catch(s){s instanceof Je&&(n=s.task);let o=M(e,"create task",s,"Failed to create task.");n&&!(s instanceof Je)?(await y(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await q(e).catch(()=>{})):n&&(await y(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function rm(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ie(t)){tm(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:g(e,{...r,selectedRunner:yn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}ti(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function nm(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Za(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){cr(e,em.dirname(r.cwd)).catch(s=>{let o=M(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ie(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){cr(e,s.path).catch(i=>{let a=M(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=_(e);o.addWorkspace(e.paths,s.path).then(async i=>{await q(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},$(e,e.state.shell),e.render()}).catch(i=>{let a=M(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function sm(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Xi(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;om(e,n)}}}async function om(e,t){let r;try{r=await Ye.readRecentErrorLines(e.paths)}catch(n){let s=M(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 im(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Zi(tl(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"?Ma(r.runner,r.enabled,_(e)):Oa(r.runner,r.path,_(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=k.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:g(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:k.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=M(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,g(e,e.state.shell),o),runnerOptions:{...tl(e),message:o}},e.render()})}function rl(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){rm(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){nm(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){lm(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=Rn(e.state.shell,r,ss(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ie(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=yt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(am(e,r))return;e.lastTerminalKey=Ii(r)?{key:r,at:Date.now()}:null;let o=Ci(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){lr(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){cr(e,e.workspaceRoot).catch(s=>{let o=M(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Ga(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{as(e,s)}).catch(s=>{let o=M(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Ha(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ja(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=fe(e.model.tasks,n.state),o=s?A(s)?.url??null:null;o?el(o).catch(i=>{let a=M(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){za(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Qa(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){as(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){_a(e,e.state.shell);return}ar(e,e.state.shell).catch(s=>{let o=M(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},Wa(e,e.state.shell).catch(()=>{}),$(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex: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:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){sm(e,r);return}if(e.state.variant==="runners"){im(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ie(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"||ie(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ie(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;Ka(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},$(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=M(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,g(e,e.state.shell),i)},$(e,e.state.shell),e.render()})}):Ua(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 nl(e,t){let r=Di(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=yt(o);if(i){ol(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(Dn(o)){e.pendingTerminalKeySequence.raw=o,sl(e);return}dr(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},$(e,e.state.shell),e.render();return}let n=vi(r);if(n!==0){lr(e,n);return}let s=yt(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
162
|
+
`}function Vf(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Je={appendErrorLog:ts,appendErrorLogBestEffort:Pa,readErrorLog:rs,readRecentErrorLines:Sa};var ba=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await J(n.paths,e.selectedTaskId),i=t??Gf(o,e.activeTab,e.preferredPtyTabKind),a=Ea(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"}`}}},Ia=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(c=>c.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(c=>c.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await y(t.paths,{...s,ptyTabs:a,selectedPtyTabId:l?.id??null}),{closedTab:i,nextSelectedTab:l}});return{closedTab:r,nextSelectedTab:n,nextShell:{activeTab:n?.id??(e.openInspectionKind?"inspection":e.activeTab),selectedPtyTabId:n?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${r.title}`}}},Ca=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await J(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await y(t.paths,{...n,selectedPtyTabId:e.activeTab})})},va=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await y(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=Ea(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await y(t.paths,{...s,selectedPtyTabId:o.id});return}await y(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Gf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Ea(e,t,r,n={}){let s=r??e.runner,o=k.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(m=>m.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let 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"?k.runners.buildCommand(s,void 0,n):[],createdAt:p,updatedAt:p}}var Xe=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Aa=async(e,t,r,n,s)=>{k.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=Ae();await R(xe(k.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 Xe(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},xa=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Da=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await J(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},$a=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},La=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await Je.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var ja=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 Ma=async(e,t,r)=>{let n=k.runners.setRunnerEnabled(r.config,e,t);return await k.save(r.paths,n),n},Oa=async(e,t,r)=>{let n=k.runners.setRunnerPath(r.config,e,t);return await k.save(r.paths,n),n};var Hf=250;function fe(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function je(e,t){return pe(t,e.ptyRuntime.getViewState(ns(e,t)))}function ns(e,t){let r=fe(e.model.tasks,t);return r?r.ptyTabs.some(n=>n.id===t.activeTab)?t.activeTab:t.activeTab==="agent"||t.activeTab==="terminal"?r.ptyTabs.find(n=>n.kind===t.activeTab)?.id??t.selectedPtyTabId:t.selectedPtyTabId:t.selectedPtyTabId}function g(e,t){return je(e,ci(t,e.model))}function Fa(e,t,r){return e.footerToastTimer&&(clearTimeout(e.footerToastTimer),e.footerToastTimer=null),r?(e.footerToastTimer=setTimeout(()=>{e.footerToastTimer=null,!(e.state.mode!=="main"||e.state.shell.footerToast!==r)&&(e.state={mode:"main",shell:g(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Na(e,t,r){return Fa(e,t,r?{tone:"success",message:r}:null)}function j(e,t,r){return Fa(e,t,{tone:"error",message:r})}function M(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return Je.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function $(e,t){if(!e.uiStateFile)return;e.runtimeState=Zo(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>he({uiStateFile:e.uiStateFile},r),()=>he({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function zf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function _(e){return{paths:e.paths,config:e.config,taskService:b,workspaceService:H,queueTaskMutation:t=>zf(e,t)}}function ss(e,t){let r=fe(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?es(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:wt(e.model),centerTabIds:si(r,t),ptyTabIds:r?.ptyTabs.map(a=>a.id)??[],filePathIds:s?.filePaths??[],fileTreeRowIds:i.map(a=>a.path),fileTreeFileIds:i.filter(a=>a.kind==="file").map(a=>a.path),fileTreeDirectoryIds:i.filter(a=>a.kind==="directory").map(a=>a.path),diffPathIds:s?.diffPaths??[],diffPathRanges:[],fileLineCount:s?.selectedFile.lines.length??0,diffLineCount:s?.selectedDiff.lines.length??0,reviewRowCount:ka(t,r),pageRows:Math.max(5,te(e.activeTerminal.width,e.activeTerminal.height).height-ee.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function Wa(e,t){await Ca(t,_(e))}async function q(e){e.model=await Pe(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:g(e,e.state.shell)}:e.state={...e.state,shell:g(e,e.state.shell)}}async function lr(e,t){let r=++e.inspectionRefreshSequence,n=Pn(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 Lo(n,s,i);if(r!==e.inspectionRefreshSequence)return;o={...e.model,inspection:a}}else if(o=await Pe(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=o,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},$(e,e.state.shell),e.render())}function _a(e,t){e.pendingLeftNavInspectionShell=t,!e.leftNavInspectionTimer&&(e.leftNavInspectionTimer=setTimeout(()=>{e.leftNavInspectionTimer=null;let r=e.pendingLeftNavInspectionShell;e.pendingLeftNavInspectionShell=null,!(!r||e.state.mode!=="main"||e.state.shell!==r)&&lr(e,r).catch(n=>{let s=M(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Hf))}function qa(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=ye(e.state.shell,r,ss(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render(),lr(e,e.state.shell).catch(s=>{let o=M(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render()}},16)))}function os(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function is(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 Ua(e){is(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function Ka(e,t){let r=g(e,t),n=fe(e.model.tasks,r),s=ns(e,r);if(!n||!s||!n.ptyTabs.some(a=>a.id===s))return r;let o=e.ptyRuntime.getViewState(s);if(o.status!=="idle"||o.rows.length>0||o.error)return pe(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,Se(te(e.activeTerminal.width,e.activeTerminal.height)));return pe({...r,inputMode:"control"},i)}function Va(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 as(e,t){try{let r=g(e,t),n=fe(e.model.tasks,r),s=r.selectedPtyTabId;if(n&&r.focusedRegion==="tasks"){let a=n.ptyTabs.find(l=>l.kind==="agent")??null;a?s=a.id:(n=await Ba(e,n),await q(e),s=n.selectedPtyTabId)}n&&!s&&(n=await Ba(e,n),await q(e),s=n.selectedPtyTabId);let o=g(e,{...r,activeTab:s??r.activeTab,selectedPtyTabId:s,focusedRegion:s?"center":r.focusedRegion});if(!o.selectedTaskId||!s){e.state={mode:"main",shell:o},e.render();return}e.state={mode:"main",shell:pe({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},$(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,Se(te(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=yt(s),e.lastTerminalKey=null,e.state={mode:"main",shell:pe({...o,inputMode:"terminal"},i)},$(e,e.state.shell)}catch(r){let n=M(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&yt(t.selectedPtyTabId)&&(await Qf(e,t.selectedTaskId,n).catch(()=>{}),await q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,ei(g(e,t),n),n)},$(e,e.state.shell)}e.render()}async function Qf(e,t,r){await xa(t,r,_(e))}async function Ga(e,t,r,n){let s=g(e,t),{nextShell:o}=await ba(s,r,n,_(e));return await q(e),g(e,{...s,...o})}async function Ha(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await Ia(r,_(e));return e.ptyRuntime.disposeSession(n.id),await q(e),g(e,{...r,...s})}async function za(e,t){let r=g(e,t),n=wt(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Da(r,_(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await q(e),g(e,{...r,...i,selectedLeftItemId:Yf(n,wt(e.model),s)})}async function Qa(e,t){let r=g(e,t),{nextShell:n}=await ja(r,_(e));return await q(e),g(e,{...r,...n})}async function Ba(e,t){return va(t,_(e))}function cr(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:je(e,e.state.shell)},e.render())},16))}function Yf(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Ya(e){if(!(e.prPollInFlight||e.state.mode!=="main")){e.prPollInFlight=!0;try{if(await $a(e.model.tasks,_(e)),e.lastBackgroundPrPollError=null,e.state.mode!=="main")return;e.model=await Pe(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state={mode:"main",shell:g(e,e.state.shell)},e.render()}catch(t){let r=t instanceof Error?t.message:"Background PR discovery failed.";r!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=r,La("background PR polling",t,_(e)))}finally{e.prPollInFlight=!1}}}async function Ja(e,t){let r=g(e,t),n=fe(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await b.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await q(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await b.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await q(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${E(a)?.requiredChecks.length??0} reported`)}return g(e,{...Na(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import tm from"node:path";import{readdir as Jf,stat as Xf}from"node:fs/promises";import Xa from"node:path";async function Zf(e){let t=await Jf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Xa.join(e,n.name);r.push({name:n.name,path:s,kind:await em(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 Za(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function el(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 dr(e,t){let r=await Zf(t);e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function em(e){let t=Xa.join(e,".git");return await Xf(t).catch(()=>null)!==null}function tl(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function rm(e){if(e.state.mode!=="main"||e.creatingTask)return;let t=e.state.shell,r=t.taskPromptInput?.trim()??"";if(!t.selectedRepoId&&!t.selectedWorkspaceId){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:g(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:g(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Aa(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,_(e));n=s.task,await q(e);let o=g(e,{...e.state.shell,...s.nextShell,selectedLeftItemId:`task:${n.id}`,inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),i=await e.ptyRuntime.ensureSession(n.id,o.selectedPtyTabId??bi(n,"agent"),Se(te(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=yt(o.selectedPtyTabId),e.state={mode:"main",shell:pe(o,i)},$(e,e.state.shell)}catch(s){s instanceof Xe&&(n=s.task);let o=M(e,"create task",s,"Failed to create task.");n&&!(s instanceof Xe)?(await y(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await q(e).catch(()=>{})):n&&(await y(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await q(e).catch(()=>{})),e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function nm(e,t){if(e.state.mode!=="main")return;let r=e.state.shell;if(r.taskPromptInput!==null){if(t==="ESCAPE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ie(t)){rm(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:g(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:g(e,{...r,selectedRunner:yn(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}ti(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function sm(e,t){if(e.state.mode!=="main")return;let r=e.state.shell.workspaceBrowser;if(!r)return;if(t==="ESCAPE"){if(r.query!==null){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:"",selectedIndex:0}})},e.render();return}if(r.query!==null&&(t==="BACKSPACE"||t==="DELETE")){let s=r.query.slice(0,-1);e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}if(r.query!==null&&t.length===1&&t>=" "){let s=r.query+t;e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=Za(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.max(0,r.selectedIndex-1),error:null}})},e.render();return}if(t==="DOWN"||t==="j"){e.state={mode:"main",shell:g(e,{...e.state.shell,workspaceBrowser:{...r,selectedIndex:Math.min(Math.max(0,n.length-1),r.selectedIndex+1),error:null}})},e.render();return}if(t==="LEFT"||t==="h"){dr(e,tm.dirname(r.cwd)).catch(s=>{let o=M(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ie(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){dr(e,s.path).catch(i=>{let a=M(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=_(e);o.addWorkspace(e.paths,s.path).then(async i=>{await q(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},$(e,e.state.shell),e.render()}).catch(i=>{let a=M(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function om(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Xi(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;im(e,n)}}}async function im(e,t){let r;try{r=await Je.readRecentErrorLines(e.paths)}catch(n){let s=M(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 am(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Zi(tl(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"?Ma(r.runner,r.enabled,_(e)):Oa(r.runner,r.path,_(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=k.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:g(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:k.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=M(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:j(e,g(e,e.state.shell),o),runnerOptions:{...tl(e),message:o}},e.render()})}function rl(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){nm(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){sm(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){cm(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=Rn(e.state.shell,r,ss(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ie(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=Pt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(lm(e,r))return;e.lastTerminalKey=Ii(r)?{key:r,at:Date.now()}:null;let o=Ci(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){cr(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){dr(e,e.workspaceRoot).catch(s=>{let o=M(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:j(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Ga(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{as(e,s)}).catch(s=>{let o=M(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Ha(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Ja(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=fe(e.model.tasks,n.state),o=s?E(s)?.url??null:null;o?el(o).catch(i=>{let a=M(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:j(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:j(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){za(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Qa(e,n.state).then(s=>{e.state={mode:"main",shell:s},$(e,e.state.shell),e.render()}).catch(s=>{let o=M(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:j(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){as(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},$(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){_a(e,e.state.shell);return}lr(e,e.state.shell).catch(s=>{let o=M(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:j(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},Wa(e,e.state.shell).catch(()=>{}),$(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex: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:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){om(e,r);return}if(e.state.variant==="runners"){am(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ie(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"||ie(r))&&(e.state={...e.state,optionsMessage:null},e.render());return}if(r==="UP"||r==="k"){e.state={...e.state,menuIndex:Math.max(0,e.state.menuIndex-1)},e.render();return}if(r==="DOWN"||r==="j"){e.state={...e.state,menuIndex:Math.min(2,e.state.menuIndex+1)},e.render();return}if(r==="ESCAPE"){e.state.variant==="pause"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ie(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control"})},e.pendingClear=!0,e.render(),n?e.bootHydrationReady.then(()=>{if(e.state.mode!=="main")return;let s=e.state.shell;Ka(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},$(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=M(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:j(e,g(e,e.state.shell),i)},$(e,e.state.shell),e.render()})}):Ua(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 nl(e,t){let r=Di(t);if(e.state.mode!=="main"||e.state.shell.inputMode!=="terminal"||r.length===0)return;if(e.pendingTerminalKeySequence){let o=`${e.pendingTerminalKeySequence.raw}${r}`,i=Pt(o);if(i){ol(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(Dn(o)){e.pendingTerminalKeySequence.raw=o,sl(e);return}ur(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:g(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},$(e,e.state.shell),e.render();return}let n=vi(r);if(n!==0){cr(e,n);return}let s=Pt(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
163
|
`&&r!==`\r
|
|
163
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),xi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function
|
|
164
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),xi(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function lm(e,t){if(e.pendingTerminalKeySequence){let r=Ei(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=Pt(n);if(s)return ol(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(Dn(n))return e.pendingTerminalKeySequence.raw=n,sl(e),!0}return ur(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>ur(e),30)},!0)}function sl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>ur(e),30))}function ur(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function ol(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function il(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){qa(e,xn(t));return}let r=xn(t);r!==0&&cr(e,r)}function cm(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var um=dm(import.meta.url),pm=um("terminal-kit"),fm=pm.terminal;function ls(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}async function al(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=se(t),n=await k.load(r),s=k.runners.getEnabled(n),o=e.uiStateFile?await Fe({uiStateFile:e.uiStateFile}):null,i=await Pe(t,void 0,s),a=kt(Xo(o,n),i);i=await Pe(t,a,s);let l={current:i},c=()=>{},d={workspaceRoot:t,onUpdate:()=>c(),resolveSessionSpec:(f,m)=>Si(l.current,m,t)},p=e.ptyRuntime??await Bi({...d,paths:r});return new Promise(f=>{let m=e.terminal??fm,w=null,u={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:kt(a,i)},get model(){return l.current},set model(A){l.current=A},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,prPollTimer:null,prPollInFlight:!1,lastBackgroundPrPollError:null,versionText:`Craig v${k.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:m,ptyRuntime:p,resolve:f,render:()=>{},exit:A=>f(A)};c=()=>{u.state.mode==="main"&&(u.ptyRenderTimer||(u.ptyRenderTimer=setTimeout(()=>{u.ptyRenderTimer=null,u.state.mode==="main"&&(u.state={mode:"main",shell:je(u,u.state.shell)},u.render())},50)))},u.render=()=>{Va(u);let A=te(m.width,m.height),le=u.state.mode==="main"?hi(A,da(g(u,u.state.shell),u.model),{centerOnly:u.state.shell.centerZoomed,focusFlashActive:u.focusFlashUntil!==null&&Date.now()<u.focusFlashUntil}):u.state.variant==="boot"?pi(A,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="pause"?fi(A,{menuIndex:u.state.menuIndex,optionsMessage:u.state.optionsMessage,versionText:u.versionText,updateText:u.updateText}):u.state.variant==="options"?Cn(A,{menuIndex:u.state.menuIndex,optionsMenuItems:Bn}):u.state.variant==="runners"?Cn(A,{menuIndex:ls(u.state).menuIndex,optionsMenuItems:Un(u.config,ls(u.state)),optionsMessage:Ji(ls(u.state)),optionsSubtitle:"Runners"}):u.state.variant==="error-log"?gi(A,{errorLogPath:u.state.errorLog?.path??r.errorLogFile,errorLogLines:u.state.errorLog?.lines??[]}):mi(A);u.pendingClear&&(m.moveTo(1,1),m.eraseDisplayBelow(),u.pendingClear=!1,w=null),m.noFormat($i(le,w)),w=le,m.hideCursor(!0)};let D=A=>rl(u,A),B=A=>nl(u,A),me=A=>il(u,A),ge=()=>{process.stdout.off("resize",T),process.off("SIGCONT",Me),m.removeListener("key",D),m.removeListener("unknown",B),m.removeListener("mouse",me),u.scrollRenderTimer&&(clearTimeout(u.scrollRenderTimer),u.scrollRenderTimer=null),u.inspectionScrollRenderTimer&&(clearTimeout(u.inspectionScrollRenderTimer),u.inspectionScrollRenderTimer=null),u.leftNavInspectionTimer&&(clearTimeout(u.leftNavInspectionTimer),u.leftNavInspectionTimer=null),u.pendingTerminalKeySequence&&(clearTimeout(u.pendingTerminalKeySequence.timer),u.pendingTerminalKeySequence=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(),m.grabInput(!1),m.hideCursor(!1),m.fullscreen(!1)};u.exit=A=>{ge(),f(A)};let T=()=>{os(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(Se(te(m.width,m.height))),u.state={mode:"main",shell:je(u,u.state.shell)}),u.render()},Me=()=>{os(u),u.state.mode==="main"&&u.state.shell.inputMode==="terminal"&&(u.ptyRuntime.resize(Se(te(m.width,m.height))),u.state={mode:"main",shell:je(u,u.state.shell)}),u.render()};process.stdout.on("resize",T),process.on("SIGCONT",Me),m.grabInput(!0),u.inputCaptureMode="control",m.hideCursor(!0),m.fullscreen(!0),m.on("key",D),m.on("unknown",B),m.on("mouse",me),u.prPollTimer=setInterval(()=>{Ya(u)},(u.config.github?.watchIntervalSeconds??5)*1e3),k.version.checkForUpdate().then(A=>{A.updateAvailable&&A.latest&&(u.updateText=`Update available: v${A.latest}`,u.render())}),u.bootHydrationReady=is(u).catch(()=>{}),u.render()})}async function mm(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=se(i);return await Ui(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=se(i);return await Ki(a),0}let e=Rs(process.argv.slice(2)),t=process.cwd(),r=se(t),n={paths:r};if(e.mode==="interactive")return await al({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await xo(e.command,n),o=Do(s);return o.length>0&&process.stdout.write(`${o}
|
|
164
165
|
`),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
165
|
-
`),1}}var
|
|
166
|
+
`),1}}var gm=await mm();process.exit(gm);
|