craig-cli 0.8.5 → 0.8.6
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/README.md +1 -1
- package/dist/cli.js +30 -30
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var ac=Object.defineProperty;var Wt=(e,t)=>{for(var r in t)ac(e,r,{get:t[r],enumerable:!0})};import{readFile as pc}from"node:fs/promises";import{randomUUID as lc}from"node:crypto";import{open as cc,readFile as Tg,rename as dc,rm as uc}from"node:fs/promises";import Lr from"node:path";async function N(e,t){let r=Lr.dirname(e),n=Lr.join(r,`.${Lr.basename(e)}.${process.pid}.${Date.now()}.${lc()}.tmp`),s=await cc(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await dc(n,e)}catch(o){throw await s.close().catch(()=>{}),await uc(n,{force:!0}).catch(()=>{}),o}}async function He(e){try{let t=await pc(e.uiStateFile,"utf8"),r=JSON.parse(t);return mc(r,e.uiStateFile)}catch(t){if(gc(t))return null;throw t}}async function Te(e,t){await N(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function Ut(){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 mc(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")||!Ke(e,"inputMode")||!Ke(e,"focusedRegion")||!Ke(e,"activeTab")||!Ke(e,"inspectorSection")||!Ke(e,"inspectionMode")||!_t(e,"openInspectionKind")||!_t(e,"selectedFileTreePath")||!_t(e,"selectedFilePath")||!_t(e,"selectedDiffPath")||!fc(e,"collapsedFileTreePaths")||!Ke(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 Ke(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function _t(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function fc(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function gc(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Or={};Wt(Or,{RUNNER_IDS:()=>$,assertEnabled:()=>
|
|
4
|
-
`)};var Wr={};Wt(Wr,{checkForUpdate:()=>
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await dc(n,e)}catch(o){throw await s.close().catch(()=>{}),await uc(n,{force:!0}).catch(()=>{}),o}}async function He(e){try{let t=await pc(e.uiStateFile,"utf8"),r=JSON.parse(t);return mc(r,e.uiStateFile)}catch(t){if(gc(t))return null;throw t}}async function Te(e,t){await N(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function Ut(){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 mc(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")||!Ke(e,"inputMode")||!Ke(e,"focusedRegion")||!Ke(e,"activeTab")||!Ke(e,"inspectorSection")||!Ke(e,"inspectionMode")||!_t(e,"openInspectionKind")||!_t(e,"selectedFileTreePath")||!_t(e,"selectedFilePath")||!_t(e,"selectedDiffPath")||!fc(e,"collapsedFileTreePaths")||!Ke(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 Ke(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function _t(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function fc(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function gc(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Or={};Wt(Or,{RUNNER_IDS:()=>$,assertEnabled:()=>Hs,buildCommand:()=>Ys,getConfiguredProfile:()=>Bt,getDefault:()=>Ks,getDisplayName:()=>zs,getEnabled:()=>qt,getProfile:()=>Ge,isRunnerType:()=>Vt,parse:()=>Gs,setRunnerEnabled:()=>Qs,setRunnerPath:()=>Js});var $=["codex","cursor","claude"];var Vs={codex:{id:"codex",displayName:"Codex",executable:"codex",defaultAgentTitle:"Codex"},cursor:{id:"cursor",displayName:"Cursor",executable:"cursor-agent",defaultAgentTitle:"Cursor"},claude:{id:"claude",displayName:"Claude",executable:"claude",defaultAgentTitle:"Claude"}};var Ge=e=>Vs[e];var Bt=(e,t={})=>{let r=Ge(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var qt=(e={})=>$.filter(t=>e.runners?.[t]?.enabled!==!1);var Ks=(e={})=>{let t=qt(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 Hs=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var Vt=e=>$.includes(e);var Gs=e=>{if(!e||e.length===0)return"codex";if(!Vt(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${$.join(", ")}.`);return e};var zs=e=>Ge(e).displayName;var Ys=(e,t,r={})=>{let n=[Bt(e,r).executable];return t&&t.length>0&&n.push(t),n};var Qs=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var Js=(e,t,r)=>{let n=e.runners?.[t]??{},{path:s,...o}=n;return{...e,runners:{...e.runners??{},[t]:r!=null?{...n,path:r}:o}}};var jr={};Wt(jr,{PREVIEW_FEATURE_IDS:()=>oe,isEnabled:()=>Xs,setEnabled:()=>Zs});var oe=["incrementalCenterPane","agentActivityIndicators"];function Xs(e,t){return e.previews?.[t]===!0}function Zs(e,t,r){return{...e,previews:{...e.previews,[t]:r}}}import{mkdir as hc,readFile as wc,writeFile as kc}from"node:fs/promises";import yc from"node:path";var Tc=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",eo=async e=>{try{return await wc(e,"utf8")}catch(t){if(Tc(t))return null;throw t}},to=async(e,t)=>{await hc(yc.dirname(e),{recursive:!0}),await kc(e,t,"utf8")};var Kt=(e,t)=>{if(typeof e!="object"||e===null)throw new Error(`Craig config at ${t} is invalid. Expected a JSON object.`);let r=e;if(r.runners!==void 0){if(typeof r.runners!="object"||r.runners===null||Array.isArray(r.runners))throw new Error(`Craig config at ${t} is invalid. "runners" must be an object.`);for(let[n,s]of Object.entries(r.runners)){if(!$.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${$.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" must be an object.`);let o=s;if(o.enabled!==void 0&&typeof o.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${n}.enabled" must be a boolean.`);if(o.path!==void 0&&(typeof o.path!="string"||o.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${n}.path" must be a non-empty string.`)}}if(r.checks!==void 0&&(typeof r.checks!="object"||r.checks===null||!Array.isArray(r.checks.commands)||!r.checks.commands.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(r.open!==void 0&&(typeof r.open!="object"||r.open===null||!Array.isArray(r.open.command)||!r.open.command.every(n=>typeof n=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}if(r.previews!==void 0){if(typeof r.previews!="object"||r.previews===null||Array.isArray(r.previews))throw new Error(`Craig config at ${t} is invalid. "previews" must be an object.`);for(let[n,s]of Object.entries(r.previews)){if(!oe.includes(n))throw new Error(`Craig config at ${t} is invalid. "previews.${n}" is not supported. Expected one of: ${oe.join(", ")}.`);if(typeof s!="boolean")throw new Error(`Craig config at ${t} is invalid. "previews.${n}" must be a boolean.`)}}return r};var Fr=async(e,t={readConfigFile:eo})=>{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 Kt(n,e.configFile)};var Nr=async(e,t,r={writeConfigFile:to})=>{Kt(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var Wr={};Wt(Wr,{checkForUpdate:()=>ro,getCurrent:()=>Ht});var Ht=()=>{try{return"0.8.6"}catch{return"unknown"}};var Rc="https://registry.npmjs.org/craig-cli/latest",bc=3600*1e3,Pc={value:null},Sc=(e,t)=>{let r=d=>d.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},ro=async(e={fetch:globalThis.fetch,getCurrent:Ht,cache:Pc})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<bc)return e.cache.value.result;let n=null;try{let o=await e.fetch(Rc,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&Sc(n,t)};return e.cache.value={result:s,cachedAt:r},s};var f={load:Fr,save:Nr,previews:jr,runners:Or,version:Wr};function no(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
|
|
5
5
|
|
|
6
6
|
`+G());return{mode:"command",command:{kind:"addRepo",path:r}}}if(t.length>=3&&t[0]==="workspace"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Workspace path cannot be empty.
|
|
7
7
|
|
|
@@ -26,12 +26,12 @@ ${G()}`)}function G(){return["Craig commands:"," craig Show the Cr
|
|
|
26
26
|
|
|
27
27
|
${G()}`);return t}function Ic(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
28
28
|
|
|
29
|
-
${G()}`);return t}var U=(e,t)=>{let r=_r(e);if(!Cc(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},_r=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Ur(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:xc(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Ec(t.repoTargets),runnerSession:t.runnerSession??vc(t),checks:Fc(t),lastCommit:t.lastCommit??null,prs:Nc(t),artifacts:Bc(t),cleanup:qc(t)}},vc=e=>{if(typeof e.title!="string")return null;let t=Ur(e.runner);return{command:f.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Cc=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"&&f.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"&&so(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||Ac(t.repoTargets))&&$c(t.runnerSession)&&Mc(t.prompt)&&oo(t.checks)&&io(t.lastCommit)&&Oc(t.prs)&&jc(t.artifacts)&&lo(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Ec=e=>{if(Array.isArray(e))return e.filter(no)},Ac=e=>Array.isArray(e)&&e.every(no),no=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)&&oo(t.checks)&&io(t.lastCommit)&&ao(t.pullRequest)&&lo(t.cleanup)},xc=e=>{if(so(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 Dc(e.id,e.title,t,Ur(e.runner))},Dc=(e,t,r,n)=>{let s=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:f.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Ur=e=>e&&f.runners.isRunnerType(e)?e:"codex",so=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"),$c=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),Mc=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",oo=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"),io=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",ao=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Lc(e.requiredChecks),Lc=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)),Oc=e=>Array.isArray(e)&&e.every(ao),jc=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),lo=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),Fc=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Nc=e=>{if(Array.isArray(e.prs))return e.prs.map(Wc);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:co(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:uo(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Wc=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:co(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:_c(t.reviewDecision),requiredChecks:uo(t.requiredChecks),comments:Uc(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},co=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,_c=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Uc=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}]}):[],uo=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})):[],Bc=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},qc=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as pd}from"node:fs/promises";import{readFile as Vc,readdir as Kc,rm as Hc}from"node:fs/promises";import po from"node:path";var Br=(e,t)=>po.join(e.workspacesDir,`${t}.json`),Gc=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"):[]}},mo=(e,t)=>{let r=Gc(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},De=async(e,t)=>{let r=Br(e,t),n=await Vc(r,"utf8");return mo(JSON.parse(n),r)},$e=async(e,t)=>{await N(Br(e,t.id),{...t,updatedAt:new Date().toISOString()})},Z=async e=>{let t=await Kc(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>De(e,po.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},fo=async(e,t)=>{await Hc(Br(e,t),{force:!0})};import{readFile as zc,readdir as Yc,rm as Qc}from"node:fs/promises";import go from"node:path";var qr=(e,t)=>go.join(e.reposDir,`${t}.json`),ho=(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},ne=async(e,t)=>{let r=qr(e,t),n=await zc(r,"utf8");return ho(JSON.parse(n),r)},Vr=async(e,t)=>{await N(qr(e,t.id),{...t,updatedAt:new Date().toISOString()})},dt=async e=>{let t=await Yc(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>ne(e,go.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},wo=async(e,t)=>{await Qc(qr(e,t),{force:!0})};import{readFile as Jc}from"node:fs/promises";var Xc=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"},Gt=(e,t,r)=>{if(!Xc(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},z=async e=>{let t=await Jc(e.indexFile,"utf8");return Gt(JSON.parse(t),e.workspaceRoot,e.indexFile)},fe=async(e,t)=>{await N(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as nd,stat as sd}from"node:fs/promises";import Ye from"node:path";import{realpath as To}from"node:fs/promises";import Ro from"node:path";import{execFile as Zc}from"node:child_process";import{promisify as ed}from"node:util";var ko=ed(Zc);async function P(e,t,r={}){try{let n=await ko(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(yo(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function x(e,t,r={}){try{let n=await ko(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(yo(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function yo(e){return e instanceof Error}var Kr=async e=>{try{let r=(await P("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([To(r).catch(()=>Ro.resolve(r)),To(e).catch(()=>Ro.resolve(e))]);return n===s}catch{return!1}},Hr=async e=>{let t=await x("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await P("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as ue,readFile as td}from"node:fs/promises";import Y from"node:path";function de(e){let t=Y.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:Y.join(t,"index.json"),reposDir:Y.join(t,"repos"),workspacesDir:Y.join(t,"workspaces"),sessionsDir:Y.join(t,"sessions"),runtimeDir:Y.join(t,"runtime"),uiStateFile:Y.join(t,"runtime","ui-state.json"),tasksDir:Y.join(t,"tasks"),jobsDir:Y.join(t,"jobs"),logsDir:Y.join(t,"logs"),errorLogFile:Y.join(t,"logs","errors.log"),artifactsDir:Y.join(t,"artifacts"),worktreesDir:Y.join(t,"worktrees"),configFile:Y.join(t,"config.json")}}var rd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",ze=async e=>{let t=de(e);await ue(t.craigDir,{recursive:!0}),await Promise.all([ue(t.reposDir,{recursive:!0}),ue(t.workspacesDir,{recursive:!0}),ue(t.sessionsDir,{recursive:!0}),ue(t.runtimeDir,{recursive:!0}),ue(t.tasksDir,{recursive:!0}),ue(t.jobsDir,{recursive:!0}),ue(t.logsDir,{recursive:!0}),ue(t.artifactsDir,{recursive:!0}),ue(t.worktreesDir,{recursive:!0})]);try{let s=await td(t.indexFile,"utf8"),o=JSON.parse(s);return Gt(o,e,t.indexFile)}catch(s){if(!rd(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await N(t.indexFile,n),n};var bo=(e,t,r)=>{let n=new Date().toISOString();return{id:od(e,Ye.basename(t)),name:Ye.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Po=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},od=(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},id=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},So=async(e,t)=>{let r=await z(e);await fe(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},ad=async(e,t)=>{let r=await nd(t,{withFileTypes:!0}),n=await dt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ye.join(t,o.name);if(!await Kr(i))continue;let a=n.find(d=>d.rootPath===i)??s.find(d=>d.rootPath===i),l=await Hr(i);s.push(a?Po(a,l):bo([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},ld=async(e,t)=>{let r=await Hr(t),n=await dt(e),s=n.find(u=>u.rootPath===t)??null,o=s?Po(s,r):bo(n,t,r),i=`workspace_${o.id}`,l=(await Z(e)).find(u=>u.id===i)??null,d=new Date().toISOString(),c=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:d,updatedAt:d};return await Vr(e,o),l||await $e(e,c),await So(e,{repoIds:[o.id],workspaceIds:[c.id]}),{kind:"createWorkspace",workspace:c,repos:[o],created:!l}},cd=async(e,t)=>{let r=await ad(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Z(e),s=id(n,Ye.basename(t)),o=n.find(d=>d.kind==="project"&&d.rootPath===t)??null,i=new Date().toISOString(),a=r.map(d=>d.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:Ye.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(d=>Vr(e,d))),await $e(e,l),await So(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},ut=async(e,t)=>{await ze(e.workspaceRoot);let r=Ye.resolve(e.workspaceRoot,t);if(!(await sd(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Kr(r)?ld(e,r):cd(e,r)};var Gr=async(e,t,r={listWorkspaceRecords:Z,ensureCraigState:ze})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var zr=async(e,t,r={readWorkspace:De,writeWorkspace:$e})=>{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 Yr=async(e,t)=>{let n={...await De(e,t),status:"active",archivedAt:null};await $e(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 Me=async(e,t,r={deleteWorkspace:fo,readCraigIndex:z,writeCraigIndex:fe})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Qr=async(e,t,r)=>{let n=await De(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 Me(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Jr={};Wt(Jr,{addRepo:()=>Io,listRegisteredRepos:()=>vo,removeRepo:()=>Co});import dd from"node:path";import{stat as ud}from"node:fs/promises";var Io=async(e,t)=>{let r=dd.resolve(e.workspaceRoot,t);if(!(await ud(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await ut(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 vo=async(e,t={listRepos:dt,ensureCraigState:ze})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Co=async(e,t,r)=>{let n=await ne(e,t),o=(await Z(e)).filter(d=>d.primaryRepoId===t),i=o.filter(d=>d.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(d=>Me(e,d.id))),await wo(e,t);let l=await z(e);return await fe(e,{...l,repoIds:l.repoIds.filter(d=>d!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Q={addWorkspace:ut,listWorkspaces:Gr,archiveWorkspace:zr,restoreWorkspace:Yr,removeWorkspace:Qr,removeWorkspaceRecord:Me,repos:Jr};var J=async(e,t)=>{let r=await pd(Zr(e,t),"utf8");return JSON.parse(r)},ee=async(e,t)=>{let r=await J(e,t);return U(r,Zr(e,t))},S=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await N(Zr(e,t.id),r)},Xr=async(e,t)=>{let r=await z(e);r.taskIds.includes(t)||await fe(e,{...r,taskIds:[...r.taskIds,t]})},Zr=(e,t)=>`${e.tasksDir}/${t}.json`;var D=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,Re=e=>e.status==="merged"||e.status==="closed",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}},pt=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Yt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Yt=e=>e.mergeable&&!md(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),md=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",en=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),mt=(e,t)=>{let r=e.isDraft??!1,n=fd(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:gd(e.reviewDecision??null),requiredChecks:ft(e.statusCheckRollup),comments:yd(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}},fd=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,gd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,ft=e=>{let t=e.map(n=>hd(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||wd(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},hd=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:Ao(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:kd(t)}:null},wd=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):zt(e)&&!zt(t)?!0:!zt(e)&&zt(t)?!1:Eo(t.status)>=Eo(e.status),zt=e=>e.conclusion?.toUpperCase()==="CANCELLED",Eo=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},kd=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},yd=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Td).filter(r=>r!==null).slice(-4):[]},Td=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=Rd(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},Rd=e=>e.replace(/\s+/g," ").trim(),Ao=(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?Ao(n,n):"unknown"};import{access as bd}from"node:fs/promises";import xo from"node:path";var v=async(e,t,r={readRawTask:J,validateTaskRecord:U})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Cd(n)?new Error(`Craig task "${t}" was not found.`):n}},B=async e=>{if(!await tn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},Je=(e,t)=>t.artifacts.logPath?xo.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:xo.join(e.workspaceRoot,t.artifacts.logPath):null,gt=async(e,t)=>{let r=await tn(t.worktreePath),n=Je(e,t),s=n?await tn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Pd(t),lastCommitSummary:Sd(t),prSummary:Id(t),cleanupSummary:vd(t)}},tn=async e=>{try{return await bd(e),!0}catch{return!1}},Pd=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},Sd=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Id=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,d)=>{let c=d.pullRequest.status??"unknown";return l[c]=(l[c]??0)+1,l},{}),a=Object.entries(i).map(([l,d])=>`${d} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
29
|
+
${G()}`);return t}var U=(e,t)=>{let r=_r(e);if(!Cc(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},_r=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:Ur(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:xc(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Ec(t.repoTargets),runnerSession:t.runnerSession??vc(t),checks:Fc(t),lastCommit:t.lastCommit??null,prs:Nc(t),artifacts:Bc(t),cleanup:qc(t)}},vc=e=>{if(typeof e.title!="string")return null;let t=Ur(e.runner);return{command:f.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Cc=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"&&f.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"&&oo(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||Ac(t.repoTargets))&&$c(t.runnerSession)&&Mc(t.prompt)&&io(t.checks)&&ao(t.lastCommit)&&Oc(t.prs)&&jc(t.artifacts)&&co(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Ec=e=>{if(Array.isArray(e))return e.filter(so)},Ac=e=>Array.isArray(e)&&e.every(so),so=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)&&io(t.checks)&&ao(t.lastCommit)&&lo(t.pullRequest)&&co(t.cleanup)},xc=e=>{if(oo(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 Dc(e.id,e.title,t,Ur(e.runner))},Dc=(e,t,r,n)=>{let s=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:f.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Ur=e=>e&&f.runners.isRunnerType(e)?e:"codex",oo=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"),$c=e=>typeof e=="object"&&e!==null&&Array.isArray(e.command)&&e.command.every(t=>typeof t=="string")&&(typeof e.pid=="number"||e.pid===null)&&(typeof e.startedAt=="string"||e.startedAt===null)&&(e.lastKnownState==="starting"||e.lastKnownState==="running"||e.lastKnownState==="exited"||e.lastKnownState==="failed")&&(typeof e.exitCode=="number"||e.exitCode===null)&&(typeof e.exitedAt=="string"||e.exitedAt===null),Mc=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",io=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"),ao=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",lo=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&Lc(e.requiredChecks),Lc=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)),Oc=e=>Array.isArray(e)&&e.every(lo),jc=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),co=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),Fc=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Nc=e=>{if(Array.isArray(e.prs))return e.prs.map(Wc);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:uo(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:po(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Wc=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:uo(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:_c(t.reviewDecision),requiredChecks:po(t.requiredChecks),comments:Uc(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},uo=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,_c=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Uc=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}]}):[],po=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})):[],Bc=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},qc=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as pd}from"node:fs/promises";import{readFile as Vc,readdir as Kc,rm as Hc}from"node:fs/promises";import mo from"node:path";var Br=(e,t)=>mo.join(e.workspacesDir,`${t}.json`),Gc=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"):[]}},fo=(e,t)=>{let r=Gc(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},De=async(e,t)=>{let r=Br(e,t),n=await Vc(r,"utf8");return fo(JSON.parse(n),r)},$e=async(e,t)=>{await N(Br(e,t.id),{...t,updatedAt:new Date().toISOString()})},Z=async e=>{let t=await Kc(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>De(e,mo.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},go=async(e,t)=>{await Hc(Br(e,t),{force:!0})};import{readFile as zc,readdir as Yc,rm as Qc}from"node:fs/promises";import ho from"node:path";var qr=(e,t)=>ho.join(e.reposDir,`${t}.json`),wo=(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},ne=async(e,t)=>{let r=qr(e,t),n=await zc(r,"utf8");return wo(JSON.parse(n),r)},Vr=async(e,t)=>{await N(qr(e,t.id),{...t,updatedAt:new Date().toISOString()})},dt=async e=>{let t=await Yc(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>ne(e,ho.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},ko=async(e,t)=>{await Qc(qr(e,t),{force:!0})};import{readFile as Jc}from"node:fs/promises";var Xc=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"},Gt=(e,t,r)=>{if(!Xc(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},z=async e=>{let t=await Jc(e.indexFile,"utf8");return Gt(JSON.parse(t),e.workspaceRoot,e.indexFile)},fe=async(e,t)=>{await N(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as nd,stat as sd}from"node:fs/promises";import Ye from"node:path";import{realpath as Ro}from"node:fs/promises";import bo from"node:path";import{execFile as Zc}from"node:child_process";import{promisify as ed}from"node:util";var yo=ed(Zc);async function P(e,t,r={}){try{let n=await yo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(To(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function x(e,t,r={}){try{let n=await yo(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(To(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function To(e){return e instanceof Error}var Kr=async e=>{try{let r=(await P("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([Ro(r).catch(()=>bo.resolve(r)),Ro(e).catch(()=>bo.resolve(e))]);return n===s}catch{return!1}},Hr=async e=>{let t=await x("git",["symbolic-ref","--quiet","--short","refs/remotes/origin/HEAD"],{cwd:e}),r=t.stdout.trim().replace(/^origin\//,"");if(t.exitCode===0&&r.length>0)return r;for(let o of["main","master","trunk"])if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await P("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"};import{mkdir as ue,readFile as td}from"node:fs/promises";import Y from"node:path";function de(e){let t=Y.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:Y.join(t,"index.json"),reposDir:Y.join(t,"repos"),workspacesDir:Y.join(t,"workspaces"),sessionsDir:Y.join(t,"sessions"),runtimeDir:Y.join(t,"runtime"),uiStateFile:Y.join(t,"runtime","ui-state.json"),tasksDir:Y.join(t,"tasks"),jobsDir:Y.join(t,"jobs"),logsDir:Y.join(t,"logs"),errorLogFile:Y.join(t,"logs","errors.log"),artifactsDir:Y.join(t,"artifacts"),worktreesDir:Y.join(t,"worktrees"),configFile:Y.join(t,"config.json")}}var rd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",ze=async e=>{let t=de(e);await ue(t.craigDir,{recursive:!0}),await Promise.all([ue(t.reposDir,{recursive:!0}),ue(t.workspacesDir,{recursive:!0}),ue(t.sessionsDir,{recursive:!0}),ue(t.runtimeDir,{recursive:!0}),ue(t.tasksDir,{recursive:!0}),ue(t.jobsDir,{recursive:!0}),ue(t.logsDir,{recursive:!0}),ue(t.artifactsDir,{recursive:!0}),ue(t.worktreesDir,{recursive:!0})]);try{let s=await td(t.indexFile,"utf8"),o=JSON.parse(s);return Gt(o,e,t.indexFile)}catch(s){if(!rd(s))throw s instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):s}let r=new Date().toISOString(),n={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await N(t.indexFile,n),n};var Po=(e,t,r)=>{let n=new Date().toISOString();return{id:od(e,Ye.basename(t)),name:Ye.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},So=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},od=(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},id=(e,t)=>{let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"workspace",n=`workspace_${r}`,s=2;for(;e.some(o=>o.id===n);)n=`workspace_${r}_${s}`,s+=1;return n},Io=async(e,t)=>{let r=await z(e);await fe(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},ad=async(e,t)=>{let r=await nd(t,{withFileTypes:!0}),n=await dt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=Ye.join(t,o.name);if(!await Kr(i))continue;let a=n.find(d=>d.rootPath===i)??s.find(d=>d.rootPath===i),l=await Hr(i);s.push(a?So(a,l):Po([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},ld=async(e,t)=>{let r=await Hr(t),n=await dt(e),s=n.find(u=>u.rootPath===t)??null,o=s?So(s,r):Po(n,t,r),i=`workspace_${o.id}`,l=(await Z(e)).find(u=>u.id===i)??null,d=new Date().toISOString(),c=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:d,updatedAt:d};return await Vr(e,o),l||await $e(e,c),await Io(e,{repoIds:[o.id],workspaceIds:[c.id]}),{kind:"createWorkspace",workspace:c,repos:[o],created:!l}},cd=async(e,t)=>{let r=await ad(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await Z(e),s=id(n,Ye.basename(t)),o=n.find(d=>d.kind==="project"&&d.rootPath===t)??null,i=new Date().toISOString(),a=r.map(d=>d.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:Ye.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(d=>Vr(e,d))),await $e(e,l),await Io(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},ut=async(e,t)=>{await ze(e.workspaceRoot);let r=Ye.resolve(e.workspaceRoot,t);if(!(await sd(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await Kr(r)?ld(e,r):cd(e,r)};var Gr=async(e,t,r={listWorkspaceRecords:Z,ensureCraigState:ze})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var zr=async(e,t,r={readWorkspace:De,writeWorkspace:$e})=>{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 Yr=async(e,t)=>{let n={...await De(e,t),status:"active",archivedAt:null};await $e(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 Me=async(e,t,r={deleteWorkspace:go,readCraigIndex:z,writeCraigIndex:fe})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Qr=async(e,t,r)=>{let n=await De(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 Me(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};var Jr={};Wt(Jr,{addRepo:()=>vo,listRegisteredRepos:()=>Co,removeRepo:()=>Eo});import dd from"node:path";import{stat as ud}from"node:fs/promises";var vo=async(e,t)=>{let r=dd.resolve(e.workspaceRoot,t);if(!(await ud(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await ut(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var Co=async(e,t={listRepos:dt,ensureCraigState:ze})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Eo=async(e,t,r)=>{let n=await ne(e,t),o=(await Z(e)).filter(d=>d.primaryRepoId===t),i=o.filter(d=>d.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(d=>Me(e,d.id))),await ko(e,t);let l=await z(e);return await fe(e,{...l,repoIds:l.repoIds.filter(d=>d!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var Q={addWorkspace:ut,listWorkspaces:Gr,archiveWorkspace:zr,restoreWorkspace:Yr,removeWorkspace:Qr,removeWorkspaceRecord:Me,repos:Jr};var J=async(e,t)=>{let r=await pd(Zr(e,t),"utf8");return JSON.parse(r)},ee=async(e,t)=>{let r=await J(e,t);return U(r,Zr(e,t))},S=async(e,t)=>{let r={...t,updatedAt:new Date().toISOString()};await N(Zr(e,t.id),r)},Xr=async(e,t)=>{let r=await z(e);r.taskIds.includes(t)||await fe(e,{...r,taskIds:[...r.taskIds,t]})},Zr=(e,t)=>`${e.tasksDir}/${t}.json`;var D=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,Re=e=>e.status==="merged"||e.status==="closed",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}},pt=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Yt(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Yt=e=>e.mergeable&&!md(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),md=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",en=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),mt=(e,t)=>{let r=e.isDraft??!1,n=fd(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:gd(e.reviewDecision??null),requiredChecks:ft(e.statusCheckRollup),comments:yd(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}},fd=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,gd=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,ft=e=>{let t=e.map(n=>hd(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||wd(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},hd=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:xo(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:kd(t)}:null},wd=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):zt(e)&&!zt(t)?!0:!zt(e)&&zt(t)?!1:Ao(t.status)>=Ao(e.status),zt=e=>e.conclusion?.toUpperCase()==="CANCELLED",Ao=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},kd=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},yd=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Td).filter(r=>r!==null).slice(-4):[]},Td=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=Rd(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},Rd=e=>e.replace(/\s+/g," ").trim(),xo=(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?xo(n,n):"unknown"};import{access as bd}from"node:fs/promises";import Do from"node:path";var v=async(e,t,r={readRawTask:J,validateTaskRecord:U})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw Cd(n)?new Error(`Craig task "${t}" was not found.`):n}},B=async e=>{if(!await tn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},Je=(e,t)=>t.artifacts.logPath?Do.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Do.join(e.workspaceRoot,t.artifacts.logPath):null,gt=async(e,t)=>{let r=await tn(t.worktreePath),n=Je(e,t),s=n?await tn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Pd(t),lastCommitSummary:Sd(t),prSummary:Id(t),cleanupSummary:vd(t)}},tn=async e=>{try{return await bd(e),!0}catch{return!1}},Pd=e=>{let t=e.checks.commands.length,r=t===1?"command":"commands",n=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${n}`},Sd=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Id=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,d)=>{let c=d.pullRequest.status??"unknown";return l[c]=(l[c]??0)+1,l},{}),a=Object.entries(i).map(([l,d])=>`${d} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
30
30
|
${o.join(`
|
|
31
|
-
`)}`}let t=D(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},vd=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",Cd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var
|
|
32
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},
|
|
31
|
+
`)}`}let t=D(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},vd=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",Cd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var $o=async(e,t)=>{let r=await x("git",["show-ref","--verify","--quiet",`refs/heads/${t}`],{cwd:e});if(r.exitCode===0)return!0;if(r.exitCode===1)return!1;throw new Error(r.stderr.trim()||r.stdout.trim()||"Unable to check git branch state.")},rn=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await x("git",["show-ref","--verify","--quiet",`refs/heads/${s}`],{cwd:e})).exitCode!==0)throw new Error(`Base branch '${s}' does not exist locally.`);let i=await Ed(e,s);await P("git",["worktree","add","-b",t,r,i],{cwd:e})},Ed=async(e,t)=>(await x("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await x("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await x("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,Qt=async e=>{let t=await x("git",["status","--short"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"Unable to inspect git status.");return t.stdout.trim().length>0},Mo=async e=>{await P("git",["add","-A"],{cwd:e})},Lo=async(e,t)=>{await P("git",["commit","-m",t],{cwd:e})},Oo=async e=>{let t=await P("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}},jo=async e=>{let t=await x("git",["branch","--show-current"],{cwd:e});if(t.exitCode!==0)return null;let r=t.stdout.trim();return r.length>0?r:null};var Fo=async(e,t)=>{await P("git",["worktree","remove","--force",t],{cwd:e})};var nn=async e=>Xe(e,e.repoRoot),Xe=async(e,t)=>{let r=await z(e),n=No(new Date),s=Wo(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await $o(t,i))return o;s+=1}},ht=async e=>{let t=await z(e),r=No(new Date),n=Wo(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},No=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},Wo=(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 sn=async(e,t,r={readRawTask:J,validateTaskRecord:U})=>{let n=await z(e),s=[],o=[];await Promise.all(n.taskIds.map(async l=>{try{let d=await r.readRawTask(e,l);s.push(r.validateTaskRecord(d,`${e.tasksDir}/${l}.json`))}catch(d){if(Ad(d)){o.push(l);return}throw d}}));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(d=>d.repoId===t.repoId)));return a.sort((l,d)=>l.id.localeCompare(d.id)),o.sort(),{kind:"listTasks",tasks:a,missingTaskIds:o,repoId:t?.repoId??null}},Ad=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var _o=["merge_ready","pr_open","checked","review","running","draft"],on=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),an=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(xd)[0]?.id??null,xd=(e,t)=>{let r=Uo(e.status),n=Uo(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},Uo=e=>{let t=_o.indexOf(e);return t>=0?t:_o.length};import Bo from"node:path";var Le=(e,t)=>t?Bo.isAbsolute(t)?t:Bo.join(e.repoRoot,t):null;import{mkdir as wt,rm as Dd,writeFile as Jt}from"node:fs/promises";import A from"node:path";var Vo=["AGENTS","md"].join("."),Ze=async(e,t,r,n={})=>{let s=await ne(e,t),o=await jd(e,s.id),i=await Xe(e,s.rootPath),a=n.sessionId??null,l=`craig/${i}`,d=A.join(e.worktreesDir,s.id,i),c=A.join(e.logsDir,`${i}.log`),u=A.join(e.artifactsDir,i);await wt(A.dirname(d),{recursive:!0}),await wt(u,{recursive:!0}),await Jt(c,"","utf8");let p=$d(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:d});return await S(e,p),await Xr(e,i),await rn(s.rootPath,l,d,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:p}},kt=async(e,t,r,n={})=>{let s=(await Z(e)).find(I=>I.id===t&&I.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 I=await Ze(e,s.primaryRepoId,r,n);return{...I,bundlePath:I.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await ht(e),a=new Date().toISOString(),l=n.runner??"codex",d=n.sessionId??null,c=`craig/${i}`,u=A.join(e.craigDir,"task-bundles",i),p=A.join(e.logsDir,`${i}.log`),k=A.join(e.artifactsDir,i);await wt(u,{recursive:!0}),await wt(k,{recursive:!0}),await Jt(p,"","utf8");let y=await Promise.all(o.map(I=>ne(e,I))),w=Ld(y),b=await Promise.all(y.map(I=>Md(e,I,i,c,A.join(u,w.get(I.id))))),q=b.find(I=>I.status==="ready")??b[0];if(!b.some(I=>I.status==="ready"))throw await Dd(u,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${b.map(I=>`${I.repoId}: ${I.failureReason??"unknown error"}`).join("; ")}`);await Jt(A.join(u,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:b.map(I=>({repoId:I.repoId,repoName:y.find(re=>re.id===I.repoId)?.name??I.repoId,path:A.relative(u,I.worktreePath),status:I.status,worktreePath:I.worktreePath,failureReason:I.failureReason}))},null,2),"utf8"),await Jt(A.join(u,Vo),Od({taskId:i,workspaceId:t,prompt:r,repos:y,repoTargets:b,bundlePath:u}),"utf8");let te=yt(i,r,a,l,n.config??{}),me={id:i,title:r,slug:Ko(r),type:"project",status:"draft",runner:l,repoId:q.repoId,workspaceId:s.id,sessionId:d,selectedPtyTabId:te[0]?.id??null,linkedRepoIds:o.filter(I=>I!==q.repoId),repoRoot:u,worktreePath:u,branch:c,bundlePath:u,selectedRepoTargetId:q.repoId,repoTargets:b,ptyTabs:te,runnerSession:{command:f.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:q.checks,lastCommit:null,prs:[],artifacts:{logPath:A.relative(e.workspaceRoot,p),checkSummaryPath:A.relative(e.workspaceRoot,A.join(k,"check-summary.json")),prDraftPath:null,prStatusPath:A.relative(e.workspaceRoot,A.join(k,"pr-status.json"))},cleanup:Xt(),lastFailureReason:b.every(I=>I.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await S(e,me),await Xr(e,i),{repoId:q.repoId,repoRoot:u,sessionId:d,workspaceId:s.id,task:me,bundlePath:u,repoTargets:b}},yt=(e,t,r,n="codex",s={})=>{let o=f.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:f.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},$d=(e,t)=>{let r=new Date().toISOString(),n=yt(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:Ko(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:f.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:{...ln(A.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:A.relative(e.workspaceRoot,A.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:A.relative(e.workspaceRoot,A.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:A.relative(e.workspaceRoot,A.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:Xt(),lastFailureReason:null,createdAt:r,updatedAt:r}},Md=async(e,t,r,n,s)=>{await wt(A.dirname(s),{recursive:!0});try{return await rn(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:ln(A.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:qo(),cleanup:Xt()}}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:ln(A.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:qo(),cleanup:Xt()}}},Ld=e=>{let t=new Set(["manifest.json",Vo]),r=new Map;for(let n of e){let s=t.has(n.name)?`${n.name}-repo`:n.name,o=s,i=2;for(;t.has(o);)o=`${s}-${i}`,i+=1;t.add(o),r.set(n.id,o)}return r},Od=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=A.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
|
-
`)},ln=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),Bo=()=>({provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}),Xt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),jd=async(e,t)=>{let n=(await Z(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},Vo=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import ti from"node:path";import{readFile as Fd,rm as Nk}from"node:fs/promises";import Nd from"node:path";var be=async(e,t)=>{let r=await Fd(cn(e,t),"utf8"),n=JSON.parse(r);return Wd(n,cn(e,t))},Oe=async(e,t)=>{await N(cn(e,t.id),{...t,updatedAt:new Date().toISOString()})};var cn=(e,t)=>Nd.join(e.sessionsDir,`${t}.json`);function Wd(e,t){let r=Bd(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")||!Ud(r.attach)||!_d(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 _d(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 Ud(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 Bd(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 qd}from"node:child_process";import{createHash as Vd}from"node:crypto";import Kd from"node:path";function Zt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Hd="craig",Ko=async(e,t,r)=>{let n=dn(e,t),s=zd(),o=await P("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Qd(o.stdout);return await Gd(e,n),i};var Gd=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 P("tmux",n,{cwd:e})},Ho=async(e,t,r)=>{await P("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},Go=async(e,t,r)=>{await P("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var zo=async(e,t,r)=>{await P("tmux",["pipe-pane","-o","-t",e,`cat >> ${Zt(t)}`],{cwd:r})},er=async(e,t,r,n)=>{let s=n??Qo(e);if(r?await P("tmux",["select-window","-t",r],{cwd:e}):await P("tmux",["select-window","-t",t],{cwd:e}),await P("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await P("tmux",["switch-client","-t",s],{cwd:e});return}await Xd(e,["attach-session","-t",s])};var Yo=async(e,t)=>{await P("tmux",["kill-session","-t",t],{cwd:e})};var Qo=e=>{let r=Kd.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Vd("sha1").update(e).digest("hex").slice(0,8);return`${Hd}-${r}-${n}`},dn=(e,t)=>`${Qo(e)}-${t.toLowerCase()}`,zd=()=>{let e=Yd();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Yd=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Qd=e=>{let t=Jd(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]}},Jd=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Xd=async(e,t)=>{await new Promise((r,n)=>{let s=qd("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 Zd,constants as eu}from"node:fs";import{homedir as Jo}from"node:os";import Pe from"node:path";var tu=[Pe.join(Jo(),".local","bin"),Pe.join(Jo(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function Zo(e=process.env){return ru([...(e.PATH??"").split(Pe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:tu])}function je(e=process.env){return{...e,PATH:Zo(e).join(Pe.delimiter)}}function un(e,t={}){if(e.includes(Pe.sep)){let r=Pe.isAbsolute(e)?e:Pe.resolve(t.cwd??process.cwd(),e);return Xo(r)?r:null}for(let r of Zo(t.env)){let n=Pe.join(r,e);if(Xo(n))return n}return null}function Fe(e,t={}){let r=un(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 Xo(e){try{return Zd(e,eu.X_OK),!0}catch{return!1}}function ru(e){return[...new Set(e)]}var Tt={async create(e,t){let r=await Ko(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await zo(r.paneId,t.logPath,t.repoRoot);let n=await ei({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||dn(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 Oe(e,s),s},async attach(e,t,r){let n=await Tt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await er(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Oe(e,s),s},async resize(e,t,r,n){await Ho(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Oe(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 Oe(e,n),n},async snapshot(e,t){return nu(e,t)}},pn={async prepare(e,t){let n=e.runnerSession.command[0],s=je();await P(Fe(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Fe(r[0],{cwd:e.worktreePath,env:je()});await Go(t.session.paneId,[n,...r.slice(1)].map(s=>Zt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},nu=async(e,t)=>{let r=await x("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return ei({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},ei=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var mn=async(e,t,r,n={})=>{let s=r.trim(),o=await f.load(e),i=n.runner??f.runners.getDefault(o);if(f.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 kt(e,n.workspaceId,s,{runner:i,config:o}):await Ze(e,t,s,{runner:i,config:o}),l=a.task,d=f.runners.buildCommand(i,s,o),c=`session_${l.id}`,u=l.artifacts.logPath?ti.resolve(e.workspaceRoot,l.artifacts.logPath):ti.join(e.logsDir,`${l.id}.log`);try{await pn.prepare(l,{repoRoot:a.repoRoot});let p=await Tt.create(e,{sessionId:c,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:d});await pn.launch(l,{repoRoot:a.repoRoot,session:p});let k=new Date().toISOString();p={...p,status:"running",startedAt:k,command:d};let y={...l,status:"running",runner:i,sessionId:p.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:p.command,pid:null,startedAt:k,lastKnownState:"running",exitCode:null,exitedAt:null}};return await S(e,y),await Oe(e,p),{kind:"createTask",taskId:y.id,repoId:y.repoId,workspaceId:y.workspaceId,sessionId:p.id,status:y.status,branch:y.branch,worktreePath:y.worktreePath,runner:y.runner}}catch(p){let k={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:p instanceof Error?p.message:"Unknown Craig error"};throw await S(e,k),p}};import{mkdir as mu}from"node:fs/promises";import fu from"node:path";var ri=3,su=1e3,ou=1e4,et=async e=>{let t=await x("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var ni=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await P("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},tr=async(e,t)=>{let r=await P("gh",ii(e),{cwd:t});return JSON.parse(r.stdout)},tt=async(e,t)=>{let r=await x("gh",ii(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},si=async(e,t,r)=>{if(r.length===0)return[];let n=uu(r),s=await iu(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 d=i[`item${l}`],c=pu(d);return{id:a.id,found:c!==null,view:c}})},oi=async e=>{let t=await x("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:du(t.stdout.trim())},iu=async(e,t)=>{let r;for(let n=0;n<=ri;n+=1)try{return await P("gh",t,{cwd:e})}catch(s){if(r=s,n===ri||!au(s))throw s;await cu(lu(n))}throw r},au=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")},lu=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||su,r=Math.min(t*2**e,ou),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},cu=e=>new Promise(t=>setTimeout(t,e)),ii=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],du=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},uu=e=>`
|
|
34
|
+
`)},ln=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),qo=()=>({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}),Xt=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),jd=async(e,t)=>{let n=(await Z(e)).find(s=>s.kind!=="project"&&s.primaryRepoId===t&&s.status==="active");if(!n)throw new Error(`Repo ${t} does not have an active workspace.`);return n},Ko=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import ri from"node:path";import{readFile as Fd,rm as Nk}from"node:fs/promises";import Nd from"node:path";var be=async(e,t)=>{let r=await Fd(cn(e,t),"utf8"),n=JSON.parse(r);return Wd(n,cn(e,t))},Oe=async(e,t)=>{await N(cn(e,t.id),{...t,updatedAt:new Date().toISOString()})};var cn=(e,t)=>Nd.join(e.sessionsDir,`${t}.json`);function Wd(e,t){let r=Bd(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")||!Ud(r.attach)||!_d(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 _d(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 Ud(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 Bd(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 qd}from"node:child_process";import{createHash as Vd}from"node:crypto";import Kd from"node:path";function Zt(e){return`'${e.replace(/'/g,"'\\''")}'`}var Hd="craig",Ho=async(e,t,r)=>{let n=dn(e,t),s=zd(),o=await P("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Qd(o.stdout);return await Gd(e,n),i};var Gd=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 P("tmux",n,{cwd:e})},Go=async(e,t,r)=>{await P("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},zo=async(e,t,r)=>{await P("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var Yo=async(e,t,r)=>{await P("tmux",["pipe-pane","-o","-t",e,`cat >> ${Zt(t)}`],{cwd:r})},er=async(e,t,r,n)=>{let s=n??Jo(e);if(r?await P("tmux",["select-window","-t",r],{cwd:e}):await P("tmux",["select-window","-t",t],{cwd:e}),await P("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await P("tmux",["switch-client","-t",s],{cwd:e});return}await Xd(e,["attach-session","-t",s])};var Qo=async(e,t)=>{await P("tmux",["kill-session","-t",t],{cwd:e})};var Jo=e=>{let r=Kd.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Vd("sha1").update(e).digest("hex").slice(0,8);return`${Hd}-${r}-${n}`},dn=(e,t)=>`${Jo(e)}-${t.toLowerCase()}`,zd=()=>{let e=Yd();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Yd=()=>{let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,n="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof n=="number"&&n>0)return{columns:r,rows:n}}return null},Qd=e=>{let t=Jd(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]}},Jd=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Xd=async(e,t)=>{await new Promise((r,n)=>{let s=qd("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 Zd,constants as eu}from"node:fs";import{homedir as Xo}from"node:os";import Pe from"node:path";var tu=[Pe.join(Xo(),".local","bin"),Pe.join(Xo(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ei(e=process.env){return ru([...(e.PATH??"").split(Pe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:tu])}function je(e=process.env){return{...e,PATH:ei(e).join(Pe.delimiter)}}function un(e,t={}){if(e.includes(Pe.sep)){let r=Pe.isAbsolute(e)?e:Pe.resolve(t.cwd??process.cwd(),e);return Zo(r)?r:null}for(let r of ei(t.env)){let n=Pe.join(r,e);if(Zo(n))return n}return null}function Fe(e,t={}){let r=un(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 Zo(e){try{return Zd(e,eu.X_OK),!0}catch{return!1}}function ru(e){return[...new Set(e)]}var Tt={async create(e,t){let r=await Ho(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Yo(r.paneId,t.logPath,t.repoRoot);let n=await ti({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||dn(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 Oe(e,s),s},async attach(e,t,r){let n=await Tt.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await er(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Oe(e,s),s},async resize(e,t,r,n){await Go(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Oe(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 Oe(e,n),n},async snapshot(e,t){return nu(e,t)}},pn={async prepare(e,t){let n=e.runnerSession.command[0],s=je();await P(Fe(n,{cwd:t.repoRoot,env:s}),["--help"],{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Fe(r[0],{cwd:e.worktreePath,env:je()});await zo(t.session.paneId,[n,...r.slice(1)].map(s=>Zt(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},nu=async(e,t)=>{let r=await x("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return ti({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},ti=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var mn=async(e,t,r,n={})=>{let s=r.trim(),o=await f.load(e),i=n.runner??f.runners.getDefault(o);if(f.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 kt(e,n.workspaceId,s,{runner:i,config:o}):await Ze(e,t,s,{runner:i,config:o}),l=a.task,d=f.runners.buildCommand(i,s,o),c=`session_${l.id}`,u=l.artifacts.logPath?ri.resolve(e.workspaceRoot,l.artifacts.logPath):ri.join(e.logsDir,`${l.id}.log`);try{await pn.prepare(l,{repoRoot:a.repoRoot});let p=await Tt.create(e,{sessionId:c,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:d});await pn.launch(l,{repoRoot:a.repoRoot,session:p});let k=new Date().toISOString();p={...p,status:"running",startedAt:k,command:d};let y={...l,status:"running",runner:i,sessionId:p.id,selectedPtyTabId:l.selectedPtyTabId,runnerSession:{command:p.command,pid:null,startedAt:k,lastKnownState:"running",exitCode:null,exitedAt:null}};return await S(e,y),await Oe(e,p),{kind:"createTask",taskId:y.id,repoId:y.repoId,workspaceId:y.workspaceId,sessionId:p.id,status:y.status,branch:y.branch,worktreePath:y.worktreePath,runner:y.runner}}catch(p){let k={...l,sessionId:null,status:"draft",runnerSession:{...l.runnerSession,lastKnownState:"failed"},lastFailureReason:p instanceof Error?p.message:"Unknown Craig error"};throw await S(e,k),p}};import{mkdir as mu}from"node:fs/promises";import fu from"node:path";var ni=3,su=1e3,ou=1e4,et=async e=>{let t=await x("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var si=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await P("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},tr=async(e,t)=>{let r=await P("gh",ai(e),{cwd:t});return JSON.parse(r.stdout)},tt=async(e,t)=>{let r=await x("gh",ai(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},oi=async(e,t,r)=>{if(r.length===0)return[];let n=uu(r),s=await iu(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 d=i[`item${l}`],c=pu(d);return{id:a.id,found:c!==null,view:c}})},ii=async e=>{let t=await x("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:du(t.stdout.trim())},iu=async(e,t)=>{let r;for(let n=0;n<=ni;n+=1)try{return await P("gh",t,{cwd:e})}catch(s){if(r=s,n===ni||!au(s))throw s;await cu(lu(n))}throw r},au=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")},lu=e=>{let t=Number(process.env.CRAIG_GH_RATE_LIMIT_RETRY_BASE_MS)||su,r=Math.min(t*2**e,ou),n=Math.floor(Math.random()*Math.max(1,Math.floor(r*.25)));return r+n},cu=e=>new Promise(t=>setTimeout(t,e)),ai=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],du=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},uu=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
|
-
`,pu=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 Ne=async(e,t)=>{let r=Le(e,t.artifacts.prStatusPath);r&&(await mu(fu.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,prs:t.prs}))},Rt=async(e,t,r,n,s={readRawTask:J,validateTaskRecord:U,writeTask:S,writePrStatusArtifact:Ne})=>{let o=mt(r,n),i=Qe(t,o),a=pt(i.prs),l={...i,status:a};await s.writePrStatusArtifact(e,l);let d=await s.readRawTask(e,t.id),c=s.validateTaskRecord(d,`${e.tasksDir}/${t.id}.json`),u=c.status==="closed"?c.status:a,p=Qe({...c,status:u},o);return await s.writeTask(e,p),p},bt=async(e,t)=>{let r=D(t),n=r?.number?String(r.number):t.branch,s=await tr(n,t.worktreePath);return Rt(e,t,s,r)},Pt=async(e,t)=>{for(let r of await fn(t)){let n=await tt(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await Rt(e,t,n,null)}}return{discovered:!1,task:t}},fn=async e=>{let t=await
|
|
113
|
+
`,pu=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 Ne=async(e,t)=>{let r=Le(e,t.artifacts.prStatusPath);r&&(await mu(fu.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,prs:t.prs}))},Rt=async(e,t,r,n,s={readRawTask:J,validateTaskRecord:U,writeTask:S,writePrStatusArtifact:Ne})=>{let o=mt(r,n),i=Qe(t,o),a=pt(i.prs),l={...i,status:a};await s.writePrStatusArtifact(e,l);let d=await s.readRawTask(e,t.id),c=s.validateTaskRecord(d,`${e.tasksDir}/${t.id}.json`),u=c.status==="closed"?c.status:a,p=Qe({...c,status:u},o);return await s.writeTask(e,p),p},bt=async(e,t)=>{let r=D(t),n=r?.number?String(r.number):t.branch,s=await tr(n,t.worktreePath);return Rt(e,t,s,r)},Pt=async(e,t)=>{for(let r of await fn(t)){let n=await tt(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await Rt(e,t,n,null)}}return{discovered:!1,task:t}},fn=async e=>{let t=await jo(e.worktreePath).catch(()=>null);return[...new Set([t,e.branch].filter(r=>!!r))]};var rt=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let i=await tr(n,r.worktreePath),a=ci(i);return r.pullRequest=a,await li(e,t,r.repoId,a),"synced"}let s=await tt(n,r.worktreePath);if(!s)return"not_found";let o=ci(s);return r.pullRequest=o,await li(e,t,r.repoId,o),"discovered"},li=async(e,t,r,n)=>{let s=await J(e,t.id),o=U(s,`${e.tasksDir}/${t.id}.json`),i=(o.repoTargets??t.repoTargets??[]).map(l=>l.repoId===r?{...l,pullRequest:n}:l),a={...o,repoTargets:i};return await S(e,a),a},ci=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:gu(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:hu(e.reviewDecision??null),requiredChecks:ft(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),gu=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,hu=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var St=async(e,t)=>{let r=await v(e,t),n=D(r);return n?.number?(await et(r.worktreePath),Re(n)?(await Pt(e,r)).task:bt(e,r)):r},hn=async(e,t)=>{let r=await v(e,t);if(r.type==="project"&&r.repoTargets?.length)return await nt(e,t),v(e,t);let n=D(r);if(await B(r),await et(r.worktreePath),!n?.number||Re(n)){let o=await Pt(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return await Ne(e,o.task),o.task}let s=await bt(e,r);return await Ne(e,s),s},nt=async(e,t)=>{let r=await v(e,t),n=(r.repoTargets??[]).filter(a=>a.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let a of n){await et(a.worktreePath);let l=a.pullRequest.number?await rt(e,r,a):await rt(e,r,a).catch(()=>"not_found");s[l==="not_found"?"notFound":l]++}let o=await J(e,r.id),i=U(o,`${e.tasksDir}/${r.id}.json`);return i.status!=="closed"&&(i.status=ui(i),await S(e,i)),s},wn=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=gn(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let c of s.repoTargets.filter(u=>u.status==="ready")){let u={id:`${s.id}:${c.repoId}`,task:s,targetRepoId:c.repoId,worktreePath:c.worktreePath,selector:c.pullRequest.number?String(c.pullRequest.number):c.branch,mode:c.pullRequest.number?"number":"head",fallbackSelectors:[]};await di(n,u).catch(async()=>{try{let p=c.pullRequest.number?await rt(e,s,c):await rt(e,s,c).catch(()=>"not_found");rr(o,p,c.pullRequest.number??null,c.pullRequest.url??null)}catch{}})}continue}let i=D(s),a=i?.number&&!Re(i),l=a?[]:await fn(s),d={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 di(n,d).catch(async()=>{try{let{disposition:c,task:u}=await nr(e,s.id),p=D(u);rr(o,c,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await et(s.worktreePath);let o=await oi(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=gn(r,a.task),c=i.get(a.id)?.view??await Ru(s.worktreePath,a);if(!c){rr(l,"not_found",null,null);continue}if(a.targetRepoId){let u=await J(e,a.task.id),p=U(u,`${e.tasksDir}/${a.task.id}.json`);await wu(e,p,a.targetRepoId,c)}else{let u=await J(e,a.task.id),p=U(u,`${e.tasksDir}/${a.task.id}.json`);await Rt(e,p,c,a.mode==="number"?D(p):null)}rr(l,a.mode==="number"?"synced":"discovered",c.number,c.url)}}catch{}for(let s of t.filter(o=>o.type==="project"&&o.repoTargets?.length)){let o=await J(e,s.id),i=U(o,`${e.tasksDir}/${s.id}.json`);i.status!=="closed"&&(i.status=ui(i),await S(e,i))}return t.map(s=>gn(r,s))},nr=async(e,t)=>{let r=await v(e,t);await B(r),await et(r.worktreePath);let n=D(r);if(n?.number&&!Re(n))return{disposition:"synced",task:await bt(e,r)};let s=await Pt(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},ui=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(bu)?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"},wu=async(e,t,r,n)=>{let s=ku(n),o=(t.repoTargets??[]).map(a=>a.repoId===r?{...a,pullRequest:s}:a),i={...t,repoTargets:o};return await S(e,i),i},ku=e=>({provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:yu(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Tu(e.reviewDecision??null),requiredChecks:ft(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}),yu=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Tu=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Ru=async(e,t)=>{if(t.mode!=="head")return null;for(let r of t.fallbackSelectors){let n=await tt(r,e);if(n)return n}return null},di=async(e,t)=>{let r=await ii(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]})},gn=(e,t)=>{let r=e.get(t.id);if(r)return r;let n={taskId:t.id,synced:0,discovered:0,notFound:0,hadPr:t.type==="project"?!!t.repoTargets?.some(s=>s.pullRequest.number):!!D(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},rr=(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},bu=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 kn=async(e,t)=>{let r=await v(e,t);try{r.type==="project"&&r.repoTargets?.length?(await nt(e,t),r=await v(e,t)):r.prs.some(o=>o.number)&&(r=await St(e,t))}catch{}let n=await gt(e,r),s=r.sessionId?await be(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var yn=async(e,t)=>{let r=await v(e,t);if(await B(r),(await P("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await Pu(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},Pu=async e=>{let t=[],r=await P("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await Su(e);for(let s of n){let o=await x("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
|
|
114
114
|
|
|
115
115
|
`)},Su=async e=>(await P("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
116
|
-
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Iu}from"node:child_process";import{access as vu}from"node:fs/promises";var Tn=async(e,t)=>{let r=await v(e,t),n=Je(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await vu(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Rn=async e=>{await new Promise((t,r)=>{let n=!1,s=Iu("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 Cu}from"node:fs/promises";import Eu from"node:path";var bn=async(e,t)=>{let r=await v(e,t);if(await B(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 Qt(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 f.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 S(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await x("sh",["-lc",i],{cwd:r.worktreePath}),d=new Date().toISOString(),c=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:d,exitCode:c}),c!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=d,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await ui(e,r),await S(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 ui(e,r),await S(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},ui=async(e,t)=>{let r=Le(e,t.artifacts.checkSummaryPath);r&&(await Cu(Eu.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var Pn=async(e,t)=>{let r=await v(e,t);await B(r);let n=await Qt(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 $o(r.worktreePath),await Mo(r.worktreePath,s);let o=await Lo(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await S(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Au}from"node:fs/promises";var Sn=async(e,t)=>{let r=await v(e,t),n=await xu(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await S(e,s),s},xu=async e=>{try{return await Au(e),!0}catch{return!1}};var In=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await be(e,t.sessionId);await Yo(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 jo(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 S(e,t)};var vn=async(e,t,r)=>{let[n,s]=await Promise.all([v(e,t),ne(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 S(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Cn=async(e,t)=>{let r=await v(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>ne(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var En=async(e,t)=>{let r=await v(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([ne(e,r.repoId),be(e,r.sessionId)]),o=await Tt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var An=async(e,t)=>{let r=await v(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await be(e,r.sessionId).catch(s=>{throw Du(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 er(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Du=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as $u}from"node:child_process";var xn=async(e,t)=>{let r=await v(e,t);await B(r);let s=(await f.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await Mu(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Mu=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=$u(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 Dn=async(e,t,r)=>{let n=await ee(e,t);await S(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},$n=async(e,t,r)=>{let n=await ee(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await S(e,s),s},Mn=async(e,t)=>{let r=await ee(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await S(e,s),s};var Ln=async(e,t,r="merge",n)=>{let s=await v(e,t),o=n??D(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await ni(s.worktreePath,o,r)};var C={listTasks:sn,getTask:v,provisionTask:Ze,provisionProjectTask:kt,createTask:mn,showTask:kn,showTaskDiff:yn,prepareTaskLogs:Tn,streamTaskLogs:Rn,runChecks:bn,commitTask:Pn,closeTask:Sn,cleanupTask:In,addTaskLink:vn,listTaskLinks:Cn,sortTasksForDisplay:on,resolveSelectedTaskId:an,allocateTaskId:nn,allocateTaskIdForRepo:Xe,allocateProjectTaskId:ht,createDefaultTaskPtyTabs:yt,assertTaskWorktreeExists:B,resolveTaskLogPath:Je,buildTaskInspection:gt,resolveArtifactPath:Le,attachTask:En,focusTask:An,openTask:xn,markRunnerFailed:Dn,recordStartupFailure:$n,markTaskStarted:Mn,prs:{refresh:St,refreshChecks:hn,discoverOrRefresh:nr,discoverOrRefreshAll:nt,discoverOrRefreshMany:wn,merge:Ln,getPrimaryPr:D,isPrTerminal:Re,isMergeReady:Yt,deriveTaskStatus:pt,upsertPr:Qe,normalizePr:mt,summarizeRequiredChecks:en,writePrStatusArtifact:Ne}};async function pi(e,t){switch(e.kind){case"addWorkspace":{let r=await Q.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await On(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Q.repos.addRepo(t.paths,e.path);return await On(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Q.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await He({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Z(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Q.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return Q.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Q.archiveWorkspace(t.paths,e.workspaceId);return await Lu(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Q.restoreWorkspace(t.paths,e.workspaceId);return await On(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Q.removeWorkspace(t.paths,e.workspaceId,{listTasks:C.listTasks});case"createTask":return C.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?C.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):C.listTasks(t.paths);case"attachTask":return C.attachTask(t.paths,e.taskId);case"addTaskLink":return C.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return C.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return C.showTask(t.paths,e.taskId);case"showSelectedTask":return C.showTask(t.paths,We(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,We(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,We(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,We(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,We(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,We(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,We(t,"commit"));case"help":return{kind:"help",text:G()};case"exit":return{kind:"exit"};default:return Ou(e)}}async function On(e,t,r){let n=await He({uiStateFile:e.uiStateFile})??Ut();await Te({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Lu(e,t){let r=await He({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Te({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Ou(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function We(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 mi(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(`
|
|
116
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Iu}from"node:child_process";import{access as vu}from"node:fs/promises";var Tn=async(e,t)=>{let r=await v(e,t),n=Je(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await vu(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},Rn=async e=>{await new Promise((t,r)=>{let n=!1,s=Iu("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 Cu}from"node:fs/promises";import Eu from"node:path";var bn=async(e,t)=>{let r=await v(e,t);if(await B(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 Qt(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 f.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 S(e,r);let o=[];for(let i of s){let a=new Date().toISOString(),l=await x("sh",["-lc",i],{cwd:r.worktreePath}),d=new Date().toISOString(),c=l.exitCode??1;if(o.push({command:i,startedAt:a,finishedAt:d,exitCode:c}),c!==0)return r.checks.results=o,r.checks.status="failed",r.checks.lastRunAt=d,r.status="review",r.lastFailureReason=l.stderr.trim()||l.stdout.trim()||`Check command failed: ${i}`,await pi(e,r),await S(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 pi(e,r),await S(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},pi=async(e,t)=>{let r=Le(e,t.artifacts.checkSummaryPath);r&&(await Cu(Eu.dirname(r),{recursive:!0}),await N(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var Pn=async(e,t)=>{let r=await v(e,t);await B(r);let n=await Qt(r.worktreePath);if(r.status==="running"&&n&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!n)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let s=r.prompt.value.trim();await Mo(r.worktreePath),await Lo(r.worktreePath,s);let o=await Oo(r.worktreePath);return r.lastCommit={sha:o.sha,message:o.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await S(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:o.sha,message:o.message}};import{access as Au}from"node:fs/promises";var Sn=async(e,t)=>{let r=await v(e,t),n=await xu(r.worktreePath),s={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:n&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await S(e,s),s},xu=async e=>{try{return await Au(e),!0}catch{return!1}};var In=async(e,t,r)=>{let n=[];try{if(t.sessionId){let s=await be(e,t.sessionId);await Qo(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 Fo(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 S(e,t)};var vn=async(e,t,r)=>{let[n,s]=await Promise.all([v(e,t),ne(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 S(e,{...n,linkedRepoIds:o}),{kind:"addTaskLink",taskId:n.id,repoId:s.id,linkedRepoIds:o}},Cn=async(e,t)=>{let r=await v(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>ne(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var En=async(e,t)=>{let r=await v(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([ne(e,r.repoId),be(e,r.sessionId)]),o=await Tt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var An=async(e,t)=>{let r=await v(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await be(e,r.sessionId).catch(s=>{throw Du(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 er(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},Du=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as $u}from"node:child_process";var xn=async(e,t)=>{let r=await v(e,t);await B(r);let s=(await f.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await Mu(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Mu=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=$u(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 Dn=async(e,t,r)=>{let n=await ee(e,t);await S(e,{...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})},$n=async(e,t,r)=>{let n=await ee(e,t),s={...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r};return await S(e,s),s},Mn=async(e,t)=>{let r=await ee(e,t),n=r.ptyTabs.find(o=>o.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);let s={...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await S(e,s),s};var Ln=async(e,t,r="merge",n)=>{let s=await v(e,t),o=n??D(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await si(s.worktreePath,o,r)};var C={listTasks:sn,getTask:v,provisionTask:Ze,provisionProjectTask:kt,createTask:mn,showTask:kn,showTaskDiff:yn,prepareTaskLogs:Tn,streamTaskLogs:Rn,runChecks:bn,commitTask:Pn,closeTask:Sn,cleanupTask:In,addTaskLink:vn,listTaskLinks:Cn,sortTasksForDisplay:on,resolveSelectedTaskId:an,allocateTaskId:nn,allocateTaskIdForRepo:Xe,allocateProjectTaskId:ht,createDefaultTaskPtyTabs:yt,assertTaskWorktreeExists:B,resolveTaskLogPath:Je,buildTaskInspection:gt,resolveArtifactPath:Le,attachTask:En,focusTask:An,openTask:xn,markRunnerFailed:Dn,recordStartupFailure:$n,markTaskStarted:Mn,prs:{refresh:St,refreshChecks:hn,discoverOrRefresh:nr,discoverOrRefreshAll:nt,discoverOrRefreshMany:wn,merge:Ln,getPrimaryPr:D,isPrTerminal:Re,isMergeReady:Yt,deriveTaskStatus:pt,upsertPr:Qe,normalizePr:mt,summarizeRequiredChecks:en,writePrStatusArtifact:Ne}};async function mi(e,t){switch(e.kind){case"addWorkspace":{let r=await Q.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await On(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await Q.repos.addRepo(t.paths,e.path);return await On(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return Q.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await He({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await Z(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await Q.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Te({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return Q.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await Q.archiveWorkspace(t.paths,e.workspaceId);return await Lu(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await Q.restoreWorkspace(t.paths,e.workspaceId);return await On(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return Q.removeWorkspace(t.paths,e.workspaceId,{listTasks:C.listTasks});case"createTask":return C.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?C.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):C.listTasks(t.paths);case"attachTask":return C.attachTask(t.paths,e.taskId);case"addTaskLink":return C.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return C.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return C.showTask(t.paths,e.taskId);case"showSelectedTask":return C.showTask(t.paths,We(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,We(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,We(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,We(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,We(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,We(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,We(t,"commit"));case"help":return{kind:"help",text:G()};case"exit":return{kind:"exit"};default:return Ou(e)}}async function On(e,t,r){let n=await He({uiStateFile:e.uiStateFile})??Ut();await Te({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Lu(e,t){let r=await He({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Te({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function Ou(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function We(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 fi(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,8 +122,8 @@ 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} ${Nu(t)} ${Wu(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}`,...ju(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 Fu(e)}}function ju(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 Fu(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Nu(e){return e.checks.status}function Wu(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 dg}from"node:module";import{readFile as _u,stat as Uu}from"node:fs/promises";import jn from"node:path";var Bu=200*1024,qu=500*1024,sr="100000";async function
|
|
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
|
|
125
|
+
`);default:return Fu(e)}}function ju(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 Fu(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function Nu(e){return e.checks.status}function Wu(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 dg}from"node:module";import{readFile as _u,stat as Uu}from"node:fs/promises";import jn from"node:path";var Bu=200*1024,qu=500*1024,sr="100000";async function hi(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return Vu(e,t,r);try{let n=Se(r.selectedFilePath??null,t.filePaths),s=Se(r.selectedDiffPath??null,t.diffPaths),o=s?await It(e.worktreePath):null,[i,a]=await Promise.all([ir(e.worktreePath,n),s?Fn(e.worktreePath,s,t.diffRows,o):Promise.resolve(H("No diff selected","No local changes found.","empty"))]),l=s?{[s]:a}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:l,selectedFile:i,selectedDiff:a,error:null}}catch(n){let s=n instanceof Error?n.message:"Unable to inspect task worktree.";return{...t,error:s}}}async function Vu(e,t,r){let n=Se(r.selectedFilePath??null,t.filePaths),s=Se(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([ki(e,n),(async()=>{if(!s)return H("No diff selected","No local changes found.","empty");let l=or(e,s),d=l?await It(l.target.worktreePath).catch(()=>null):null;return yi(e,s,t.diffRows,d)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function wi(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return Ku(e,t);try{await B(e);let r=await It(e.worktreePath),[n,s]=await Promise.all([Ti(e.worktreePath),Ri(e.worktreePath,r)]),o=[...new Set(s.map(u=>u.path))],i=Se(t.selectedFilePath??null,n),a=Se(t.selectedDiffPath??null,o),[l,d]=await Promise.all([ir(e.worktreePath,i),a?Fn(e.worktreePath,a,s,r):Promise.resolve(H("No diff selected","No local changes found.","empty"))]),c=a?{[a]:d}:{};return{taskId:e.id,fileRows:Si(n),filePaths:n,diffRows:s,diffPaths:o,diffContents:c,selectedFilePath:i,selectedDiffPath:a,selectedFile:l,selectedDiff:d,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:H("Files unavailable",n,"error"),selectedDiff:H("Diff unavailable",n,"error"),error:n}}}async function Ku(e,t){let r=(e.repoTargets??[]).filter(p=>p.status==="ready"),n=await Promise.all(r.map(async p=>{let k=await It(p.worktreePath).catch(()=>null),[y,w]=await Promise.all([Ti(p.worktreePath).catch(()=>[]),Ri(p.worktreePath,k).catch(()=>[])]);return{target:p,baseRef:k,targetFiles:y,targetDiffRows:w}})),s=[],o=[];for(let{target:p,targetFiles:k,targetDiffRows:y}of n)s.push(...k.map(w=>`${p.repoId}/${w}`)),o.push(...y.map(w=>({...w,path:`${p.repoId}/${w.path}`})));let i=[...new Set(o.map(p=>p.path))].sort(),a=Se(t.selectedFilePath??null,s),l=Se(t.selectedDiffPath??null,i),[d,c]=await Promise.all([ki(e,a),(async()=>{if(!l)return H("No diff selected","No local changes found.","empty");let p=or(e,l),k=p?n.find(y=>y.target.repoId===p.target.repoId):null;return yi(e,l,o,k?.baseRef??null)})()]),u=l?{[l]:c}:{};return{taskId:e.id,fileRows:Si(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:u,selectedFilePath:a,selectedDiffPath:l,selectedFile:d,selectedDiff:c,error:null}}async function ki(e,t){let r=or(e,t);if(!r)return H("No file selected","No Git-visible files found.","empty");let n=await ir(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function yi(e,t,r,n=null){let s=or(e,t);return s?{...await Fn(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}:H(t,"Repo target is unavailable.","error",t)}function or(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 Ti(e){let t=await P("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Ii(t.stdout)}async function Ri(e,t){let[r,n,s,o]=await Promise.all([Hu(e,t),gi(e,"staged"),gi(e,"unstaged"),Gu(e)]);return[...r,...n,...s,...o]}async function Hu(e,t){if(!t)return[];let[r,n]=await Promise.all([P("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),P("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=bi(r.stdout),o=Pi(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 gi(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([P("git",[...r,"--name-status"],{cwd:e}),P("git",[...r,"--numstat"],{cwd:e})]),o=bi(n.stdout),i=Pi(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 Gu(e){let t=await P("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Ii(t.stdout);return await Promise.all(r.map(async s=>{let o=await ir(e,s),i=o.status==="ready"?zu(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function bi(e){return e.split(`
|
|
126
|
+
`).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...n]=t.split(" ");return{status:r,path:n.at(-1)??""}}).filter(t=>t.path.length>0)}function Pi(e){let t=new Map;for(let r of e.split(`
|
|
127
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 It(e){return(await x("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await x("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function ir(e,t){if(!t)return H("No file selected","No Git-visible files found.","empty");let r=Yu(e,t);try{let n=await Uu(r);if(n.size>Bu)return H(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await _u(r);return Qu(s)?H(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
128
|
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return H(t,s,"missing",t,null)}}async function Fn(e,t,r,n=null){if(!t)return H("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 It(e);if(a){let l=await P("git",["diff","--stat","--patch",`--unified=${sr}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
129
129
|
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await P("git",["diff","--cached","--stat","--patch",`--unified=${sr}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
@@ -132,36 +132,36 @@ ${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await x("git",["diff",
|
|
|
132
132
|
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
133
133
|
|
|
134
134
|
`);return i.length>qu?H(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?H(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
|
|
136
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Yu(e,t){let r=jn.resolve(e,t),n=jn.resolve(e);if(r!==n&&!r.startsWith(`${n}${jn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Qu(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function H(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Ju=["tasks","center","inspector","actions"],
|
|
137
|
-
`}function
|
|
138
|
-
`)}function
|
|
139
|
-
`)}function
|
|
140
|
-
`),center:w}}function Yn(e,t,r={}){let n=r.color??!0,s=
|
|
141
|
-
`)}function bp(e,t,r,n){let s=Ep(e.runners),o=1,i=e.leftTree.map(l=>Cp(l,t,n));return[...At(i,r-o),s]}function Pp(e,t,r,n){let s=e.tabs.find(i=>i.active)?.id??"agent",o=e.centerHeader.tabLabel==="BROWSER"||!_n(s)?e.centerTranscript.map(i=>({...i})):Sp(e);return At([...
|
|
135
|
+
`):["No diff for this file."],byteLength:i.length}}function Si(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 Se(e,t){return e&&t.includes(e)?e:t[0]??null}function zu(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Ii(e){return[...new Set(e.split(`
|
|
136
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Yu(e,t){let r=jn.resolve(e,t),n=jn.resolve(e);if(r!==n&&!r.startsWith(`${n}${jn.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Qu(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function H(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Ju=["tasks","center","inspector","actions"],vi=["agent","terminal"],Ci=[],E="inspection",OR=[...vi,...Ci],Nn=["commit","push","refresh-checks","close-task"],Ei=["refresh-checks","close-task"],Ai=["task","checks","pr","setup-run","actions","next-action"],Wn=["files","review"];function xi(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=np(e?.openInspectionKind)??r,s=f.runners.getEnabled(t);return{inputMode:op(e?.inputMode),focusedRegion:tp(e?.focusedRegion),selectedRepoId:ge(e?.selectedRepoId),selectedWorkspaceId:ge(e?.selectedWorkspaceId),selectedTaskId:ge(e?.selectedTaskId),selectedPtyTabId:ge(e?.selectedPtyTabId),selectedLeftItemId:up(ge(e?.selectedTaskId)),activeTab:r?E:ge(e?.activeTab)??"agent",preferredPtyTabKind:sp(e?.preferredPtyTabKind),inspectorSection:vt(e?.inspectorSection,Ai,"task"),inspectionMode:rp(e?.inspectionMode,r==="diff"?"review":"files"),openInspectionKind:n,selectedFileTreePath:ge(e?.selectedFileTreePath),selectedFilePath:ge(e?.selectedFilePath),selectedDiffPath:ge(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:vt(e?.selectedActionId,Nn,"commit"),selectedProjectTargetId:null,selectedRunner:ip(e?.selectedRunner,s,f.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:Xu(),centerZoomed:!1}}function Xu(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Di(e,t){return{...e??Ut(),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 Ct(e,t,r={}){let n=dp(e,t),s=Un(n),o=(s?.kind==="workspace"?t.workspaces?.find(c=>c.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(c=>c.id===t.tasks.find(u=>u.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(c=>c.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(c=>c.id===s.id)??null:s?.kind==="task"?t.repos.find(c=>c.id===t.tasks.find(u=>u.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(c=>c.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(c.id))??null:null)??(o?.kind!=="project"?t.repos.find(c=>c.id===o?.primaryRepoId)??null:null)??t.repos.find(c=>c.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(c=>c.workspaceId===o.id):a?t.tasks.filter(c=>c.repoId===a):[],d=(s?.kind==="task"?l.find(c=>c.id===s.id)??null:null)??l.find(c=>c.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:d?.id??null,...ap(d,e.activeTab,e.selectedPtyTabId),selectedFilePath:ep(e,t,d?.id??null),...lp(e,t,d?.id??null),selectedDiffPath:Zu(e,t,d?.id??null),inspectorSection:vt(e.inspectorSection,Ai,"task")}}function he(e,t){return{...e,terminal:t}}function $i(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Mi(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 Li(e){return e.length===1&&e>=" "&&e!=="\x7F"}function _n(e){return ji(e)||st(e)!==null}function Oi(e){return Ci.includes(e)}function ji(e){return vi.includes(e)}function Fi(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[E]:[]]}function Zu(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function ep(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function vt(e,t,r){return t.includes(e??"")?e:r}function tp(e){return e==="tabs"?"center":vt(e,Ju,"tasks")}function rp(e,t){return e==="checks"||e==="actions"||e==="diff"||e==="review"?"review":vt(e,Wn,t)}function np(e){return e==="file"||e==="diff"?e:null}function sp(e){return e==="terminal"?"terminal":"agent"}function op(e){return e==="terminal"?"terminal":"control"}function ip(e,t=[...$],r="codex"){return e&&f.runners.isRunnerType(e)&&t.includes(e)?e:r}function ar(e,t=$){let r=t.length>0?t:$,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function st(e){let t=$.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function ap(e,t,r){if(!e)return{activeTab:t===E?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(ji(t)){let l=e.ptyTabs.find(d=>d.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??E,selectedPtyTabId:l?.id??null}}if(t===E)return{activeTab:E,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??E,selectedPtyTabId:i?.id??null}}function lp(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?cp(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function cp(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 dp(e,t){let r=_e(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 _e(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 Un(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 ge(e){return typeof e=="string"?e:null}function up(e){return e?`task:${e}`:null}function Et(e){return typeof e=="string"&&e.startsWith("task:")}function lr(e){return typeof e=="string"&&e.startsWith("new-task:")}function cr(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Ni(e){return typeof e=="string"&&e.startsWith("workspace:")}function Bn(e){return lr(e)?e.slice(9):null}function qn(e){return cr(e)?e.slice(19):null}async function Ie(e,t,r){let n=de(e),[s,o]=await Promise.all([Q.repos.listRegisteredRepos(n),Q.listWorkspaces(n,{archived:!1})]),i=await C.listTasks(n),a=Vn(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},d=a?await wi(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:d,...r?{enabledRunnerIds:r}:{}}}function Vn(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function Wi(e,t){return Ct(e,t)}import es from"node:path";import VR from"picocolors";var pp=[" \u2584\u2588\u2588\u2588\u2588\u2584 \u2588\u2588\u2580\u2588\u2588\u2588 \u2584\u2584\u2584 \u2588\u2588\u2593 \u2584\u2588\u2588\u2588\u2588"," \u2592\u2588\u2588\u2580 \u2580\u2588 \u2593\u2588\u2588 \u2592 \u2588\u2588\u2592\u2592\u2588\u2588\u2588\u2588\u2584 \u2593\u2588\u2588\u2592 \u2588\u2588\u2592 \u2580\u2588\u2592"," \u2592\u2593\u2588 \u2584 \u2593\u2588\u2588 \u2591\u2584\u2588 \u2592\u2592\u2588\u2588 \u2580\u2588\u2584 \u2592\u2588\u2588\u2592\u2592\u2588\u2588\u2591\u2584\u2584\u2584\u2591"," \u2592\u2593\u2593\u2584 \u2584\u2588\u2588\u2592\u2592\u2588\u2588\u2580\u2580\u2588\u2584 \u2591\u2588\u2588\u2584\u2584\u2584\u2584\u2588\u2588 \u2591\u2588\u2588\u2591\u2591\u2593\u2588 \u2588\u2588\u2593"," \u2592 \u2593\u2588\u2588\u2588\u2580 \u2591\u2591\u2588\u2588\u2593 \u2592\u2588\u2588\u2592 \u2593\u2588 \u2593\u2588\u2588\u2592\u2591\u2588\u2588\u2591\u2591\u2592\u2593\u2588\u2588\u2588\u2580\u2592"," \u2591 \u2591\u2592 \u2592 \u2591\u2591 \u2592\u2593 \u2591\u2592\u2593\u2591 \u2592\u2592 \u2593\u2592\u2588\u2591\u2591\u2593 \u2591\u2592 \u2592"," \u2591 \u2592 \u2591\u2592 \u2591 \u2592\u2591 \u2592 \u2592\u2592 \u2591 \u2592 \u2591 \u2591 \u2591"," \u2591 \u2591\u2591 \u2591 \u2591 \u2592 \u2592 \u2591\u2591 \u2591 \u2591"," \u2591 \u2591 \u2591 \u2591 \u2591 \u2591 \u2591"," \u2591"];function Kn(){return[...pp]}var dr={width:120,height:36},W={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function se(e,t){return{width:Math.max(e??dr.width,dr.width),height:Math.max(t??dr.height,dr.height)}}var mp=["Start","Options","Exit"],fp=["Resume","Options","Exit"],pr=2,mr=2,fr=2,gp=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),hp=new RegExp("\x1B\\[(?:0)?m","g"),wp=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),kp=/https?:\/\/[^\s<>"']+/g,Gn="\x1B[0m",zn="\x1B]8;;\x1B\\",R={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"}},Hn=["3d59a1","506eb8","6386d0","7aa2f7","6386d0","506eb8"];function Bi(e,t={}){return Qn(e,{subtitle:"crAIg is that you?",menuItems:mp,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function qi(e,t={}){return Qn(e,{subtitle:"Control mode is paused.",menuItems:fp,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var ur=[" 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."],yp=["Help"],Tp=5;function wr(e,t={}){return Qn(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??yp,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function Vi(e,t={}){let r=t.color??!0,n=R.overlay,s=new Array(e.height).fill(L(" ".repeat(e.width),r,n)),o=Kn(),i=Math.max(1,Math.floor((e.height-o.length-2-ur.length)/2));for(let c=0;c<o.length&&!(i+c>=e.height);c+=1)s[i+c]=L(Zi(o[c]??"",e.width),r,R.overlayLogo);let a=Math.max(...ur.map(c=>c.length)),l=Math.max(0,Math.floor((e.width-a)/2)),d=i+o.length+2;for(let c=0;c<ur.length;c+=1){let u=d+c;if(u>=e.height)break;let p=ur[c]??"";s[u]=L(pe(" ".repeat(l)+p,e.width),r,n)}return s.join(`
|
|
138
|
+
`)}function Ki(e,t={}){let r=t.color??!0,n=R.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),d=Math.max(0,Math.floor((e.width-l)/2)),c=[{text:o,tone:"selected"},{text:i,tone:"muted"},ae(),...a.length>0?a.map(k=>({text:k})):[{text:"No Craig errors have been logged.",tone:"muted"}],ae(),{text:"Esc returns to Options.",tone:"muted"}],u=At(c,e.height-2),p=Math.max(1,Math.floor((e.height-u.length)/2));for(let k=0;k<u.length;k+=1){let y=p+k;if(y>=e.height)break;let w=u[k]??ae(),b=`${" ".repeat(d)}${kr(w.text,l)}`,q=w.tone==="selected"?R.overlayMenuSelected:w.tone==="muted"?R.overlay:R.panelBg;s[y]=L(pe(b,e.width),r,q)}return s.join(`
|
|
139
|
+
`)}function Hi(e,t,r={}){let n=r.color??!0,s=W.leftWidth,o=W.rightWidth,i=r.centerOnly??!1,a=e.height-W.topRailHeight-1,l=r.focusFlashActive??!1,d={bg:R.divider.bg,fg:"9ece6a"},c=l&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?d:R.divider,u=l&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?d:R.divider,p=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,k=L(pe(p,e.width),n,R.rail),y=bp(t,s-pr-mr,a,n),w=Yn(e,t,{color:n,centerOnly:i}),b=Ip(t,o,a,n),q=t.inputMode==="terminal",te=[];for(let re=0;re<a;re+=1){if(i){te.push(w.rows[re]??"");continue}let Ve=gr(y[re]??ae(),s,n,"left"),m=L("\u2502",n,c),Ae=w.rows[re]??"",Ot=L("\u2502",n,u),jt=gr(b[re]??ae(),o,n,"right");te.push(`${Ve}${m}${Ae}${Ot}${jt}`)}let me=q||t.modalInput?R.panelBg:R.panelMuted,I=Rp(t.footerText,t.footerToast,e.width,n,me);return{frame:[k,...te,I].join(`
|
|
140
|
+
`),center:w}}function Yn(e,t,r={}){let n=r.color??!0,s=zi(e,r.centerOnly??!1),o=Pp(t,s.width,s.rowCount,n);return{row:s.row,column:s.column,width:s.width,rows:o.map(i=>gr(i,s.width,n,"center"))}}function Gi(e,t,r,n={}){let s=t.tabs.find(d=>d.active)?.id??"";if(!_n(s)||t.centerHeader.tabLabel==="BROWSER"||t.terminal.error||t.terminal.rows.length===0||r.some(d=>d<0||d>=t.terminal.rows.length))return null;let o=n.color??!0,i=zi(e,n.centerOnly??!1),a=Yi(t,i.width,o).length,l=[...new Set(r)].map(d=>({terminalIndex:d,index:a+d})).filter(({index:d})=>d<i.rowCount).map(({terminalIndex:d,index:c})=>({index:c,row:gr(Qi(t.terminal.rows[d]),i.width,o,"center")}));return{...i,rows:l}}function zi(e,t){return{row:W.topRailHeight+1,column:t?1:W.leftWidth+W.dividerWidth+1,width:t?e.width:e.width-W.leftWidth-W.rightWidth-W.dividerWidth*2,rowCount:e.height-W.topRailHeight-1}}function Rp(e,t,r,n,s){let o=` ${e}`;if(!t)return L(pe(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=X(i),l=X(o),d=Math.max(1,r-l-a-2),c=l+d+a+2>r?kr(o,Math.max(0,r-a-3)):o,u=Math.max(1,r-X(c)-a-2),p=t.tone==="error"?Vp(i,n,s):ot(i,n,s),k=`${c}${" ".repeat(u)}${p} `;return L(pe(k,r),n,s)}function Qn(e,t){let r=new Array(e.height).fill(L(" ".repeat(e.width),t.color,R.overlay)),n=Kn(),s=t.menuItems.map((d,c)=>`${c===t.menuIndex?">":" "} ${d}`),o=t.optionsMessage?["",t.optionsMessage]:[],i=[...s,...o];for(;i.length<Tp;)i.push("");let a=[...n,"",t.subtitle,"",...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let d=0;d<a.length;d+=1){let c=Zi(a[d]??"",e.width);if(d<n.length){r[l+d]=L(c,t.color,R.overlayLogo);continue}if(d===n.length+1){r[l+d]=L(c,t.color,R.overlaySubtitle);continue}let u=d-(n.length+3),k=u>=0&&u<t.menuItems.length&&u===t.menuIndex?R.overlayMenuSelected:R.overlay;r[l+d]=L(c,t.color,k)}if(t.versionText){let d=t.updateText?" (update available)":"",c=`${t.versionText}${d} `,u=" ".repeat(Math.max(0,e.width-X(c)));r[e.height-1]=L(`${u}${Zn(c,t.color,R.overlay)}`,t.color,R.overlay)}return r.join(`
|
|
141
|
+
`)}function bp(e,t,r,n){let s=Ep(e.runners),o=1,i=e.leftTree.map(l=>Cp(l,t,n));return[...At(i,r-o),s]}function Pp(e,t,r,n){let s=e.tabs.find(i=>i.active)?.id??"agent",o=e.centerHeader.tabLabel==="BROWSER"||!_n(s)?e.centerTranscript.map(i=>({...i})):Sp(e);return At([...Yi(e,t,n),...o],r)}function Yi(e,t,r){let n=t-2,s=e.tabs.find(b=>b.active)?.label??"AGENT",o=e.inputMode==="terminal"?0:Up(e.tabs),i=e.inputMode==="terminal"?n:s.length+1,a="\u2500".repeat(Math.max(0,i)),l=`${" ".repeat(o)}${e.inputMode==="terminal"?ot(a,r,R.panelBg):hr(a,r,R.panelMuted)}`,d=[`${hr(e.centerHeader.tabLabel,r,R.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),c=Ap(e.tabs,r,e.focusedRegion==="center"),u=" engaged ",p=u.length+2,k=e.inputMode==="terminal"?ot(`${u}\u25CF `,r,R.panelBg):"",y=e.inputMode==="terminal"?" ".repeat(Math.max(0,n-X(c)-p)):"";return[{text:e.inputMode==="terminal"?`${c}${y}${k}`:c},{text:l,tone:"muted"},{text:d},ae()]}function Sp(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},ae(),{text:e.terminal.error},ae(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(n=>n.active)?.id??"",r=t==="agent"||/:agent(?:-\d+)?$/.test(t)?"agent":"terminal";return e.terminal.rows.length===0?[{text:`Press Enter on the ${r.toUpperCase()} tab to attach a PTY.`}]:e.terminal.rows.map(Qi)}function Qi(e){return{text:Xn(e.segments),segments:e.segments,fullBleed:!0}}function Ip(e,t,r,n){let s=e.rightInspection?vp(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):At([{text:"CONTEXT"},ae(),...e.rightContext.map(o=>xp(o,n)),...e.actionMessage?[ae(),{text:e.actionMessage}]:[]],r);return At(s,r)}function vp(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:qp(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>_i(a)),...n.slice(i,i+s).map(a=>_i(a))]}function _i(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 Cp(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${ot("\u25CF",r,e.selected?R.panelSelected:R.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((y,w)=>y+X(w.text),0):0,l=t-X(o)-X(s)-a,d=e.activity?`${e.selected?"\u25B8":" "} \u25CF `:"",c=e.selected?e.text:e.focused?ot(e.text,r,R.panelBg):e.panelHeader?hr(e.text,r,R.panelMuted):e.text,u=pe(`${n}${d}${c}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.activity){let y=`${n}${e.selected?"\u25B8":" "} `,w=u.slice(y.length+2),b=[{text:y},Ji(e.activity,e.activityAnimationFrame??0),{text:` ${w}${o}${i}`},...e.prBadge??[]];return{text:Xn(b),segments:b,tone:p}}if(e.prBadge){let y=[{text:`${u}${o}${i}`},...e.prBadge];return{text:`${u}${o}${e.prBadge.map(b=>b.text).join("")}`,segments:y,tone:p}}return{text:`${u}${o}${i}`,tone:p}}function Ep(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:R.success.fg}}):r.push({text:s.text,style:{fg:R.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function Ap(e,t,r){return e.map(n=>{let s=n.active?r?ot(n.label,t,R.panelBg):hr(n.label,t,R.panelBg):Zn(n.label,t,R.panelBg),o=n.activity?Jn(Ji(n.activity,n.activityAnimationFrame??0),t,R.panelBg):"";return`${s}${o?` ${o}`:""}`}).join(" ")}function Ji(e,t){return{text:"\u25CF",style:{fg:e==="working"?Hn[t%Hn.length]??Hn[0]:e==="ready"?R.success.fg:e==="error"?R.error.fg:R.panelMuted.fg}}}function xp(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Zn(e.value,t,R.panelBg):e.value}`}}function gr(e,t,r,n){let s=Dp(n,e.tone??"default"),o=$p(e,r,s);if(n==="left"){if(e.fullBleed)return L(pe(o,t),r,s);let a=t-pr-mr;if(e.rightAlign){let d=X(o),c=Math.max(0,a-d),u=`${" ".repeat(pr)}${" ".repeat(c)}${o}${" ".repeat(mr)}`;return L(u,r,s)}let l=`${" ".repeat(pr)}${pe(o,a)}${" ".repeat(mr)}`;return L(l,r,s)}return n==="center"&&e.fullBleed?Mp(e,t,r,s):L(pe(` ${o}`,t),r,s)}function Dp(e,t){return t==="selected"||t==="focused"?R.panelSelected:t==="muted"?R.panelMuted:R.panelBg}function At(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(ae());return r}function ae(){return{text:""}}function $p(e,t,r){return e.segments?e.segments.map(n=>Jn(n,t,r)).join(""):e.text}function Mp(e,t,r,n){let s=" ".repeat(fr),o=Math.max(0,t-fr*2);if(!e.segments)return L(`${s}${pe(e.text,o)}${s}`,r,n);let i=jp(e.segments,o),a=`${s}${i.map(l=>Jn(l,r,n)).join("")}${s}${r?zn:""}`;return L(a,r,n)}function Jn(e,t,r){let n=e.href?`${Xi(e.href)}${e.text}${zn}`:Lp(e.text);return!t||!e.style?n:`${xt(Wp(e.style,r))}${_p(e.style)}${n}${Gn}${xt(r)}`}function Lp(e){return e.replace(kp,t=>{let[r,n]=Op(t);return`${Xi(r)}${r}${zn}${n}`})}function Op(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function Xi(e){return`\x1B]8;;${e}\x1B\\`}function jp(e,t){let r=Fp(e,t);return Np(r,t)}function Fp(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=X(s.text);if(o<=n){r.push(s),n-=o;continue}let i=kr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function Np(e,t){let r=X(Xn(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 Wp(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 _p(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 Up(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+(r.activity?2:0)+3}return 0}function Zi(e,t){let r=Math.max(0,t-X(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function pe(e,t){let r=X(e);return r>=t?Bp(e,t):e+" ".repeat(t-r)}function Bp(e,t){if(t<=0)return"";if(X(e)<=t)return e;let r=ta(e);return kr(r,Math.max(0,t-1))+"\u2026"}function X(e){let t=0;for(let r of Array.from(ta(e)))t+=ea(r);return t}function kr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=ea(s);if(n+o>t)break;r+=s,n+=o}return r}function ea(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 qp(e,t,r){return Math.min(Math.max(e,t),r)}function ta(e){return e.replace(wp,"").replace(gp,"")}function Xn(e){return e.map(t=>t.text).join("")}function L(e,t,r){if(!t)return e;let n=xt(r),s=e.replace(hp,`${Gn}${n}`);return`${n}${s}${Gn}`}function xt(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 ot(e,t,r){return yr(e,t,R.success.fg,r)}function Vp(e,t,r){return yr(e,t,R.error.fg,r)}function hr(e,t,r){return yr(e,t,R.accent.fg,r)}function Zn(e,t,r){return yr(e,t,R.mutedfg.fg,r)}function yr(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${xt(s)}${e}${xt(n)}`}function ra(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"?Hp(s):[];return n?.type==="project"?{cwd:o,command:i,env:{GIT_CEILING_DIRECTORIES:Kp(process.env.GIT_CEILING_DIRECTORIES,o)}}:{cwd:o,command:i}}function Kp(e,t){let r=(e??"").split(es.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(es.delimiter):[...r,t].join(es.delimiter)}function Hp(e){return e.command.length>0?e.command:["codex"]}function na(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 ve(e){return{columns:Math.max(20,e.width-W.leftWidth-W.rightWidth-W.dividerWidth-fr*2),rows:Math.max(5,e.height-W.topRailHeight-5)}}function sa(e){return e.length===1||ie(e)||e==="BACKSPACE"||e==="TAB"}function Ce(e){return typeof e=="string"&&new RegExp(`:(?:agent|${$.join("|")})(?:-\\d+)?$`).test(e)}function oa(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 ts(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function ia(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 Dt(e){return la.includes(e)?"SHIFT_ENTER":null}function rs(e){return la.some(t=>t.startsWith(e))}function aa(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var la=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function ca(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
142
142
|
`||r===`\r
|
|
143
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function
|
|
143
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function da(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function ua(e,t=null){let r=t?.split(`
|
|
144
144
|
`)??[];return e.split(`
|
|
145
|
-
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function
|
|
146
|
-
`,TAB:" ",SHIFT_TAB:"\x1B[Z",BACK_TAB:"\x1B[Z",BACKSPACE:"\x7F",DELETE:"\x1B[3~",ESCAPE:"\x1B",UP:"\x1B[A",DOWN:"\x1B[B",RIGHT:"\x1B[C",LEFT:"\x1B[D",HOME:"\x1B[H",END:"\x1B[F",PAGE_UP:"\x1B[5~",PAGE_DOWN:"\x1B[6~",CTRL_C:"",CTRL_D:""},Tr=class{sessions=new Map;activitySnapshots=new Map;shell;env;spawn;onUpdate;onActivity;onActivityRemoved;activityEnabled;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.onActivity=t.onActivity,this.onActivityRemoved=t.onActivityRemoved,this.activityEnabled=t.activityEnabled??!0,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")os(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,
|
|
147
|
-
`))&&this.touchActivity(r))}writeKey(t){let r=cm(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&&
|
|
148
|
-
[process exited ${k.exitCode}]`).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}touchActivity(t){t.lastActivityAt=Date.now(),this.activityEnabled&&this.notifyActivity(t)}notifyActivity(t){this.activityEnabled&&this.recordActivity(this.buildActivitySnapshot(t))}recordActivity(t){this.activityEnabled&&(this.activitySnapshots.set(t.tabId,t),this.onActivity?.(t))}removeActivity(t){this.activitySnapshots.delete(t)&&this.onActivityRemoved?.(t)}buildActivitySnapshot(t){return{taskId:t.taskId,tabId:t.tabId,sessionState:t.status==="failed"?"failed":t.status==="exited"?"exited":"running",lastActivityAt:t.lastActivityAt,exitCode:t.exitCode,error:t.error}}};function cm(e){if(e.length===1)return e;let t=lm[e];if(t!==void 0)return t;let r=sm.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function
|
|
145
|
+
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function pa(e,t,r,n){return e.map((s,o)=>t?.[o]===s?"":`\x1B[${r+o};${n}H${s}`).join("")}import{spawn as hm}from"node:child_process";import{createHash as wm}from"node:crypto";import{createServer as km,createConnection as Ra}from"node:net";import{openSync as ym}from"node:fs";import{mkdir as Tm,readFile as cs,rm as Be,writeFile as Rm}from"node:fs/promises";import{tmpdir as bm}from"node:os";import it from"node:path";import{createRequire as rm}from"node:module";import Gp from"@xterm/headless";var zp=1e3,Yp=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function fa(e){return new Gp.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:zp,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function ga(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function ss(e,t){return new Promise(r=>{e.write(t,r)})}function ha(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 d=[];for(let c=0;c<e.cols;c+=1){let u=l.getCell(c,s);!u||u.getWidth()===0||d.push({text:u.getChars()||" ",style:Xp(u,i+a===o&&c===r.cursorX)})}n.push({segments:Qp(Jp(d))})}return n}function Qp(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&tm(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};wa(r.style)||(s.style=r.style),t.push(s)}return t}function Jp(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!wa(r.style))break;t-=1}return e.slice(0,t)}function Xp(e,t){let r={},n=ma(e,"fg"),s=ma(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 ma(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let n=t==="fg"?e.isFgRGB():e.isBgRGB(),s=t==="fg"?e.getFgColor():e.getBgColor();return n?s.toString(16).padStart(6,"0"):Yp[s]??Zp(s)}function Zp(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(em).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 em(e){return e===0?0:55+e*40}function tm(e,t){return ns(e)===ns(t)}function ns(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function wa(e){return ns(e)===""}var nm=rm(import.meta.url),sm=/^CTRL_([A-Z])$/,om="\x1B[6n",im="\x1B[c",am="\x1B[?u",lm={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:""},Tr=class{sessions=new Map;activitySnapshots=new Map;shell;env;spawn;onUpdate;onActivity;onActivityRemoved;activityEnabled;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.onActivity=t.onActivity,this.onActivityRemoved=t.onActivityRemoved,this.activityEnabled=t.activityEnabled??!0,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")os(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,ka(o,n),this.getViewState(r);let i;try{i=this.createSession(t,r,n,s)}catch(a){throw this.recordActivity({taskId:t,tabId:r,sessionState:"failed",lastActivityAt:Date.now(),exitCode:null,error:a instanceof Error?a.message:String(a)}),a}return this.sessions.set(r,i),this.notifyActivity(i),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||(r.pty.write(t),(t.includes("\r")||t.includes(`
|
|
147
|
+
`))&&this.touchActivity(r))}writeKey(t){let r=cm(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&&ka(r,t)}detach(){this.attachedTabId=null}sessionTabIds(){return[...this.sessions.keys()]}getActivitySnapshots(){return[...this.activitySnapshots.values()]}setActivityEnabled(t){if(this.activityEnabled!==t&&(this.activityEnabled=t,!!t))for(let r of this.sessions.values())this.notifyActivity(r)}disposeSession(t){let r=this.sessions.get(t);r&&(os(r),this.sessions.delete(t)),this.removeActivity(t),this.attachedTabId===t&&(this.attachedTabId=null)}disposeAll(){for(let t of this.sessions.values())os(t);this.sessions.clear();for(let t of this.activitySnapshots.keys())this.onActivityRemoved?.(t);this.activitySnapshots.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:dm(r),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??pm().spawn,i=fa(n),a=s??this.resolveSessionSpec(t,r),l=je({...this.env,...a.env??{}}),{executable:d,args:c}=mm(this.shell,a.command,{cwd:a.cwd,env:l}),u=o(d,c,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:fm(l)}),p={taskId:t,tabId:r,pty:u,terminal:i,status:"running",error:null,disposables:[],scrollbackLines:0,rows:[],renderedScrollbackLines:null,screenDirty:!0,lastActivityAt:Date.now(),exitCode:null};return p.disposables.push(u.onData(k=>{this.touchActivity(p),gm(u,k),ss(p.terminal,k).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p.disposables.push(u.onExit(k=>{p.status="exited",p.exitCode=k.exitCode,p.lastActivityAt=Date.now(),this.notifyActivity(p),ss(p.terminal,`\r
|
|
148
|
+
[process exited ${k.exitCode}]`).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}touchActivity(t){t.lastActivityAt=Date.now(),this.activityEnabled&&this.notifyActivity(t)}notifyActivity(t){this.activityEnabled&&this.recordActivity(this.buildActivitySnapshot(t))}recordActivity(t){this.activityEnabled&&(this.activitySnapshots.set(t.tabId,t),this.onActivity?.(t))}removeActivity(t){this.activitySnapshots.delete(t)&&this.onActivityRemoved?.(t)}buildActivitySnapshot(t){return{taskId:t.taskId,tabId:t.tabId,sessionState:t.status==="failed"?"failed":t.status==="exited"?"exited":"running",lastActivityAt:t.lastActivityAt,exitCode:t.exitCode,error:t.error}}};function cm(e){if(e.length===1)return e;let t=lm[e];if(t!==void 0)return t;let r=sm.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function ka(e,t){um(e.pty,t),ga(e.terminal,t),e.screenDirty=!0}function dm(e){return(e.screenDirty||e.renderedScrollbackLines!==e.scrollbackLines)&&(e.rows=ha(e.terminal,e.scrollbackLines),e.renderedScrollbackLines=e.scrollbackLines,e.screenDirty=!1),e.rows}function os(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function um(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function pm(){return nm("node-pty")}function mm(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Fe(t[0],r),...t.slice(1)].map(ya).join(" ")}; exec ${ya(e)} -l`;return{executable:e,args:["-lc",s]}}function ya(e){return`'${e.replaceAll("'","'\\''")}'`}function fm(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 gm(e,t){for(let r=0;r<is(t,om);r+=1)e.write("\x1B[1;1R");for(let r=0;r<is(t,im);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<is(t,am);r+=1)e.write("\x1B[?0u")}function is(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 ba=6,Pm=new Set([ba]),Sm=16,Im=250;async function Pa(e){let t=ds(e.paths);await Am(t,e.paths,e.spawnDaemon);let r=await xa(t.socketPath),n=new as(r,e);return await n.ready(),n}async function Sa(e,t={}){let r=ds(e);await Tm(e.runtimeDir,{recursive:!0}),await Be(r.socketPath,{force:!0});let n=new ls(e,t),s=km(o=>n.handleConnection(o));await Om(s,r.socketPath),await Rm(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 Be(r.socketPath,{force:!0}),await Be(r.pidPath,{force:!0}),n.disposeAll()}async function Ia(e){let t=ds(e);return await br(t.socketPath)?(await Ea(t.socketPath),!0):!1}var as=class{constructor(t,r){this.socket=t;this.options=r,this.viewUpdateMode=r.viewUpdateMode??"snapshot",this.activityEnabled=r.activityEnabled??!1,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||(this.closed=!0,this.rejectAll(new Error("Craig PTY daemon connection closed.")),this.failRunningActivities("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;activityCache=new Map;activityRevisionByTabId=new Map;activityRevision=0;attachedTabId=null;viewedTabId=null;subscribedTabId=null;viewUpdateMode;activityEnabled;buffer="";closed=!1;options;async ready(){let t=await this.send({type:"ping"});if(!Ca(t.protocolVersion))throw new Error("Craig PTY daemon protocol mismatch.");await this.send({type:"setViewUpdateMode",mode:this.viewUpdateMode}),await this.send({type:"setActivityEnabled",enabled:this.activityEnabled}),this.activityEnabled&&await this.refreshActivitySnapshots()}async ensureSession(t,r,n){let s=await this.send({type:"ensureSession",taskId:t,tabId:r,size:n,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r,this.viewedTabId=r;let o=s.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,o),o}async hydrateSessions(t){for(let r of t)try{let n=await this.send({type:"hydrateSession",tabId:r});n.view&&this.viewCache.set(r,n.view)}catch(n){let s=n instanceof Error?n.message:String(n);this.viewCache.set(r,{status:"failed",rows:[],error:s})}this.activityEnabled&&await this.refreshActivitySnapshots()}async pruneStale(t){await this.send({type:"pruneStale",keepTabIds:t})}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){let r=this.attachedTabId;this.send({type:"scrollViewport",lines:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}resize(t){let r=this.attachedTabId;this.send({type:"resize",size:t}).then(n=>{r&&n.view&&(this.viewCache.set(r,n.view),this.notifyFullUpdate(r))}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}setViewedTab(t){this.closed||(this.viewedTabId=t,this.viewUpdateMode==="incremental"&&this.subscribeToView(t))}setViewUpdateMode(t){if(this.closed||this.viewUpdateMode===t)return;this.viewUpdateMode=t,this.subscribedTabId=null;let r=this.viewedTabId;this.send({type:"setViewUpdateMode",mode:t}).then(n=>{r&&n.view&&this.viewCache.set(r,n.view),this.viewUpdateMode===t&&this.viewedTabId===r&&this.notifyFullUpdate(r),t==="incremental"&&this.viewUpdateMode===t&&(this.viewedTabId===r&&this.subscribedTabId===null?this.subscribedTabId=r:this.viewedTabId!==r&&this.subscribeToView(this.viewedTabId))}).catch(()=>{this.viewUpdateMode===t&&(this.subscribedTabId=null)})}setActivityEnabled(t){if(!(this.closed||this.activityEnabled===t)){if(this.activityEnabled=t,!t){for(let r of[...this.activityCache.keys()])this.removeCachedActivity(r);this.send({type:"setActivityEnabled",enabled:t}).catch(()=>{});return}this.send({type:"setActivityEnabled",enabled:t}).then(()=>this.refreshActivitySnapshots(!0)).catch(()=>{})}}disposeSession(t){this.viewCache.delete(t),this.removeCachedActivity(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}}getActivitySnapshots(){return[...this.activityCache.values()]}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)}
|
|
149
149
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
150
150
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
151
151
|
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}if(r.type==="update"){if("view"in r){this.viewCache.set(r.tabId,r.view),this.notifyFullUpdate(r.tabId);return}let n=this.viewCache.get(r.tabId)??{status:"idle",rows:[],error:null,scrolledBack:!1},s=Em(n,r.patch),o=n.rows.slice(0,r.patch.rowCount);for(let i of r.patch.rows)o[i.index]=i.row;this.viewCache.set(r.tabId,{status:r.patch.status,rows:o,error:r.patch.error,scrolledBack:r.patch.scrolledBack}),this.viewUpdateMode==="incremental"&&this.viewedTabId===r.tabId&&this.options.onUpdate?.(s?{tabId:r.tabId,kind:"full"}:{tabId:r.tabId,kind:"rows",rowIndices:r.patch.rows.map(i=>i.index)})}r.type==="activity"&&(this.recordCachedActivity(r.snapshot),this.options.onActivity?.(r.snapshot)),r.type==="activityRemoved"&&this.removeCachedActivity(r.tabId)}subscribeToView(t){this.closed||this.viewUpdateMode!=="incremental"||this.subscribedTabId===t||(this.subscribedTabId=t,this.send({type:"subscribeView",tabId:t}).then(r=>{t&&r.view&&this.viewCache.set(t,r.view),this.viewUpdateMode==="incremental"&&this.viewedTabId===t&&this.subscribedTabId===t&&this.notifyFullUpdate(t)}).catch(()=>{this.subscribedTabId===t&&(this.subscribedTabId=null)}))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}notifyFullUpdate(t){t&&this.options.onUpdate?.({tabId:t,kind:"full"})}replaceActivityCache(t,r){let n=new Map;for(let[s,o]of this.activityRevisionByTabId)o>r&&n.set(s,this.activityCache.get(s)??null);this.activityCache.clear();for(let s of t)this.activityCache.set(s.tabId,s);for(let[s,o]of n)o?this.activityCache.set(s,o):this.activityCache.delete(s)}async refreshActivitySnapshots(t=!1){let r=this.activityRevision,n=await this.send({type:"getActivitySnapshots"});if(this.replaceActivityCache(n.activities??[],r),t)for(let s of this.activityCache.values())this.options.onActivity?.(s)}recordCachedActivity(t){this.activityRevision+=1,this.activityRevisionByTabId.set(t.tabId,this.activityRevision),this.activityCache.set(t.tabId,t)}removeCachedActivity(t){this.activityRevision+=1,this.activityRevisionByTabId.set(t,this.activityRevision),this.activityCache.delete(t),this.options.onActivityRemoved?.(t)}failRunningActivities(t){for(let r of this.activityCache.values()){if(r.sessionState!=="running")continue;let n={...r,sessionState:"failed",lastActivityAt:Date.now(),error:t};this.recordCachedActivity(n),this.options.onActivity?.(n)}}},ls=class{onShutdown=null;clients=new Set;subscriptions=new Map;updateTimers=new Map;activityTimers=new Map;pendingActivities=new Map;runtime;attachedTabId=null;constructor(t,r){this.runtime=new Tr({...r,workspaceRoot:t.workspaceRoot,activityEnabled:!1,onUpdate:n=>this.handleRuntimeUpdate(n.tabId),onActivity:n=>this.handleActivityUpdate(n),onActivityRemoved:n=>this.handleActivityRemoved(n)})}handleConnection(t){let r="";this.clients.add(t),this.subscriptions.set(t,{mode:"snapshot",activityEnabled:!1,tabId:null,view:null,rowKeys:[]}),t.setEncoding("utf8"),t.on("data",s=>{r+=String(s);let o=r.indexOf(`
|
|
152
152
|
`);for(;o!==-1;){let i=r.slice(0,o);r=r.slice(o+1),this.handleLine(t,i),o=r.indexOf(`
|
|
153
|
-
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t),this.hasActivitySubscribers()||(this.runtime.setActivityEnabled(!1),this.clearPendingActivityBroadcasts())};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear();for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear(),this.runtime.setActivityEnabled(!1)}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{Ue(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(t,n);Ue(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:
|
|
154
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
153
|
+
`)}});let n=()=>{this.clients.delete(t),this.subscriptions.delete(t),this.hasActivitySubscribers()||(this.runtime.setActivityEnabled(!1),this.clearPendingActivityBroadcasts())};t.on("close",n),t.on("error",n)}disposeAll(){for(let t of this.updateTimers.values())clearTimeout(t);this.updateTimers.clear();for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear(),this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear(),this.subscriptions.clear(),this.runtime.setActivityEnabled(!1)}async handleLine(t,r){if(r.trim().length===0)return;let n;try{n=JSON.parse(r)}catch{Ue(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(t,n);Ue(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:ba}:{},...n.type==="getActivitySnapshots"?{activities:this.runtime.getActivitySnapshots()}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);Ue(t,{id:n.id,ok:!1,error:o})}}handleRequest(t,r){switch(r.type){case"ping":return null;case"ensureSession":return this.attachedTabId=r.tabId,this.subscribe(t,r.tabId,this.runtime.ensureSession(r.taskId,r.tabId,r.size,r.spec));case"hydrateSession":return this.runtime.getViewState(r.tabId);case"write":return this.runtime.write(r.input),null;case"writeKey":return this.runtime.writeKey(r.key),null;case"scrollViewport":return this.runtime.scrollViewport(r.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(r.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(r.tabId),this.attachedTabId===r.tabId&&(this.attachedTabId=null),null;case"setViewUpdateMode":return this.setViewUpdateMode(t,r.mode);case"setActivityEnabled":return this.setActivityEnabled(t,r.enabled),null;case"subscribeView":return this.subscribe(t,r.tabId,this.runtime.getViewState(r.tabId));case"pruneStale":{let n=new Set(r.keepTabIds),s=new Set([...this.runtime.sessionTabIds(),...this.runtime.getActivitySnapshots().map(o=>o.tabId)]);for(let o of s)n.has(o)||(this.runtime.disposeSession(o),this.attachedTabId===o&&(this.attachedTabId=null));return null}case"getViewState":return this.runtime.getViewState(r.tabId);case"getActivitySnapshots":return null;case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return jm(r)}}subscribe(t,r,n){let s=this.subscriptions.get(t),o=s?.mode??"snapshot";return this.subscriptions.set(t,{mode:o,activityEnabled:s?.activityEnabled??!1,tabId:r,view:n,rowKeys:n.rows.map(Rr)}),n}setViewUpdateMode(t,r){let n=this.subscriptions.get(t),s=n?.tabId??null,o=this.runtime.getViewState(s);return this.subscriptions.set(t,{mode:r,activityEnabled:n?.activityEnabled??!1,tabId:s,view:o,rowKeys:o.rows.map(Rr)}),o}setActivityEnabled(t,r){let n=this.subscriptions.get(t);if(!n)return;this.subscriptions.set(t,{...n,activityEnabled:r});let s=this.hasActivitySubscribers();this.runtime.setActivityEnabled(s),s||this.clearPendingActivityBroadcasts()}handleRuntimeUpdate(t){let r=null;for(let n of this.clients)this.subscriptions.get(n)?.mode==="snapshot"&&(r??=this.runtime.getViewState(t),Ue(n,{type:"update",tabId:t,view:r}));this.scheduleBroadcastUpdate(t)}handleActivityUpdate(t){if(this.hasActivitySubscribers()){if(this.pendingActivities.set(t.tabId,t),t.sessionState!=="running"){let r=this.activityTimers.get(t.tabId);r&&(clearTimeout(r),this.activityTimers.delete(t.tabId)),this.broadcastActivity(t.tabId);return}this.activityTimers.has(t.tabId)||this.activityTimers.set(t.tabId,setTimeout(()=>{this.activityTimers.delete(t.tabId),this.broadcastActivity(t.tabId)},Im))}}handleActivityRemoved(t){let r=this.activityTimers.get(t);r&&(clearTimeout(r),this.activityTimers.delete(t)),this.pendingActivities.delete(t);for(let[n,s]of this.subscriptions)s.activityEnabled&&Ue(n,{type:"activityRemoved",tabId:t})}broadcastActivity(t){let r=this.pendingActivities.get(t);if(r){this.pendingActivities.delete(t);for(let[n,s]of this.subscriptions)s.activityEnabled&&Ue(n,{type:"activity",snapshot:r})}}hasActivitySubscribers(){return[...this.subscriptions.values()].some(t=>t.activityEnabled)}clearPendingActivityBroadcasts(){for(let t of this.activityTimers.values())clearTimeout(t);this.activityTimers.clear(),this.pendingActivities.clear()}scheduleBroadcastUpdate(t){this.updateTimers.has(t)||!this.hasViewSubscriber(t)||this.updateTimers.set(t,setTimeout(()=>{this.updateTimers.delete(t),this.broadcastUpdate(t)},Sm))}hasViewSubscriber(t){for(let r of this.subscriptions.values())if(r.mode==="incremental"&&r.tabId===t)return!0;return!1}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let n of this.clients){let s=this.subscriptions.get(n);if(!s||s.mode!=="incremental"||s.tabId!==t)continue;let o=vm(s,r),i=Cm(s.view,r);s.view=r,s.rowKeys=r.rows.map(Rr),(o.rows.length>0||i)&&Ue(n,{type:"update",tabId:t,patch:o})}}};function vm(e,t){let r=[];for(let n=0;n<t.rows.length;n+=1){let s=t.rows[n];e.rowKeys[n]!==Rr(s)&&r.push({index:n,row:s})}return{status:t.status,error:t.error,scrolledBack:t.scrolledBack??!1,rowCount:t.rows.length,rows:r}}function Cm(e,t){return!e||e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==(t.scrolledBack??!1)||e.rows.length!==t.rows.length}function Em(e,t){return e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==t.scrolledBack||e.rows.length!==t.rowCount}function Rr(e){return JSON.stringify(e)}function ds(e){let t=wm("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:it.join(bm(),`craig-${t}.sock`),pidPath:it.join(e.runtimeDir,"pty-daemon.pid")}}async function Am(e,t,r){if(await xm(e.socketPath,1e3))return;await br(e.socketPath)&&(await Ea(e.socketPath),await Ta(e.socketPath,1e3)),await br(e.socketPath)&&(await Mm(e),await Ta(e.socketPath,1e3)),await $m(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=Dm(n),l=ym(it.join(t.runtimeDir,"pty-daemon.log"),"a");hm(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 va(e.socketPath))return;await us(50)}let o=await cs(it.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
154
|
+
${o.slice(-2e3)}`:""}`)}async function va(e){let t=await Lm(e).catch(()=>null);return t?.ok===!0&&Ca(t.protocolVersion)}function Ca(e){return e!==void 0&&Pm.has(e)}async function xm(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await va(e))return!0;await us(50)}return!1}function Dm(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=it.resolve(it.dirname(t),"..","node_modules",".bin","tsx");return{command:un("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 $m(e){let t=await cs(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Da(r))return}await Be(e.socketPath,{force:!0}),await Be(e.pidPath,{force:!0})}async function br(e){let t=await xa(e).catch(()=>null);return t?(t.end(),!0):!1}async function Ea(e){await Aa(e,{id:1,type:"shutdown"}).catch(()=>null)}async function Mm(e){let t=await cs(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!Da(r)){await Be(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await Be(e.socketPath,{force:!0})}}async function Lm(e){return Aa(e,{id:1,type:"ping"})}function Aa(e,t){return new Promise((r,n)=>{let s=Ra(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)}
|
|
155
155
|
`)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let d=o.indexOf(`
|
|
156
|
-
`);if(d===-1)return;let c=o.slice(0,d);a(),s.end();try{r(JSON.parse(c))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function
|
|
157
|
-
`)}catch{}}function
|
|
158
|
-
`}function Nm(e){return e.length===1&&e>=" "&&e!==""}import Mt from"node:path";function Wa(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 _a="\u{F024B} ",Ua="\u{F0DCF} ",Ba="\u25CB",fs="\uEA64",qa="\uEAFE",Va="\uEBDA",gs="\u25CB",hs="\u25CF",ws="\u2713",ks="\u2715";function Ka(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 Ha={idle:0,working:1,ready:2,error:3};function $t(e,t,r,n="idle"){let s=t.find(o=>o.tabId===e);return s?s.sessionState==="failed"||s.sessionState==="exited"&&s.exitCode!==0?"error":s.sessionState==="exited"?"ready":r-s.lastActivityAt<5e3?"working":"ready":n}function ys(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return $t(t,r,n,o)}function Ts(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=ys(e,s.id,t,r);Ha[o]>Ha[n]&&(n=o)}return n}function Ga(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&$t(s.id,t,r)==="working"))}var Ir="empty",_={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Ja(e,t,r){let n=Um(t,e),s=t.repos.find(b=>b.id===e.selectedRepoId)??t.repos[0]??null,o=n?t.tasks.filter(b=>b.workspaceId===n.id):t.tasks,i=n?.kind==="project"?o:s?o.filter(b=>b.repoId===s.id):[],a=i.find(b=>b.id===e.selectedTaskId)??i[0]??null,l=a?.type==="project",d=bf(t.tasks),c=Vm(e,a),u=qm(e,a,c,r),p=u.find(b=>b.id===c)??u[0]??{id:"agent",label:"CODEX"},k=t.inspection?.taskId===a?.id?t.inspection:null,y=s?.name??"no repo",w=a?f.runners.getDisplayName(a.runner):f.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 ${s?`[${s.name}]`:"[no repo]"} \xB7 ${f.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 [${f.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Et(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"?a===null?"n new task Tab tasks Esc pause ? help":c===E?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${f.runners.getDisplayName(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?l?"\u2191\u2193 targets Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:Mt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Mt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Wm(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(b=>Pf(b,d[b])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:w},centerTranscript:Bm(c,e,s,a,e.workspaceBrowser,k,n),tabs:u,rightContext:Rf(s,a),rightInspection:nf(e,a,k)}}function Wm(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return _m(n,e,t.repos,t.tasks,r);let s=t.workspaces;if(s.length===0)n.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let i of s){let a=e.selectedLeftItemId===`workspace:${i.id}`;n.push({id:`workspace:${i.id}`,text:`${i.kind==="project"?"\u2261":"\u2013"} ${i.name??i.id}`,selected:a,focused:a&&e.focusedRegion==="tasks"});let l=i.kind==="project"?i.discoveredRepoIds??[]:[i.primaryRepoId],d=t.tasks.filter(c=>c.workspaceId===i.id);if(d.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of d){let u=e.selectedLeftItemId===`task:${c.id}`,p=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,k={id:`task:${c.id}`,taskId:c.id,text:r?p:`${u?"\u25B8":"\u2022"} ${p}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:Ts(c,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},y=Za(c);y&&(k.prBadge=y),n.push(k)}if(i.kind==="project"){let c=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===c;n.push({id:c,text:`+ New Project Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(i.kind==="repo"){let c=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===c;n.push({id:c,text:`+ New Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}else{n.push({text:` Repos (${l.length})`,indent:0,muted:!0});for(let c of l.slice(0,6)){let u=t.repos.find(p=>p.id===c);n.push({text:` \xB7 ${u?.name??c}`,indent:0,muted:!0})}l.length>6&&n.push({text:` \xB7 ${l.length-6} more`,indent:0,muted:!0})}}let o=e.selectedLeftItemId==="new-workspace";return n.push({text:"",muted:!0}),n.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&e.focusedRegion==="tasks"}),n}function _m(e,t,r,n,s){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let i of r){let a=t.selectedLeftItemId===`repo:${i.id}`;e.push({id:`repo:${i.id}`,text:`\u2013 ${i.name}`,selected:a,focused:a&&t.focusedRegion==="tasks"});let l=n.filter(u=>u.repoId===i.id);if(l.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let u of l){let p=t.selectedLeftItemId===`task:${u.id}`,k=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,y={id:`task:${u.id}`,taskId:u.id,text:s?k:`${p?"\u25B8":"\u2022"} ${k}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks",...s?{activity:Ts(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},w=Za(u);w&&(y.prBadge=w),e.push(y)}let d=`new-task:${i.id}`,c=t.selectedLeftItemId===d;e.push({id:d,text:`+ New Task [${f.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let o=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&t.focusedRegion==="tasks"}),e}function Um(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 Bm(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,d=l.length===0?["No matching directories or git repos."]:l.map((u,p)=>{let k=p===s.selectedIndex?"\u25B8":" ",y=u.kind==="repo"?" [git repo]":"/";return`${k} ${u.name}${y}`}),c=s.query!==null?`Search: ${s.query}\u2588`:"";return le(["Browse for a workspace to register.",s.cwd,...c?[c]:[],"",...d,"",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 le(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",d=l?i.name??"this workspace":r.name,c=l?"Project Task":"Task";return le([`No tasks in ${d}.`,"",`Press n or choose + New ${c} to create one with ${f.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?le([`${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."]):le([`${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===E&&t.openInspectionKind==="file"?Gm(n,o,t.fileScrollOffset):e===E&&t.openInspectionKind==="diff"?zm(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?le(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):le(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function qm(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Km(i),...i.kind==="agent"&&n&&t?{activity:ys(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:Ir,label:"EMPTY",active:r===Ir,focused:e.focusedRegion==="center"&&r===Ir}];let o=e.openInspectionKind||r===E?[{id:E,label:Hm(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Vm(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===E&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??E:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??E:Ir}function Km(e){return e.title.toUpperCase()}function Hm(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Mt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Gm(e,t,r){if(!e)return le(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return le(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=Xa(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:""},...Ym(n.lines,r,s)]}function zm(e,t,r){if(!e)return le(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return le(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=Xa(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:""},...Qm(n.lines,r,s)]}function le(e){return e.map(t=>({text:t}))}function Ym(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:_.lineNumber}},{text:" \u2502 ",style:{fg:_.gutter}},...Rs(o,r)],tone:"default"}})}function Qm(e,t,r){let n=Jm(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>Xm(o,r))}function Jm(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 Xm(e,t){let r=za(e.oldNumber),n=za(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:_.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:_.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?ef(Rs(e.text,t),o.bg,o.fallbackFg):Rs(e.text,t),l=o?{fg:_.lineNumber,bg:o.bg}:{fg:_.lineNumber},d=o?{fg:_.gutter,bg:o.bg}:{fg:_.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:d},...a],fullBleed:o!==null}}function za(e){return e===null?" ":String(e).padStart(4," ")}function Xa(e){let t=Mt.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 Rs(e,t){return t==="diff"?Zm(e):t==="markdown"?tf(e):t==="json"?bs(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?bs(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 Zm(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:_.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:_.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:_.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:_.diffMeta}}]:[{text:e}]}function ef(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function tf(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:_.markup,bold:!0}}]:bs(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function bs(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:rf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function rf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:_.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:_.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:_.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:_.markup}:{fg:_.keyword}}function nf(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"?el(t.repoTargets??[]):s?.pullRequest??(t?D(t):null),i=[sf(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=nl(e,t),l=Ps(e,r),d=df([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...d]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...kf(e,r)]}:{title:"",rows:[...i,...Ps(e,r)]}}function sf(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let d=n[l];l>0&&s.push({text:" "});let c=d.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:d.label,style:{fg:c}})}let o=Ss(t),i=Is(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Ya(e){return[{text:" "},Ss(e),{text:" "},Is(e)]}function Za(e){if(e.type==="project"&&e.repoTargets?.length){let r=el(e.repoTargets);return r?Ya(r):null}let t=D(e);return t?.number?Ya(t):null}function el(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=af(r);return{number:-1,status:of(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 of(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 af(e){let t=e.map(r=>tl(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function Ss(e){return!e||!e.number?{text:Ba,style:{fg:"565f89"}}:e.status==="merged"?{text:qa,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Va,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:fs,style:{fg:"565f89"}}:{text:fs,style:{fg:"9ece6a"}}}function Is(e){return e?.aggregateReadiness?Qa(e.aggregateReadiness):Qa(tl(e))}function Qa(e){return e==="failed"?{text:ks,style:{fg:"f7768e"}}:e==="pending"?{text:hs,style:{fg:"e0af68"}}:e==="success"?{text:ws,style:{fg:"9ece6a"}}:{text:gs,style:{fg:"565f89"}}}function tl(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")?rl(e)?"failed":lf(e)?"success":"pending":"pending"}function lf(e){return!!(e.mergeable&&!e.draft&&!rl(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function rl(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function nl(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return cf(e,t);let r=D(t),n=ol("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var Sr=32;function cf(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,d=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,p=Sr-u.length-1,k=d.length>p?d.slice(0,p-1)+"\u2026":d,y=Sr-k.length-u.length;r.push({id:`project-review:${i.repoId}`,text:k+" ".repeat(Math.max(1,y))+u,selected:a,focused:l,muted:!0})}else{let c=Ss(i.pullRequest),u=Is(i.pullRequest),p=`${c.text} ${u.text}`,k=Sr-p.length-1,y=d.length>k?d.slice(0,k-1)+"\u2026":d,w=Sr-y.length-p.length,b=y+" ".repeat(Math.max(1,w));r.push({id:`project-review:${i.repoId}`,text:b+p,selected:a,focused:l,segments:[{text:b},{...c,text:c.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...ol("target",o.branch,o.pullRequest))),r}function sl(e,t,r=null){return 3+nl(e,t).length+Ps(e,r).length}function ol(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=uf(r.reviewDecision,r.mergeStateStatus),d=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:`${d} \xB7 ${l}`,muted:!0,segments:[{text:d},{text:" \xB7 "},{text:l,style:{fg:pf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:d,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${il(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(mf)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let c=r.comments??[];return c.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${c.length})`}),s.push(...c.slice(-4).flatMap((u,p)=>ff(u,n(`comment:${p}`))))),s}function df(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 uf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function pf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function il(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 mf(e){let{icon:t,color:r}=hf(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," ")} ${wf(e.status)}`,color:r,muted:!1}}function ff(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${il(e.createdAt)}`:"",s=gf(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,d)=>({id:`${t}:body:${d}`,text:` ${i&&d===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function gf(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 hf(e){switch(e){case"success":return{icon:ws,color:"9ece6a"};case"pending":return{icon:hs,color:"e0af68"};case"failed":return{icon:ks,color:"f7768e"};case"skipped":return{icon:gs,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function wf(e){return e==="success"?"passing":e==="failed"?"failing":e}function kf(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=vs(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 d=l.kind==="file"?r.get(l.path):void 0,c=d==="A"?"9ece6a":d==="M"?"e0af68":d==="D"?"f7768e":d==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?_a:Ua:Wa(l.label),p=l.kind==="directory"?"7aa2f7":Ka(l.label),k=" ".repeat(l.depth),y=p?{text:u,style:{fg:p}}:{text:u},w=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:c?{text:l.label,style:{fg:c}}:{text:l.label},b=[{text:k},y,w];return{id:l.path,text:`${k}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:b}})]}function vs(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 Ps(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(yf(t))return Tf(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>al(o,e,t))))}return r}function yf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Tf(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(d=>d.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(d=>al(d,e,t,s.length+1))))}}return r}function al(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Rf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:f.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Mt.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 bf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Pf(e,t){return{name:f.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function ll(e,t,r,n,s=null){if(s)return Sf(e,t,r,n,s);let o=Yn(e,t,{centerOnly:n});return If(r,o)?{output:ua(o.rows,r.rows,o.row,o.column),region:o}:null}function Sf(e,t,r,n,s){let o=Hi(e,t,s,{centerOnly:n});if(!o||!vf(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:d})=>i[l]===d?"":(i[l]=d,`\x1B[${o.row+l};${o.column}H${d}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function If(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function vf(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}import{appendFile as Cf,mkdir as Ef,readFile as Af}from"node:fs/promises";import xf from"node:path";var cl=80,Cs=async(e,t)=>{await Ef(xf.dirname(e.errorLogFile),{recursive:!0}),await Cf(e.errorLogFile,Df(t),"utf8")},dl=async(e,t)=>{try{await Cs(e,t)}catch{}},Es=async(e,t=cl)=>{try{let n=(await Af(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
159
|
-
`).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if($f(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},
|
|
156
|
+
`);if(d===-1)return;let c=o.slice(0,d);a(),s.end();try{r(JSON.parse(c))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function Ta(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await br(e))return;await us(50)}}function xa(e){return new Promise((t,r)=>{let n=Ra(e);n.once("connect",()=>t(n)),n.once("error",r)})}function Om(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function Ue(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
157
|
+
`)}catch{}}function Da(e){try{return process.kill(e,0),!0}catch{return!1}}function us(e){return new Promise(t=>setTimeout(t,e))}function jm(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var ps=["Runners","Feature Previews","Error Log","Help"],Ma={incrementalCenterPane:"Incremental center pane",agentActivityIndicators:"Agent activity indicators"};function ms(e,t){return $.map(r=>{let n=f.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 La(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 Oa(e){return oe.map(t=>`${f.previews.isEnabled(e,t)?"[x]":"[ ]"} ${Ma[t]}`)}function ja(e){return e.message??"Experimental features may change or be removed. Enter toggles."}function Fa(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(ps.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:Pr(t)?e===0?{kind:"runners"}:e===1?{kind:"previews"}:e===2?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Na(e,t,r){if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(oe.length-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(!Pr(r))return{kind:"noop",state:e};let n=oe[e.menuIndex]??oe[0],s=!f.previews.isEnabled(t,n);return{kind:"save-enabled",feature:n,enabled:s,state:{...e,message:`${Ma[n]} ${s?"enabled":"disabled"}.`}}}function Wa(e,t,r,n){if(e.pathEdit)return Fm({...e,pathEdit:e.pathEdit},t,r);let s=ms(t,e).length;if(r==="UP"||r==="k")return{kind:"render",state:{...e,menuIndex:Math.max(0,e.menuIndex-1),message:null}};if(r==="DOWN"||r==="j")return{kind:"render",state:{...e,menuIndex:Math.min(s-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let a=$[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!Pr(r))return{kind:"noop",state:e};let o=$[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${f.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function Fm(e,t,r){if(r==="ESCAPE")return{kind:"render",state:$a({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(Pr(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:$a({...e,message:s.length>0?`${f.runners.getProfile(n).displayName} executable saved.`:`${f.runners.getProfile(n).displayName} executable reset to default.`})}}return Nm(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function $a(e){let t={...e};return delete t.pathEdit,t}function Pr(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
158
|
+
`}function Nm(e){return e.length===1&&e>=" "&&e!==""}import Mt from"node:path";function _a(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 Ua="\u{F024B} ",Ba="\u{F0DCF} ",qa="\u25CB",fs="\uEA64",Va="\uEAFE",Ka="\uEBDA",gs="\u25CB",hs="\u25CF",ws="\u2713",ks="\u2715";function Ha(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 Ga={idle:0,working:1,ready:2,error:3};function $t(e,t,r,n="idle"){let s=t.find(o=>o.tabId===e);return s?s.sessionState==="failed"||s.sessionState==="exited"&&s.exitCode!==0?"error":s.sessionState==="exited"?"ready":r-s.lastActivityAt<5e3?"working":"ready":n}function ys(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return $t(t,r,n,o)}function Ts(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=ys(e,s.id,t,r);Ga[o]>Ga[n]&&(n=o)}return n}function za(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&$t(s.id,t,r)==="working"))}var Ir="empty",_={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Xa(e,t,r){let n=Um(t,e),s=t.repos.find(b=>b.id===e.selectedRepoId)??t.repos[0]??null,o=n?t.tasks.filter(b=>b.workspaceId===n.id):t.tasks,i=n?.kind==="project"?o:s?o.filter(b=>b.repoId===s.id):[],a=i.find(b=>b.id===e.selectedTaskId)??i[0]??null,l=a?.type==="project",d=bf(t.tasks),c=Vm(e,a),u=qm(e,a,c,r),p=u.find(b=>b.id===c)??u[0]??{id:"agent",label:"CODEX"},k=t.inspection?.taskId===a?.id?t.inspection:null,y=s?.name??"no repo",w=a?f.runners.getDisplayName(a.runner):f.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 ${s?`[${s.name}]`:"[no repo]"} \xB7 ${f.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 [${f.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:Et(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"?a===null?"n new task Tab tasks Esc pause ? help":c===E?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${f.runners.getDisplayName(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?l?"\u2191\u2193 targets Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 changes Enter open change Wheel/PgUp/PgDn scroll o open PR R refresh checks X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?e.fileSearchQuery!==null?`Search: ${e.fileSearchQuery} \u2191\u2193 navigate Enter open Esc cancel search`:"\u2191\u2193 navigate / search Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:Mt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${Mt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Wm(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(b=>Pf(b,d[b])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:w},centerTranscript:Bm(c,e,s,a,e.workspaceBrowser,k,n),tabs:u,rightContext:Rf(s,a),rightInspection:nf(e,a,k)}}function Wm(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return _m(n,e,t.repos,t.tasks,r);let s=t.workspaces;if(s.length===0)n.push({text:"No workspaces registered.",indent:2,muted:!0});else for(let i of s){let a=e.selectedLeftItemId===`workspace:${i.id}`;n.push({id:`workspace:${i.id}`,text:`${i.kind==="project"?"\u2261":"\u2013"} ${i.name??i.id}`,selected:a,focused:a&&e.focusedRegion==="tasks"});let l=i.kind==="project"?i.discoveredRepoIds??[]:[i.primaryRepoId],d=t.tasks.filter(c=>c.workspaceId===i.id);if(d.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let c of d){let u=e.selectedLeftItemId===`task:${c.id}`,p=c.title.length>28?`${c.title.slice(0,25)}\u2026`:c.title,k={id:`task:${c.id}`,taskId:c.id,text:r?p:`${u?"\u25B8":"\u2022"} ${p}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:Ts(c,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},y=el(c);y&&(k.prBadge=y),n.push(k)}if(i.kind==="project"){let c=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===c;n.push({id:c,text:`+ New Project Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(i.kind==="repo"){let c=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===c;n.push({id:c,text:`+ New Task [${f.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}else{n.push({text:` Repos (${l.length})`,indent:0,muted:!0});for(let c of l.slice(0,6)){let u=t.repos.find(p=>p.id===c);n.push({text:` \xB7 ${u?.name??c}`,indent:0,muted:!0})}l.length>6&&n.push({text:` \xB7 ${l.length-6} more`,indent:0,muted:!0})}}let o=e.selectedLeftItemId==="new-workspace";return n.push({text:"",muted:!0}),n.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&e.focusedRegion==="tasks"}),n}function _m(e,t,r,n,s){if(r.length===0)e.push({text:"No repos registered.",indent:2,muted:!0});else for(let i of r){let a=t.selectedLeftItemId===`repo:${i.id}`;e.push({id:`repo:${i.id}`,text:`\u2013 ${i.name}`,selected:a,focused:a&&t.focusedRegion==="tasks"});let l=n.filter(u=>u.repoId===i.id);if(l.length===0)e.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let u of l){let p=t.selectedLeftItemId===`task:${u.id}`,k=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,y={id:`task:${u.id}`,taskId:u.id,text:s?k:`${p?"\u25B8":"\u2022"} ${k}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks",...s?{activity:Ts(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},w=el(u);w&&(y.prBadge=w),e.push(y)}let d=`new-task:${i.id}`,c=t.selectedLeftItemId===d;e.push({id:d,text:`+ New Task [${f.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:c,focused:c&&t.focusedRegion==="tasks",muted:!c})}let o=t.selectedLeftItemId==="new-workspace";return e.push({text:"",muted:!0}),e.push({id:"new-workspace",text:"+ New Workspace",selected:o,focused:o&&t.focusedRegion==="tasks"}),e}function Um(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 Bm(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,d=l.length===0?["No matching directories or git repos."]:l.map((u,p)=>{let k=p===s.selectedIndex?"\u25B8":" ",y=u.kind==="repo"?" [git repo]":"/";return`${k} ${u.name}${y}`}),c=s.query!==null?`Search: ${s.query}\u2588`:"";return le(["Browse for a workspace to register.",s.cwd,...c?[c]:[],"",...d,"",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 le(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",d=l?i.name??"this workspace":r.name,c=l?"Project Task":"Task";return le([`No tasks in ${d}.`,"",`Press n or choose + New ${c} to create one with ${f.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?le([`${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."]):le([`${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===E&&t.openInspectionKind==="file"?Gm(n,o,t.fileScrollOffset):e===E&&t.openInspectionKind==="diff"?zm(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?le(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):le(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function qm(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Km(i),...i.kind==="agent"&&n&&t?{activity:ys(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:Ir,label:"EMPTY",active:r===Ir,focused:e.focusedRegion==="center"&&r===Ir}];let o=e.openInspectionKind||r===E?[{id:E,label:Hm(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Vm(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===E&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??E:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??E:Ir}function Km(e){return e.title.toUpperCase()}function Hm(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?Mt.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Gm(e,t,r){if(!e)return le(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return le(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=Za(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:""},...Ym(n.lines,r,s)]}function zm(e,t,r){if(!e)return le(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return le(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=Za(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:""},...Qm(n.lines,r,s)]}function le(e){return e.map(t=>({text:t}))}function Ym(e,t,r){let n=Math.max(3,String(e.length).length),s=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(s).map((o,i)=>{let a=s+i+1;return{text:`${`${String(a).padStart(n," ")} \u2502 `}${o}`,segments:[{text:String(a).padStart(n," "),style:{fg:_.lineNumber}},{text:" \u2502 ",style:{fg:_.gutter}},...Rs(o,r)],tone:"default"}})}function Qm(e,t,r){let n=Jm(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>Xm(o,r))}function Jm(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 Xm(e,t){let r=Ya(e.oldNumber),n=Ya(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:_.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:_.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?ef(Rs(e.text,t),o.bg,o.fallbackFg):Rs(e.text,t),l=o?{fg:_.lineNumber,bg:o.bg}:{fg:_.lineNumber},d=o?{fg:_.gutter,bg:o.bg}:{fg:_.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:d},...a],fullBleed:o!==null}}function Ya(e){return e===null?" ":String(e).padStart(4," ")}function Za(e){let t=Mt.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 Rs(e,t){return t==="diff"?Zm(e):t==="markdown"?tf(e):t==="json"?bs(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?bs(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 Zm(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:_.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:_.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:_.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:_.diffMeta}}]:[{text:e}]}function ef(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function tf(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:_.markup,bold:!0}}]:bs(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function bs(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:rf(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function rf(e){return e.startsWith("//")||e.startsWith("/*")?{fg:_.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:_.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:_.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:_.markup}:{fg:_.keyword}}function nf(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"?tl(t.repoTargets??[]):s?.pullRequest??(t?D(t):null),i=[sf(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=sl(e,t),l=Ps(e,r),d=df([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...d]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...kf(e,r)]}:{title:"",rows:[...i,...Ps(e,r)]}}function sf(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let d=n[l];l>0&&s.push({text:" "});let c=d.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:d.label,style:{fg:c}})}let o=Ss(t),i=Is(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Qa(e){return[{text:" "},Ss(e),{text:" "},Is(e)]}function el(e){if(e.type==="project"&&e.repoTargets?.length){let r=tl(e.repoTargets);return r?Qa(r):null}let t=D(e);return t?.number?Qa(t):null}function tl(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=af(r);return{number:-1,status:of(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 of(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 af(e){let t=e.map(r=>rl(r));return t.some(r=>r==="failed")?"failed":t.some(r=>r==="pending")?"pending":t.length>0&&t.every(r=>r==="success")?"success":"none"}function Ss(e){return!e||!e.number?{text:qa,style:{fg:"565f89"}}:e.status==="merged"?{text:Va,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Ka,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:fs,style:{fg:"565f89"}}:{text:fs,style:{fg:"9ece6a"}}}function Is(e){return e?.aggregateReadiness?Ja(e.aggregateReadiness):Ja(rl(e))}function Ja(e){return e==="failed"?{text:ks,style:{fg:"f7768e"}}:e==="pending"?{text:hs,style:{fg:"e0af68"}}:e==="success"?{text:ws,style:{fg:"9ece6a"}}:{text:gs,style:{fg:"565f89"}}}function rl(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")?nl(e)?"failed":lf(e)?"success":"pending":"pending"}function lf(e){return!!(e.mergeable&&!e.draft&&!nl(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function nl(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function sl(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return cf(e,t);let r=D(t),n=il("pr",t.branch,r??{number:null,url:null,baseBranch:null,headBranch:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,lastSyncedAt:null,requiredChecks:[],comments:[]}),s=t.prs.filter(o=>o!==r&&(o.status==="merged"||o.status==="closed")).length;return s>0&&n.push({id:"pr-history",text:`+ ${s} previous PR${s!==1?"s":""}`,muted:!0}),n}var Sr=32;function cf(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,d=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,p=Sr-u.length-1,k=d.length>p?d.slice(0,p-1)+"\u2026":d,y=Sr-k.length-u.length;r.push({id:`project-review:${i.repoId}`,text:k+" ".repeat(Math.max(1,y))+u,selected:a,focused:l,muted:!0})}else{let c=Ss(i.pullRequest),u=Is(i.pullRequest),p=`${c.text} ${u.text}`,k=Sr-p.length-1,y=d.length>k?d.slice(0,k-1)+"\u2026":d,w=Sr-y.length-p.length,b=y+" ".repeat(Math.max(1,w));r.push({id:`project-review:${i.repoId}`,text:b+p,selected:a,focused:l,segments:[{text:b},{...c,text:c.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...il("target",o.branch,o.pullRequest))),r}function ol(e,t,r=null){return 3+sl(e,t).length+Ps(e,r).length}function il(e,t,r){let n=u=>`${e}-${u}`;if(!r.number)return[{id:n("no-pr"),text:t,muted:!0}];let s=[],o=`#${r.number}`;s.push(r.url?{id:n("pr-number"),text:`${o} Open in GitHub \u2197`,segments:[{text:o},{text:" Open in GitHub \u2197",style:{fg:"7aa2f7",underline:!0},href:r.url}]}:{id:n("pr-number"),text:o});let i=r.baseBranch??"?",a=r.headBranch??t;s.push({id:n("pr-branches"),text:`${i} \u2192 ${a}`,muted:!0});let l=uf(r.reviewDecision,r.mergeStateStatus),d=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:`${d} \xB7 ${l}`,muted:!0,segments:[{text:d},{text:" \xB7 "},{text:l,style:{fg:pf(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:d,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${al(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(mf)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let c=r.comments??[];return c.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${c.length})`}),s.push(...c.slice(-4).flatMap((u,p)=>ff(u,n(`comment:${p}`))))),s}function df(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 uf(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function pf(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function al(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 mf(e){let{icon:t,color:r}=hf(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," ")} ${wf(e.status)}`,color:r,muted:!1}}function ff(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${al(e.createdAt)}`:"",s=gf(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,d)=>({id:`${t}:body:${d}`,text:` ${i&&d===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function gf(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 hf(e){switch(e){case"success":return{icon:ws,color:"9ece6a"};case"pending":return{icon:hs,color:"e0af68"};case"failed":return{icon:ks,color:"f7768e"};case"skipped":return{icon:gs,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function wf(e){return e==="success"?"passing":e==="failed"?"failing":e}function kf(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=vs(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 d=l.kind==="file"?r.get(l.path):void 0,c=d==="A"?"9ece6a":d==="M"?"e0af68":d==="D"?"f7768e":d==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?Ua:Ba:_a(l.label),p=l.kind==="directory"?"7aa2f7":Ha(l.label),k=" ".repeat(l.depth),y=p?{text:u,style:{fg:p}}:{text:u},w=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:c?{text:l.label,style:{fg:c}}:{text:l.label},b=[{text:k},y,w];return{id:l.path,text:`${k}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:b}})]}function vs(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 Ps(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(yf(t))return Tf(e,t);let r=[];for(let n of["branch","staged","unstaged","untracked"]){let s=t.diffRows.filter(o=>o.group===n);s.length!==0&&(r.push({id:n,text:n.toUpperCase(),muted:!0}),r.push(...s.map(o=>ll(o,e,t))))}return r}function yf(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Tf(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(d=>d.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(d=>ll(d,e,t,s.length+1))))}}return r}function ll(e,t,r,n=0){let s=e.additions===null?"-":`+${e.additions}`,o=e.deletions===null?"-":`-${e.deletions}`,i=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68",a=n>0?e.path.slice(n):e.path;return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${a} ${s}/${o}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:i}}function Rf(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:f.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:Mt.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 bf(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function Pf(e,t){return{name:f.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function cl(e,t,r,n,s=null){if(s)return Sf(e,t,r,n,s);let o=Yn(e,t,{centerOnly:n});return If(r,o)?{output:pa(o.rows,r.rows,o.row,o.column),region:o}:null}function Sf(e,t,r,n,s){let o=Gi(e,t,s,{centerOnly:n});if(!o||!vf(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:d})=>i[l]===d?"":(i[l]=d,`\x1B[${o.row+l};${o.column}H${d}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function If(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function vf(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}import{appendFile as Cf,mkdir as Ef,readFile as Af}from"node:fs/promises";import xf from"node:path";var dl=80,Cs=async(e,t)=>{await Ef(xf.dirname(e.errorLogFile),{recursive:!0}),await Cf(e.errorLogFile,Df(t),"utf8")},ul=async(e,t)=>{try{await Cs(e,t)}catch{}},Es=async(e,t=dl)=>{try{let n=(await Af(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
159
|
+
`).filter(s=>s.length>0);return{path:e.errorLogFile,lines:n.slice(Math.max(0,n.length-t)),empty:n.length===0}}catch(r){if($f(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},pl=async(e,t=dl)=>Es(e,t);function Df(e){let r=[`[${new Date().toISOString()}] ${e.context}`,`message: ${e.message}`];return e.details&&e.details.trim().length>0&&(r.push("details:"),r.push(...e.details.trimEnd().split(`
|
|
160
160
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
161
161
|
`)}
|
|
162
162
|
|
|
163
|
-
`}function $f(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var at={appendErrorLog:Cs,appendErrorLogBestEffort:dl,readErrorLog:Es,readRecentErrorLines:ul};var Mf=["tasks","center","inspector"];function Lf(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 xs(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return $s({...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 $s(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return $i(t)?h({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):h({state:e});if(e.fileSearchQuery!==null)return Lf(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"&&(lr(e.selectedLeftItemId)||cr(e.selectedLeftItemId)))return h({state:{...e,selectedRunner:ar(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return pl(e,1);if(t==="SHIFT_TAB"||t==="[")return pl(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===E?Ee(e,-1,r):xs(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===E?Ee(e,1,r):xs(e,1,r);if(t==="PAGE_UP")return Ee(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Ee(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Ee(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Ee(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??$,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return 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=Bf(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"&&Et(e.selectedLeftItemId)&&e.selectedTaskId)return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Fi(e.selectedLeftItemId)&&e.selectedWorkspaceId)return h({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&gl(e.activeTab,r.ptyTabIds??[]))return h({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return As(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return ml(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return As(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return ml(e,1)}if(ie(t)){if(e.focusedRegion==="tasks"&&(lr(e.selectedLeftItemId)||cr(e.selectedLeftItemId))){let n=Bn(e.selectedLeftItemId),s=qn(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"&&Et(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return h({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:st(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&gl(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return h({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:st(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===E)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:Ff({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return h({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:E,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?h({state:{...e,selectedDiffPath:n,activeTab:E,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):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})}return 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 Ee(e,t,r){if(t===0)return h({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?hl(e,t,r):e.inspectionMode==="review"?fl(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):h({state:e});if(e.focusedRegion==="center"&&e.activeTab===E){if(e.openInspectionKind==="file")return fl(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return Nf(e,t,r)}return h({state:e})}function pl(e,t){return vr(e,"focusedRegion",Mf,t)}function As(e,t,r){let n=vr(e,"activeTab",r&&r.length>0?r:qf(e),t);return!n.changed||Li(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:st(n.state.activeTab)??n.state.preferredPtyTabKind}}}function xs(e,t,r){if(e.focusedRegion==="tasks")return Of(e,t,r.leftItemIds);if(e.focusedRegion==="center")return As(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return hl(e,t,r);if(r.projectTargetIds?.length){let s=Ds(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=Ds(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:E,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:vr(e,"selectedActionId",Ci,t)}return vr(e,"selectedActionId",Nn,t)}function Of(e,t,r){let n=Ds(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Un(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=Bn(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=qn(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function jf(e,t){if(e.inspectionMode===t)return h({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?E:e.activeTab;return h({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function ml(e,t){return jf(e,Uf(e.inspectionMode,Wn,t))}function hl(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=we(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?E:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Ff(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 fl(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=we(e[t]+r,0,o);return i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Nf(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Wf(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 c=we(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let c=we(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}if(t>0&&i>o){let c=a[l+1]??null;return c?h({state:{...e,selectedDiffPath:c,activeTab:E,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 c=a[l-1]??null;return c?h({state:{...e,selectedDiffPath:c,activeTab:E,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 d=we(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}function Wf(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=we(e.diffScrollOffset+t,0,o),a=_f(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 _f(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function vr(e,t,r,n){let s=r.indexOf(e[t]),o=we(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 Ds(e,t,r,n,s=!1){if(r.length===0)return h({state:e});let o=r.indexOf(e[t]??r[0]??""),i=we(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 Uf(e,t,r){let n=t.indexOf(e);return t[we(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 gl(e,t){return t.includes(e)}function Bf(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":st(e.activeTab)??e.preferredPtyTabKind}function qf(e){return[e.selectedPtyTabId,e.openInspectionKind?E:null].filter(t=>typeof t=="string")}function we(e,t,r){return Math.min(r,Math.max(t,e))}var wl=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await ee(n.paths,e.selectedTaskId),i=t??Vf(o,e.activeTab,e.preferredPtyTabKind),a=Rl(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await S(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"}`}}},kl=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(d=>d.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(d=>d.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await S(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}`}}},yl=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await ee(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await S(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Tl=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await S(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=Rl(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await S(t.paths,{...s,selectedPtyTabId:o.id});return}await S(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Vf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Rl(e,t,r,n={}){let s=r??e.runner,o=f.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(k=>k.id)),d=1,c=a;for(;l.has(c);)d+=1,c=`${a}-${d}`;let u=new Date().toISOString(),p=r&&r!==e.runner?r:void 0;return{id:c,kind:t,...p?{runner:p}:{},title:d===1?i:`${i} ${d}`,command:t==="agent"?f.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var lt=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},bl=async(e,t,r,n,s)=>{f.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=je();await P(Fe(f.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{cwd:o.repoRoot,env:l})}catch(l){let d=l instanceof Error?l.message:"Failed to start runner.",c=await s.taskService.recordStartupFailure(s.paths,o.task.id,d);throw new lt(d,c)}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}},Pl=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Sl=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},Il=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Cr=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await at.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var vl=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 Cl=async(e,t,r)=>{let n=f.runners.setRunnerEnabled(r.config,e,t);return await f.save(r.paths,n),n},El=async(e,t,r)=>{let n=f.runners.setRunnerPath(r.config,e,t);return await f.save(r.paths,n),n},Al=async(e,t,r)=>{let n=f.previews.setEnabled(r.config,e,t);return await f.save(r.paths,n),n};var Kf=250;function ke(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function qe(e,t){return he(t,e.ptyRuntime.getViewState(Lt(e,t)))}function Lt(e,t){let r=ke(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 qe(e,Ni(t,e.model))}function xl(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 Dl(e,t,r){return xl(e,t,r?{tone:"success",message:r}:null)}function O(e,t,r){return xl(e,t,{tone:"error",message:r})}function j(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return at.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function M(e,t){if(!e.uiStateFile)return;e.runtimeState=xi(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Te({uiStateFile:e.uiStateFile},r),()=>Te({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Hf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function F(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:Q,queueTaskMutation:t=>Hf(e,t)}}function Ms(e,t){let r=ke(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?vs(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:_e(e.model),centerTabIds:ji(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:sl(t,r,s),pageRows:Math.max(5,se(e.activeTerminal.width,e.activeTerminal.height).height-W.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function $l(e,t){await yl(t,F(e))}async function K(e){e.model=await Ie(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 Er(e,t){let r=++e.inspectionRefreshSequence,n=Vn(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await gi(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await Ie(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},M(e,e.state.shell),e.render())}function Ml(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)&&Er(e,r).catch(n=>{let s=j(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Kf))}function Ll(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=Ee(e.state.shell,r,Ms(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),Er(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render()}},16)))}function Ls(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Os(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 jl(e){Os(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function Fl(e,t){let r=g(e,t),n=ke(e.model.tasks,r),s=Lt(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 he(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ve(se(e.activeTerminal.width,e.activeTerminal.height)));return he({...r,inputMode:"control"},i)}function Nl(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 js(e,t){try{let r=g(e,t),n=ke(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 Ol(e,n),await K(e),s=n.selectedPtyTabId)}n&&!s&&(n=await Ol(e,n),await K(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:he({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},M(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ve(se(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ce(s),e.lastTerminalKey=null,e.state={mode:"main",shell:he({...o,inputMode:"terminal"},i)},M(e,e.state.shell)}catch(r){let n=j(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Ce(t.selectedPtyTabId)&&(await Gf(e,t.selectedTaskId,n).catch(()=>{}),await K(e).catch(()=>{})),e.state={mode:"main",shell:O(e,Di(g(e,t),n),n)},M(e,e.state.shell)}e.render()}async function Gf(e,t,r){await Pl(t,r,F(e))}async function Wl(e,t,r,n){let s=g(e,t),{nextShell:o}=await wl(s,r,n,F(e));return await K(e),g(e,{...s,...o})}async function _l(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await kl(r,F(e));return e.ptyRuntime.disposeSession(n.id),await K(e),g(e,{...r,...s})}async function Ul(e,t){let r=g(e,t),n=_e(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Sl(r,F(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await K(e),g(e,{...r,...i,selectedLeftItemId:zf(n,_e(e.model),s)})}async function Bl(e,t){let r=g(e,t),{nextShell:n}=await vl(r,F(e));return await K(e),g(e,{...r,...n})}async function Ol(e,t){return Tl(t,F(e))}function Ar(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:qe(e,e.state.shell)},e.render())},16))}function zf(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 ql(e,t){if(!(t?.aborted||e.state.mode!=="main"))try{if(await Il(e.model.tasks,F(e)),t?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;let r=await Ie(e.workspaceRoot,e.state.shell,e.enabledRunnerIds);if(t?.aborted)return;e.model=r,e.state={mode:"main",shell:g(e,e.state.shell)},e.render()}catch(r){if(t?.aborted)return;let n=r instanceof Error?r.message:"Background PR discovery failed.";n!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=n,Cr("background PR polling",r,F(e)))}}async function Vl(e,t){let r=g(e,t),n=ke(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await C.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await K(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await C.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await K(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${D(a)?.requiredChecks.length??0} reported`)}return g(e,{...Dl(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Zf from"node:path";import{readdir as Yf,stat as Qf}from"node:fs/promises";import Kl from"node:path";async function Jf(e){let t=await Yf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Kl.join(e,n.name);r.push({name:n.name,path:s,kind:await Xf(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 Hl(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Gl(e){let{spawn:t}=await import("node:child_process"),r=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await new Promise((n,s)=>{let o=t(r,[e],{stdio:"ignore",detached:!0});o.unref(),o.on("error",s),o.on("spawn",n)})}async function xr(e,t){let r=await Jf(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 Xf(e){let t=Kl.join(e,".git");return await Qf(t).catch(()=>null)!==null}function zl(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Yl(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function eg(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 bl(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,F(e));n=s.task,await K(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??ra(n,"agent"),ve(se(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ce(o.selectedPtyTabId),e.state={mode:"main",shell:he(o,i)},M(e,e.state.shell)}catch(s){s instanceof lt&&(n=s.task);let o=j(e,"create task",s,"Failed to create task.");n&&!(s instanceof lt)?(await S(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await K(e).catch(()=>{})):n&&(await S(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await K(e).catch(()=>{})),e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function tg(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)){eg(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:ar(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}Mi(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function rg(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=Hl(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"){xr(e,Zf.dirname(r.cwd)).catch(s=>{let o=j(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ie(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){xr(e,s.path).catch(i=>{let a=j(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=F(e);o.addWorkspace(e.paths,s.path).then(async i=>{await K(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},M(e,e.state.shell),e.render()}).catch(i=>{let a=j(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function ng(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=ja(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;sg(e,n)}}}async function sg(e,t){let r;try{r=await at.readRecentErrorLines(e.paths)}catch(n){let s=j(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function og(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Na(zl(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"?Cl(r.runner,r.enabled,F(e)):El(r.runner,r.path,F(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=f.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:f.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=j(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:O(e,g(e,e.state.shell),o),runnerOptions:{...zl(e),message:o}},e.render()})}function ig(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=Fa(Yl(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}Al(r.feature,r.enabled,F(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,r.feature==="incrementalCenterPane"&&e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),r.feature==="agentActivityIndicators"&&e.setAgentActivityEnabled(r.enabled),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=j(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:O(e,g(e,e.state.shell),s),previewOptions:{...Yl(e),message:s}},e.render()})}}function Ql(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){tg(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){rg(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){lg(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=$s(e.state.shell,r,Ms(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ie(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=Dt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(ag(e,r))return;e.lastTerminalKey=na(r)?{key:r,at:Date.now()}:null;let o=sa(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){Ar(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){xr(e,e.workspaceRoot).catch(s=>{let o=j(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:O(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){Wl(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{js(e,s)}).catch(s=>{let o=j(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){_l(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Vl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=ke(e.model.tasks,n.state),o=s?D(s)?.url??null:null;o?Gl(o).catch(i=>{let a=j(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:O(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:O(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){Ul(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Bl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){js(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){Ml(e,e.state.shell);return}Er(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},$l(e,e.state.shell).catch(()=>{}),M(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){ng(e,r);return}if(e.state.variant==="runners"){og(e,r);return}if(e.state.variant==="previews"){ig(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:2,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;Fl(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},M(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=j(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:O(e,g(e,e.state.shell),i)},M(e,e.state.shell),e.render()})}):jl(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 Jl(e,t){let r=ca(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=Dt(o);if(i){Zl(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(rs(o)){e.pendingTerminalKeySequence.raw=o,Xl(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"})},M(e,e.state.shell),e.render();return}let n=oa(r);if(n!==0){Ar(e,n);return}let s=Dt(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
163
|
+
`}function $f(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var at={appendErrorLog:Cs,appendErrorLogBestEffort:ul,readErrorLog:Es,readRecentErrorLines:pl};var Mf=["tasks","center","inspector"];function Lf(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 xs(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return $s({...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 $s(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Mi(t)?h({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):h({state:e});if(e.fileSearchQuery!==null)return Lf(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"&&(lr(e.selectedLeftItemId)||cr(e.selectedLeftItemId)))return h({state:{...e,selectedRunner:ar(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return ml(e,1);if(t==="SHIFT_TAB"||t==="[")return ml(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===E?Ee(e,-1,r):xs(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===E?Ee(e,1,r):xs(e,1,r);if(t==="PAGE_UP")return Ee(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return Ee(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return Ee(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return Ee(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??$,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return 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=Bf(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"&&Et(e.selectedLeftItemId)&&e.selectedTaskId)return h({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Ni(e.selectedLeftItemId)&&e.selectedWorkspaceId)return h({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&hl(e.activeTab,r.ptyTabIds??[]))return h({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return As(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return fl(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return As(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return fl(e,1)}if(ie(t)){if(e.focusedRegion==="tasks"&&(lr(e.selectedLeftItemId)||cr(e.selectedLeftItemId))){let n=Bn(e.selectedLeftItemId),s=qn(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"&&Et(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return h({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:st(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&hl(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return h({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:st(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===E)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:Ff({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return h({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:E,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}if(e.focusedRegion==="inspector"&&e.inspectionMode==="review"){let n=e.selectedDiffPath??r.diffPathIds?.[0]??null;return n?h({state:{...e,selectedDiffPath:n,activeTab:E,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):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})}return 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 Ee(e,t,r){if(t===0)return h({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?wl(e,t,r):e.inspectionMode==="review"?gl(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):h({state:e});if(e.focusedRegion==="center"&&e.activeTab===E){if(e.openInspectionKind==="file")return gl(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return Nf(e,t,r)}return h({state:e})}function ml(e,t){return vr(e,"focusedRegion",Mf,t)}function As(e,t,r){let n=vr(e,"activeTab",r&&r.length>0?r:qf(e),t);return!n.changed||Oi(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:st(n.state.activeTab)??n.state.preferredPtyTabKind}}}function xs(e,t,r){if(e.focusedRegion==="tasks")return Of(e,t,r.leftItemIds);if(e.focusedRegion==="center")return As(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return wl(e,t,r);if(r.projectTargetIds?.length){let s=Ds(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=Ds(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:E,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:vr(e,"selectedActionId",Ei,t)}return vr(e,"selectedActionId",Nn,t)}function Of(e,t,r){let n=Ds(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Un(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=Bn(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=qn(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function jf(e,t){if(e.inspectionMode===t)return h({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?E:e.activeTab;return h({state:{...e,inspectionMode:t,activeTab:n,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,reviewScrollOffset:t==="review"?0:e.reviewScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function fl(e,t){return jf(e,Uf(e.inspectionMode,Wn,t))}function wl(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=we(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?E:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Ff(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 gl(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=we(e[t]+r,0,o);return i===e[t]?h({state:e}):h({state:{...e,[t]:i,actionMessage:null},changed:!0})}function Nf(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Wf(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 c=we(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let c=we(i,0,o);return c===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}if(t>0&&i>o){let c=a[l+1]??null;return c?h({state:{...e,selectedDiffPath:c,activeTab:E,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 c=a[l-1]??null;return c?h({state:{...e,selectedDiffPath:c,activeTab:E,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 d=we(i,0,o);return d===e.diffScrollOffset?h({state:e}):h({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}function Wf(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=we(e.diffScrollOffset+t,0,o),a=_f(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 _f(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function vr(e,t,r,n){let s=r.indexOf(e[t]),o=we(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 Ds(e,t,r,n,s=!1){if(r.length===0)return h({state:e});let o=r.indexOf(e[t]??r[0]??""),i=we(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 Uf(e,t,r){let n=t.indexOf(e);return t[we(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 hl(e,t){return t.includes(e)}function Bf(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":st(e.activeTab)??e.preferredPtyTabKind}function qf(e){return[e.selectedPtyTabId,e.openInspectionKind?E:null].filter(t=>typeof t=="string")}function we(e,t,r){return Math.min(r,Math.max(t,e))}var kl=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>{let o=await ee(n.paths,e.selectedTaskId),i=t??Vf(o,e.activeTab,e.preferredPtyTabKind),a=bl(o,i,r??void 0,n.config),l={...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id};return await S(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"}`}}},yl=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:r,nextSelectedTab:n}=await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.selectedTaskId),o=s.ptyTabs.findIndex(d=>d.id===e.activeTab);if(o===-1)throw new Error("Only PTY tabs can be closed.");let i=s.ptyTabs[o],a=s.ptyTabs.filter(d=>d.id!==i.id),l=a[Math.min(o,a.length-1)]??null;return await S(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}`}}},Tl=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{let n=await ee(t.paths,r);!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab||await S(t.paths,{...n,selectedPtyTabId:e.activeTab})})},Rl=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;o&&await S(t.paths,{...s,selectedPtyTabId:o.id})}),{...e,selectedPtyTabId:r.id};let n=bl(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.id),o=s.ptyTabs.find(i=>i.kind==="agent")??null;if(o){await S(t.paths,{...s,selectedPtyTabId:o.id});return}await S(t.paths,{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Vf(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function bl(e,t,r,n={}){let s=r??e.runner,o=f.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(k=>k.id)),d=1,c=a;for(;l.has(c);)d+=1,c=`${a}-${d}`;let u=new Date().toISOString(),p=r&&r!==e.runner?r:void 0;return{id:c,kind:t,...p?{runner:p}:{},title:d===1?i:`${i} ${d}`,command:t==="agent"?f.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var lt=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Pl=async(e,t,r,n,s)=>{f.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=je();await P(Fe(f.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l}),["--help"],{cwd:o.repoRoot,env:l})}catch(l){let d=l instanceof Error?l.message:"Failed to start runner.",c=await s.taskService.recordStartupFailure(s.paths,o.task.id,d);throw new lt(d,c)}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}},Sl=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Il=async(e,t)=>{if(!e.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:r,task:n}=await t.queueTaskMutation(async()=>{let s=await ee(t.paths,e.selectedTaskId),o=await t.taskService.closeTask(t.paths,e.selectedTaskId);return{taskBeforeClose:s,task:o}});return{closedTabIds:r.ptyTabs.map(s=>s.id),nextShell:{selectedActionId:"close-task",actionMessage:n.cleanup.preservedWorktree?`Archived task ${n.id}; worktree preserved`:`Archived task ${n.id}`}}},vl=async(e,t)=>{await t.taskService.prs.discoverOrRefreshMany(t.paths,e)},Cr=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await at.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var Cl=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 El=async(e,t,r)=>{let n=f.runners.setRunnerEnabled(r.config,e,t);return await f.save(r.paths,n),n},Al=async(e,t,r)=>{let n=f.runners.setRunnerPath(r.config,e,t);return await f.save(r.paths,n),n},xl=async(e,t,r)=>{let n=f.previews.setEnabled(r.config,e,t);return await f.save(r.paths,n),n};var Kf=250;function ke(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function qe(e,t){return he(t,e.ptyRuntime.getViewState(Lt(e,t)))}function Lt(e,t){let r=ke(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 qe(e,Wi(t,e.model))}function Dl(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 $l(e,t,r){return Dl(e,t,r?{tone:"success",message:r}:null)}function O(e,t,r){return Dl(e,t,{tone:"error",message:r})}function j(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return at.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function M(e,t){if(!e.uiStateFile)return;e.runtimeState=Di(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Te({uiStateFile:e.uiStateFile},r),()=>Te({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Hf(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function F(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:Q,queueTaskMutation:t=>Hf(e,t)}}function Ms(e,t){let r=ke(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?vs(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:_e(e.model),centerTabIds:Fi(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:ol(t,r,s),pageRows:Math.max(5,se(e.activeTerminal.width,e.activeTerminal.height).height-W.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function Ml(e,t){await Tl(t,F(e))}async function K(e){e.model=await Ie(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 Er(e,t){let r=++e.inspectionRefreshSequence,n=Vn(e.model.tasks,t),s=e.model.inspection,o=t.focusedRegion==="inspector"&&t.inspectionMode==="review"&&t.openInspectionKind!=="diff",i;if(n&&s?.taskId===n.id&&!o){let a={selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath},l=await hi(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await Ie(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},M(e,e.state.shell),e.render())}function Ll(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)&&Er(e,r).catch(n=>{let s=j(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Kf))}function Ol(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=Ee(e.state.shell,r,Ms(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),Er(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render()}},16)))}function Ls(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Os(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 Fl(e){Os(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:g(e,e.state.shell)},e.render())})}async function Nl(e,t){let r=g(e,t),n=ke(e.model.tasks,r),s=Lt(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 he(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,ve(se(e.activeTerminal.width,e.activeTerminal.height)));return he({...r,inputMode:"control"},i)}function Wl(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 js(e,t){try{let r=g(e,t),n=ke(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 jl(e,n),await K(e),s=n.selectedPtyTabId)}n&&!s&&(n=await jl(e,n),await K(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:he({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},M(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,ve(se(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ce(s),e.lastTerminalKey=null,e.state={mode:"main",shell:he({...o,inputMode:"terminal"},i)},M(e,e.state.shell)}catch(r){let n=j(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Ce(t.selectedPtyTabId)&&(await Gf(e,t.selectedTaskId,n).catch(()=>{}),await K(e).catch(()=>{})),e.state={mode:"main",shell:O(e,$i(g(e,t),n),n)},M(e,e.state.shell)}e.render()}async function Gf(e,t,r){await Sl(t,r,F(e))}async function _l(e,t,r,n){let s=g(e,t),{nextShell:o}=await kl(s,r,n,F(e));return await K(e),g(e,{...s,...o})}async function Ul(e,t){let r=g(e,t),{closedTab:n,nextShell:s}=await yl(r,F(e));return e.ptyRuntime.disposeSession(n.id),await K(e),g(e,{...r,...s})}async function Bl(e,t){let r=g(e,t),n=_e(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Il(r,F(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await K(e),g(e,{...r,...i,selectedLeftItemId:zf(n,_e(e.model),s)})}async function ql(e,t){let r=g(e,t),{nextShell:n}=await Cl(r,F(e));return await K(e),g(e,{...r,...n})}async function jl(e,t){return Rl(t,F(e))}function Ar(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:qe(e,e.state.shell)},e.render())},16))}function zf(e,t,r){if(t.length===0)return null;for(let n=r-1;n>=0;n-=1){let s=e[n];if(s&&t.includes(s))return s}return t[Math.min(Math.max(0,r),t.length-1)]??null}async function Vl(e,t){if(!(t?.aborted||e.state.mode!=="main"))try{if(await vl(e.model.tasks,F(e)),t?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;let r=await Ie(e.workspaceRoot,e.state.shell,e.enabledRunnerIds);if(t?.aborted)return;e.model=r,e.state={mode:"main",shell:g(e,e.state.shell)},e.render()}catch(r){if(t?.aborted)return;let n=r instanceof Error?r.message:"Background PR discovery failed.";n!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=n,Cr("background PR polling",r,F(e)))}}async function Kl(e,t){let r=g(e,t),n=ke(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await C.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await K(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await C.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await K(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${D(a)?.requiredChecks.length??0} reported`)}return g(e,{...$l(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}import Zf from"node:path";import{readdir as Yf,stat as Qf}from"node:fs/promises";import Hl from"node:path";async function Jf(e){let t=await Yf(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Hl.join(e,n.name);r.push({name:n.name,path:s,kind:await Xf(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 Gl(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function zl(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 xr(e,t){let r=await Jf(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 Xf(e){let t=Hl.join(e,".git");return await Qf(t).catch(()=>null)!==null}function Yl(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Ql(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function eg(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 Pl(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,F(e));n=s.task,await K(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??na(n,"agent"),ve(se(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Ce(o.selectedPtyTabId),e.state={mode:"main",shell:he(o,i)},M(e,e.state.shell)}catch(s){s instanceof lt&&(n=s.task);let o=j(e,"create task",s,"Failed to create task.");n&&!(s instanceof lt)?(await S(e.paths,{...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o}).catch(()=>{}),await K(e).catch(()=>{})):n&&(await S(e.paths,{...n,lastFailureReason:o}).catch(()=>{}),await K(e).catch(()=>{})),e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,inputMode:"control",selectedTaskId:n?.id??e.state.shell.selectedTaskId,selectedPtyTabId:n?.selectedPtyTabId??e.state.shell.selectedPtyTabId,selectedLeftItemId:n?`task:${n.id}`:e.state.shell.selectedLeftItemId,activeTab:n?.selectedPtyTabId??e.state.shell.activeTab,taskPromptInput:n?null:"",taskPromptError:o,actionMessage:null}),o)}}finally{e.creatingTask=!1,e.render()}}function tg(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)){eg(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:ar(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}Li(t)&&(e.state={mode:"main",shell:g(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function rg(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=Gl(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"){xr(e,Zf.dirname(r.cwd)).catch(s=>{let o=j(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ie(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){xr(e,s.path).catch(i=>{let a=j(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=F(e);o.addWorkspace(e.paths,s.path).then(async i=>{await K(e);let a=i.repos[0]??null,l=g(e,{...e.state.shell,workspaceBrowser:null,selectedLeftItemId:`workspace:${i.workspace.id}`,selectedWorkspaceId:i.workspace.id,selectedRepoId:a?.id??null,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${i.workspace.name??i.workspace.id}`});e.state={mode:"main",shell:l},M(e,e.state.shell),e.render()}).catch(i=>{let a=j(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function ng(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Fa(e.state.menuIndex,t);if(r.kind!=="noop"){if(r.kind==="render"){e.state={...e.state,menuIndex:r.menuIndex},e.render();return}if(r.kind==="back"){e.state.parentVariant&&(e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render());return}if(r.kind==="help"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell,viaOptions:!0,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="runners"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="previews"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"previews",menuIndex:0,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="error-log"){let n=e.state.parentVariant;sg(e,n)}}}async function sg(e,t){let r;try{r=await at.readRecentErrorLines(e.paths)}catch(n){let s=j(e,"open error log",n,"Failed to read Craig error log.");r={path:e.paths.errorLogFile,lines:[`Unable to read error log: ${s}`],empty:!1}}e.state.mode==="overlay"&&(e.state={mode:"overlay",variant:"error-log",menuIndex:0,optionsMessage:null,shell:e.state.shell,errorLog:r,...t!==void 0?{parentVariant:t}:{}},e.pendingClear=!0,e.render())}function og(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Wa(Yl(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"?El(r.runner,r.enabled,F(e)):Al(r.runner,r.path,F(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=f.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:f.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=j(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:O(e,g(e,e.state.shell),o),runnerOptions:{...Yl(e),message:o}},e.render()})}function ig(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=Na(Ql(e),e.config,t);if(r.kind!=="noop"){if(r.kind==="back"){let n=e.state.parentVariant;e.state={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:e.state.shell,...n!==void 0?{parentVariant:n}:{}},e.pendingClear=!0,e.render();return}if(r.kind==="render"){e.state={...e.state,previewOptions:r.state},e.render();return}xl(r.feature,r.enabled,F(e)).then(n=>{e.state.mode!=="overlay"||e.state.variant!=="previews"||(e.config=n,r.feature==="incrementalCenterPane"&&e.ptyRuntime.setViewUpdateMode?.(r.enabled?"incremental":"snapshot"),r.feature==="agentActivityIndicators"&&e.setAgentActivityEnabled(r.enabled),e.state={...e.state,previewOptions:r.state},e.render())}).catch(n=>{if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let s=j(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:O(e,g(e,e.state.shell),s),previewOptions:{...Ql(e),message:s}},e.render()})}}function Jl(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){tg(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){rg(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){lg(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=$s(e.state.shell,r,Ms(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ie(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=Dt(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(ag(e,r))return;e.lastTerminalKey=sa(r)?{key:r,at:Date.now()}:null;let o=oa(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){Ar(e,o);return}e.ptyRuntime.writeKey(r);return}if(r==="CTRL_C"){e.exit(0);return}if(r==="?"&&e.state.shell.inputMode==="control"){e.state={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:e.state.shell},e.pendingClear=!0,e.render();return}if(n.pause){e.state={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:g(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){xr(e,e.workspaceRoot).catch(s=>{let o=j(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:O(e,g(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){_l(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{js(e,s)}).catch(s=>{let o=j(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Ul(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Kl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=ke(e.model.tasks,n.state),o=s?D(s)?.url??null:null;o?zl(o).catch(i=>{let a=j(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:O(e,g(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:O(e,g(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){Bl(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){ql(e,n.state).then(s=>{e.state={mode:"main",shell:s},M(e,e.state.shell),e.render()}).catch(s=>{let o=j(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:O(e,g(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){js(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:g(e,n.state)},M(e,e.state.shell),e.render(),e.state.shell.focusedRegion==="tasks"){Ll(e,e.state.shell);return}Er(e,e.state.shell).catch(s=>{let o=j(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:O(e,g(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:g(e,n.state)},Ml(e,e.state.shell).catch(()=>{}),M(e,e.state.shell),e.render());return}if(e.state.variant==="help"){e.state.viaOptions&&e.state.parentVariant?e.state={mode:"overlay",variant:"options",menuIndex:3,optionsMessage:null,shell:e.state.shell,parentVariant:e.state.parentVariant}:e.state.parentVariant?e.state={mode:"overlay",variant:e.state.parentVariant,menuIndex:1,optionsMessage:null,shell:e.state.shell}:e.state={mode:"main",shell:g(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){ng(e,r);return}if(e.state.variant==="runners"){og(e,r);return}if(e.state.variant==="previews"){ig(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:2,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;Nl(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},M(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=j(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:O(e,g(e,e.state.shell),i)},M(e,e.state.shell),e.render()})}):Fl(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 Xl(e,t){let r=da(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=Dt(o);if(i){ec(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(rs(o)){e.pendingTerminalKeySequence.raw=o,Zl(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"})},M(e,e.state.shell),e.render();return}let n=ia(r);if(n!==0){Ar(e,n);return}let s=Dt(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
164
164
|
`&&r!==`\r
|
|
165
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),la(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function ag(e,t){if(e.pendingTerminalKeySequence){let r=ia(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=Dt(n);if(s)return Zl(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(rs(n))return e.pendingTerminalKeySequence.raw=n,Xl(e),!0}return Dr(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>Dr(e),30)},!0)}function Xl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>Dr(e),30))}function Dr(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function Zl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function ec(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){Ll(e,ts(t));return}let r=ts(t);r!==0&&Ar(e,r)}function lg(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var $r=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=Fs(t.resolutionMs??1e3,"Heartbeat resolution"),this.now=t.now??Date.now,this.onError=t.onError}register(t){if(this.jobs.has(t.id))throw new Error(`Heartbeat job "${t.id}" is already registered.`);let r={...t,intervalMs:Fs(t.intervalMs,`Heartbeat job "${t.id}" interval`),inFlight:!1,nextRunAt:this.timer?this.now()+t.intervalMs:null};this.jobs.set(t.id,r)}start(){if(this.timer)return;let t=this.now();for(let r of this.jobs.values())r.nextRunAt=t+r.intervalMs;this.abortController=new AbortController,this.timer=setInterval(()=>this.tick(),this.resolutionMs)}stop(){this.abortController?.abort(),this.abortController=null,this.timer&&(clearInterval(this.timer),this.timer=null);for(let t of this.jobs.values())t.nextRunAt=null}setResolutionMs(t){let r=Fs(t,"Heartbeat resolution");r!==this.resolutionMs&&(this.resolutionMs=r,this.timer&&(clearInterval(this.timer),this.timer=setInterval(()=>this.tick(),this.resolutionMs)))}tick(){let t=this.abortController?.signal;if(!t)return;let r=this.now();for(let n of this.jobs.values())n.inFlight||n.nextRunAt===null||r<n.nextRunAt||(n.inFlight=!0,n.nextRunAt=r+n.intervalMs,Promise.resolve().then(()=>n.run(t)).catch(s=>{if(!t.aborted)return Promise.resolve(this.onError(n.id,s)).catch(()=>{})}).finally(()=>{n.inFlight=!1}))}};function Fs(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var tc=1e3,rc=250,ug=dg(import.meta.url),pg=ug("terminal-kit"),mg=pg.terminal;function Ns(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function nc(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function fg(e,t){return e?e.tabId!==t.tabId?{tabId:t.tabId,kind:"full"}:e.kind==="full"||t.kind==="full"?{tabId:t.tabId,kind:"full"}:{tabId:t.tabId,kind:"rows",rowIndices:[...new Set([...e.rowIndices,...t.rowIndices])]}:t}async function sc(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=de(t),n=await f.load(r),s=f.runners.getEnabled(n),o=e.uiStateFile?await He({uiStateFile:e.uiStateFile}):null,i=await Ie(t,void 0,s),a=Ct(Ai(o,n),i);i=await Ie(t,a,s);let l={current:i},d=()=>{},c=()=>{},u=()=>{},p={workspaceRoot:t,onUpdate:y=>d(y),onActivity:y=>c(y),onActivityRemoved:y=>u(y),resolveSessionSpec:(y,w)=>ta(l.current,w,t)},k=e.ptyRuntime??await ba({...p,paths:r,viewUpdateMode:f.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:f.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(y=>{let w=e.terminal??mg,b=null,q=null,te=null,me=null,I=0,re=!1,Ve=new Map,m,Ae=new $r({resolutionMs:f.previews.isEnabled(n,"agentActivityIndicators")?rc:tc,onError:(T,V)=>Cr(`heartbeat job "${T}"`,V,F(m))});m={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Ct(a,i)},get model(){return l.current},set model(T){l.current=T},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,lastBackgroundPrPollError:null,versionText:`Craig v${f.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:w,ptyRuntime:k,resolve:y,render:()=>{},exit:T=>y(T),setAgentActivityEnabled:T=>{Ae.setResolutionMs(T?rc:tc),m.ptyRuntime.setActivityEnabled?.(T)}},m.setAgentActivityEnabled(f.previews.isEnabled(n,"agentActivityIndicators")),d=T=>{m.state.mode==="main"&&(me=fg(me,T),m.ptyRenderTimer||(m.ptyRenderTimer=setTimeout(()=>{m.ptyRenderTimer=null;let V=me;if(me=null,m.state.mode==="main"){let ye=qe(m,m.state.shell);if(m.state={mode:"main",shell:ye},!f.previews.isEnabled(m.config,"incrementalCenterPane")||!te||!q){m.render();return}let Nt=se(w.width,w.height),ct={...te,terminal:ye.terminal},xe=ll(Nt,ct,q,ye.centerZoomed,V?.kind==="rows"?V.rowIndices:null);if(!xe){m.render();return}xe.output.length>0&&w.noFormat(xe.output),te=ct,q=xe.region,w.hideCursor(!0)}},f.previews.isEnabled(m.config,"incrementalCenterPane")?0:50)))},c=T=>{m.state.mode==="main"&&f.previews.isEnabled(m.config,"agentActivityIndicators")&&Ce(T.tabId)&&Ve.get(T.tabId)!==$t(T.tabId,[T],Date.now())&&m.render()},u=T=>{m.state.mode==="main"&&f.previews.isEnabled(m.config,"agentActivityIndicators")&&Ce(T)&&Ve.get(T)!=="idle"&&m.render()},m.render=()=>{Nl(m);let T=m.state;m.ptyRuntime.setViewedTab?.(T.mode==="main"?Lt(m,T.shell):null);let V=se(w.width,w.height),ye;if(T.mode==="main"){let Ft=f.previews.isEnabled(m.config,"agentActivityIndicators"),Nt=Ft?m.ptyRuntime.getActivitySnapshots?.()??[]:[],ct=Date.now(),xe=Ja(g(m,T.shell),m.model,Ft?{snapshots:Nt,now:ct,animationFrame:I}:void 0);if(Ve.clear(),Ft)for(let ic of m.model.tasks)for(let Mr of ic.ptyTabs)Mr.kind==="agent"&&Ve.set(Mr.id,$t(Mr.id,Nt,ct));let Bs=Ki(V,xe,{centerOnly:T.shell.centerZoomed,focusFlashActive:m.focusFlashUntil!==null&&Date.now()<m.focusFlashUntil});ye=Bs.frame,te=xe,q=Bs.center}else ye=T.variant==="boot"?Ui(V,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="pause"?Bi(V,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="options"?wr(V,{menuIndex:T.menuIndex,optionsMenuItems:ps}):T.variant==="runners"?wr(V,{menuIndex:Ns(T).menuIndex,optionsMenuItems:ms(m.config,Ns(T)),optionsMessage:Ma(Ns(T)),optionsSubtitle:"Runners"}):T.variant==="previews"?wr(V,{menuIndex:nc(T).menuIndex,optionsMenuItems:La(m.config),optionsMessage:Oa(nc(T)),optionsSubtitle:"Feature Previews - Experimental"}):T.variant==="error-log"?Vi(V,{errorLogPath:T.errorLog?.path??r.errorLogFile,errorLogLines:T.errorLog?.lines??[]}):qi(V),te=null,q=null;m.pendingClear&&(w.moveTo(1,1),w.eraseDisplayBelow(),m.pendingClear=!1,b=null),w.noFormat(da(ye,b)),b=ye,w.hideCursor(!0)};let Ot=T=>Ql(m,T),jt=T=>Jl(m,T),Ws=T=>ec(m,T),oc=()=>{process.stdout.off("resize",_s),process.off("SIGCONT",Us),w.removeListener("key",Ot),w.removeListener("unknown",jt),w.removeListener("mouse",Ws),m.scrollRenderTimer&&(clearTimeout(m.scrollRenderTimer),m.scrollRenderTimer=null),m.inspectionScrollRenderTimer&&(clearTimeout(m.inspectionScrollRenderTimer),m.inspectionScrollRenderTimer=null),m.leftNavInspectionTimer&&(clearTimeout(m.leftNavInspectionTimer),m.leftNavInspectionTimer=null),m.pendingTerminalKeySequence&&(clearTimeout(m.pendingTerminalKeySequence.timer),m.pendingTerminalKeySequence=null),m.ptyRenderTimer&&(clearTimeout(m.ptyRenderTimer),m.ptyRenderTimer=null),m.footerToastTimer&&(clearTimeout(m.footerToastTimer),m.footerToastTimer=null),m.focusFlashTimer&&(clearTimeout(m.focusFlashTimer),m.focusFlashTimer=null),Ae.stop(),m.ptyRuntime.disposeAll(),w.grabInput(!1),w.hideCursor(!1),w.fullscreen(!1)};m.exit=T=>{oc(),y(T)};let _s=()=>{Ls(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(ve(se(w.width,w.height))),m.state={mode:"main",shell:qe(m,m.state.shell)}),m.render()},Us=()=>{Ls(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(ve(se(w.width,w.height))),m.state={mode:"main",shell:qe(m,m.state.shell)}),m.render()};process.stdout.on("resize",_s),process.on("SIGCONT",Us),w.grabInput(!0),m.inputCaptureMode="control",w.hideCursor(!0),w.fullscreen(!0),w.on("key",Ot),w.on("unknown",jt),w.on("mouse",Ws),Ae.register({id:"github.pull-requests",intervalMs:(m.config.github?.watchIntervalSeconds??5)*1e3,run:T=>ql(m,T)}),Ae.register({id:"agent.activity-indicators",intervalMs:500,run:()=>{if(!f.previews.isEnabled(m.config,"agentActivityIndicators")){I=0,re=!1;return}let T=Date.now(),V=Ga(m.model.tasks,m.ptyRuntime.getActivitySnapshots?.()??[],T);(V||re)&&(I=(I+1)%4,m.state.mode==="main"&&m.render()),re=V}}),Ae.start(),f.version.checkForUpdate().then(T=>{T.updateAvailable&&T.latest&&(m.updateText=`Update available: v${T.latest}`,m.render())}),m.bootHydrationReady=Os(m).catch(()=>{}),m.render()})}async function gg(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=de(i);return await Pa(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=de(i);return await Sa(a),0}let e=ro(process.argv.slice(2)),t=process.cwd(),r=de(t),n={paths:r};if(e.mode==="interactive")return await sc({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await pi(e.command,n),o=mi(s);return o.length>0&&process.stdout.write(`${o}
|
|
165
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),ca(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function ag(e,t){if(e.pendingTerminalKeySequence){let r=aa(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=Dt(n);if(s)return ec(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(rs(n))return e.pendingTerminalKeySequence.raw=n,Zl(e),!0}return Dr(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>Dr(e),30)},!0)}function Zl(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>Dr(e),30))}function Dr(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function ec(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function tc(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){Ol(e,ts(t));return}let r=ts(t);r!==0&&Ar(e,r)}function lg(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var $r=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=Fs(t.resolutionMs??1e3,"Heartbeat resolution"),this.now=t.now??Date.now,this.onError=t.onError}register(t){if(this.jobs.has(t.id))throw new Error(`Heartbeat job "${t.id}" is already registered.`);let r={...t,intervalMs:Fs(t.intervalMs,`Heartbeat job "${t.id}" interval`),inFlight:!1,nextRunAt:this.timer?this.now()+t.intervalMs:null};this.jobs.set(t.id,r)}start(){if(this.timer)return;let t=this.now();for(let r of this.jobs.values())r.nextRunAt=t+r.intervalMs;this.abortController=new AbortController,this.timer=setInterval(()=>this.tick(),this.resolutionMs)}stop(){this.abortController?.abort(),this.abortController=null,this.timer&&(clearInterval(this.timer),this.timer=null);for(let t of this.jobs.values())t.nextRunAt=null}setResolutionMs(t){let r=Fs(t,"Heartbeat resolution");r!==this.resolutionMs&&(this.resolutionMs=r,this.timer&&(clearInterval(this.timer),this.timer=setInterval(()=>this.tick(),this.resolutionMs)))}tick(){let t=this.abortController?.signal;if(!t)return;let r=this.now();for(let n of this.jobs.values())n.inFlight||n.nextRunAt===null||r<n.nextRunAt||(n.inFlight=!0,n.nextRunAt=r+n.intervalMs,Promise.resolve().then(()=>n.run(t)).catch(s=>{if(!t.aborted)return Promise.resolve(this.onError(n.id,s)).catch(()=>{})}).finally(()=>{n.inFlight=!1}))}};function Fs(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var rc=1e3,ug=dg(import.meta.url),pg=ug("terminal-kit"),mg=pg.terminal;function Ws(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function nc(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function fg(e,t){return e?e.tabId!==t.tabId?{tabId:t.tabId,kind:"full"}:e.kind==="full"||t.kind==="full"?{tabId:t.tabId,kind:"full"}:{tabId:t.tabId,kind:"rows",rowIndices:[...new Set([...e.rowIndices,...t.rowIndices])]}:t}async function sc(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=de(t),n=await f.load(r),s=f.runners.getEnabled(n),o=e.uiStateFile?await He({uiStateFile:e.uiStateFile}):null,i=await Ie(t,void 0,s),a=Ct(xi(o,n),i);i=await Ie(t,a,s);let l={current:i},d=()=>{},c=()=>{},u=()=>{},p={workspaceRoot:t,onUpdate:y=>d(y),onActivity:y=>c(y),onActivityRemoved:y=>u(y),resolveSessionSpec:(y,w)=>ra(l.current,w,t)},k=e.ptyRuntime??await Pa({...p,paths:r,viewUpdateMode:f.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:f.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(y=>{let w=e.terminal??mg,b=null,q=null,te=null,me=null,I=0,re=!1,Ve=new Map,m,Ae=new $r({resolutionMs:f.previews.isEnabled(n,"agentActivityIndicators")?150:rc,onError:(T,V)=>Cr(`heartbeat job "${T}"`,V,F(m))});m={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Ct(a,i)},get model(){return l.current},set model(T){l.current=T},config:n,enabledRunnerIds:s,creatingTask:!1,suppressTerminalEnterOnAttach:!1,lastTerminalKey:null,pendingScrollLines:0,pendingInspectionScrollLines:0,leftNavInspectionTimer:null,pendingLeftNavInspectionShell:null,pendingTerminalKeySequence:null,scrollRenderTimer:null,inspectionScrollRenderTimer:null,ptyRenderTimer:null,footerToastTimer:null,focusFlashUntil:null,focusFlashTimer:null,lastBackgroundPrPollError:null,versionText:`Craig v${f.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:w,ptyRuntime:k,resolve:y,render:()=>{},exit:T=>y(T),setAgentActivityEnabled:T=>{Ae.setResolutionMs(T?150:rc),m.ptyRuntime.setActivityEnabled?.(T)}},m.setAgentActivityEnabled(f.previews.isEnabled(n,"agentActivityIndicators")),d=T=>{m.state.mode==="main"&&(me=fg(me,T),m.ptyRenderTimer||(m.ptyRenderTimer=setTimeout(()=>{m.ptyRenderTimer=null;let V=me;if(me=null,m.state.mode==="main"){let ye=qe(m,m.state.shell);if(m.state={mode:"main",shell:ye},!f.previews.isEnabled(m.config,"incrementalCenterPane")||!te||!q){m.render();return}let Nt=se(w.width,w.height),ct={...te,terminal:ye.terminal},xe=cl(Nt,ct,q,ye.centerZoomed,V?.kind==="rows"?V.rowIndices:null);if(!xe){m.render();return}xe.output.length>0&&w.noFormat(xe.output),te=ct,q=xe.region,w.hideCursor(!0)}},f.previews.isEnabled(m.config,"incrementalCenterPane")?0:50)))},c=T=>{m.state.mode==="main"&&f.previews.isEnabled(m.config,"agentActivityIndicators")&&Ce(T.tabId)&&Ve.get(T.tabId)!==$t(T.tabId,[T],Date.now())&&m.render()},u=T=>{m.state.mode==="main"&&f.previews.isEnabled(m.config,"agentActivityIndicators")&&Ce(T)&&Ve.get(T)!=="idle"&&m.render()},m.render=()=>{Wl(m);let T=m.state;m.ptyRuntime.setViewedTab?.(T.mode==="main"?Lt(m,T.shell):null);let V=se(w.width,w.height),ye;if(T.mode==="main"){let Ft=f.previews.isEnabled(m.config,"agentActivityIndicators"),Nt=Ft?m.ptyRuntime.getActivitySnapshots?.()??[]:[],ct=Date.now(),xe=Xa(g(m,T.shell),m.model,Ft?{snapshots:Nt,now:ct,animationFrame:I}:void 0);if(Ve.clear(),Ft)for(let ic of m.model.tasks)for(let Mr of ic.ptyTabs)Mr.kind==="agent"&&Ve.set(Mr.id,$t(Mr.id,Nt,ct));let qs=Hi(V,xe,{centerOnly:T.shell.centerZoomed,focusFlashActive:m.focusFlashUntil!==null&&Date.now()<m.focusFlashUntil});ye=qs.frame,te=xe,q=qs.center}else ye=T.variant==="boot"?Bi(V,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="pause"?qi(V,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="options"?wr(V,{menuIndex:T.menuIndex,optionsMenuItems:ps}):T.variant==="runners"?wr(V,{menuIndex:Ws(T).menuIndex,optionsMenuItems:ms(m.config,Ws(T)),optionsMessage:La(Ws(T)),optionsSubtitle:"Runners"}):T.variant==="previews"?wr(V,{menuIndex:nc(T).menuIndex,optionsMenuItems:Oa(m.config),optionsMessage:ja(nc(T)),optionsSubtitle:"Feature Previews - Experimental"}):T.variant==="error-log"?Ki(V,{errorLogPath:T.errorLog?.path??r.errorLogFile,errorLogLines:T.errorLog?.lines??[]}):Vi(V),te=null,q=null;m.pendingClear&&(w.moveTo(1,1),w.eraseDisplayBelow(),m.pendingClear=!1,b=null),w.noFormat(ua(ye,b)),b=ye,w.hideCursor(!0)};let Ot=T=>Jl(m,T),jt=T=>Xl(m,T),_s=T=>tc(m,T),oc=()=>{process.stdout.off("resize",Us),process.off("SIGCONT",Bs),w.removeListener("key",Ot),w.removeListener("unknown",jt),w.removeListener("mouse",_s),m.scrollRenderTimer&&(clearTimeout(m.scrollRenderTimer),m.scrollRenderTimer=null),m.inspectionScrollRenderTimer&&(clearTimeout(m.inspectionScrollRenderTimer),m.inspectionScrollRenderTimer=null),m.leftNavInspectionTimer&&(clearTimeout(m.leftNavInspectionTimer),m.leftNavInspectionTimer=null),m.pendingTerminalKeySequence&&(clearTimeout(m.pendingTerminalKeySequence.timer),m.pendingTerminalKeySequence=null),m.ptyRenderTimer&&(clearTimeout(m.ptyRenderTimer),m.ptyRenderTimer=null),m.footerToastTimer&&(clearTimeout(m.footerToastTimer),m.footerToastTimer=null),m.focusFlashTimer&&(clearTimeout(m.focusFlashTimer),m.focusFlashTimer=null),Ae.stop(),m.ptyRuntime.disposeAll(),w.grabInput(!1),w.hideCursor(!1),w.fullscreen(!1)};m.exit=T=>{oc(),y(T)};let Us=()=>{Ls(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(ve(se(w.width,w.height))),m.state={mode:"main",shell:qe(m,m.state.shell)}),m.render()},Bs=()=>{Ls(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(ve(se(w.width,w.height))),m.state={mode:"main",shell:qe(m,m.state.shell)}),m.render()};process.stdout.on("resize",Us),process.on("SIGCONT",Bs),w.grabInput(!0),m.inputCaptureMode="control",w.hideCursor(!0),w.fullscreen(!0),w.on("key",Ot),w.on("unknown",jt),w.on("mouse",_s),Ae.register({id:"github.pull-requests",intervalMs:(m.config.github?.watchIntervalSeconds??5)*1e3,run:T=>Vl(m,T)}),Ae.register({id:"agent.activity-indicators",intervalMs:150,run:()=>{if(!f.previews.isEnabled(m.config,"agentActivityIndicators")){I=0,re=!1;return}let T=Date.now(),V=za(m.model.tasks,m.ptyRuntime.getActivitySnapshots?.()??[],T);(V||re)&&(I=(I+1)%6,m.state.mode==="main"&&m.render()),re=V}}),Ae.start(),f.version.checkForUpdate().then(T=>{T.updateAvailable&&T.latest&&(m.updateText=`Update available: v${T.latest}`,m.render())}),m.bootHydrationReady=Os(m).catch(()=>{}),m.render()})}async function gg(){try{if(process.argv[2]==="__craig-daemon"){let i=process.argv[3]??process.cwd(),a=de(i);return await Sa(a),0}if(process.argv[2]==="__craig-daemon-shutdown"){let i=process.argv[3]??process.cwd(),a=de(i);return await Ia(a),0}let e=no(process.argv.slice(2)),t=process.cwd(),r=de(t),n={paths:r};if(e.mode==="interactive")return await sc({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let s=await mi(e.command,n),o=fi(s);return o.length>0&&process.stdout.write(`${o}
|
|
166
166
|
`),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
167
167
|
`),1}}var hg=await gg();process.exit(hg);
|