craig-cli 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +51 -47
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await
|
|
4
|
-
`)};var
|
|
5
|
-
`).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(
|
|
2
|
+
var Wd=Object.defineProperty;var cr=(e,t)=>{for(var r in t)Wd(e,r,{get:t[r],enumerable:!0})};import Z from"node:path";function ee(e){let t=Z.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:Z.join(t,"index.json"),reposDir:Z.join(t,"repos"),workspacesDir:Z.join(t,"workspaces"),sessionsDir:Z.join(t,"sessions"),runtimeDir:Z.join(t,"runtime"),uiStateFile:Z.join(t,"runtime","ui-state.json"),tasksDir:Z.join(t,"tasks"),jobsDir:Z.join(t,"jobs"),logsDir:Z.join(t,"logs"),errorLogFile:Z.join(t,"logs","errors.log"),artifactsDir:Z.join(t,"artifacts"),worktreesDir:Z.join(t,"worktrees"),configFile:Z.join(t,"config.json")}}import{readFile as Kd}from"node:fs/promises";import{randomUUID as qd}from"node:crypto";import{open as Ud,readFile as Xk,rename as Bd,rm as Vd}from"node:fs/promises";import bn from"node:path";async function U(e,t){let r=bn.dirname(e),n=bn.join(r,`.${bn.basename(e)}.${process.pid}.${Date.now()}.${qd()}.tmp`),s=await Ud(n,"w");try{let o=`${JSON.stringify(t,null,2)}
|
|
3
|
+
`;await s.writeFile(o,"utf8"),await s.sync(),await s.close(),await Bd(n,e)}catch(o){throw await s.close().catch(()=>{}),await Vd(n,{force:!0}).catch(()=>{}),o}}async function at(e){try{let t=await Kd(e.uiStateFile,"utf8"),r=JSON.parse(t);return Gd(r,e.uiStateFile)}catch(t){if(zd(t))return null;throw t}}async function Ee(e,t){await U(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function ur(){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 Gd(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")||!it(e,"inputMode")||!it(e,"focusedRegion")||!it(e,"activeTab")||!it(e,"inspectorSection")||!it(e,"inspectionMode")||!dr(e,"openInspectionKind")||!dr(e,"selectedFileTreePath")||!dr(e,"selectedFilePath")||!dr(e,"selectedDiffPath")||!Hd(e,"collapsedFileTreePaths")||!it(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 it(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function dr(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Hd(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function zd(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var Pn={};cr(Pn,{RUNNER_IDS:()=>M,assertEnabled:()=>ei,buildCommand:()=>ni,getConfiguredProfile:()=>pr,getDefault:()=>Zo,getDisplayName:()=>ri,getEnabled:()=>mr,getProfile:()=>lt,isRunnerType:()=>fr,parse:()=>ti,setRunnerEnabled:()=>si,setRunnerPath:()=>oi});var M=["codex","cursor","claude"];var Xo={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 lt=e=>Xo[e];var pr=(e,t={})=>{let r=lt(e),n=t.runners?.[e]?.path?.trim();return{...r,executable:n&&n.length>0?n:r.executable}};var mr=(e={})=>M.filter(t=>e.runners?.[t]?.enabled!==!1);var Zo=(e={})=>{let t=mr(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 ei=(e,t={})=>{if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var fr=e=>M.includes(e);var ti=e=>{if(!e||e.length===0)return"codex";if(!fr(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${M.join(", ")}.`);return e};var ri=e=>lt(e).displayName;var ni=(e,t,r={})=>{let n=[pr(e,r).executable];return t&&t.length>0&&n.push(t),n};var si=(e,t,r)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}});var oi=(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 Sn={};cr(Sn,{PREVIEW_FEATURE_IDS:()=>de,isEnabled:()=>ii,setEnabled:()=>ai});var de=["incrementalCenterPane","agentActivityIndicators"];function ii(e,t){return e.previews?.[t]===!0}function ai(e,t,r){return{...e,previews:{...e.previews,[t]:r}}}import{mkdir as Yd,readFile as Jd,writeFile as Qd}from"node:fs/promises";import Xd from"node:path";var Zd=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",li=async e=>{try{return await Jd(e,"utf8")}catch(t){if(Zd(t))return null;throw t}},ci=async(e,t)=>{await Yd(Xd.dirname(e),{recursive:!0}),await Qd(e,t,"utf8")};var gr=(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(!M.includes(n))throw new Error(`Craig config at ${t} is invalid. "runners.${n}" is not supported. Expected one of: ${M.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(!de.includes(n))throw new Error(`Craig config at ${t} is invalid. "previews.${n}" is not supported. Expected one of: ${de.join(", ")}.`);if(typeof s!="boolean")throw new Error(`Craig config at ${t} is invalid. "previews.${n}" must be a boolean.`)}}return r};var In=async(e,t={readConfigFile:li})=>{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 gr(n,e.configFile)};var vn=async(e,t,r={writeConfigFile:ci})=>{gr(t,e.configFile),await r.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)};var Cn={};cr(Cn,{checkForUpdate:()=>di,getCurrent:()=>hr});var hr=()=>{try{return"0.11.0"}catch{return"unknown"}};var eu="https://registry.npmjs.org/craig-cli/latest",tu=3600*1e3,ru={value:null},nu=(e,t)=>{let r=c=>c.split(".").map(Number),[n=0,s=0,o=0]=r(e),[i=0,a=0,l=0]=r(t);return n!==i?n>i:s!==a?s>a:o>l},di=async(e={fetch:globalThis.fetch,getCurrent:hr,cache:ru})=>{let t=e.getCurrent(),r=Date.now();if(e.cache.value&&r-e.cache.value.cachedAt<tu)return e.cache.value.result;let n=null;try{let o=await e.fetch(eu,{signal:AbortSignal.timeout(5e3)});o.ok&&(n=(await o.json()).version??null)}catch{}let s={current:t,latest:n,updateAvailable:n!==null&&n!==t&&nu(n,t)};return e.cache.value={result:s,cachedAt:r},s};var g={load:In,save:vn,previews:Sn,runners:Pn,version:Cn};var ui={CLI_USAGE:2,INPUT_REQUIRED:2,WORKSPACE_CONTEXT_NOT_FOUND:3,WORKSPACE_CONTEXT_INVALID:4,WORKSPACE_NOT_FOUND:3,WORKSPACE_RECORD_INVALID:2,TASK_CONTEXT_NOT_FOUND:3,TASK_CONTEXT_AMBIGUOUS:4,TASK_CONTEXT_CONFLICT:4,TASK_NOT_FOUND:3,TASK_RECORD_INVALID:2,REPO_NOT_FOUND:3,REPO_RECORD_INVALID:2,PR_REPOSITORY_MISMATCH:4,PR_BRANCH_MISMATCH:4,EXTERNAL_DEPENDENCY_FAILED:5,OPERATION_TIMEOUT:6,OPERATION_CANCELLED:6,PARTIAL_RESULT:7,INTERNAL_ERROR:1},y=class extends Error{code;exitCode;retryable;details;constructor(t,r,n){super(r,n.cause===void 0?void 0:{cause:n.cause}),this.name="CraigError",this.code=t,this.exitCode=ui[t],this.retryable=n.retryable??!1,this.details=n.details??{}}};function An(e){return e instanceof y?e:new y("INTERNAL_ERROR",e instanceof Error?e.message:"Unknown Craig error",{cause:e})}import{appendFile as su,mkdir as ou,readFile as iu}from"node:fs/promises";import au from"node:path";var pi=80,En=async(e,t)=>{await ou(au.dirname(e.errorLogFile),{recursive:!0}),await su(e.errorLogFile,lu(t),"utf8")},mi=async(e,t)=>{try{await En(e,t)}catch{}},xn=async(e,t=pi)=>{try{let n=(await iu(e.errorLogFile,"utf8")).trimEnd().split(`
|
|
5
|
+
`).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(cu(r))return{path:e.errorLogFile,lines:[],empty:!0};throw r}},fi=async(e,t=pi)=>xn(e,t);function lu(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(`
|
|
6
6
|
`).map(n=>` ${n}`))),`${r.join(`
|
|
7
7
|
`)}
|
|
8
8
|
|
|
9
|
-
`}function
|
|
10
|
-
`)}function
|
|
9
|
+
`}function cu(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var ct={appendErrorLog:En,appendErrorLogBestEffort:mi,readErrorLog:xn,readRecentErrorLines:fi};function Ti(e){let{commandTokens:t,options:r,help:n}=uu(e);if(n)return gi({kind:"help"},r);if(t.length===0)return{mode:"interactive",options:r};let[s,o,...i]=t,a;switch(`${s??""}:${o??""}`){case"context:show":kr(i,"context show"),a={kind:"showContext"};break;case"repo:add":a={kind:"addRepo",path:ki(i,"Repo path")};break;case"repo:list":kr(i,"repo list"),a={kind:"listRepos"};break;case"repo:remove":a={kind:"removeRepo",repoId:se(i,"Repo id")};break;case"workspace:add":a={kind:"addWorkspace",path:ki(i,"Workspace path")};break;case"workspace:list":a=pu(i);break;case"workspace:archive":a={kind:"archiveWorkspace",workspaceId:se(i,"Workspace id")};break;case"workspace:restore":a={kind:"restoreWorkspace",workspaceId:se(i,"Workspace id")};break;case"workspace:remove":a={kind:"removeWorkspace",workspaceId:se(i,"Workspace id")};break;case"task:new":a=fu(i);break;case"task:list":a=mu(i);break;case"task:current":kr(i,"task current"),a={kind:"currentTask"};break;case"task:show":a=i.length===0?{kind:"showCurrentTask"}:{kind:"showTask",taskId:se(i,"Task id")};break;case"task:pr":a=gu(i);break;case"task:wait":a=Tu(i);break;case"agent:list":kr(i,"agent list"),a={kind:"listAgents"};break;case"agent:status":a=wu(i);break;case"task:attach":a={kind:"attachTask",taskId:se(i,"Task id")};break;case"task:logs":a={kind:"streamTaskLogs",taskId:se(i,"Task id")};break;case"task:diff":a={kind:"showTaskDiff",taskId:se(i,"Task id")};break;case"task:focus":a={kind:"focusTask",taskId:se(i,"Task id")};break;case"task:open":a={kind:"openTask",taskId:se(i,"Task id")};break;case"task:check":a={kind:"runChecks",taskId:se(i,"Task id")};break;case"task:commit":a={kind:"commitTask",taskId:se(i,"Task id")};break;case"link:add":a={kind:"addTaskLink",taskId:wi(i,0,"Task id"),repoId:wi(i,1,"Repo id")},Ri(i,2,"link add");break;case"link:list":a={kind:"listTaskLinks",taskId:se(i,"Task id")};break;default:if(t.length===1&&(s==="help"||s==="--help"||s==="-h")){a={kind:"help"};break}throw A(`Unsupported command: ${t.join(" ")}`)}return gi(a,r)}function yi(e){let t=e[0]==="--"?e.slice(1):e,r=!0;for(let n of t){if(n==="--"){r=!1;continue}if(r&&n==="--json")return!0}return!1}function du(e){return{addWorkspace:"workspace.add",addRepo:"repo.add",listRepos:"repo.list",removeRepo:"repo.remove",listWorkspaces:"workspace.list",archiveWorkspace:"workspace.archive",restoreWorkspace:"workspace.restore",removeWorkspace:"workspace.remove",createTask:"task.new",listTasks:"task.list",currentTask:"task.current",showTask:"task.show",showCurrentTask:"task.show",showTaskPr:"task.pr.show",discoverTaskPr:"task.pr.discover",linkTaskPr:"task.pr.link",refreshTaskPr:"task.pr.refresh",unlinkTaskPr:"task.pr.unlink",listAgents:"agent.list",showAgentStatus:"agent.status",waitTask:"task.wait",attachTask:"task.attach",addTaskLink:"link.add",listTaskLinks:"link.list",refreshInteractiveState:"interactive.refresh",showSelectedTask:"task.show",streamTaskLogs:"task.logs",streamSelectedTaskLogs:"task.logs",showTaskDiff:"task.diff",showSelectedTaskDiff:"task.diff",focusTask:"task.focus",focusSelectedTask:"task.focus",openTask:"task.open",openSelectedTask:"task.open",runChecks:"task.check",runSelectedTaskChecks:"task.check",commitTask:"task.commit",commitSelectedTask:"task.commit",showContext:"context.show",help:"help",exit:"exit"}[e.kind]}function Dn(){return["Craig commands:"," craig [--workspace-root <path>] [--task <id>] [--json] [--no-input] <command>"," craig context show Show resolved workspace, task, and agent-tab context"," craig repo add <path> Register a repo in the current Craig workspace"," craig workspace add <path> Register a repo or parent-directory workspace"," craig repo list List registered repos"," craig repo remove <id> Remove a registered repo"," craig workspace list [--archived] List workspaces"," craig workspace archive <id> Archive a workspace"," craig workspace restore <id> Restore an archived workspace"," craig workspace remove <id> Remove an archived workspace"," craig task new --repo <repo-id> [--runner codex|cursor|claude] <prompt>"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude] <prompt>"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task current Show the task resolved from flags, environment, or cwd"," craig task show [<id>] Show task details; omit id to use resolved context"," craig task pr show [<id>] [--repo <repo-id>]"," craig task pr discover [<id>] [--repo <repo-id>]"," craig task pr link [<id>] --pr <url|number> [--repo <repo-id>]"," craig task pr refresh [<id>] [--repo <repo-id>]"," craig task pr unlink [<id>] --pr <url|number> [--repo <repo-id>]"," craig agent list [--task <task-id>] List agent-tab and task roll-up states"," craig agent status [--task <task-id>] [--tab <tab-id>] Show agent state details"," craig task wait [<id>] --state <states> [--tab <tab-id>] [--timeout <duration>]"," craig task logs <id> Stream Craig-managed logs for a task"," craig task diff <id> Show the current worktree diff for a task"," craig task attach <id> Attach to a live task session"," craig task focus <id> Focus the tmux pane for a task"," craig task open <id> Open the task worktree or print its path"," craig task check <id> Run configured checks for a task"," craig task commit <id> Commit all task worktree changes"," craig link add <task-id> <repo-id> Add a linked repo to a task"," craig link list <task-id> List linked repos for a task"].join(`
|
|
10
|
+
`)}function uu(e){let t=[...e];t[0]==="--"&&t.shift();let r=[],n={json:!1,noInput:!1},s=new Set,o=!1,i=!0;for(let a=0;a<t.length;a+=1){let l=t[a];if(l==="--"){i=!1,r.push(l);continue}if(!i||!hi(l)){r.push(l);continue}if(s.has(l))throw A(`Global option ${l} may only be provided once.`);if(s.add(l),l==="--json"){n.json=!0;continue}if(l==="--no-input"){n.noInput=!0;continue}if(l==="--help"||l==="-h"){o=!0;continue}let c=t[a+1];if(c===void 0||c==="--"||hi(c))throw A(`Global option ${l} requires a value.`);a+=1,l==="--workspace-root"?n.workspaceRoot=z(c,"Workspace root"):n.taskId=z(c,"Task id")}return{commandTokens:r,options:n,help:o}}function pu(e){if(e.length===0)return{kind:"listWorkspaces",archived:!1};if(e.length===1&&e[0]==="--archived")return{kind:"listWorkspaces",archived:!0};throw A(`Unsupported command: workspace list ${e.join(" ")}`)}function mu(e){if(e.length===0)return{kind:"listTasks"};if(e.length===2&&e[0]==="--repo")return{kind:"listTasks",repoId:z(e[1],"Repo id")};throw A(`Unsupported command: task list ${e.join(" ")}`)}function fu(e){let t,r,n,s=[],o=!0;for(let a=0;a<e.length;a+=1){let l=e[a];if(l==="--"){o=!1;continue}if(!o||!["--repo","--workspace","--runner"].includes(l)){if(o&&l.startsWith("--"))throw A(`Unsupported task new option: ${l}`);s.push(l);continue}let c=e[a+1];if(c===void 0||c==="--")throw A(`Task option ${l} requires a value.`);if(a+=1,l==="--repo"){if(t!==void 0)throw A("Task option --repo may only be provided once.");t=z(c,"Repo id")}else if(l==="--workspace"){if(r!==void 0)throw A("Task option --workspace may only be provided once.");r=z(c,"Workspace id")}else{if(n!==void 0)throw A("Task option --runner may only be provided once.");try{n=g.runners.parse(c)}catch(d){throw A(d instanceof Error?d.message:"Unsupported runner.")}}}if(!t&&!r)throw A("Task creation requires '--repo <repo-id>' or '--workspace <workspace-id>'.");if(t&&r)throw A("Task creation accepts either '--repo' or '--workspace', not both.");let i=z(s.join(" "),"Task prompt");return{kind:"createTask",...t?{repoId:t}:{},...r?{workspaceId:r}:{},...n?{runner:n}:{},prompt:i}}function gu(e){let[t,...r]=e;if(!["show","discover","link","refresh","unlink"].includes(t??""))throw A(`Unsupported command: task pr ${e.join(" ")}`);let n,s,o;for(let a=0;a<r.length;a+=1){let l=r[a];if(l!=="--repo"&&l!=="--pr"){if(l.startsWith("--"))throw A(`Unsupported task pr ${t} option: ${l}`);if(n!==void 0)throw A(`task pr ${t} accepts at most one task id.`);n=z(l,"Task id");continue}let c=r[a+1];if(c===void 0||c==="--")throw A(`Task PR option ${l} requires a value.`);if(a+=1,l==="--repo"){if(s!==void 0)throw A("Task PR option --repo may only be provided once.");s=z(c,"Repo id")}else{if(o!==void 0)throw A("Task PR option --pr may only be provided once.");o=z(c,"Pull request selector")}}if((t==="link"||t==="unlink")&&o===void 0)throw A(`task pr ${t} requires --pr <url|number>.`);if(t!=="link"&&t!=="unlink"&&o!==void 0)throw A(`task pr ${t} does not accept --pr.`);let i={...n?{taskId:n}:{},...s?{repoId:s}:{}};switch(t){case"show":return{kind:"showTaskPr",...i};case"discover":return{kind:"discoverTaskPr",...i};case"link":return{kind:"linkTaskPr",...i,pullRequest:o};case"refresh":return{kind:"refreshTaskPr",...i};case"unlink":return{kind:"unlinkTaskPr",...i,pullRequest:o};default:throw A(`Unsupported command: task pr ${e.join(" ")}`)}}var hu=300*1e3,ku=new Set(["idle","working","ready","error"]);function wu(e){if(e.length===0)return{kind:"showAgentStatus"};if(e.length===2&&e[0]==="--tab")return{kind:"showAgentStatus",tabId:z(e[1],"Agent tab id")};throw A(`Unsupported command: agent status ${e.join(" ")}`)}function Tu(e){let t,r,n,s=hu,o=new Set;for(let i=0;i<e.length;i+=1){let a=e[i];if(!["--state","--tab","--timeout"].includes(a)){if(a.startsWith("--"))throw A(`Unsupported task wait option: ${a}`);if(t!==void 0)throw A("task wait accepts at most one task id.");t=z(a,"Task id");continue}if(o.has(a))throw A(`Task wait option ${a} may only be provided once.`);o.add(a);let l=e[i+1];if(l===void 0||l.startsWith("--"))throw A(`Task wait option ${a} requires a value.`);i+=1,a==="--state"?r=yu(l):a==="--tab"?n=z(l,"Agent tab id"):s=Ru(l)}if(!r)throw A("task wait requires --state <idle|working|ready|error>[,...].");return{kind:"waitTask",...t?{taskId:t}:{},states:r,...n?{tabId:n}:{},timeoutMs:s}}function yu(e){let t=e.split(",").map(r=>r.trim()).filter(Boolean);if(t.length===0||t.some(r=>!ku.has(r)))throw A(`Invalid agent state list "${e}". Use idle, working, ready, or error.`);return[...new Set(t)]}function Ru(e){let t=/^(\d+)(ms|s|m|h)$/.exec(e.trim());if(!t)throw A(`Invalid duration "${e}". Use values such as 500ms, 30s, 5m, or 1h.`);let r=Number(t[1]),n={ms:1,s:1e3,m:6e4,h:36e5}[t[2]],s=r*n;if(!Number.isSafeInteger(s))throw A(`Duration "${e}" is too large.`);return s}function gi(e,t){return{mode:"command",command:e,commandName:du(e),options:t}}function hi(e){return["--json","--no-input","--workspace-root","--task","--help","-h"].includes(e)}function kr(e,t){Ri(e,0,t)}function Ri(e,t,r){if(e.length!==t)throw A(`Command ${r} received an unexpected number of arguments.`)}function se(e,t){if(e.length!==1)throw A(`${t} is required and must be provided once.`);return z(e[0],t)}function ki(e,t){return z(e.join(" "),t)}function wi(e,t,r){return z(e[t]??"",r)}function z(e,t){let r=e.trim();if(r.length===0)throw A(`${t} cannot be empty.`);return r}function A(e){return new y("CLI_USAGE",`${e}
|
|
11
11
|
|
|
12
|
-
${Pn()}`,{})}var ae=(e,t)=>{let r=Sn(e);if(!ou(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Sn=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:In(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:lu(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:iu(t.repoTargets),runnerSession:t.runnerSession??su(t),checks:gu(t),lastCommit:t.lastCommit??null,prs:hu(t),artifacts:yu(t),cleanup:Ru(t)}},su=e=>{if(typeof e.title!="string")return null;let t=In(e.runner);return{command:f.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},ou=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"&&gi(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||au(t.repoTargets))&&du(t.runnerSession)&&uu(t.prompt)&&hi(t.checks)&&wi(t.lastCommit)&&mu(t.prs)&&fu(t.artifacts)&&Ti(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},iu=e=>{if(Array.isArray(e))return e.filter(fi)},au=e=>Array.isArray(e)&&e.every(fi),fi=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)&&hi(t.checks)&&wi(t.lastCommit)&&ki(t.pullRequest)&&Ti(t.cleanup)},lu=e=>{if(gi(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 cu(e.id,e.title,t,In(e.runner))},cu=(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}]},In=e=>e&&f.runners.isRunnerType(e)?e:"codex",gi=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"),du=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),uu=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",hi=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"),wi=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",ki=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&pu(e.requiredChecks),pu=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)),mu=e=>Array.isArray(e)&&e.every(ki),fu=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),Ti=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),gu=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},hu=e=>{if(Array.isArray(e.prs))return e.prs.map(wu);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:yi(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Ri(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},wu=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:yi(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:ku(t.reviewDecision),requiredChecks:Ri(t.requiredChecks),comments:Tu(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},yi=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,ku=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Tu=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}]}):[],Ri=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})):[],yu=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Ru=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as op}from"node:fs/promises";import{readFile as bu,readdir as Pu,rm as Su}from"node:fs/promises";import bi from"node:path";var Cn=(e,t)=>bi.join(e.workspacesDir,`${t}.json`),Iu=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"):[]}},Pi=(e,t)=>{let r=Iu(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Ve=async(e,t)=>{let r=Cn(e,t);try{let n=await bu(r,"utf8");return Pi(JSON.parse(n),r)}catch(n){throw Cu(n)?new R("WORKSPACE_NOT_FOUND",`Craig workspace "${t}" was not found.`,{details:{workspaceId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig workspace record at ")?new R("WORKSPACE_RECORD_INVALID",n instanceof Error?n.message:`Craig workspace "${t}" is invalid.`,{details:{workspaceId:t},cause:n}):n}},Ke=async(e,t)=>{await q(Cn(e,t.id),{...t,updatedAt:new Date().toISOString()})},se=async e=>{let t=await Pu(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Ve(e,bi.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},Si=async(e,t)=>{await Su(Cn(e,t),{force:!0})},Cu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as vu,readdir as Au,rm as Eu}from"node:fs/promises";import Ii from"node:path";var vn=(e,t)=>Ii.join(e.reposDir,`${t}.json`),Ci=(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},le=async(e,t)=>{let r=vn(e,t);try{let n=await vu(r,"utf8");return Ci(JSON.parse(n),r)}catch(n){throw xu(n)?new R("REPO_NOT_FOUND",`Craig repo "${t}" was not found.`,{details:{repoId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig repo record at ")?new R("REPO_RECORD_INVALID",n instanceof Error?n.message:`Craig repo "${t}" is invalid.`,{details:{repoId:t},cause:n}):n}},An=async(e,t)=>{await q(vn(e,t.id),{...t,updatedAt:new Date().toISOString()})},Et=async e=>{let t=await Au(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>le(e,Ii.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},vi=async(e,t)=>{await Eu(vn(e,t),{force:!0})},xu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Du}from"node:fs/promises";var $u=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"},ct=(e,t,r)=>{if(!$u(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},ee=async e=>{let t=await Du(e.indexFile,"utf8");return ct(JSON.parse(t),e.workspaceRoot,e.indexFile)},ye=async(e,t)=>{await q(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as ju,stat as Fu}from"node:fs/promises";import ut from"node:path";import{realpath as xi}from"node:fs/promises";import fr from"node:path";import{execFile as Ou}from"node:child_process";import{promisify as Mu}from"node:util";var Ai=Mu(Ou);async function S(e,t,r={}){try{let n=await Ai(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(Ei(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function D(e,t,r={}){try{let n=await Ai(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(Ei(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function Ei(e){return e instanceof Error}var En=async e=>{try{let r=(await S("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([xi(r).catch(()=>fr.resolve(r)),xi(e).catch(()=>fr.resolve(e))]);return n===s}catch{return!1}},xn=async e=>{let t=await D("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 D("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await S("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"},Di=async e=>{let t=await D("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd:e}),r=t.stdout.trim();if(t.exitCode!==0||r.length===0)return null;let n=fr.resolve(e,r);return fr.dirname(n)};import{mkdir as fe,readFile as Lu}from"node:fs/promises";var Nu=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",dt=async e=>{let t=Z(e);await fe(t.craigDir,{recursive:!0}),await Promise.all([fe(t.reposDir,{recursive:!0}),fe(t.workspacesDir,{recursive:!0}),fe(t.sessionsDir,{recursive:!0}),fe(t.runtimeDir,{recursive:!0}),fe(t.tasksDir,{recursive:!0}),fe(t.jobsDir,{recursive:!0}),fe(t.logsDir,{recursive:!0}),fe(t.artifactsDir,{recursive:!0}),fe(t.worktreesDir,{recursive:!0})]);try{let s=await Lu(t.indexFile,"utf8"),o=JSON.parse(s);return ct(o,e,t.indexFile)}catch(s){if(!Nu(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 q(t.indexFile,n),n};var $i=(e,t,r)=>{let n=new Date().toISOString();return{id:_u(e,ut.basename(t)),name:ut.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},Oi=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},_u=(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},Wu=(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},Mi=async(e,t)=>{let r=await ee(e);await ye(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},qu=async(e,t)=>{let r=await ju(t,{withFileTypes:!0}),n=await Et(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=ut.join(t,o.name);if(!await En(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await xn(i);s.push(a?Oi(a,l):$i([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},Uu=async(e,t)=>{let r=await xn(t),n=await Et(e),s=n.find(u=>u.rootPath===t)??null,o=s?Oi(s,r):$i(n,t,r),i=`workspace_${o.id}`,l=(await se(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await An(e,o),l||await Ke(e,d),await Mi(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},Bu=async(e,t)=>{let r=await qu(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await se(e),s=Wu(n,ut.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:ut.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>An(e,c))),await Ke(e,l),await Mi(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},xt=async(e,t)=>{await dt(e.workspaceRoot);let r=ut.resolve(e.workspaceRoot,t);if(!(await Fu(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await En(r)?Uu(e,r):Bu(e,r)};var Dn=async(e,t,r={listWorkspaceRecords:se,ensureCraigState:dt})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var $n=async(e,t,r={readWorkspace:Ve,writeWorkspace:Ke})=>{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 On=async(e,t)=>{let n={...await Ve(e,t),status:"active",archivedAt:null};await Ke(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 Ge=async(e,t,r={deleteWorkspace:Si,readCraigIndex:ee,writeCraigIndex:ye})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Mn=async(e,t,r)=>{let n=await Ve(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await Ge(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};import{readFile as Vu,realpath as ji,stat as Ku}from"node:fs/promises";import gr from"node:path";async function Ln(e){let t=await _i(e.cwd,"Current working directory");if(e.explicitWorkspaceRoot!==void 0)return Li(e.explicitWorkspaceRoot,"explicit",t,e.allowUninitializedCwd??!1);if(e.environmentWorkspaceRoot!==void 0)return Li(e.environmentWorkspaceRoot,"environment",t,e.allowUninitializedCwd??!1);let r=await Ni(t);if(r)return{workspaceRoot:r,source:"ancestor",initialized:!0};let n=await Di(t);if(n){let s=await Ni(n);if(s)return{workspaceRoot:s,source:"git_common_dir",initialized:!0}}if(e.allowUninitializedCwd)return{workspaceRoot:t,source:"cwd",initialized:!1};throw new R("WORKSPACE_CONTEXT_NOT_FOUND",`No Craig workspace was found from ${t}. Use --workspace-root <path> or run Craig inside an initialized workspace.`,{details:{cwd:t}})}async function Li(e,t,r,n){let s=t==="explicit"?"Workspace root":"CRAIG_WORKSPACE_ROOT",o=await _i(gr.resolve(r,e),s),i=await Fi(o);if(i)return{workspaceRoot:i,source:t,initialized:!0};if(n)return{workspaceRoot:o,source:t,initialized:!1};throw new R("WORKSPACE_CONTEXT_NOT_FOUND",`${s} ${o} is not an initialized Craig workspace.`,{details:{workspaceRoot:o,source:t}})}async function Ni(e){let t=e;for(;;){let r=await Fi(t);if(r)return r;let n=gr.dirname(t);if(n===t)return null;t=n}}async function Fi(e){let t=Z(e);try{let r=await Vu(t.indexFile,"utf8"),n=JSON.parse(r),s=typeof n=="object"&&n!==null&&"workspaceRoot"in n&&typeof n.workspaceRoot=="string"?n.workspaceRoot:e,o=ct(n,s,t.indexFile);if(await ji(o.workspaceRoot).catch(()=>gr.resolve(o.workspaceRoot))!==e)throw new Error(`Craig index at ${t.indexFile} belongs to ${o.workspaceRoot}, not ${e}. Remove or repair the file before rerunning Craig.`);return o.workspaceRoot}catch(r){if(Gu(r))return null;throw r instanceof R?r:new R("WORKSPACE_CONTEXT_INVALID",r instanceof Error?r.message:`Craig workspace at ${e} is invalid.`,{details:{workspaceRoot:e},cause:r})}}async function _i(e,t){let r=gr.resolve(e);try{if(!(await Ku(r)).isDirectory())throw new R("WORKSPACE_CONTEXT_INVALID",`${t} ${r} is not a directory.`,{details:{path:r}});return await ji(r)}catch(n){throw n instanceof R?n:new R("WORKSPACE_CONTEXT_NOT_FOUND",`${t} ${r} does not exist or cannot be read.`,{details:{path:r},cause:n})}}function Gu(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Nn={};ir(Nn,{addRepo:()=>Wi,listRegisteredRepos:()=>qi,removeRepo:()=>Ui});import Hu from"node:path";import{stat as zu}from"node:fs/promises";var Wi=async(e,t)=>{let r=Hu.resolve(e.workspaceRoot,t);if(!(await zu(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await xt(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 qi=async(e,t={listRepos:Et,ensureCraigState:dt})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ui=async(e,t,r)=>{let n=await le(e,t),o=(await se(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Ge(e,c.id))),await vi(e,t);let l=await ee(e);return await ye(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var G={addWorkspace:xt,listWorkspaces:Dn,archiveWorkspace:$n,restoreWorkspace:On,removeWorkspace:Mn,removeWorkspaceRecord:Ge,resolveContext:Ln,repos:Nn};import{mkdir as Bi,readFile as Yu,rm as wr,stat as Ju,writeFile as Qu}from"node:fs/promises";import hr from"node:path";var Xu=25,Zu=3e4,ep=5e3;async function xe(e,t,r){let n=hr.join(e.runtimeDir,"task-locks"),s=hr.join(n,`${t}.lock`);await Bi(n,{recursive:!0});let o=Date.now();for(;;)try{await Bi(s);try{await Qu(hr.join(s,"owner.json"),JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()}),"utf8")}catch(i){throw await wr(s,{recursive:!0,force:!0}),i}break}catch(i){if(!np(i))throw i;if(await tp(s))continue;if(Date.now()-o>=Zu)throw new R("OPERATION_TIMEOUT",`Timed out waiting to update task ${t}.`,{retryable:!0,details:{taskId:t}});await sp(Xu)}try{return await r()}finally{await wr(s,{recursive:!0,force:!0})}}async function tp(e){let t=await Yu(hr.join(e,"owner.json"),"utf8").then(n=>JSON.parse(n)).catch(()=>null);if(t&&typeof t.pid=="number")return rp(t.pid)?!1:(await wr(e,{recursive:!0,force:!0}),!0);let r=await Ju(e).catch(()=>null);return!r||Date.now()-r.mtimeMs<ep?!1:(await wr(e,{recursive:!0,force:!0}),!0)}function rp(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="EPERM"}}var np=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="EEXIST",sp=e=>new Promise(t=>setTimeout(t,e));var Re=async(e,t)=>{let r=await op(kr(e,t),"utf8");return JSON.parse(r)},Dt=async(e,t)=>{let r=await Re(e,t);return ae(r,kr(e,t))},be=async(e,t)=>{let r=Vi(t);await q(kr(e,t.id),r)},E=async(e,t,r)=>xe(e,t,async()=>{let n=await Dt(e,t),s=await r(n);if(s.id!==t)throw new Error(`Task mutation cannot change task id ${t} to ${s.id}.`);let o=Vi(s);return await q(kr(e,t),o),o}),jn=async(e,t)=>{let r=await ee(e);r.taskIds.includes(t)||await ye(e,{...r,taskIds:[...r.taskIds,t]})},kr=(e,t)=>`${e.tasksDir}/${t}.json`,Vi=e=>({...e,updatedAt:new Date().toISOString()});var A=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,De=e=>e.status==="merged"||e.status==="closed",Pe=(e,t)=>{let r=e.prs.findIndex(s=>pt(s,t)),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},pt=(e,t)=>e.number===null||t.number===null||e.number!==t.number?!1:!e.owner||!e.repo||!t.owner||!t.repo?!0:e.owner.toLowerCase()===t.owner.toLowerCase()&&e.repo.toLowerCase()===t.repo.toLowerCase(),He=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return yr(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},yr=e=>e.mergeable&&!ip(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),ip=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Fn=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),Se=(e,t,r)=>{let n=e.isDraft??!1,s=ap(e.state,n);return{provider:"github",owner:r?.owner??t?.owner??null,repo:r?.name??t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:s,draft:n,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:lp(e.reviewDecision??null),requiredChecks:_n(e.statusCheckRollup),comments:e.comments===void 0?t?.comments??[]:pp(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}},ap=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,lp=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,_n=e=>{let t=e.map(n=>cp(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||dp(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},cp=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:Gi(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:up(t)}:null},dp=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Tr(e)&&!Tr(t)?!0:!Tr(e)&&Tr(t)?!1:Ki(t.status)>=Ki(e.status),Tr=e=>e.conclusion?.toUpperCase()==="CANCELLED",Ki=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},up=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},pp=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(mp).filter(r=>r!==null).slice(-4):[]},mp=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=fp(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},fp=e=>e.replace(/\s+/g," ").trim(),Gi=(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?Gi(n,n):"unknown"};var ge=class extends Error{constructor(t){super(t),this.name="GitHubRateLimitError"}};import{access as gp}from"node:fs/promises";import Hi from"node:path";var I=async(e,t,r={readRawTask:Re,validateTaskRecord:ae})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw yp(n)?new R("TASK_NOT_FOUND",`Craig task "${t}" was not found.`,{details:{taskId:t}}):Rp(n)?new R("TASK_RECORD_INVALID",n instanceof Error?n.message:`Craig task "${t}" is invalid.`,{details:{taskId:t},cause:n}):n}},K=async e=>{if(!await Wn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},mt=(e,t)=>t.artifacts.logPath?Hi.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:Hi.join(e.workspaceRoot,t.artifacts.logPath):null,$t=async(e,t)=>{let r=await Wn(t.worktreePath),n=mt(e,t),s=n?await Wn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:hp(t),lastCommitSummary:wp(t),prSummary:kp(t),cleanupSummary:Tp(t)}},Wn=async e=>{try{return await gp(e),!0}catch{return!1}},hp=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}`},wp=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",kp=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
12
|
+
${Dn()}`,{})}var ae=(e,t)=>{let r=$n(e);if(!Pu(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},$n=e=>{if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:On(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:vu(t),bundlePath:typeof t.bundlePath=="string"||t.bundlePath===null?t.bundlePath:null,selectedRepoTargetId:typeof t.selectedRepoTargetId=="string"||t.selectedRepoTargetId===null?t.selectedRepoTargetId:null,repoTargets:Su(t.repoTargets),runnerSession:t.runnerSession??bu(t),checks:Ou(t),lastCommit:t.lastCommit??null,prs:Mu(t),artifacts:_u(t),cleanup:Fu(t)}},bu=e=>{if(typeof e.title!="string")return null;let t=On(e.runner);return{command:g.runners.buildCommand(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}},Pu=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.id=="string"&&typeof t.title=="string"&&typeof t.slug=="string"&&(t.type==="repo"||t.type==="project")&&typeof t.status=="string"&&g.runners.isRunnerType(t.runner??"")&&typeof t.repoId=="string"&&typeof t.workspaceId=="string"&&(typeof t.sessionId=="string"||t.sessionId===null)&&(typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null)&&Array.isArray(t.linkedRepoIds)&&t.linkedRepoIds.every(r=>typeof r=="string")&&typeof t.repoRoot=="string"&&typeof t.worktreePath=="string"&&typeof t.branch=="string"&&Pi(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||Iu(t.repoTargets))&&Au(t.runnerSession)&&Eu(t.prompt)&&Si(t.checks)&&Ii(t.lastCommit)&&Du(t.prs)&&$u(t.artifacts)&&Ci(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},Su=e=>{if(Array.isArray(e))return e.filter(bi)},Iu=e=>Array.isArray(e)&&e.every(bi),bi=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)&&Si(t.checks)&&Ii(t.lastCommit)&&vi(t.pullRequest)&&Ci(t.cleanup)},vu=e=>{if(Pi(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 Cu(e.id,e.title,t,On(e.runner))},Cu=(e,t,r,n)=>{let s=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:s.defaultAgentTitle,command:g.runners.buildCommand(n),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},On=e=>e&&g.runners.isRunnerType(e)?e:"codex",Pi=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"),Au=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),Eu=e=>typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string",Si=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"),Ii=e=>e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string",vi=e=>typeof e=="object"&&e!==null&&e.provider==="github"&&xu(e.requiredChecks),xu=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)),Du=e=>Array.isArray(e)&&e.every(vi),$u=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),Ci=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),Ou=e=>e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]},Mu=e=>{if(Array.isArray(e.prs))return e.prs.map(Nu);let t=e.pullRequest;return!t||!t.number?[]:[{provider:"github",owner:null,repo:null,number:t.number,url:t.url??null,title:null,status:Ai(t.status),draft:!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:null,requiredChecks:Ei(t.requiredChecks),comments:[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}]},Nu=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:Ai(t.status),draft:t.draft??!1,baseBranch:t.baseBranch??null,headBranch:t.headBranch??null,mergeable:t.mergeable??!1,mergeStateStatus:t.mergeStateStatus??null,reviewDecision:Lu(t.reviewDecision),requiredChecks:Ei(t.requiredChecks),comments:ju(t.comments),createdAt:t.createdAt??null,updatedAt:t.updatedAt??null,mergedAt:t.mergedAt??null,lastSyncedAt:t.lastSyncedAt??null,lastSyncedHeadSha:t.lastSyncedHeadSha??null}},Ai=e=>e==="open"||e==="closed"||e==="merged"||e==="draft"?e:null,Lu=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,ju=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}]}):[],Ei=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})):[],_u=e=>{let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}},Fu=e=>e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null};import{readFile as Pp}from"node:fs/promises";import{readFile as Wu,readdir as qu,rm as Uu}from"node:fs/promises";import xi from"node:path";var Mn=(e,t)=>xi.join(e.workspacesDir,`${t}.json`),Bu=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"):[]}},Di=(e,t)=>{let r=Bu(e);if(typeof r!="object"||r===null||typeof r.id!="string"||r.kind!=="repo"&&r.kind!=="project"||typeof r.name!="string"||typeof r.rootPath!="string"||typeof r.primaryRepoId!="string"||typeof r.branch!="string"||r.status!=="active"&&r.status!=="archived"||!Array.isArray(r.linkedRepoIds)||!(r.linkedRepoIds??[]).every(n=>typeof n=="string")||!(r.repoId===void 0||typeof r.repoId=="string")||!Array.isArray(r.discoveredRepoIds)||!(r.discoveredRepoIds??[]).every(n=>typeof n=="string")||!(r.archivedAt===null||typeof r.archivedAt=="string")||typeof r.createdAt!="string"||typeof r.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r},Ve=async(e,t)=>{let r=Mn(e,t);try{let n=await Wu(r,"utf8");return Di(JSON.parse(n),r)}catch(n){throw Vu(n)?new y("WORKSPACE_NOT_FOUND",`Craig workspace "${t}" was not found.`,{details:{workspaceId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig workspace record at ")?new y("WORKSPACE_RECORD_INVALID",n instanceof Error?n.message:`Craig workspace "${t}" is invalid.`,{details:{workspaceId:t},cause:n}):n}},Ke=async(e,t)=>{await U(Mn(e,t.id),{...t,updatedAt:new Date().toISOString()})},oe=async e=>{let t=await qu(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>Ve(e,xi.basename(n.name,".json"))))).sort((n,s)=>n.id.localeCompare(s.id))},$i=async(e,t)=>{await Uu(Mn(e,t),{force:!0})},Vu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Ku,readdir as Gu,rm as Hu}from"node:fs/promises";import Oi from"node:path";var Nn=(e,t)=>Oi.join(e.reposDir,`${t}.json`),Mi=(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},le=async(e,t)=>{let r=Nn(e,t);try{let n=await Ku(r,"utf8");return Mi(JSON.parse(n),r)}catch(n){throw zu(n)?new y("REPO_NOT_FOUND",`Craig repo "${t}" was not found.`,{details:{repoId:t}}):n instanceof SyntaxError||n instanceof Error&&n.message.startsWith("Craig repo record at ")?new y("REPO_RECORD_INVALID",n instanceof Error?n.message:`Craig repo "${t}" is invalid.`,{details:{repoId:t},cause:n}):n}},Ln=async(e,t)=>{await U(Nn(e,t.id),{...t,updatedAt:new Date().toISOString()})},Mt=async e=>{let t=await Gu(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(n=>n.isFile()&&n.name.endsWith(".json")).map(n=>le(e,Oi.basename(n.name,".json"))))).sort((n,s)=>n.name.localeCompare(s.name)||n.id.localeCompare(s.id))},Ni=async(e,t)=>{await Hu(Nn(e,t),{force:!0})},zu=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT";import{readFile as Yu}from"node:fs/promises";var Ju=e=>{if(typeof e!="object"||e===null)return!1;let t=e;return t.version===2&&typeof t.workspaceRoot=="string"&&Array.isArray(t.repoIds)&&t.repoIds.every(r=>typeof r=="string")&&Array.isArray(t.workspaceIds)&&t.workspaceIds.every(r=>typeof r=="string")&&Array.isArray(t.taskIds)&&t.taskIds.every(r=>typeof r=="string")&&Array.isArray(t.jobIds)&&t.jobIds.every(r=>typeof r=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"},dt=(e,t,r)=>{if(!Ju(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},te=async e=>{let t=await Yu(e.indexFile,"utf8");return dt(JSON.parse(t),e.workspaceRoot,e.indexFile)},ye=async(e,t)=>{await U(e.indexFile,{...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()})};import{readdir as tp,stat as rp}from"node:fs/promises";import pt from"node:path";import{realpath as _i}from"node:fs/promises";import wr from"node:path";import{execFile as Qu}from"node:child_process";import{promisify as Xu}from"node:util";var Li=Xu(Qu);async function I(e,t,r={}){try{let n=await Li(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr}}catch(n){if(ji(n)){let s=n.stderr?.trim()||n.stdout?.trim()||n.message;throw new Error(`${e} ${t.join(" ")} failed: ${s}`)}throw n}}async function $(e,t,r={}){try{let n=await Li(e,t,{cwd:r.cwd,env:r.env});return{stdout:n.stdout,stderr:n.stderr,exitCode:0}}catch(n){if(ji(n))return{stdout:n.stdout??"",stderr:n.stderr??"",exitCode:typeof n.code=="number"?n.code:null};throw n}}function ji(e){return e instanceof Error}var jn=async e=>{try{let r=(await I("git",["rev-parse","--show-toplevel"],{cwd:e})).stdout.trim(),[n,s]=await Promise.all([_i(r).catch(()=>wr.resolve(r)),_i(e).catch(()=>wr.resolve(e))]);return n===s}catch{return!1}},_n=async e=>{let t=await $("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 $("git",["show-ref","--verify","--quiet",`refs/heads/${o}`],{cwd:e})).exitCode===0)return o;let s=(await I("git",["branch","--show-current"],{cwd:e})).stdout.trim();return s.length>0?s:"HEAD"},Fi=async e=>{let t=await $("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd:e}),r=t.stdout.trim();if(t.exitCode!==0||r.length===0)return null;let n=wr.resolve(e,r);return wr.dirname(n)};import{mkdir as fe,readFile as Zu}from"node:fs/promises";var ep=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",ut=async e=>{let t=ee(e);await fe(t.craigDir,{recursive:!0}),await Promise.all([fe(t.reposDir,{recursive:!0}),fe(t.workspacesDir,{recursive:!0}),fe(t.sessionsDir,{recursive:!0}),fe(t.runtimeDir,{recursive:!0}),fe(t.tasksDir,{recursive:!0}),fe(t.jobsDir,{recursive:!0}),fe(t.logsDir,{recursive:!0}),fe(t.artifactsDir,{recursive:!0}),fe(t.worktreesDir,{recursive:!0})]);try{let s=await Zu(t.indexFile,"utf8"),o=JSON.parse(s);return dt(o,e,t.indexFile)}catch(s){if(!ep(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 U(t.indexFile,n),n};var Wi=(e,t,r)=>{let n=new Date().toISOString();return{id:np(e,pt.basename(t)),name:pt.basename(t),rootPath:t,defaultBranch:r,createdAt:n,updatedAt:n}},qi=(e,t)=>e.defaultBranch===t?e:{...e,defaultBranch:t,updatedAt:new Date().toISOString()},np=(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},sp=(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},Ui=async(e,t)=>{let r=await te(e);await ye(e,{...r,repoIds:[...new Set([...r.repoIds,...t.repoIds])],workspaceIds:[...new Set([...r.workspaceIds,...t.workspaceIds])]})},op=async(e,t)=>{let r=await tp(t,{withFileTypes:!0}),n=await Mt(e),s=[];for(let o of r){if(!o.isDirectory()||o.name.startsWith("."))continue;let i=pt.join(t,o.name);if(!await jn(i))continue;let a=n.find(c=>c.rootPath===i)??s.find(c=>c.rootPath===i),l=await _n(i);s.push(a?qi(a,l):Wi([...n,...s],i,l))}return s.sort((o,i)=>o.name.localeCompare(i.name)||o.id.localeCompare(i.id))},ip=async(e,t)=>{let r=await _n(t),n=await Mt(e),s=n.find(u=>u.rootPath===t)??null,o=s?qi(s,r):Wi(n,t,r),i=`workspace_${o.id}`,l=(await oe(e)).find(u=>u.id===i)??null,c=new Date().toISOString(),d=l??{id:i,kind:"repo",name:o.name,rootPath:t,primaryRepoId:o.id,repoId:o.id,discoveredRepoIds:[o.id],branch:r,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:c,updatedAt:c};return await Ln(e,o),l||await Ke(e,d),await Ui(e,{repoIds:[o.id],workspaceIds:[d.id]}),{kind:"createWorkspace",workspace:d,repos:[o],created:!l}},ap=async(e,t)=>{let r=await op(e,t);if(r.length===0)throw new Error(`Workspace path does not contain direct child Git repos: ${t}`);let n=await oe(e),s=sp(n,pt.basename(t)),o=n.find(c=>c.kind==="project"&&c.rootPath===t)??null,i=new Date().toISOString(),a=r.map(c=>c.id),l=o?{...o,discoveredRepoIds:a,primaryRepoId:a[0]??o.primaryRepoId,status:"active",archivedAt:null}:{id:s,kind:"project",name:pt.basename(t),rootPath:t,primaryRepoId:a[0]??"",discoveredRepoIds:a,branch:"project",status:"active",linkedRepoIds:a,archivedAt:null,createdAt:i,updatedAt:i};return await Promise.all(r.map(c=>Ln(e,c))),await Ke(e,l),await Ui(e,{repoIds:a,workspaceIds:[l.id]}),{kind:"createWorkspace",workspace:l,repos:r,created:!o}},Nt=async(e,t)=>{await ut(e.workspaceRoot);let r=pt.resolve(e.workspaceRoot,t);if(!(await rp(r).catch(()=>null))?.isDirectory())throw new Error(`Workspace path does not exist: ${r}`);return await jn(r)?ip(e,r):ap(e,r)};var Fn=async(e,t,r={listWorkspaceRecords:oe,ensureCraigState:ut})=>(await r.ensureCraigState(e.workspaceRoot),{kind:"listWorkspaces",workspaces:(await r.listWorkspaceRecords(e)).filter(s=>s.status===(t.archived?"archived":"active")),archivedOnly:t.archived});var Wn=async(e,t,r={readWorkspace:Ve,writeWorkspace:Ke})=>{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 qn=async(e,t)=>{let n={...await Ve(e,t),status:"active",archivedAt:null};await Ke(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 Ge=async(e,t,r={deleteWorkspace:$i,readCraigIndex:te,writeCraigIndex:ye})=>{await r.deleteWorkspace(e,t);let n=await r.readCraigIndex(e);await r.writeCraigIndex(e,{...n,workspaceIds:n.workspaceIds.filter(s=>s!==t)})};var Un=async(e,t,r)=>{let n=await Ve(e,t),s=await r.listTasks(e,{workspaceId:t,includeClosed:!0});if(n.status==="active")throw new Error(`Cannot remove workspace ${t} while it is active. Archive it first.`);if(s.tasks.length>0)throw new Error(`Cannot remove workspace ${t} while task records still reference it.`);return await Ge(e,t),{kind:"removeWorkspace",workspaceId:n.id,rootPath:n.rootPath??""}};import{readFile as lp,realpath as Ki,stat as cp}from"node:fs/promises";import Tr from"node:path";async function Bn(e){let t=await Hi(e.cwd,"Current working directory");if(e.explicitWorkspaceRoot!==void 0)return Bi(e.explicitWorkspaceRoot,"explicit",t,e.allowUninitializedCwd??!1);if(e.environmentWorkspaceRoot!==void 0)return Bi(e.environmentWorkspaceRoot,"environment",t,e.allowUninitializedCwd??!1);let r=await Vi(t);if(r)return{workspaceRoot:r,source:"ancestor",initialized:!0};let n=await Fi(t);if(n){let s=await Vi(n);if(s)return{workspaceRoot:s,source:"git_common_dir",initialized:!0}}if(e.allowUninitializedCwd)return{workspaceRoot:t,source:"cwd",initialized:!1};throw new y("WORKSPACE_CONTEXT_NOT_FOUND",`No Craig workspace was found from ${t}. Use --workspace-root <path> or run Craig inside an initialized workspace.`,{details:{cwd:t}})}async function Bi(e,t,r,n){let s=t==="explicit"?"Workspace root":"CRAIG_WORKSPACE_ROOT",o=await Hi(Tr.resolve(r,e),s),i=await Gi(o);if(i)return{workspaceRoot:i,source:t,initialized:!0};if(n)return{workspaceRoot:o,source:t,initialized:!1};throw new y("WORKSPACE_CONTEXT_NOT_FOUND",`${s} ${o} is not an initialized Craig workspace.`,{details:{workspaceRoot:o,source:t}})}async function Vi(e){let t=e;for(;;){let r=await Gi(t);if(r)return r;let n=Tr.dirname(t);if(n===t)return null;t=n}}async function Gi(e){let t=ee(e);try{let r=await lp(t.indexFile,"utf8"),n=JSON.parse(r),s=typeof n=="object"&&n!==null&&"workspaceRoot"in n&&typeof n.workspaceRoot=="string"?n.workspaceRoot:e,o=dt(n,s,t.indexFile);if(await Ki(o.workspaceRoot).catch(()=>Tr.resolve(o.workspaceRoot))!==e)throw new Error(`Craig index at ${t.indexFile} belongs to ${o.workspaceRoot}, not ${e}. Remove or repair the file before rerunning Craig.`);return o.workspaceRoot}catch(r){if(dp(r))return null;throw r instanceof y?r:new y("WORKSPACE_CONTEXT_INVALID",r instanceof Error?r.message:`Craig workspace at ${e} is invalid.`,{details:{workspaceRoot:e},cause:r})}}async function Hi(e,t){let r=Tr.resolve(e);try{if(!(await cp(r)).isDirectory())throw new y("WORKSPACE_CONTEXT_INVALID",`${t} ${r} is not a directory.`,{details:{path:r}});return await Ki(r)}catch(n){throw n instanceof y?n:new y("WORKSPACE_CONTEXT_NOT_FOUND",`${t} ${r} does not exist or cannot be read.`,{details:{path:r},cause:n})}}function dp(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Vn={};cr(Vn,{addRepo:()=>zi,listRegisteredRepos:()=>Yi,removeRepo:()=>Ji});import up from"node:path";import{stat as pp}from"node:fs/promises";var zi=async(e,t)=>{let r=up.resolve(e.workspaceRoot,t);if(!(await pp(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);let s=await Nt(e,t),o=s.repos[0];if(!o||s.workspace.kind==="project")throw new Error(`Repo path is not a git repository: ${r}`);return{kind:"createRepo",repo:o,workspaceId:s.workspace.id,created:s.created}};var Yi=async(e,t={listRepos:Mt,ensureCraigState:ut})=>(await t.ensureCraigState(e.workspaceRoot),{kind:"listRepos",repos:await t.listRepos(e)});var Ji=async(e,t,r)=>{let n=await le(e,t),o=(await oe(e)).filter(c=>c.primaryRepoId===t),i=o.filter(c=>c.status==="active"),a=await r.listTasks(e,{repoId:t});if(i.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(a.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(o.map(c=>Ge(e,c.id))),await Ni(e,t);let l=await te(e);return await ye(e,{...l,repoIds:l.repoIds.filter(c=>c!==t)}),{kind:"removeRepo",repoId:n.id,rootPath:n.rootPath}};var G={addWorkspace:Nt,listWorkspaces:Fn,archiveWorkspace:Wn,restoreWorkspace:qn,removeWorkspace:Un,removeWorkspaceRecord:Ge,resolveContext:Bn,repos:Vn};import{mkdir as Qi,readFile as mp,rm as Rr,stat as fp,writeFile as gp}from"node:fs/promises";import yr from"node:path";var hp=25,kp=3e4,wp=5e3;async function xe(e,t,r){let n=yr.join(e.runtimeDir,"task-locks"),s=yr.join(n,`${t}.lock`);await Qi(n,{recursive:!0});let o=Date.now();for(;;)try{await Qi(s);try{await gp(yr.join(s,"owner.json"),JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()}),"utf8")}catch(i){throw await Rr(s,{recursive:!0,force:!0}),i}break}catch(i){if(!Rp(i))throw i;if(await Tp(s))continue;if(Date.now()-o>=kp)throw new y("OPERATION_TIMEOUT",`Timed out waiting to update task ${t}.`,{retryable:!0,details:{taskId:t}});await bp(hp)}try{return await r()}finally{await Rr(s,{recursive:!0,force:!0})}}async function Tp(e){let t=await mp(yr.join(e,"owner.json"),"utf8").then(n=>JSON.parse(n)).catch(()=>null);if(t&&typeof t.pid=="number")return yp(t.pid)?!1:(await Rr(e,{recursive:!0,force:!0}),!0);let r=await fp(e).catch(()=>null);return!r||Date.now()-r.mtimeMs<wp?!1:(await Rr(e,{recursive:!0,force:!0}),!0)}function yp(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="EPERM"}}var Rp=e=>typeof e=="object"&&e!==null&&"code"in e&&e.code==="EEXIST",bp=e=>new Promise(t=>setTimeout(t,e));var Re=async(e,t)=>{let r=await Pp(br(e,t),"utf8");return JSON.parse(r)},Lt=async(e,t)=>{let r=await Re(e,t);return ae(r,br(e,t))},be=async(e,t)=>{let r=Xi(t);await U(br(e,t.id),r)},x=async(e,t,r)=>xe(e,t,async()=>{let n=await Lt(e,t),s=await r(n);if(s.id!==t)throw new Error(`Task mutation cannot change task id ${t} to ${s.id}.`);let o=Xi(s);return await U(br(e,t),o),o}),Kn=async(e,t)=>{let r=await te(e);r.taskIds.includes(t)||await ye(e,{...r,taskIds:[...r.taskIds,t]})},br=(e,t)=>`${e.tasksDir}/${t}.json`,Xi=e=>({...e,updatedAt:new Date().toISOString()});var E=e=>e.prs.length===0?null:[...e.prs].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e.prs[e.prs.length-1]??null,De=e=>e.status==="merged"||e.status==="closed",Pe=(e,t)=>{let r=e.prs.findIndex(s=>mt(s,t)),n=r>=0?e.prs.map((s,o)=>o===r?t:s):[...e.prs,t];return{...e,prs:n}},mt=(e,t)=>e.number===null||t.number===null||e.number!==t.number?!1:!e.owner||!e.repo||!t.owner||!t.repo?!0:e.owner.toLowerCase()===t.owner.toLowerCase()&&e.repo.toLowerCase()===t.repo.toLowerCase(),He=e=>{if(e.length===0)return"checked";let t=[...e].reverse().find(r=>r.status!=="merged"&&r.status!=="closed")??e[e.length-1];return Sr(t)?"merge_ready":t.status==="merged"?"merged":t.status==="open"?"pr_open":"checked"},Sr=e=>e.mergeable&&!Sp(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"),Sp=e=>e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED",Gn=e=>e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", "),Se=(e,t,r)=>{let n=e.isDraft??!1,s=Ip(e.state,n);return{provider:"github",owner:r?.owner??t?.owner??null,repo:r?.name??t?.repo??null,number:e.number,url:e.url,title:e.title??t?.title??null,status:s,draft:n,baseBranch:e.baseRefName,headBranch:e.headRefName,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:vp(e.reviewDecision??null),requiredChecks:Hn(e.statusCheckRollup),comments:e.comments===void 0?t?.comments??[]:xp(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}},Ip=(e,t)=>t?"draft":e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,vp=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null,Hn=e=>{let t=e.map(n=>Cp(n)).filter(n=>n!==null),r=new Map;for(let n of t){let s=r.get(n.name);(!s||Ap(s,n))&&r.set(n.name,n)}return[...r.values()].map(n=>({name:n.name,status:n.status,conclusion:n.conclusion}))},Cp=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:ea(n??null,t.conclusion??null),conclusion:t.conclusion??null,sortTime:Ep(t)}:null},Ap=(e,t)=>e.sortTime!==null||t.sortTime!==null?(t.sortTime??0)>=(e.sortTime??0):Pr(e)&&!Pr(t)?!0:!Pr(e)&&Pr(t)?!1:Zi(t.status)>=Zi(e.status),Pr=e=>e.conclusion?.toUpperCase()==="CANCELLED",Zi=e=>{switch(e){case"pending":return 5;case"failed":return 4;case"success":return 3;case"skipped":return 2;default:return 1}},Ep=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},xp=e=>{let t=Array.isArray(e)?e:e?.nodes;return Array.isArray(t)?t.map(Dp).filter(r=>r!==null).slice(-4):[]},Dp=e=>{if(typeof e!="object"||e===null)return null;let t=e,r=$p(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},$p=e=>e.replace(/\s+/g," ").trim(),ea=(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?ea(n,n):"unknown"};var ge=class extends Error{constructor(t){super(t),this.name="GitHubRateLimitError"}};import{access as Op}from"node:fs/promises";import ta from"node:path";var v=async(e,t,r={readRawTask:Re,validateTaskRecord:ae})=>{try{let n=await r.readRawTask(e,t);return r.validateTaskRecord(n,`${e.tasksDir}/${t}.json`)}catch(n){throw _p(n)?new y("TASK_NOT_FOUND",`Craig task "${t}" was not found.`,{details:{taskId:t}}):Fp(n)?new y("TASK_RECORD_INVALID",n instanceof Error?n.message:`Craig task "${t}" is invalid.`,{details:{taskId:t},cause:n}):n}},K=async e=>{if(!await zn(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)},ft=(e,t)=>t.artifacts.logPath?ta.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:ta.join(e.workspaceRoot,t.artifacts.logPath):null,jt=async(e,t)=>{let r=await zn(t.worktreePath),n=ft(e,t),s=n?await zn(n):!1;return{worktreeExists:r,logExists:s,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Mp(t),lastCommitSummary:Np(t),prSummary:Lp(t),cleanupSummary:jp(t)}},zn=async e=>{try{return await Op(e),!0}catch{return!1}},Mp=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}`},Np=e=>e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed",Lp=e=>{if(e.type==="project"&&e.repoTargets?.length){let s=e.repoTargets.filter(l=>l.pullRequest.number);if(s.length===0)return"not linked";let o=s.map(l=>` ${l.repoId} #${l.pullRequest.number} ${l.pullRequest.status??"unknown"}`),i=s.reduce((l,c)=>{let d=c.pullRequest.status??"unknown";return l[d]=(l[d]??0)+1,l},{}),a=Object.entries(i).map(([l,c])=>`${c} ${l}`).join(", ");return`${s.length} PR${s.length!==1?"s":""} (${a})
|
|
13
13
|
${o.join(`
|
|
14
|
-
`)}`}let t=
|
|
15
|
-
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},
|
|
14
|
+
`)}`}let t=E(e);if(!t?.number||!t.url)return"not linked";let r=t.requiredChecks.length,n=r===1?"check":"checks";return`#${t.number} ${t.status??"unknown"} mergeable=${t.mergeable} mergeState=${t.mergeStateStatus??"unknown"} (${r} ${n})`},jp=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",_p=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Fp=e=>e instanceof SyntaxError||e instanceof Error&&e.message.startsWith("Craig task record at ");var ra=async(e,t)=>{let r=await $("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.")},Yn=async(e,t,r,n="main")=>{let s=n.trim()||"main";if((await $("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 Wp(e,s);await I("git",["worktree","add","-b",t,r,i],{cwd:e})},Wp=async(e,t)=>(await $("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await $("git",["fetch","origin",t],{cwd:e})).exitCode!==0?t:(await $("git",["show-ref","--verify","--quiet",`refs/remotes/origin/${t}`],{cwd:e})).exitCode===0?`refs/remotes/origin/${t}`:t,Ir=async e=>{let t=await $("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},na=async e=>{await I("git",["add","-A"],{cwd:e})},sa=async(e,t)=>{await I("git",["commit","-m",t],{cwd:e})},oa=async e=>{let t=await I("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",n=""]=t.stdout.trim().split(`
|
|
15
|
+
`);if(!r||!n)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:n}},ia=async e=>{let t=await $("git",["branch","--show-current"],{cwd:e});if(t.exitCode!==0)return null;let r=t.stdout.trim();return r.length>0?r:null};var aa=async(e,t)=>{await I("git",["worktree","remove","--force",t],{cwd:e})};var Jn=async e=>gt(e,e.repoRoot),gt=async(e,t)=>{let r=await te(e),n=la(new Date),s=ca(r.taskIds,n);for(;;){let o=`task_${n}_${String(s).padStart(2,"0")}`,i=`craig/${o}`;if(!await ra(t,i))return o;s+=1}},_t=async e=>{let t=await te(e),r=la(new Date),n=ca(t.taskIds,r);return`task_${r}_${String(n).padStart(2,"0")}`},la=e=>{let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${t}${r}${n}`},ca=(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 Ft=async(e,t,r={readRawTask:Re,validateTaskRecord:ae})=>{let n=await te(e),s=[],o=[];await Promise.all(n.taskIds.map(async l=>{try{let c=await r.readRawTask(e,l);s.push(r.validateTaskRecord(c,`${e.tasksDir}/${l}.json`))}catch(c){if(qp(c)){o.push(l);return}throw c}}));let a=(t?.includeClosed?s:s.filter(l=>l.status!=="closed")).filter(l=>!(t?.workspaceId&&l.workspaceId!==t.workspaceId||t?.repoId&&l.repoId!==t.repoId&&!(l.repoTargets??[]).some(c=>c.repoId===t.repoId)));return a.sort((l,c)=>l.id.localeCompare(c.id)),o.sort(),{kind:"listTasks",tasks:a,missingTaskIds:o,repoId:t?.repoId??null}},qp=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";var da=["merge_ready","pr_open","checked","review","running","draft"],Qn=e=>[...e].sort((t,r)=>t.id.localeCompare(r.id)),Xn=(e,t)=>t&&e.some(n=>n.id===t)?t:e.length===0?null:[...e].sort(Up)[0]?.id??null,Up=(e,t)=>{let r=ua(e.status),n=ua(t.status);return r!==n?r-n:t.updatedAt.localeCompare(e.updatedAt)},ua=e=>{let t=da.indexOf(e);return t>=0?t:da.length};import pa from"node:path";var ze=(e,t)=>t?pa.isAbsolute(t)?t:pa.join(e.repoRoot,t):null;import{mkdir as Wt,rm as Bp,writeFile as vr}from"node:fs/promises";import O from"node:path";var fa=["AGENTS","md"].join("."),ht=async(e,t,r,n={})=>{let s=await le(e,t),[o,i]=await Promise.all([zp(e,s.id),gt(e,s.rootPath)]),a=n.sessionId??null,l=`craig/${i}`,c=O.join(e.worktreesDir,s.id,i),d=O.join(e.logsDir,`${i}.log`),u=O.join(e.artifactsDir,i);await Promise.all([Wt(O.dirname(c),{recursive:!0}),Wt(u,{recursive:!0}),vr(d,"","utf8")]);let p=Vp(e,{taskId:i,repoId:s.id,workspaceId:o.id,sessionId:a,repoRoot:s.rootPath,prompt:r,runner:n.runner??"codex",config:n.config??{},branch:l,worktreePath:c});return await be(e,p),await Kn(e,i),await Yn(s.rootPath,l,c,s.defaultBranch),{repoId:s.id,repoRoot:s.rootPath,sessionId:a,workspaceId:o.id,task:p}},qt=async(e,t,r,n={})=>{let s=(await oe(e)).find(C=>C.id===t&&C.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 C=await ht(e,s.primaryRepoId,r,n);return{...C,bundlePath:C.task.worktreePath,repoTargets:[]}}let o=s.discoveredRepoIds??[];if(o.length===0)throw new Error(`Project workspace ${t} has no discovered repos.`);let i=await _t(e),a=new Date().toISOString(),l=n.runner??"codex",c=n.sessionId??null,d=`craig/${i}`,u=O.join(e.craigDir,"task-bundles",i),p=O.join(e.logsDir,`${i}.log`),f=O.join(e.artifactsDir,i);await Wt(u,{recursive:!0}),await Wt(f,{recursive:!0}),await vr(p,"","utf8");let w=await Promise.all(o.map(C=>le(e,C))),h=Gp(w),b=await Promise.all(w.map(C=>Kp(e,C,i,d,O.join(u,h.get(C.id))))),q=b.find(C=>C.status==="ready")??b[0];if(!b.some(C=>C.status==="ready"))throw await Bp(u,{recursive:!0,force:!0}),new Error(`No project repo targets could be provisioned for ${t}: ${b.map(C=>`${C.repoId}: ${C.failureReason??"unknown error"}`).join("; ")}`);await vr(O.join(u,"manifest.json"),JSON.stringify({taskId:i,workspaceId:t,prompt:r,repos:b.map(C=>({repoId:C.repoId,repoName:w.find(we=>we.id===C.repoId)?.name??C.repoId,path:O.relative(u,C.worktreePath),status:C.status,worktreePath:C.worktreePath,failureReason:C.failureReason}))},null,2),"utf8"),await vr(O.join(u,fa),Hp({taskId:i,workspaceId:t,prompt:r,repos:w,repoTargets:b,bundlePath:u}),"utf8");let H=Ut(i,r,a,l,n.config??{}),ne={id:i,title:r,slug:ga(r),type:"project",status:"draft",runner:l,repoId:q.repoId,workspaceId:s.id,sessionId:c,selectedPtyTabId:H[0]?.id??null,linkedRepoIds:o.filter(C=>C!==q.repoId),repoRoot:u,worktreePath:u,branch:d,bundlePath:u,selectedRepoTargetId:q.repoId,repoTargets:b,ptyTabs:H,runnerSession:{command:g.runners.buildCommand(l,r,n.config??{}),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:r},checks:q.checks,lastCommit:null,prs:[],artifacts:{logPath:O.relative(e.workspaceRoot,p),checkSummaryPath:O.relative(e.workspaceRoot,O.join(f,"check-summary.json")),prDraftPath:null,prStatusPath:O.relative(e.workspaceRoot,O.join(f,"pr-status.json"))},cleanup:Cr(),lastFailureReason:b.every(C=>C.status==="unavailable")?"No project repo targets could be provisioned.":null,createdAt:a,updatedAt:a};return await be(e,ne),await Kn(e,i),{repoId:q.repoId,repoRoot:u,sessionId:c,workspaceId:s.id,task:ne,bundlePath:u,repoTargets:b}},Ut=(e,t,r,n="codex",s={})=>{let o=g.runners.getProfile(n);return[{id:`${e}:agent`,kind:"agent",title:o.defaultAgentTitle,command:g.runners.buildCommand(n,void 0,s),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]},Vp=(e,t)=>{let r=new Date().toISOString(),n=Ut(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:ga(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:n[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:n,runnerSession:{command:g.runners.buildCommand(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{...Zn(O.relative(e.workspaceRoot,e.configFile))},lastCommit:null,prs:[],artifacts:{logPath:O.relative(e.workspaceRoot,O.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:O.relative(e.workspaceRoot,O.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:O.relative(e.workspaceRoot,O.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:Cr(),lastFailureReason:null,createdAt:r,updatedAt:r}},Kp=async(e,t,r,n,s)=>{await Wt(O.dirname(s),{recursive:!0});try{return await Yn(t.rootPath,n,s,t.defaultBranch),{repoId:t.id,branch:n,repoRoot:t.rootPath,worktreePath:s,status:"ready",failureReason:null,checks:Zn(O.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:ma(),cleanup:Cr()}}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:Zn(O.relative(e.workspaceRoot,e.configFile)),lastCommit:null,pullRequest:ma(),cleanup:Cr()}}},Gp=e=>{let t=new Set(["manifest.json",fa]),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},Hp=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=O.relative(e.bundlePath,n.worktreePath),i=n.status==="ready"?"ready":`unavailable: ${n.failureReason??"unknown error"}`;return`- \`${o}/\` - ${s} (${n.repoId}, ${i})`}).join(`
|
|
16
16
|
`);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(`
|
|
17
|
-
`)},Kn=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),oa=()=>({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}),Pr=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),xp=async(e,t)=>{let n=(await se(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},aa=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import ka from"node:path";import{readFile as Dp,rm as uR}from"node:fs/promises";import $p from"node:path";var $e=async(e,t)=>{let r=await Dp(Gn(e,t),"utf8"),n=JSON.parse(r);return Op(n,Gn(e,t))},Ye=async(e,t)=>{await q(Gn(e,t.id),{...t,updatedAt:new Date().toISOString()})};var Gn=(e,t)=>$p.join(e.sessionsDir,`${t}.json`);function Op(e,t){let r=Np(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")||!Lp(r.attach)||!Mp(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 Mp(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 Lp(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 Np(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 jp}from"node:child_process";import{createHash as Fp}from"node:crypto";import _p from"node:path";function Sr(e){return`'${e.replace(/'/g,"'\\''")}'`}var Wp="craig",la=async(e,t,r)=>{let n=Hn(e,t),s=Up(),o=await S("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=Vp(o.stdout);return await qp(e,n),i};var qp=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 S("tmux",n,{cwd:e})},ca=async(e,t,r)=>{await S("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},da=async(e,t,r)=>{await S("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var ua=async(e,t,r)=>{await S("tmux",["pipe-pane","-o","-t",e,`cat >> ${Sr(t)}`],{cwd:r})},Ir=async(e,t,r,n)=>{let s=n??ma(e);if(r?await S("tmux",["select-window","-t",r],{cwd:e}):await S("tmux",["select-window","-t",t],{cwd:e}),await S("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await S("tmux",["switch-client","-t",s],{cwd:e});return}await Gp(e,["attach-session","-t",s])};var pa=async(e,t)=>{await S("tmux",["kill-session","-t",t],{cwd:e})};var ma=e=>{let r=_p.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=Fp("sha1").update(e).digest("hex").slice(0,8);return`${Wp}-${r}-${n}`},Hn=(e,t)=>`${ma(e)}-${t.toLowerCase()}`,Up=()=>{let e=Bp();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},Bp=()=>{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},Vp=e=>{let t=Kp(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]}},Kp=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),Gp=async(e,t)=>{await new Promise((r,n)=>{let s=jp("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 Hp,constants as zp}from"node:fs";import{homedir as fa}from"node:os";import Oe from"node:path";var Yp=[Oe.join(fa(),".local","bin"),Oe.join(fa(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function ha(e=process.env){return Jp([...(e.PATH??"").split(Oe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:Yp])}function Je(e=process.env){return{...e,PATH:ha(e).join(Oe.delimiter)}}function zn(e,t={}){if(e.includes(Oe.sep)){let r=Oe.isAbsolute(e)?e:Oe.resolve(t.cwd??process.cwd(),e);return ga(r)?r:null}for(let r of ha(t.env)){let n=Oe.join(r,e);if(ga(n))return n}return null}function Qe(e,t={}){let r=zn(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 ga(e){try{return Hp(e,zp.X_OK),!0}catch{return!1}}function Jp(e){return[...new Set(e)]}var Ft={async create(e,t){let r=await la(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await ua(r.paneId,t.logPath,t.repoRoot);let n=await wa({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||Hn(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 Ye(e,s),s},async attach(e,t,r){let n=await Ft.snapshot(t,r);if(!n.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Ir(r,t.paneId,t.windowTarget,t.sessionName);let s={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:n};return await Ye(e,s),s},async resize(e,t,r,n){await ca(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ye(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 Ye(e,n),n},async snapshot(e,t){return Qp(e,t)}},Yn={async prepare(e,t){let n=e.runnerSession.command[0],s=Je();Qe(n,{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Qe(r[0],{cwd:e.worktreePath,env:Je()});await da(t.session.paneId,[n,...r.slice(1)].map(s=>Sr(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},Qp=async(e,t)=>{let r=await D("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return wa({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},wa=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var Jn=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 Nt(e,n.workspaceId,s,{runner:i,config:o}):await gt(e,t,s,{runner:i,config:o}),l=a.task,c=f.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?ka.resolve(e.workspaceRoot,l.artifacts.logPath):ka.join(e.logsDir,`${l.id}.log`);try{await Yn.prepare(l,{repoRoot:a.repoRoot});let m=await Ft.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await Yn.launch(l,{repoRoot:a.repoRoot,session:m});let g=new Date().toISOString();m={...m,status:"running",startedAt:g,command:c};let y=await E(e,l.id,w=>({...w,status:"running",runner:i,sessionId:m.id,selectedPtyTabId:w.selectedPtyTabId,runnerSession:{command:m.command,pid:null,startedAt:g,lastKnownState:"running",exitCode:null,exitedAt:null}}));return await Ye(e,m),{kind:"createTask",taskId:y.id,repoId:y.repoId,workspaceId:y.workspaceId,sessionId:m.id,status:y.status,branch:y.branch,worktreePath:y.worktreePath,runner:y.runner}}catch(m){throw await E(e,l.id,g=>({...g,sessionId:null,status:"draft",runnerSession:{...g.runnerSession,lastKnownState:"failed"},lastFailureReason:m instanceof Error?m.message:"Unknown Craig error"})),m}};import{mkdir as nm}from"node:fs/promises";import sm from"node:path";var Me=async e=>{let t=await D("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Ta=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await S("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},ht=async(e,t)=>{let r=await S("gh",Qn(e),{cwd:t});return JSON.parse(r.stdout)},wt=async(e,t)=>{let r=await D("gh",Qn(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},ya=async(e,t)=>{let r=await D("gh",Qn(e),{cwd:t});if(r.exitCode===0)return JSON.parse(r.stdout);let n=r.stderr.trim()||r.stdout.trim();if(Zp(n))return null;throw new Error(n||`GitHub CLI failed while discovering a pull request for ${e}.`)},Ra=async(e,t,r)=>{if(r.length===0)return[];let n=tm(r),s;try{s=await S("gh",["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`])}catch(a){throw Xp(a)?new ge(a instanceof Error?a.message:String(a)):a}let i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=rm(c);return{id:a.id,found:d!==null,view:d}})},Cr=async e=>{let t=await D("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:em(t.stdout.trim())},Le=e=>{let t=e.trim().match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/([1-9]\d*)(?:[/?#].*)?$/);return!t?.[1]||!t[2]||!t[3]?null:{owner:t[1],name:t[2],number:Number(t[3])}},Xp=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")},Zp=e=>{let t=e.toLowerCase();return t.includes("no pull requests found")||t.includes("could not resolve to a pullrequest")},Qn=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],em=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},tm=e=>`
|
|
17
|
+
`)},Zn=e=>({source:{type:"repo_config",path:e},lastRunAt:null,status:"not_run",commands:[],results:[]}),ma=()=>({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}),Cr=()=>({paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}),zp=async(e,t)=>{let n=(await oe(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},ga=e=>e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-");import va from"node:path";import{readFile as Yp,rm as FR}from"node:fs/promises";import Jp from"node:path";var $e=async(e,t)=>{let r=await Yp(es(e,t),"utf8"),n=JSON.parse(r);return Qp(n,es(e,t))},Ye=async(e,t)=>{await U(es(e,t.id),{...t,updatedAt:new Date().toISOString()})};var es=(e,t)=>Jp.join(e.sessionsDir,`${t}.json`);function Qp(e,t){let r=em(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")||!Zp(r.attach)||!Xp(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 Xp(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 Zp(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 em(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 tm}from"node:child_process";import{createHash as rm}from"node:crypto";import nm from"node:path";function Ar(e){return`'${e.replace(/'/g,"'\\''")}'`}var sm="craig",ha=async(e,t,r)=>{let n=ts(e,t),s=im(),o=await I("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",n,"-n","runner",...s,"-c",r],{cwd:e}),i=lm(o.stdout);return await om(e,n),i};var om=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 I("tmux",n,{cwd:e})},ka=async(e,t,r)=>{await I("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})},wa=async(e,t,r)=>{await I("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})};var Ta=async(e,t,r)=>{await I("tmux",["pipe-pane","-o","-t",e,`cat >> ${Ar(t)}`],{cwd:r})},Er=async(e,t,r,n)=>{let s=n??Ra(e);if(r?await I("tmux",["select-window","-t",r],{cwd:e}):await I("tmux",["select-window","-t",t],{cwd:e}),await I("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await I("tmux",["switch-client","-t",s],{cwd:e});return}await dm(e,["attach-session","-t",s])};var ya=async(e,t)=>{await I("tmux",["kill-session","-t",t],{cwd:e})};var Ra=e=>{let r=nm.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",n=rm("sha1").update(e).digest("hex").slice(0,8);return`${sm}-${r}-${n}`},ts=(e,t)=>`${Ra(e)}-${t.toLowerCase()}`,im=()=>{let e=am();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]},am=()=>{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},lm=e=>{let t=cm(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]}},cm=e=>e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0),dm=async(e,t)=>{await new Promise((r,n)=>{let s=tm("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 um,constants as pm}from"node:fs";import{homedir as ba}from"node:os";import Oe from"node:path";var mm=[Oe.join(ba(),".local","bin"),Oe.join(ba(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function Sa(e=process.env){return fm([...(e.PATH??"").split(Oe.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:mm])}function Je(e=process.env){return{...e,PATH:Sa(e).join(Oe.delimiter)}}function rs(e,t={}){if(e.includes(Oe.sep)){let r=Oe.isAbsolute(e)?e:Oe.resolve(t.cwd??process.cwd(),e);return Pa(r)?r:null}for(let r of Sa(t.env)){let n=Oe.join(r,e);if(Pa(n))return n}return null}function Qe(e,t={}){let r=rs(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 Pa(e){try{return um(e,pm.X_OK),!0}catch{return!1}}function fm(e){return[...new Set(e)]}var Bt={async create(e,t){let r=await ha(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Ta(r.paneId,t.logPath,t.repoRoot);let n=await Ia({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||ts(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 Ye(e,s),s},async attach(e,t,r){let n=await Bt.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 Ye(e,s),s},async resize(e,t,r,n){await ka(n,t.sessionName,r);let s={...t,attach:{...t.attach,lastSize:r}};return await Ye(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 Ye(e,n),n},async snapshot(e,t){return gm(e,t)}},ns={async prepare(e,t){let n=e.runnerSession.command[0],s=Je();Qe(n,{cwd:t.repoRoot,env:s})},async launch(e,t){let r=e.runnerSession.command,n=Qe(r[0],{cwd:e.worktreePath,env:Je()});await wa(t.session.paneId,[n,...r.slice(1)].map(s=>Ar(s)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}},gm=async(e,t)=>{let r=await $("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return Ia({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(n=>n.trim()===e.paneId)})},Ia=async e=>({paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()});var ss=async(e,t,r,n={})=>{let s=r.trim(),o=await g.load(e),i=n.runner??g.runners.getDefault(o);if(g.runners.assertEnabled(i,o),t.trim().length===0)throw new Error(n.workspaceId?"Workspace id cannot be empty.":"Repo id cannot be empty.");if(s.length===0)throw new Error("Task prompt cannot be empty.");let a=n.workspaceId?await qt(e,n.workspaceId,s,{runner:i,config:o}):await ht(e,t,s,{runner:i,config:o}),l=a.task,c=g.runners.buildCommand(i,s,o),d=`session_${l.id}`,u=l.artifacts.logPath?va.resolve(e.workspaceRoot,l.artifacts.logPath):va.join(e.logsDir,`${l.id}.log`);try{await ns.prepare(l,{repoRoot:a.repoRoot});let p=await Bt.create(e,{sessionId:d,taskId:l.id,repoId:a.repoId,workspaceId:a.workspaceId,repoRoot:a.repoRoot,worktreePath:l.worktreePath,logPath:u,command:c});await ns.launch(l,{repoRoot:a.repoRoot,session:p});let f=new Date().toISOString();p={...p,status:"running",startedAt:f,command:c};let w=await x(e,l.id,h=>({...h,status:"running",runner:i,sessionId:p.id,selectedPtyTabId:h.selectedPtyTabId,runnerSession:{command:p.command,pid:null,startedAt:f,lastKnownState:"running",exitCode:null,exitedAt:null}}));return await Ye(e,p),{kind:"createTask",taskId:w.id,repoId:w.repoId,workspaceId:w.workspaceId,sessionId:p.id,status:w.status,branch:w.branch,worktreePath:w.worktreePath,runner:w.runner}}catch(p){throw await x(e,l.id,f=>({...f,sessionId:null,status:"draft",runnerSession:{...f.runnerSession,lastKnownState:"failed"},lastFailureReason:p instanceof Error?p.message:"Unknown Craig error"})),p}};import{mkdir as Rm}from"node:fs/promises";import bm from"node:path";var Me=async e=>{let t=await $("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")};var Ca=async(e,t,r)=>{let n=r==="merge"?"--merge":r==="rebase"?"--rebase":"--squash";await I("gh",["pr","merge",String(t),n,"--delete-branch=false"],{cwd:e})},kt=async(e,t)=>{let r=await I("gh",os(e),{cwd:t});return JSON.parse(r.stdout)},wt=async(e,t)=>{let r=await $("gh",os(e),{cwd:t});return r.exitCode!==0?null:JSON.parse(r.stdout)},Aa=async(e,t)=>{let r=await $("gh",os(e),{cwd:t});if(r.exitCode===0)return JSON.parse(r.stdout);let n=r.stderr.trim()||r.stdout.trim();if(km(n))return null;throw new Error(n||`GitHub CLI failed while discovering a pull request for ${e}.`)},Ea=async(e,t,r)=>{if(r.length===0)return[];let n=Tm(r),s;try{s=await I("gh",["api","graphql","-f",`query=${n}`,"-F",`owner=${t.owner}`,"-F",`name=${t.name}`])}catch(a){throw hm(a)?new ge(a instanceof Error?a.message:String(a)):a}let i=JSON.parse(s.stdout).data?.repository??{};return r.map((a,l)=>{let c=i[`item${l}`],d=ym(c);return{id:a.id,found:d!==null,view:d}})},xr=async e=>{let t=await $("git",["remote","get-url","origin"],{cwd:e});return t.exitCode!==0?null:wm(t.stdout.trim())},Ne=e=>{let t=e.trim().match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/([1-9]\d*)(?:[/?#].*)?$/);return!t?.[1]||!t[2]||!t[3]?null:{owner:t[1],name:t[2],number:Number(t[3])}},hm=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")},km=e=>{let t=e.toLowerCase();return t.includes("no pull requests found")||t.includes("could not resolve to a pullrequest")},os=e=>["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,isDraft,title,createdAt,updatedAt,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments"],wm=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},Tm=e=>`
|
|
18
18
|
query CraigPullRequestBatch($owner: String!, $name: String!) {
|
|
19
19
|
repository(owner: $owner, name: $name) {
|
|
20
20
|
${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(`
|
|
@@ -68,57 +68,61 @@ fragment PrFields on PullRequest {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
`,
|
|
71
|
+
`,ym=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??[];return{number:r.number,url:r.url,baseRefName:r.baseRefName,headRefName:r.headRefName,headRefOid:r.headRefOid??null,state:r.state,isDraft:r.isDraft??!1,title:r.title??null,createdAt:r.createdAt??null,updatedAt:r.updatedAt??null,mergedAt:r.mergedAt??null,mergeable:r.mergeable,mergeStateStatus:r.mergeStateStatus,reviewDecision:r.reviewDecision??null,statusCheckRollup:n,comments:r.comments?.nodes??[]}};var Xe=async(e,t)=>{let r=ze(e,t.artifacts.prStatusPath);r&&(await Rm(bm.dirname(r),{recursive:!0}),await U(r,{taskId:t.id,prs:t.prs}))},Vt=async(e,t,r={writeTask:be,writePrStatusArtifact:Xe})=>{await r.writeTask(e,t);try{await r.writePrStatusArtifact(e,t)}catch(n){throw new y("PARTIAL_RESULT",`Task ${t.id} was updated, but its PR status artifact could not be written.`,{retryable:!0,details:{taskId:t.id},cause:n})}return t},Kt=async(e,t,r,n,s={readRawTask:Re,validateTaskRecord:ae,writeTask:be,writePrStatusArtifact:Xe,withTaskLock:xe})=>s.withTaskLock(e,t.id,async()=>{let o=await s.readRawTask(e,t.id),i=s.validateTaskRecord(o,`${e.tasksDir}/${t.id}.json`),a=i.prs.find(p=>n?.number!==null&&p.number===n?.number)??n,l=Se(r,a),c=Pe(i,l),d=i.status==="closed"?i.status:He(c.prs),u={...c,status:d};return Vt(e,u,s)}),Gt=async(e,t)=>{let r=E(t),n=r?.number?String(r.number):t.branch,s=await kt(n,t.worktreePath);return Kt(e,t,s,r)},Ht=async(e,t)=>{for(let r of await is(t)){let n=await wt(r,t.worktreePath);if(!n)continue;return{discovered:!0,task:await Kt(e,t,n,null)}}return{discovered:!1,task:t}},is=async e=>{let t=await ia(e.worktreePath).catch(()=>null);return[...new Set([t,e.branch].filter(r=>!!r))]};async function zt(e,t,r,n){return xe(e,t,async()=>{let s=await v(e,t);if(!s.repoTargets?.find(f=>f.repoId===r))throw new Error(`Project task ${t} has no repo target ${r}.`);let i=Ne(n.url),a=s.prs.find(f=>i?mt(f,{owner:i.owner,repo:i.name,number:n.number}):f.number===n.number)??null,l=Se(n,a,i??void 0),c=Pm(n),d=Pe(s,l),u={...d,repoTargets:(d.repoTargets??[]).map(f=>f.repoId===r?{...f,pullRequest:c}:f)},p={...u,status:u.status==="closed"?u.status:as(u)};return Vt(e,p)})}function Pm(e){let t=Ne(e.url);return{provider:"github",owner:t?.owner??null,repo:t?.name??null,number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Sm(e.state),draft:e.isDraft??!1,mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,reviewDecision:Im(e.reviewDecision??null),requiredChecks:Hn(e.statusCheckRollup),comments:[],lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}}function as(e){let t=(e.repoTargets??[]).filter(n=>n.status==="ready"),r=t.map(n=>n.pullRequest).filter(n=>n.number!==null);return r.length===0?"checked":r.every(n=>n.status==="merged")?"merged":r.length===t.length&&r.every(n=>n.mergeable&&n.reviewDecision!=="REVIEW_REQUIRED"&&n.reviewDecision!=="CHANGES_REQUESTED"&&n.mergeStateStatus!=="REVIEW_REQUIRED"&&n.requiredChecks.length>0&&n.requiredChecks.every(s=>s.status==="success"||s.status==="skipped"))?"merge_ready":r.some(n=>n.status==="open")?"pr_open":"checked"}var Sm=e=>e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null,Im=e=>e==="APPROVED"||e==="CHANGES_REQUESTED"||e==="REVIEW_REQUIRED"?e:null;var Tt=async(e,t,r)=>{let n=r.pullRequest.number?String(r.pullRequest.number):r.branch;if(r.pullRequest.number){let o=await kt(n,r.worktreePath);return await zt(e,t.id,r.repoId,o),"synced"}let s=await wt(n,r.worktreePath);return s?(await zt(e,t.id,r.repoId,s),"discovered"):"not_found"};var Yt=async(e,t)=>{let r=await v(e,t),n=E(r);return n?.number?(await Me(r.worktreePath),De(n)?(await Ht(e,r)).task:Gt(e,r)):r},cs=async(e,t)=>{let r=await v(e,t);if(r.type==="project"&&r.repoTargets?.length)return await yt(e,t),v(e,t);let n=E(r);if(await K(r),await Me(r.worktreePath),!n?.number||De(n)){let o=await Ht(e,r);if(!o.discovered&&!n?.number)throw new Error(`No PR found for ${r.branch}.`);return o.task}return await Gt(e,r)},yt=async(e,t)=>{let r=await v(e,t),n=(r.repoTargets??[]).filter(o=>o.status==="ready"),s={synced:0,discovered:0,notFound:0};for(let o of n){await Me(o.worktreePath);let i=o.pullRequest.number?await Tt(e,r,o):await Tt(e,r,o).catch(()=>"not_found");s[i==="not_found"?"notFound":i]++}return s},ds=async(e,t)=>{let r=new Map,n=new Map;for(let s of t){let o=ls(r,s);if(s.type==="project"&&s.repoTargets?.length){for(let d of s.repoTargets.filter(u=>u.status==="ready")){let u={id:`${s.id}:${d.repoId}`,task:s,targetRepoId:d.repoId,worktreePath:d.worktreePath,selector:d.pullRequest.number?String(d.pullRequest.number):d.branch,mode:d.pullRequest.number?"number":"head",fallbackSelectors:[]};await xa(n,u).catch(async()=>{try{let p=d.pullRequest.number?await Tt(e,s,d):await Tt(e,s,d).catch(()=>"not_found");Dr(o,p,d.pullRequest.number??null,d.pullRequest.url??null)}catch{}})}continue}let i=E(s),a=i?.number&&!De(i),l=a?[]:await is(s),c={id:s.id,task:s,worktreePath:s.worktreePath,selector:a?String(i.number):l[0]??s.branch,mode:a?"number":"head",fallbackSelectors:a?[]:l.slice(1)};await xa(n,c).catch(async()=>{try{let{disposition:d,task:u}=await $r(e,s.id),p=E(u);Dr(o,d,p?.number??null,p?.url??null)}catch{}})}for(let s of n.values())try{await Me(s.worktreePath);let o=await Ea(s.worktreePath,s.repository,s.items),i=new Map(o.map(a=>[a.id,a]));for(let a of s.items){let l=ls(r,a.task),d=i.get(a.id)?.view??await vm(s.worktreePath,a);if(!d){Dr(l,"not_found",null,null);continue}if(a.targetRepoId)await zt(e,a.task.id,a.targetRepoId,d);else{let u=await Re(e,a.task.id),p=ae(u,`${e.tasksDir}/${a.task.id}.json`);await Kt(e,p,d,a.mode==="number"?E(p):null)}Dr(l,a.mode==="number"?"synced":"discovered",d.number,d.url)}}catch(o){if(o instanceof ge)throw o}return t.map(s=>ls(r,s))},$r=async(e,t)=>{let r=await v(e,t);await K(r),await Me(r.worktreePath);let n=E(r);if(n?.number&&!De(n))return{disposition:"synced",task:await Gt(e,r)};let s=await Ht(e,r);return{disposition:s.discovered?"discovered":"not_found",task:s.task}},vm=async(e,t)=>{if(t.mode!=="head")return null;for(let r of t.fallbackSelectors){let n=await wt(r,e);if(n)return n}return null},xa=async(e,t)=>{let r=await xr(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]})},ls=(e,t)=>{let r=e.get(t.id);if(r)return r;let n={taskId:t.id,synced:0,discovered:0,notFound:0,hadPr:t.type==="project"?!!t.repoTargets?.some(s=>s.pullRequest.number):!!E(t)?.number,firstDiscoveredPrNumber:null,firstDiscoveredPrUrl:null};return e.set(t.id,n),n},Dr=(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};var us=async(e,t)=>{let r=await v(e,t);try{r.type==="project"&&r.repoTargets?.length?(await yt(e,t),r=await v(e,t)):r.prs.some(o=>o.number)&&(r=await Yt(e,t))}catch{}let n=await jt(e,r),s=r.sessionId?await $e(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:n,session:s}};var ps=async(e,t)=>{let r=await v(e,t);if(await K(r),(await I("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let s=await Cm(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:s,isEmpty:!1}},Cm=async e=>{let t=[],r=await I("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let n=await Am(e);for(let s of n){let o=await $("git",["diff","--no-index","--stat","--patch","--","/dev/null",s],{cwd:e});t.push(o.stdout.trimEnd())}return t.join(`
|
|
72
72
|
|
|
73
|
-
`)},
|
|
74
|
-
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as um}from"node:child_process";import{access as pm}from"node:fs/promises";var os=async(e,t)=>{let r=await I(e,t),n=mt(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await pm(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},is=async e=>{await new Promise((t,r)=>{let n=!1,s=um("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 mm}from"node:fs/promises";import fm from"node:path";var as=async(e,t)=>{let r=await I(e,t);if(await K(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 Rr(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".`);await E(e,r.id,a=>({...a,status:a.status==="running"?r.status:a.status,checks:{...a.checks,status:"running",commands:[...s],results:[]}}));let o=[];for(let a of s){let l=new Date().toISOString(),c=await D("sh",["-lc",a],{cwd:r.worktreePath}),d=new Date().toISOString(),u=c.exitCode??1;if(o.push({command:a,startedAt:l,finishedAt:d,exitCode:u}),u!==0){let m=c.stderr.trim()||c.stdout.trim()||`Check command failed: ${a}`,g=await E(e,r.id,y=>({...y,status:"review",checks:{...y.checks,results:o,status:"failed",lastRunAt:d},lastFailureReason:m}));return await Pa(e,g),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}}let i=await E(e,r.id,a=>({...a,status:a.status==="review"||a.status==="checked"?"checked":a.status,checks:{...a.checks,results:o,status:"passed",lastRunAt:new Date().toISOString()},lastFailureReason:null}));return await Pa(e,i),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Pa=async(e,t)=>{let r=ze(e,t.artifacts.checkSummaryPath);r&&(await mm(fm.dirname(r),{recursive:!0}),await q(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var ls=async(e,t)=>{let r=await I(e,t);await K(r);let n=await Rr(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 Yi(r.worktreePath),await Ji(r.worktreePath,s);let o=await Qi(r.worktreePath),i=new Date().toISOString(),a=await E(e,r.id,l=>({...l,status:l.status==="running"?r.status:l.status,lastCommit:{sha:o.sha,message:o.message,committedAt:i},lastFailureReason:null}));return{kind:"commitTask",taskId:r.id,status:a.status,commitSha:o.sha,message:o.message}};import{access as gm}from"node:fs/promises";var cs=async(e,t)=>{let r=await I(e,t),n=await hm(r.worktreePath);return E(e,t,s=>({...s,status:"closed",cleanup:{...s.cleanup,preservedWorktree:n&&s.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null}))},hm=async e=>{try{return await gm(e),!0}catch{return!1}};var ds=async(e,t,r)=>{let n=[],s=null,o=null;try{if(t.sessionId){let i=await $e(e,t.sessionId);await pa(e.repoRoot,i.sessionName),s=new Date().toISOString()}}catch(i){n.push(i instanceof Error?i.message:"Failed to close tmux session.")}if(!r.preserveWorktree)try{await Zi(e.repoRoot,t.worktreePath),o=new Date().toISOString()}catch(i){n.push(i instanceof Error?i.message:"Failed to remove worktree.")}await E(e,t.id,i=>({...i,cleanup:{...i.cleanup,paneClosedAt:s??i.cleanup.paneClosedAt,worktreeRemovedAt:o??i.cleanup.worktreeRemovedAt,preservedWorktree:r.preserveWorktree,warning:n.length>0?n.join(" "):null}}))};var us=async(e,t,r)=>{let n=await le(e,r),s=await E(e,t,o=>{if(o.repoId===n.id)throw new Error(`Repo ${n.id} is already the primary repo for task ${o.id}.`);return{...o,linkedRepoIds:o.linkedRepoIds.includes(n.id)?o.linkedRepoIds:[...o.linkedRepoIds,n.id]}});return{kind:"addTaskLink",taskId:s.id,repoId:n.id,linkedRepoIds:s.linkedRepoIds}},ps=async(e,t)=>{let r=await I(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>le(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var ms=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[n,s]=await Promise.all([le(e,r.repoId),$e(e,r.sessionId)]),o=await Ft.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var fs=async(e,t)=>{let r=await I(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let n=await $e(e,r.sessionId).catch(s=>{throw wm(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 Ir(e.repoRoot,n.paneId,n.windowTarget,n.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:n.paneId}},wm=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as km}from"node:child_process";var gs=async(e,t)=>{let r=await I(e,t);await K(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 Tm(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},Tm=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=km(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 hs=async(e,t,r)=>{await E(e,t,n=>({...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r}))},ws=async(e,t,r)=>E(e,t,n=>({...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})),ks=async(e,t)=>E(e,t,r=>{let n=r.ptyTabs.find(s=>s.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);return{...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}}});import{realpath as Ia}from"node:fs/promises";import Kt from"node:path";async function ys(e,t){if(t.explicitTaskId!==void 0){let l=await Sa(e,t.explicitTaskId,"explicit");return Ts(l,"explicit",t.environmentAgentTabId)}if(t.environmentTaskId!==void 0){let l=await Sa(e,t.environmentTaskId,"environment");return Ts(l,"environment",t.environmentAgentTabId)}let r=await Ia(t.cwd).catch(()=>Kt.resolve(t.cwd)),n=await Mt(e,{includeClosed:!0}),o=(await Promise.all(n.tasks.map(async l=>({task:l,matches:await Rm(l,r)})))).filter(l=>l.matches).map(l=>l.task),i=[...new Map(o.map(l=>[l.id,l])).values()];if(i.length>1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Multiple Craig tasks match ${r}: ${i.map(l=>l.id).join(", ")}. Use --task <id>.`,{details:{cwd:r,taskIds:i.map(l=>l.id)}});let a=i[0];if(a)return Ts(a,"cwd",t.environmentAgentTabId);if(t.environmentAgentTabId!==void 0)throw new R("TASK_CONTEXT_CONFLICT",`CRAIG_AGENT_TAB_ID is set to ${t.environmentAgentTabId}, but no task context could be resolved.`,{details:{agentTabId:t.environmentAgentTabId}});if(t.required)throw new R("TASK_CONTEXT_NOT_FOUND",`No Craig task was found from ${r}. Use --task <id> or run the command inside a task worktree.`,{details:{cwd:r}});return null}async function Sa(e,t,r){try{return await I(e,t)}catch(n){throw!(n instanceof R)||n.code!=="TASK_NOT_FOUND"?n:new R("TASK_CONTEXT_NOT_FOUND",`Craig task "${t}" from ${r==="explicit"?"--task":"CRAIG_TASK_ID"} was not found.`,{details:{taskId:t,source:r},cause:n})}}function Ts(e,t,r){let n=r??null;if(n!==null){let s=e.ptyTabs.find(o=>o.id===n);if(!s||s.kind!=="agent")throw new R("TASK_CONTEXT_CONFLICT",`Agent tab ${n} does not belong to Craig task ${e.id}.`,{details:{taskId:e.id,agentTabId:n}})}return{task:e,source:t,agentTabId:n}}function ym(e){return[e.worktreePath,...e.bundlePath?[e.bundlePath]:[],...(e.repoTargets??[]).map(t=>t.worktreePath)]}async function Rm(e,t){return(await Promise.all(ym(e).map(n=>Ia(n).catch(()=>Kt.resolve(n))))).some(n=>bm(n,t))}function bm(e,t){let r=Kt.relative(Kt.resolve(e),t);return r===""||!r.startsWith("..")&&!Kt.isAbsolute(r)}var Rs=async(e,t,r="merge",n)=>{let s=await I(e,t),o=n??A(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Ta(s.worktreePath,o,r)};var Gt={readTask:I,writeTask:be,withTaskLock:xe,ensureGhAuthenticated:Me,fetchPrView:ht,discoverPrView:ya,getGitHubRepositoryLocator:Cr,writePrStatusArtifact:Xe};async function Ps(e,t,r,n=Gt){let s=await n.readTask(e,t),o=await Sm(s,r,n);return Ne(s,o,"showTaskPr","shown",[])}async function Ss(e,t,r,n=Gt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await Es(s,r,null,n);await xs(o,n);let i=await xr(`discover a pull request for ${o.branch}`,()=>n.discoverPrView(o.branch,o.worktreePath));if(!i)return Ne(s,o,"discoverTaskPr","not_found",[]);Ds(i,o);let a=Dr(s,o,i.number),l=await $s(e,s,o,i,n);return Ne(l,o,"discoverTaskPr",a?"synced":"discovered",[])})}async function Is(e,t,r,n,s=Gt){let o=As(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await Es(i,n,o.repository,s);va(o.repository,a),await xs(a,s);let l=await xr(`fetch pull request ${r}`,()=>s.fetchPrView(r,a.worktreePath));Im(l,o),Ds(l,a);let c=Dr(i,a,l.number),d=Os(i,a),u=d&&!pt(d,{owner:a.repository.owner,repo:a.repository.name,number:l.number})&&d.status!=="closed"&&d.status!=="merged"?[`Pull request #${l.number} becomes active; #${d.number} remains in task history.`]:[],m=await $s(e,i,a,l,s);return Ne(m,a,"linkTaskPr",c?"unchanged":"linked",u)})}async function Pm(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);let i=e.prs.find(a=>a.number===r.number)??A(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Er(i,e.worktreePath,e.repoId,n),projectTarget:null}}if(t){let i=e.repoTargets?.find(c=>c.repoId===t);if(!i)throw yt(e,t);let a=Ca(i.pullRequest),l=e.prs.find(c=>c.number===r.number&&(!c.headBranch||c.headBranch===i.branch)&&(!a||!!(c.owner&&c.repo&&he({owner:c.owner,name:c.repo},a))))??i.pullRequest;return{repoId:t,branch:i.branch,worktreePath:i.worktreePath,repository:await Er(l,i.worktreePath,t,n),projectTarget:i}}if(!r.repository)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for a numeric pull request selector.`,{details:{taskId:e.id,pullRequestNumber:r.number}});let s=r.repository,o=[];for(let i of e.repoTargets??[]){let a=i.pullRequest.owner&&i.pullRequest.repo&&he({owner:i.pullRequest.owner,name:i.pullRequest.repo},s),l=e.prs.some(c=>c.number===r.number&&c.owner&&c.repo&&he({owner:c.owner,name:c.repo},s)&&(!c.headBranch||c.headBranch===i.branch));(a||l)&&o.push({repoId:i.repoId,branch:i.branch,worktreePath:i.worktreePath,repository:s,projectTarget:i})}if(o.length!==1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.repository.owner}/${r.repository.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.repository.owner,repo:r.repository.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Cs(e,t,r,n=Gt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await Es(s,r,null,n),i=Os(s,o);if(!i?.number)return Ne(s,o,"refreshTaskPr","not_found",[]);await xs(o,n);let a=await xr(`refresh pull request #${i.number}`,()=>n.fetchPrView(String(i.number),o.worktreePath));Ds(a,o);let l=await $s(e,s,o,a,n);return Ne(l,o,"refreshTaskPr","synced",[])})}async function vs(e,t,r,n,s=Gt){let o=As(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await Pm(i,n,o,s);if(va(o.repository,a),!Dr(i,a,o.number))return Ne(i,a,"unlinkTaskPr","unchanged",[]);let c=Cm(i,a,o.number),d=await Ea(e,c,s);return Ne(d,a,"unlinkTaskPr","unlinked",[])})}function As(e){let t=e.trim(),r=Le(t);if(r)return{number:r.number,repository:r};if(/^[1-9]\d*$/.test(t))return{number:Number(t),repository:null};throw new R("CLI_USAGE",`Invalid pull request selector "${e}". Use a GitHub pull request URL or positive number.`,{details:{selector:e}})}async function Es(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);return bs(e.repoId,e.branch,e.worktreePath,null,n)}let s=e.repoTargets??[];if(t){let i=s.find(a=>a.repoId===t);if(!i)throw yt(e,t);return bs(i.repoId,i.branch,i.worktreePath,i,n)}if(!r)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:s.map(i=>i.repoId)}});let o=[];for(let i of s){let a=await bs(i.repoId,i.branch,i.worktreePath,i,n).catch(l=>{if(l instanceof R&&l.code==="EXTERNAL_DEPENDENCY_FAILED"&&l.message.includes("does not have a supported GitHub origin remote"))return null;throw l});a&&he(a.repository,r)&&o.push(a)}if(o.length!==1)throw new R("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.owner}/${r.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.owner,repo:r.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Sm(e,t,r){if(e.type==="repo"){if(t&&t!==e.repoId)throw yt(e,t);let s=A(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Er(s,e.worktreePath,e.repoId,r),projectTarget:null}}if(!t)throw new R("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:(e.repoTargets??[]).map(s=>s.repoId)}});let n=e.repoTargets?.find(s=>s.repoId===t);if(!n)throw yt(e,t);return{repoId:t,branch:n.branch,worktreePath:n.worktreePath,repository:await Er(n.pullRequest,n.worktreePath,t,r),projectTarget:n}}async function Er(e,t,r,n){let s=Ca(e);return s||(await n.getGitHubRepositoryLocator(t).catch(()=>null)??{owner:"",name:r})}function Ca(e){return e?.owner&&e.repo?{owner:e.owner,name:e.repo}:e?.url?Le(e.url):null}async function bs(e,t,r,n,s){let o=await s.getGitHubRepositoryLocator(r);if(!o)throw new R("EXTERNAL_DEPENDENCY_FAILED",`Repo ${e} does not have a supported GitHub origin remote.`,{details:{repoId:e,worktreePath:r}});return{repoId:e,branch:t,worktreePath:r,repository:o,projectTarget:n}}async function xs(e,t){await xr("verify GitHub CLI authentication",()=>t.ensureGhAuthenticated(e.worktreePath))}async function xr(e,t){try{return await t()}catch(r){throw r instanceof R?r:new R("EXTERNAL_DEPENDENCY_FAILED",`Failed to ${e}: ${r instanceof Error?r.message:String(r)}`,{retryable:!0,cause:r})}}function va(e,t){if(e&&!he(e,t.repository))throw Aa(e,t)}function Im(e,t){let r=Le(e.url);if(!r||r.number!==t.number)throw new R("TASK_CONTEXT_CONFLICT",`GitHub returned ${e.url} for pull request selector #${t.number}.`,{details:{selectorNumber:t.number,returnedUrl:e.url}});if(t.repository&&!he(t.repository,r))throw new R("PR_REPOSITORY_MISMATCH",`GitHub returned a pull request from ${r.owner}/${r.name}, not ${t.repository.owner}/${t.repository.name}.`,{details:{selectorRepository:t.repository,returnedRepository:r}})}function Ds(e,t){let r=Le(e.url);if(!r||!he(r,t.repository))throw Aa(r,t);if(e.headRefName!==t.branch)throw new R("PR_BRANCH_MISMATCH",`Pull request #${e.number} uses head branch ${e.headRefName}, not task branch ${t.branch}.`,{details:{repoId:t.repoId,pullRequestNumber:e.number,expectedBranch:t.branch,actualBranch:e.headRefName}})}function Aa(e,t){return new R("PR_REPOSITORY_MISMATCH",`Pull request repository ${e?`${e.owner}/${e.name}`:"is invalid"} does not match task repo ${t.repository.owner}/${t.repository.name}.`,{details:{repoId:t.repoId,expectedOwner:t.repository.owner,expectedRepo:t.repository.name,actualOwner:e?.owner??null,actualRepo:e?.name??null}})}function yt(e,t){return new R("TASK_CONTEXT_CONFLICT",`Repo ${t} is not a target of task ${e.id}.`,{details:{taskId:e.id,repoId:t}})}function he(e,t){return e.owner.toLowerCase()===t.owner.toLowerCase()&&e.name.toLowerCase()===t.name.toLowerCase()}async function $s(e,t,r,n,s){let o=Dr(t,r,n.number),i=Se(n,o,r.repository),a=Pe(t,i);return r.projectTarget&&(a={...a,repoTargets:(a.repoTargets??[]).map(l=>l.repoId===r.repoId?{...l,pullRequest:$a(i)}:l)}),Ea(e,a,s)}function Cm(e,t,r){let n=e.prs.filter(o=>!Da(o,t,r)),s={...e,prs:n};if(t.projectTarget?.pullRequest.number===r){let o=xa(n.filter(i=>i.owner&&i.repo&&he({owner:i.owner,name:i.repo},t.repository)));s={...s,repoTargets:(s.repoTargets??[]).map(i=>i.repoId===t.repoId?{...i,pullRequest:o?$a(o):Am(t.repository)}:i)}}return s}async function Ea(e,t,r){let n=t.status==="closed"?t.status:t.type==="project"?Zn(t):He(t.prs),s={...t,status:n};return _t(e,s,r)}function Dr(e,t,r){return Ms(e,t).find(n=>Da(n,t,r))??null}function Os(e,t){if(!t.projectTarget)return A(e);let r=Ms(e,t);return xa(r)}function xa(e){return[...e].reverse().find(t=>t.status!=="merged"&&t.status!=="closed")??e[e.length-1]??null}function Ms(e,t){if(!t.projectTarget)return e.prs;let r=e.prs.filter(o=>o.owner&&o.repo&&he({owner:o.owner,name:o.repo},t.repository)),n=e.repoTargets?.find(o=>o.repoId===t.repoId),s=n?.pullRequest.number?vm(n.pullRequest,t.repository):null;return s&&!r.some(o=>pt(o,s))?[...r,s]:r}function Da(e,t,r){return e.number!==r?!1:!e.owner||!e.repo||he({owner:e.owner,name:e.repo},t.repository)}function Ne(e,t,r,n,s){let o=Ms(e,t);return{kind:r,taskId:e.id,repoId:t.repoId,disposition:n,pullRequests:o,primaryPullRequest:Os(e,t),warnings:s}}function $a(e){return{provider:"github",owner:e.owner,repo:e.repo,number:e.number,url:e.url,baseBranch:e.baseBranch,headBranch:e.headBranch,status:e.status==="draft"?"open":e.status,draft:e.draft,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function vm(e,t){return{provider:"github",owner:e.owner??t.owner,repo:e.repo??t.name,number:e.number,url:e.url,title:null,status:e.draft?"draft":e.status,draft:e.draft??!1,baseBranch:e.baseBranch,headBranch:e.headBranch,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function Am(e){return{provider:"github",owner:e.owner,repo:e.name,number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}}var C={listTasks:Mt,getTask:I,provisionTask:gt,provisionProjectTask:Nt,createTask:Jn,showTask:ns,showTaskDiff:ss,prepareTaskLogs:os,streamTaskLogs:is,runChecks:as,commitTask:ls,closeTask:cs,cleanupTask:ds,addTaskLink:us,listTaskLinks:ps,sortTasksForDisplay:Bn,resolveSelectedTaskId:Vn,allocateTaskId:Un,allocateTaskIdForRepo:ft,allocateProjectTaskId:Ot,createDefaultTaskPtyTabs:jt,assertTaskWorktreeExists:K,resolveTaskLogPath:mt,buildTaskInspection:$t,resolveArtifactPath:ze,attachTask:ms,focusTask:fs,openTask:gs,markRunnerFailed:hs,recordStartupFailure:ws,markTaskStarted:ks,resolveContext:ys,prs:{refresh:Vt,refreshChecks:ts,discoverOrRefresh:Ar,discoverOrRefreshAll:Tt,discoverOrRefreshMany:rs,show:Ps,discover:Ss,link:Is,refreshAssociation:Cs,unlink:vs,merge:Rs,getPrimaryPr:A,isPrTerminal:De,isMergeReady:yr,deriveTaskStatus:He,upsertPr:Pe,normalizePr:Se,summarizeRequiredChecks:Fn,writePrStatusArtifact:Xe}};async function Oa(e,t){switch(e.kind){case"addWorkspace":{let r=await G.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await Ls(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await G.repos.addRepo(t.paths,e.path);return await Ls(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return G.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await it({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await se(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await G.repos.removeRepo(t.paths,e.repoId,{listTasks:C.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return G.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await G.archiveWorkspace(t.paths,e.workspaceId);return await Em(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await G.restoreWorkspace(t.paths,e.workspaceId);return await Ls(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return G.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"currentTask":{let r=Ns(t);return{kind:"currentTask",task:r.task,context:{source:r.source,agentTabId:r.agentTabId}}}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"showCurrentTask":return C.showTask(t.paths,Ns(t).task.id);case"showTaskPr":return C.prs.show(t.paths,Ht(e.taskId,t),e.repoId);case"discoverTaskPr":return C.prs.discover(t.paths,Ht(e.taskId,t),e.repoId);case"linkTaskPr":return C.prs.link(t.paths,Ht(e.taskId,t),e.pullRequest,e.repoId);case"refreshTaskPr":return C.prs.refreshAssociation(t.paths,Ht(e.taskId,t),e.repoId);case"unlinkTaskPr":return C.prs.unlink(t.paths,Ht(e.taskId,t),e.pullRequest,e.repoId);case"showSelectedTask":return C.showTask(t.paths,Ze(t,"show"));case"streamTaskLogs":return C.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return C.prepareTaskLogs(t.paths,Ze(t,"logs"));case"showTaskDiff":return C.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return C.showTaskDiff(t.paths,Ze(t,"diff"));case"focusTask":return C.focusTask(t.paths,e.taskId);case"focusSelectedTask":return C.focusTask(t.paths,Ze(t,"focus"));case"openTask":return C.openTask(t.paths,e.taskId);case"openSelectedTask":return C.openTask(t.paths,Ze(t,"open"));case"runChecks":return C.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return C.runChecks(t.paths,Ze(t,"check"));case"commitTask":return C.commitTask(t.paths,e.taskId);case"commitSelectedTask":return C.commitTask(t.paths,Ze(t,"commit"));case"showContext":{let r=Dm(t);return{kind:"showContext",workspace:{root:r.workspaceRoot,source:r.source,initialized:r.initialized},task:t.taskContext?{id:t.taskContext.task.id,source:t.taskContext.source,agentTabId:t.taskContext.agentTabId}:null}}case"help":return{kind:"help",text:Pn()};case"exit":return{kind:"exit"};default:return xm(e)}}async function Ls(e,t,r){let n=await it({uiStateFile:e.uiStateFile})??lr();await Ee({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function Em(e,t){let r=await it({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Ee({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function xm(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Ze(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 Ns(e){if(e.taskContext)return e.taskContext;throw new Error("Command requires resolved task context.")}function Ht(e,t){return e??Ns(t).task.id}function Dm(e){if(e.workspaceContext)return e.workspaceContext;throw new Error("Command requires resolved workspace context.")}function Ma(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(`
|
|
73
|
+
`)},Am=async e=>(await I("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
74
|
+
`).map(r=>r.trim()).filter(r=>r.length>0);import{spawn as Em}from"node:child_process";import{access as xm}from"node:fs/promises";var ms=async(e,t)=>{let r=await v(e,t),n=ft(e,r);if(!n)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await xm(n)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${n}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:n}},fs=async e=>{await new Promise((t,r)=>{let n=!1,s=Em("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 Dm}from"node:fs/promises";import $m from"node:path";var gs=async(e,t)=>{let r=await v(e,t);if(await K(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 Ir(r.worktreePath)&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot run checks from status "${r.status}".`);let s=(await g.load(e)).checks?.commands??[];if(s.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);await x(e,r.id,a=>({...a,status:a.status==="running"?r.status:a.status,checks:{...a.checks,status:"running",commands:[...s],results:[]}}));let o=[];for(let a of s){let l=new Date().toISOString(),c=await $("sh",["-lc",a],{cwd:r.worktreePath}),d=new Date().toISOString(),u=c.exitCode??1;if(o.push({command:a,startedAt:l,finishedAt:d,exitCode:u}),u!==0){let p=c.stderr.trim()||c.stdout.trim()||`Check command failed: ${a}`,f=await x(e,r.id,w=>({...w,status:"review",checks:{...w.checks,results:o,status:"failed",lastRunAt:d},lastFailureReason:p}));return await Da(e,f),{kind:"runChecks",taskId:r.id,status:"failed",commands:s}}}let i=await x(e,r.id,a=>({...a,status:a.status==="review"||a.status==="checked"?"checked":a.status,checks:{...a.checks,results:o,status:"passed",lastRunAt:new Date().toISOString()},lastFailureReason:null}));return await Da(e,i),{kind:"runChecks",taskId:r.id,status:"passed",commands:s}},Da=async(e,t)=>{let r=ze(e,t.artifacts.checkSummaryPath);r&&(await Dm($m.dirname(r),{recursive:!0}),await U(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))};var hs=async(e,t)=>{let r=await v(e,t);await K(r);let n=await Ir(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 na(r.worktreePath),await sa(r.worktreePath,s);let o=await oa(r.worktreePath),i=new Date().toISOString(),a=await x(e,r.id,l=>({...l,status:l.status==="running"?r.status:l.status,lastCommit:{sha:o.sha,message:o.message,committedAt:i},lastFailureReason:null}));return{kind:"commitTask",taskId:r.id,status:a.status,commitSha:o.sha,message:o.message}};import{access as Om}from"node:fs/promises";var ks=async(e,t)=>{let r=await v(e,t),n=await Mm(r.worktreePath);return x(e,t,s=>({...s,status:"closed",cleanup:{...s.cleanup,preservedWorktree:n&&s.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null}))},Mm=async e=>{try{return await Om(e),!0}catch{return!1}};var ws=async(e,t,r)=>{let n=[],s=null,o=null;try{if(t.sessionId){let i=await $e(e,t.sessionId);await ya(e.repoRoot,i.sessionName),s=new Date().toISOString()}}catch(i){n.push(i instanceof Error?i.message:"Failed to close tmux session.")}if(!r.preserveWorktree)try{await aa(e.repoRoot,t.worktreePath),o=new Date().toISOString()}catch(i){n.push(i instanceof Error?i.message:"Failed to remove worktree.")}await x(e,t.id,i=>({...i,cleanup:{...i.cleanup,paneClosedAt:s??i.cleanup.paneClosedAt,worktreeRemovedAt:o??i.cleanup.worktreeRemovedAt,preservedWorktree:r.preserveWorktree,warning:n.length>0?n.join(" "):null}}))};var Ts=async(e,t,r)=>{let n=await le(e,r),s=await x(e,t,o=>{if(o.repoId===n.id)throw new Error(`Repo ${n.id} is already the primary repo for task ${o.id}.`);return{...o,linkedRepoIds:o.linkedRepoIds.includes(n.id)?o.linkedRepoIds:[...o.linkedRepoIds,n.id]}});return{kind:"addTaskLink",taskId:s.id,repoId:n.id,linkedRepoIds:s.linkedRepoIds}},ys=async(e,t)=>{let r=await v(e,t),n=await Promise.all(r.linkedRepoIds.map(s=>le(e,s)));return{kind:"listTaskLinks",taskId:r.id,repos:n}};var Rs=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([le(e,r.repoId),$e(e,r.sessionId)]),o=await Bt.attach(e,s,n.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:o.id,disposition:"attached"}};var bs=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 $e(e,r.sessionId).catch(s=>{throw Nm(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}},Nm=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT";import{spawn as Lm}from"node:child_process";var Ps=async(e,t)=>{let r=await v(e,t);await K(r);let s=(await g.load(e)).open?.command??[];if(s.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let o=[...s,r.worktreePath];return await jm(o,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:o}},jm=async(e,t)=>{await new Promise((r,n)=>{let[s,...o]=e,i=Lm(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 Ss=async(e,t,r)=>{await x(e,t,n=>({...n,status:n.status==="running"?"draft":n.status,runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r}))},Is=async(e,t,r)=>x(e,t,n=>({...n,status:"draft",runnerSession:{...n.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:r})),vs=async(e,t)=>x(e,t,r=>{let n=r.ptyTabs.find(s=>s.kind==="agent");if(!n)throw new Error(`Task ${t} is missing its agent PTY tab.`);return{...r,status:"running",selectedPtyTabId:n.id,runnerSession:{...r.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}}});import{realpath as Oa}from"node:fs/promises";import Jt from"node:path";async function As(e,t){if(t.explicitTaskId!==void 0){let l=await $a(e,t.explicitTaskId,"explicit");return Cs(l,"explicit",t.environmentAgentTabId)}if(t.environmentTaskId!==void 0){let l=await $a(e,t.environmentTaskId,"environment");return Cs(l,"environment",t.environmentAgentTabId)}let r=await Oa(t.cwd).catch(()=>Jt.resolve(t.cwd)),n=await Ft(e,{includeClosed:!0}),o=(await Promise.all(n.tasks.map(async l=>({task:l,matches:await Fm(l,r)})))).filter(l=>l.matches).map(l=>l.task),i=[...new Map(o.map(l=>[l.id,l])).values()];if(i.length>1)throw new y("TASK_CONTEXT_AMBIGUOUS",`Multiple Craig tasks match ${r}: ${i.map(l=>l.id).join(", ")}. Use --task <id>.`,{details:{cwd:r,taskIds:i.map(l=>l.id)}});let a=i[0];if(a)return Cs(a,"cwd",t.environmentAgentTabId);if(t.environmentAgentTabId!==void 0)throw new y("TASK_CONTEXT_CONFLICT",`CRAIG_AGENT_TAB_ID is set to ${t.environmentAgentTabId}, but no task context could be resolved.`,{details:{agentTabId:t.environmentAgentTabId}});if(t.required)throw new y("TASK_CONTEXT_NOT_FOUND",`No Craig task was found from ${r}. Use --task <id> or run the command inside a task worktree.`,{details:{cwd:r}});return null}async function $a(e,t,r){try{return await v(e,t)}catch(n){throw!(n instanceof y)||n.code!=="TASK_NOT_FOUND"?n:new y("TASK_CONTEXT_NOT_FOUND",`Craig task "${t}" from ${r==="explicit"?"--task":"CRAIG_TASK_ID"} was not found.`,{details:{taskId:t,source:r},cause:n})}}function Cs(e,t,r){let n=r??null;if(n!==null){let s=e.ptyTabs.find(o=>o.id===n);if(!s||s.kind!=="agent")throw new y("TASK_CONTEXT_CONFLICT",`Agent tab ${n} does not belong to Craig task ${e.id}.`,{details:{taskId:e.id,agentTabId:n}})}return{task:e,source:t,agentTabId:n}}function _m(e){return[e.worktreePath,...e.bundlePath?[e.bundlePath]:[],...(e.repoTargets??[]).map(t=>t.worktreePath)]}async function Fm(e,t){return(await Promise.all(_m(e).map(n=>Oa(n).catch(()=>Jt.resolve(n))))).some(n=>Wm(n,t))}function Wm(e,t){let r=Jt.relative(Jt.resolve(e),t);return r===""||!r.startsWith("..")&&!Jt.isAbsolute(r)}var Es=async(e,t,r="merge",n)=>{let s=await v(e,t),o=n??E(s)?.number;if(!o)throw new Error(`Task ${s.id} has no pull request to merge.`);await Ca(s.worktreePath,o,r)};var Qt={readTask:v,writeTask:be,withTaskLock:xe,ensureGhAuthenticated:Me,fetchPrView:kt,discoverPrView:Aa,getGitHubRepositoryLocator:xr,writePrStatusArtifact:Xe};async function Ds(e,t,r,n=Qt){let s=await n.readTask(e,t),o=await Um(s,r,n);return Le(s,o,"showTaskPr","shown",[])}async function $s(e,t,r,n=Qt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await js(s,r,null,n);await _s(o,n);let i=await Mr(`discover a pull request for ${o.branch}`,()=>n.discoverPrView(o.branch,o.worktreePath));if(!i)return Le(s,o,"discoverTaskPr","not_found",[]);Fs(i,o);let a=Nr(s,o,i.number),l=await Ws(e,s,o,i,n);return Le(l,o,"discoverTaskPr",a?"synced":"discovered",[])})}async function Os(e,t,r,n,s=Qt){let o=Ls(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await js(i,n,o.repository,s);Na(o.repository,a),await _s(a,s);let l=await Mr(`fetch pull request ${r}`,()=>s.fetchPrView(r,a.worktreePath));Bm(l,o),Fs(l,a);let c=Nr(i,a,l.number),d=qs(i,a),u=d&&!mt(d,{owner:a.repository.owner,repo:a.repository.name,number:l.number})&&d.status!=="closed"&&d.status!=="merged"?[`Pull request #${l.number} becomes active; #${d.number} remains in task history.`]:[],p=await Ws(e,i,a,l,s);return Le(p,a,"linkTaskPr",c?"unchanged":"linked",u)})}async function qm(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw Rt(e,t);let i=e.prs.find(a=>a.number===r.number)??E(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Or(i,e.worktreePath,e.repoId,n),projectTarget:null}}if(t){let i=e.repoTargets?.find(c=>c.repoId===t);if(!i)throw Rt(e,t);let a=Ma(i.pullRequest),l=e.prs.find(c=>c.number===r.number&&(!c.headBranch||c.headBranch===i.branch)&&(!a||!!(c.owner&&c.repo&&he({owner:c.owner,name:c.repo},a))))??i.pullRequest;return{repoId:t,branch:i.branch,worktreePath:i.worktreePath,repository:await Or(l,i.worktreePath,t,n),projectTarget:i}}if(!r.repository)throw new y("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for a numeric pull request selector.`,{details:{taskId:e.id,pullRequestNumber:r.number}});let s=r.repository,o=[];for(let i of e.repoTargets??[]){let a=i.pullRequest.owner&&i.pullRequest.repo&&he({owner:i.pullRequest.owner,name:i.pullRequest.repo},s),l=e.prs.some(c=>c.number===r.number&&c.owner&&c.repo&&he({owner:c.owner,name:c.repo},s)&&(!c.headBranch||c.headBranch===i.branch));(a||l)&&o.push({repoId:i.repoId,branch:i.branch,worktreePath:i.worktreePath,repository:s,projectTarget:i})}if(o.length!==1)throw new y("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.repository.owner}/${r.repository.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.repository.owner,repo:r.repository.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Ms(e,t,r,n=Qt){return n.withTaskLock(e,t,async()=>{let s=await n.readTask(e,t),o=await js(s,r,null,n),i=qs(s,o);if(!i?.number)return Le(s,o,"refreshTaskPr","not_found",[]);await _s(o,n);let a=await Mr(`refresh pull request #${i.number}`,()=>n.fetchPrView(String(i.number),o.worktreePath));Fs(a,o);let l=await Ws(e,s,o,a,n);return Le(l,o,"refreshTaskPr","synced",[])})}async function Ns(e,t,r,n,s=Qt){let o=Ls(r);return s.withTaskLock(e,t,async()=>{let i=await s.readTask(e,t),a=await qm(i,n,o,s);if(Na(o.repository,a),!Nr(i,a,o.number))return Le(i,a,"unlinkTaskPr","unchanged",[]);let c=Vm(i,a,o.number),d=await ja(e,c,s);return Le(d,a,"unlinkTaskPr","unlinked",[])})}function Ls(e){let t=e.trim(),r=Ne(t);if(r)return{number:r.number,repository:r};if(/^[1-9]\d*$/.test(t))return{number:Number(t),repository:null};throw new y("CLI_USAGE",`Invalid pull request selector "${e}". Use a GitHub pull request URL or positive number.`,{details:{selector:e}})}async function js(e,t,r,n){if(e.type==="repo"){if(t&&t!==e.repoId)throw Rt(e,t);return xs(e.repoId,e.branch,e.worktreePath,null,n)}let s=e.repoTargets??[];if(t){let i=s.find(a=>a.repoId===t);if(!i)throw Rt(e,t);return xs(i.repoId,i.branch,i.worktreePath,i,n)}if(!r)throw new y("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:s.map(i=>i.repoId)}});let o=[];for(let i of s){let a=await xs(i.repoId,i.branch,i.worktreePath,i,n).catch(l=>{if(l instanceof y&&l.code==="EXTERNAL_DEPENDENCY_FAILED"&&l.message.includes("does not have a supported GitHub origin remote"))return null;throw l});a&&he(a.repository,r)&&o.push(a)}if(o.length!==1)throw new y("TASK_CONTEXT_AMBIGUOUS",`Pull request repository ${r.owner}/${r.name} does not map to exactly one target in project task ${e.id}.`,{details:{taskId:e.id,owner:r.owner,repo:r.name,matchingRepoIds:o.map(i=>i.repoId)}});return o[0]}async function Um(e,t,r){if(e.type==="repo"){if(t&&t!==e.repoId)throw Rt(e,t);let s=E(e);return{repoId:e.repoId,branch:e.branch,worktreePath:e.worktreePath,repository:await Or(s,e.worktreePath,e.repoId,r),projectTarget:null}}if(!t)throw new y("CLI_USAGE",`Project task ${e.id} requires --repo <repo-id> for pull request commands.`,{details:{taskId:e.id,repoIds:(e.repoTargets??[]).map(s=>s.repoId)}});let n=e.repoTargets?.find(s=>s.repoId===t);if(!n)throw Rt(e,t);return{repoId:t,branch:n.branch,worktreePath:n.worktreePath,repository:await Or(n.pullRequest,n.worktreePath,t,r),projectTarget:n}}async function Or(e,t,r,n){let s=Ma(e);return s||(await n.getGitHubRepositoryLocator(t).catch(()=>null)??{owner:"",name:r})}function Ma(e){return e?.owner&&e.repo?{owner:e.owner,name:e.repo}:e?.url?Ne(e.url):null}async function xs(e,t,r,n,s){let o=await s.getGitHubRepositoryLocator(r);if(!o)throw new y("EXTERNAL_DEPENDENCY_FAILED",`Repo ${e} does not have a supported GitHub origin remote.`,{details:{repoId:e,worktreePath:r}});return{repoId:e,branch:t,worktreePath:r,repository:o,projectTarget:n}}async function _s(e,t){await Mr("verify GitHub CLI authentication",()=>t.ensureGhAuthenticated(e.worktreePath))}async function Mr(e,t){try{return await t()}catch(r){throw r instanceof y?r:new y("EXTERNAL_DEPENDENCY_FAILED",`Failed to ${e}: ${r instanceof Error?r.message:String(r)}`,{retryable:!0,cause:r})}}function Na(e,t){if(e&&!he(e,t.repository))throw La(e,t)}function Bm(e,t){let r=Ne(e.url);if(!r||r.number!==t.number)throw new y("TASK_CONTEXT_CONFLICT",`GitHub returned ${e.url} for pull request selector #${t.number}.`,{details:{selectorNumber:t.number,returnedUrl:e.url}});if(t.repository&&!he(t.repository,r))throw new y("PR_REPOSITORY_MISMATCH",`GitHub returned a pull request from ${r.owner}/${r.name}, not ${t.repository.owner}/${t.repository.name}.`,{details:{selectorRepository:t.repository,returnedRepository:r}})}function Fs(e,t){let r=Ne(e.url);if(!r||!he(r,t.repository))throw La(r,t);if(e.headRefName!==t.branch)throw new y("PR_BRANCH_MISMATCH",`Pull request #${e.number} uses head branch ${e.headRefName}, not task branch ${t.branch}.`,{details:{repoId:t.repoId,pullRequestNumber:e.number,expectedBranch:t.branch,actualBranch:e.headRefName}})}function La(e,t){return new y("PR_REPOSITORY_MISMATCH",`Pull request repository ${e?`${e.owner}/${e.name}`:"is invalid"} does not match task repo ${t.repository.owner}/${t.repository.name}.`,{details:{repoId:t.repoId,expectedOwner:t.repository.owner,expectedRepo:t.repository.name,actualOwner:e?.owner??null,actualRepo:e?.name??null}})}function Rt(e,t){return new y("TASK_CONTEXT_CONFLICT",`Repo ${t} is not a target of task ${e.id}.`,{details:{taskId:e.id,repoId:t}})}function he(e,t){return e.owner.toLowerCase()===t.owner.toLowerCase()&&e.name.toLowerCase()===t.name.toLowerCase()}async function Ws(e,t,r,n,s){let o=Nr(t,r,n.number),i=Se(n,o,r.repository),a=Pe(t,i);return r.projectTarget&&(a={...a,repoTargets:(a.repoTargets??[]).map(l=>l.repoId===r.repoId?{...l,pullRequest:Wa(i)}:l)}),ja(e,a,s)}function Vm(e,t,r){let n=e.prs.filter(o=>!Fa(o,t,r)),s={...e,prs:n};if(t.projectTarget?.pullRequest.number===r){let o=_a(n.filter(i=>i.owner&&i.repo&&he({owner:i.owner,name:i.repo},t.repository)));s={...s,repoTargets:(s.repoTargets??[]).map(i=>i.repoId===t.repoId?{...i,pullRequest:o?Wa(o):Gm(t.repository)}:i)}}return s}async function ja(e,t,r){let n=t.status==="closed"?t.status:t.type==="project"?as(t):He(t.prs),s={...t,status:n};return Vt(e,s,r)}function Nr(e,t,r){return Us(e,t).find(n=>Fa(n,t,r))??null}function qs(e,t){if(!t.projectTarget)return E(e);let r=Us(e,t);return _a(r)}function _a(e){return[...e].reverse().find(t=>t.status!=="merged"&&t.status!=="closed")??e[e.length-1]??null}function Us(e,t){if(!t.projectTarget)return e.prs;let r=e.prs.filter(o=>o.owner&&o.repo&&he({owner:o.owner,name:o.repo},t.repository)),n=e.repoTargets?.find(o=>o.repoId===t.repoId),s=n?.pullRequest.number?Km(n.pullRequest,t.repository):null;return s&&!r.some(o=>mt(o,s))?[...r,s]:r}function Fa(e,t,r){return e.number!==r?!1:!e.owner||!e.repo||he({owner:e.owner,name:e.repo},t.repository)}function Le(e,t,r,n,s){let o=Us(e,t);return{kind:r,taskId:e.id,repoId:t.repoId,disposition:n,pullRequests:o,primaryPullRequest:qs(e,t),warnings:s}}function Wa(e){return{provider:"github",owner:e.owner,repo:e.repo,number:e.number,url:e.url,baseBranch:e.baseBranch,headBranch:e.headBranch,status:e.status==="draft"?"open":e.status,draft:e.draft,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function Km(e,t){return{provider:"github",owner:e.owner??t.owner,repo:e.repo??t.name,number:e.number,url:e.url,title:null,status:e.draft?"draft":e.status,draft:e.draft??!1,baseBranch:e.baseBranch,headBranch:e.headBranch,mergeable:e.mergeable,mergeStateStatus:e.mergeStateStatus,reviewDecision:e.reviewDecision??null,requiredChecks:e.requiredChecks,comments:e.comments??[],createdAt:null,updatedAt:null,mergedAt:null,lastSyncedAt:e.lastSyncedAt,lastSyncedHeadSha:e.lastSyncedHeadSha}}function Gm(e){return{provider:"github",owner:e.owner,repo:e.name,number:null,url:null,baseBranch:null,headBranch:null,status:null,draft:!1,mergeable:!1,mergeStateStatus:null,reviewDecision:null,requiredChecks:[],comments:[],lastSyncedAt:null,lastSyncedHeadSha:null}}var S={listTasks:Ft,getTask:v,provisionTask:ht,provisionProjectTask:qt,createTask:ss,showTask:us,showTaskDiff:ps,prepareTaskLogs:ms,streamTaskLogs:fs,runChecks:gs,commitTask:hs,closeTask:ks,cleanupTask:ws,addTaskLink:Ts,listTaskLinks:ys,sortTasksForDisplay:Qn,resolveSelectedTaskId:Xn,allocateTaskId:Jn,allocateTaskIdForRepo:gt,allocateProjectTaskId:_t,createDefaultTaskPtyTabs:Ut,assertTaskWorktreeExists:K,resolveTaskLogPath:ft,buildTaskInspection:jt,resolveArtifactPath:ze,attachTask:Rs,focusTask:bs,openTask:Ps,markRunnerFailed:Ss,recordStartupFailure:Is,markTaskStarted:vs,resolveContext:As,prs:{refresh:Yt,refreshChecks:cs,discoverOrRefresh:$r,discoverOrRefreshAll:yt,discoverOrRefreshMany:ds,show:Ds,discover:$s,link:Os,refreshAssociation:Ms,unlink:Ns,merge:Es,getPrimaryPr:E,isPrTerminal:De,isMergeReady:Sr,deriveTaskStatus:He,upsertPr:Pe,normalizePr:Se,summarizeRequiredChecks:Gn,writePrStatusArtifact:Xe}};var qa={idle:0,working:1,ready:2,error:3};function Ze(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 bt(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return Ze(t,r,n,o)}function Pt(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=bt(e,s.id,t,r);qa[o]>qa[n]&&(n=o)}return n}function Lr(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&Ze(s.id,t,r)==="working"))}function St(e,t,r){let n=e.flatMap(o=>o.ptyTabs.filter(i=>i.kind==="agent").map(i=>{let a=t.find(c=>c.tabId===i.id),l=bt(o,i.id,t,r);return{taskId:o.id,tabId:i.id,title:i.title,runner:i.runner??o.runner,state:l,sessionState:a?.sessionState??null,lastActivityAt:a?.lastActivityAt??null,exitCode:a?.exitCode??null,error:a?.error??(l==="error"?o.lastFailureReason??null:null)}})),s=e.map(o=>({taskId:o.id,state:Pt(o,t,r),agentTabIds:n.filter(i=>i.taskId===o.id).map(i=>i.tabId)}));return{agents:n,tasks:s}}async function Bs(e,t,r){let n=r.now??Date.now;if(r.tabId&&!e.ptyTabs.some(l=>l.kind==="agent"&&l.id===r.tabId))throw new y("TASK_CONTEXT_CONFLICT",`Agent tab ${r.tabId} does not belong to task ${e.id}.`,{details:{taskId:e.id,tabId:r.tabId}});let s=0,o=null,i=t.subscribe(()=>{s+=1,o?.()}),a=n()+r.timeoutMs;try{for(;;){let l=n(),c=St([e],t.getSnapshots(),l),d=r.tabId?c.agents.find(f=>f.tabId===r.tabId)?.state??"idle":c.tasks[0]?.state??"idle";if(r.states.includes(d))return{kind:"waitTask",taskId:e.id,tabId:r.tabId??null,state:d,matchedStates:[...r.states],observedAt:new Date(l).toISOString()};if(r.signal?.aborted)throw Ua(e.id);let u=a-n();if(u<=0)throw Hm(e.id,r.states,r.timeoutMs);let p=s;await new Promise((f,w)=>{let h=()=>{clearTimeout(q),r.signal?.removeEventListener("abort",b),f()},b=()=>{clearTimeout(q),w(Ua(e.id))},q=setTimeout(h,u);o=h,r.signal?.addEventListener("abort",b,{once:!0}),s!==p&&o()}),o=null}}finally{i()}}var Hm=(e,t,r)=>new y("OPERATION_TIMEOUT",`Timed out after ${r}ms waiting for task ${e} agent state ${t.join(",")}.`,{retryable:!0,details:{taskId:e,states:t,timeoutMs:r}}),Ua=e=>new y("OPERATION_CANCELLED",`Cancelled while waiting for task ${e} agent state.`,{retryable:!0,details:{taskId:e,cancelled:!0}});import{createConnection as Qm}from"node:net";import{createHash as Ym}from"node:crypto";import{tmpdir as Jm}from"node:os";import Ba from"node:path";var jr=6;function It(e){let t=Ym("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:Ba.join(Jm(),`craig-${t}.sock`),pidPath:Ba.join(e.runtimeDir,"pty-daemon.pid")}}async function Va(e){let t=null;try{let r=await Xm(It(e.paths).socketPath);return t=new Vs(r,e),await t.ready(),t}catch{return t?.close(),null}}var Vs=class{constructor(t,r){this.socket=t;this.options=r;t.setEncoding("utf8"),t.on("data",n=>this.handleData(String(n))),t.on("error",n=>this.rejectAll(n instanceof Error?n:new Error(String(n)))),t.on("close",()=>this.handleClose())}socket;options;pending=new Map;snapshots=new Map;revisionByTabId=new Map;nextRequestId=1;revision=0;buffer="";closed=!1;async ready(){if((await this.send({type:"ping"})).protocolVersion!==jr)throw new Error("Craig PTY daemon protocol mismatch.");await this.send({type:"setActivityEnabled",enabled:!0});let r=this.revision,n=await this.send({type:"getActivitySnapshots"});this.replaceSnapshots(n.activities??[],r)}getSnapshots(){return[...this.snapshots.values()]}close(){this.closed||(this.closed=!0,this.socket.end(),this.rejectAll(new Error("Craig PTY daemon activity connection closed.")))}async send(t){if(this.closed||this.socket.destroyed)throw new Error("Craig PTY daemon activity connection is closed.");let r=this.nextRequestId++,n=new Promise((o,i)=>{this.pending.set(r,{resolve:o,reject:i})});this.socket.write(`${JSON.stringify({...t,id:r})}
|
|
75
|
+
`);let s=await n;if(!s.ok)throw new Error(s.error);return s}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
76
|
+
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
77
|
+
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let n=this.pending.get(r.id);if(!n)return;this.pending.delete(r.id),n.resolve(r);return}r.type==="activity"?(this.recordSnapshot(r.snapshot),this.options.onActivity?.(r.snapshot)):r.type==="activityRemoved"&&(this.removeSnapshot(r.tabId),this.options.onActivityRemoved?.(r.tabId))}replaceSnapshots(t,r){let n=new Map;for(let[s,o]of this.revisionByTabId)o>r&&n.set(s,this.snapshots.get(s)??null);this.snapshots.clear();for(let s of t)this.snapshots.set(s.tabId,s);for(let[s,o]of n)o?this.snapshots.set(s,o):this.snapshots.delete(s)}recordSnapshot(t){this.revision+=1,this.revisionByTabId.set(t.tabId,this.revision),this.snapshots.set(t.tabId,t)}removeSnapshot(t){this.revision+=1,this.revisionByTabId.set(t,this.revision),this.snapshots.delete(t)}handleClose(){if(this.closed)return;this.closed=!0;let t=new Error("Craig PTY daemon connection closed.");this.rejectAll(t);for(let r of this.snapshots.values()){if(r.sessionState!=="running")continue;let n={...r,sessionState:"failed",lastActivityAt:Date.now(),error:t.message};this.recordSnapshot(n),this.options.onActivity?.(n)}this.options.onDaemonClose?.()}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}};function Xm(e){return new Promise((t,r)=>{let n=Qm(e);n.once("connect",()=>t(n)),n.once("error",r)})}var Gs={openObserver:rf,listTasks:e=>S.listTasks(e),getTask:(e,t)=>S.getTask(e,t),now:Date.now};async function Zm(e,t,r=Gs){let n=await Ka(e,t,r),s=await r.openObserver(e);try{return{kind:"listAgents",...St(n,s.getSnapshots(),r.now()),daemonAvailable:s.daemonAvailable}}finally{s.close()}}async function ef(e,t,r=Gs){let n=await Ka(e,t.taskId,r),s=await r.openObserver(e);try{let o=St(n,s.getSnapshots(),r.now()),i=t.tabId?o.agents.filter(l=>l.tabId===t.tabId):o.agents;if(t.tabId&&i.length===0)throw new y("TASK_CONTEXT_NOT_FOUND",`Agent tab ${t.tabId} was not found${t.taskId?` in task ${t.taskId}`:""}.`,{details:{taskId:t.taskId??null,tabId:t.tabId}});let a=new Set(i.map(l=>l.taskId));return{kind:"showAgentStatus",agents:i,tasks:t.tabId?o.tasks.filter(l=>a.has(l.taskId)):o.tasks,daemonAvailable:s.daemonAvailable}}finally{s.close()}}async function tf(e,t,r,n=Gs){let s=await n.getTask(e,t),o=await n.openObserver(e);try{return await Bs(s,o,{...r,now:n.now})}finally{o.close()}}async function Ka(e,t,r){return t?[await r.getTask(e,t)]:(await r.listTasks(e)).tasks}async function rf(e){return Ks.open(e)}var Ks=class e{listeners=new Set;snapshots=new Map;client=null;reconnectTimer=null;reconnectDelayMs=250;closed=!1;paths;constructor(t){this.paths=t}static async open(t){let r=new e(t);return await r.connect(),r}get daemonAvailable(){return this.client!==null}getSnapshots(){return[...this.snapshots.values()]}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}close(){this.closed=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.client?.close(),this.client=null}async connect(){if(this.closed)return;let t=await Va({paths:this.paths,onActivity:r=>{this.snapshots.set(r.tabId,r),this.notify()},onActivityRemoved:r=>{this.snapshots.delete(r),this.notify()},onDaemonClose:()=>{this.client=null,this.notify(),this.scheduleReconnect()}});if(this.closed){t?.close();return}if(this.client=t,t){this.reconnectDelayMs=250,this.snapshots.clear();for(let r of t.getSnapshots())this.snapshots.set(r.tabId,r);this.notify()}else this.scheduleReconnect()}scheduleReconnect(){if(this.closed||this.reconnectTimer)return;let t=this.reconnectDelayMs;this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,1e3),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},t)}notify(){for(let t of this.listeners)t()}},_r={listAgents:Zm,showAgentStatus:ef,waitForTask:tf};async function Ga(e,t){switch(e.kind){case"addWorkspace":{let r=await G.addWorkspace(t.paths,e.path),n=r.workspace.kind==="project"?r.workspace.discoveredRepoIds?.[0]??null:r.repos[0]?.id??null;return await Hs(t.paths,r.workspace.id,n),r}case"addRepo":{let r=await G.repos.addRepo(t.paths,e.path);return await Hs(t.paths,r.workspaceId,r.repo.id),r}case"listRepos":return G.repos.listRegisteredRepos(t.paths);case"removeRepo":{let r=await at({uiStateFile:t.paths.uiStateFile}),n=r?.selectedWorkspaceId?(await oe(t.paths)).filter(o=>o.primaryRepoId===e.repoId).map(o=>o.id):[],s=await G.repos.removeRepo(t.paths,e.repoId,{listTasks:S.listTasks});if(r){let o=n.includes(r.selectedWorkspaceId??""),i=r.selectedRepoId===e.repoId;o?await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}):i&&await Ee({uiStateFile:t.paths.uiStateFile},{...r,selectedRepoId:null})}return s}case"listWorkspaces":return G.listWorkspaces(t.paths,{archived:e.archived});case"archiveWorkspace":{let r=await G.archiveWorkspace(t.paths,e.workspaceId);return await nf(t.paths,e.workspaceId),r}case"restoreWorkspace":{let r=await G.restoreWorkspace(t.paths,e.workspaceId);return await Hs(t.paths,e.workspaceId,r.primaryRepoId),r}case"removeWorkspace":return G.removeWorkspace(t.paths,e.workspaceId,{listTasks:S.listTasks});case"createTask":return S.createTask(t.paths,e.repoId??e.workspaceId??"",e.prompt,{...e.runner?{runner:e.runner}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}});case"listTasks":return e.repoId||e.workspaceId?S.listTasks(t.paths,{...e.repoId?{repoId:e.repoId}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{}}):S.listTasks(t.paths);case"currentTask":{let r=zs(t);return{kind:"currentTask",task:r.task,context:{source:r.source,agentTabId:r.agentTabId}}}case"attachTask":return S.attachTask(t.paths,e.taskId);case"addTaskLink":return S.addTaskLink(t.paths,e.taskId,e.repoId);case"listTaskLinks":return S.listTaskLinks(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return S.showTask(t.paths,e.taskId);case"showCurrentTask":return S.showTask(t.paths,zs(t).task.id);case"showTaskPr":return S.prs.show(t.paths,vt(e.taskId,t),e.repoId);case"discoverTaskPr":return S.prs.discover(t.paths,vt(e.taskId,t),e.repoId);case"linkTaskPr":return S.prs.link(t.paths,vt(e.taskId,t),e.pullRequest,e.repoId);case"refreshTaskPr":return S.prs.refreshAssociation(t.paths,vt(e.taskId,t),e.repoId);case"unlinkTaskPr":return S.prs.unlink(t.paths,vt(e.taskId,t),e.pullRequest,e.repoId);case"listAgents":return _r.listAgents(t.paths,e.taskId);case"showAgentStatus":return _r.showAgentStatus(t.paths,{...e.taskId?{taskId:e.taskId}:{},...e.tabId?{tabId:e.tabId}:{}});case"waitTask":return _r.waitForTask(t.paths,vt(e.taskId,t),{states:e.states,timeoutMs:e.timeoutMs,...e.tabId?{tabId:e.tabId}:{},...t.signal?{signal:t.signal}:{}});case"showSelectedTask":return S.showTask(t.paths,et(t,"show"));case"streamTaskLogs":return S.prepareTaskLogs(t.paths,e.taskId);case"streamSelectedTaskLogs":return S.prepareTaskLogs(t.paths,et(t,"logs"));case"showTaskDiff":return S.showTaskDiff(t.paths,e.taskId);case"showSelectedTaskDiff":return S.showTaskDiff(t.paths,et(t,"diff"));case"focusTask":return S.focusTask(t.paths,e.taskId);case"focusSelectedTask":return S.focusTask(t.paths,et(t,"focus"));case"openTask":return S.openTask(t.paths,e.taskId);case"openSelectedTask":return S.openTask(t.paths,et(t,"open"));case"runChecks":return S.runChecks(t.paths,e.taskId);case"runSelectedTaskChecks":return S.runChecks(t.paths,et(t,"check"));case"commitTask":return S.commitTask(t.paths,e.taskId);case"commitSelectedTask":return S.commitTask(t.paths,et(t,"commit"));case"showContext":{let r=of(t);return{kind:"showContext",workspace:{root:r.workspaceRoot,source:r.source,initialized:r.initialized},task:t.taskContext?{id:t.taskContext.task.id,source:t.taskContext.source,agentTabId:t.taskContext.agentTabId}:null}}case"help":return{kind:"help",text:Dn()};case"exit":return{kind:"exit"};default:return sf(e)}}async function Hs(e,t,r){let n=await at({uiStateFile:e.uiStateFile})??ur();await Ee({uiStateFile:e.uiStateFile},{...n,selectedWorkspaceId:t,selectedRepoId:r,selectedTaskId:null})}async function nf(e,t){let r=await at({uiStateFile:e.uiStateFile});r?.selectedWorkspaceId===t&&await Ee({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}function sf(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function et(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 zs(e){if(e.taskContext)return e.taskContext;throw new Error("Command requires resolved task context.")}function vt(e,t){return e??zs(t).task.id}function of(e){if(e.workspaceContext)return e.workspaceContext;throw new Error("Command requires resolved workspace context.")}function Ha(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(`
|
|
75
78
|
`);case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
|
|
76
79
|
`);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(`
|
|
77
80
|
`);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(`
|
|
78
81
|
`);case"archiveWorkspace":return`Archived workspace ${e.workspaceId} on branch ${e.branch}`;case"restoreWorkspace":return`Restored workspace ${e.workspaceId} on branch ${e.branch}`;case"removeWorkspace":return`Removed workspace ${e.workspaceId} (${e.rootPath})`;case"createTask":return[`Created task ${e.taskId}`,`Repo: ${e.repoId}`,`Workspace: ${e.workspaceId}`,`Session: ${e.sessionId}`,`Status: ${e.status}`,`Branch: ${e.branch}`,`Worktree: ${e.worktreePath}`,`Runner: ${e.runner}`].join(`
|
|
79
82
|
`);case"attachTask":return`Attached to task ${e.taskId} via session ${e.sessionId}`;case"addTaskLink":return`Linked repo ${e.repoId} to task ${e.taskId}: ${e.linkedRepoIds.join(", ")}`;case"listTaskLinks":return e.repos.length===0?`Task ${e.taskId} has no linked repos.`:["ID NAME BRANCH PATH",...e.repos.map(t=>`${t.id} ${t.name} ${t.defaultBranch} ${t.rootPath}`)].join(`
|
|
80
|
-
`);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} ${
|
|
81
|
-
`);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}`,...
|
|
83
|
+
`);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} ${uf(t)} ${pf(t)} ${t.title}`)].join(`
|
|
84
|
+
`);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}`,...cf(e)].join(`
|
|
82
85
|
`);case"currentTask":return[`${e.task.id}: ${e.task.title}`,`Workspace: ${e.task.workspaceId}`,`Repo: ${e.task.repoId}`,`Worktree: ${e.task.worktreePath}`,`Context source: ${e.context.source}`,`Agent tab: ${e.context.agentTabId??"none"}`].join(`
|
|
83
|
-
`);case"showTaskPr":case"discoverTaskPr":case"linkTaskPr":case"refreshTaskPr":case"unlinkTaskPr":return
|
|
86
|
+
`);case"showTaskPr":case"discoverTaskPr":case"linkTaskPr":case"refreshTaskPr":case"unlinkTaskPr":return lf(e);case"listAgents":case"showAgentStatus":return af(e);case"waitTask":return`Task ${e.taskId}${e.tabId?` tab ${e.tabId}`:""} reached ${e.state}.`;case"showContext":return[`Workspace: ${e.workspace.root}`,`Workspace source: ${e.workspace.source}`,`Initialized: ${e.workspace.initialized?"yes":"no"}`,`Task: ${e.task?.id??"none"}`,`Task source: ${e.task?.source??"none"}`,`Agent tab: ${e.task?.agentTabId??"none"}`].join(`
|
|
84
87
|
`);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(`
|
|
85
|
-
`);default:return
|
|
86
|
-
`)}function
|
|
87
|
-
`),
|
|
88
|
-
`),
|
|
89
|
-
`).
|
|
90
|
-
`)
|
|
91
|
-
`)
|
|
92
|
-
|
|
93
|
-
${
|
|
94
|
-
${a.stdout.trimEnd()}`)}if(o.includes("
|
|
88
|
+
`);default:return df(e)}}function af(e){return e.agents.length===0?"No agent tabs found.":["TASK TAB RUNNER STATE SESSION ERROR",...e.agents.map(t=>`${t.taskId} ${t.tabId} ${t.runner} ${t.state} ${t.sessionState??"none"} ${t.error??""}`),...e.daemonAvailable?[]:["Warning: PTY daemon unavailable; live agent tabs report idle unless a durable startup failure exists."]].join(`
|
|
89
|
+
`)}function lf(e){let t=`${e.taskId} (${e.repoId}): ${e.disposition}`,r=e.pullRequests.length===0?["No pull requests associated."]:["PR STATUS HEAD URL",...e.pullRequests.map(n=>`#${n.number??"-"} ${n.status??"unknown"} ${n.headBranch??"-"} ${n.url??"-"}`)];return[t,...r,...e.warnings.map(n=>`Warning: ${n}`)].join(`
|
|
90
|
+
`)}function cf(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 df(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function uf(e){return e.checks.status}function pf(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"}`:"-"}function za(e,t){let{data:r,warnings:n}=mf(t);return JSON.stringify({schemaVersion:1,command:e,ok:!0,data:r,warnings:n})}function mf(e){if("warnings"in e&&Array.isArray(e.warnings)){let{warnings:t,...r}=e;return{data:r,warnings:t}}return{data:e,warnings:[]}}function Ya(e,t){let r={schemaVersion:1,command:e,ok:!1,error:{code:t.code,message:t.message,retryable:t.retryable,details:t.details}};return JSON.stringify(r)}async function Ys(e){let t=await G.resolveContext({cwd:e.cwd,...e.explicitWorkspaceRoot!==void 0?{explicitWorkspaceRoot:e.explicitWorkspaceRoot}:{},...e.environmentWorkspaceRoot!==void 0?{environmentWorkspaceRoot:e.environmentWorkspaceRoot}:{},...e.allowUninitializedWorkspace!==void 0?{allowUninitializedCwd:e.allowUninitializedWorkspace}:{}}),r=ee(t.workspaceRoot),n=e.resolveTask===!0||e.requireTask===!0||e.explicitTaskId!==void 0||e.environmentTaskId!==void 0||e.environmentAgentTabId!==void 0;if(n&&!t.initialized)throw new y("TASK_CONTEXT_NOT_FOUND",`Task context cannot be resolved because ${t.workspaceRoot} is not an initialized Craig workspace.`,{details:{workspaceRoot:t.workspaceRoot}});let s=n&&t.initialized?await S.resolveContext(r,{cwd:e.cwd,...e.explicitTaskId!==void 0?{explicitTaskId:e.explicitTaskId}:{},...e.environmentTaskId!==void 0?{environmentTaskId:e.environmentTaskId}:{},...e.environmentAgentTabId!==void 0?{environmentAgentTabId:e.environmentAgentTabId}:{},...e.requireTask!==void 0?{required:e.requireTask}:{}}):null;return{paths:r,workspace:t,task:s}}async function Ja(e){let t="cli",r=yi(e.argv);try{let n=Ti(e.argv);if(r=n.options.json,n.mode==="interactive"){if(n.options.noInput||n.options.json||Rf(e.env)||!e.isInputTty||!e.isOutputTty)throw new y("INPUT_REQUIRED","Interactive Craig requires a TTY. Provide a command instead of starting the terminal application.",{});let u=await Ys({cwd:e.cwd,...n.options.workspaceRoot!==void 0?{explicitWorkspaceRoot:n.options.workspaceRoot}:{},...e.env.CRAIG_WORKSPACE_ROOT!==void 0?{environmentWorkspaceRoot:e.env.CRAIG_WORKSPACE_ROOT}:{},allowUninitializedWorkspace:!0});return e.runInteractive(u.workspace.workspaceRoot)}if(!n.command||!n.commandName)throw new y("CLI_USAGE","Command mode requires a command.",{});t=n.commandName,hf(n.command,n.options.taskId);let s=wf(n.command,n.options.taskId),o=gf(s);kf(s,n.options.taskId,o);let i=o!=="none",a=await Ys({cwd:e.cwd,...n.options.workspaceRoot!==void 0?{explicitWorkspaceRoot:n.options.workspaceRoot}:{},...e.env.CRAIG_WORKSPACE_ROOT!==void 0?{environmentWorkspaceRoot:e.env.CRAIG_WORKSPACE_ROOT}:{},...i&&n.options.taskId!==void 0?{explicitTaskId:n.options.taskId}:{},...i&&e.env.CRAIG_TASK_ID!==void 0?{environmentTaskId:e.env.CRAIG_TASK_ID}:{},...i&&e.env.CRAIG_AGENT_TAB_ID!==void 0?{environmentAgentTabId:e.env.CRAIG_AGENT_TAB_ID}:{},allowUninitializedWorkspace:ff(s),resolveTask:o!=="none",requireTask:o==="required"}),l=Tf(s,e.signal),c;try{c=await Ga(s,{paths:a.paths,workspaceContext:a.workspace,taskContext:a.task,...l.signal?{signal:l.signal}:{}})}finally{l.dispose()}let d=r?za(t,c):Ha(c);return d.length>0&&e.writeStdout(`${d}
|
|
91
|
+
`),0}catch(n){let s=An(n),o=r?Ya(t,s):s.message;return e.writeStderr(`${o}
|
|
92
|
+
`),s.exitCode}}function ff(e){return["addWorkspace","addRepo","listRepos","listWorkspaces","help"].includes(e.kind)}function gf(e){return e.kind==="showContext"?"optional":e.kind==="currentTask"||e.kind==="showCurrentTask"?"required":yf(e)?e.taskId?"none":"required":e.kind==="listAgents"||e.kind==="showAgentStatus"?"none":e.kind==="waitTask"?e.taskId?"none":"required":"none"}function hf(e,t){let r=Qa(e);if(!(r===void 0||t===void 0||t===r))throw new y("CLI_USAGE",`Task ${r} conflicts with --task ${t}. Provide only one task target.`,{details:{positionalTaskId:r,globalTaskId:t}})}function kf(e,t,r){if(!(t===void 0||r!=="none"||Qa(e)===t))throw new y("CLI_USAGE",`--task is not supported by ${e.kind}. Use it with context show, task current, or task show without an id.`,{details:{commandKind:e.kind,globalTaskId:t}})}function Qa(e){switch(e.kind){case"showTask":case"attachTask":case"listTaskLinks":case"streamTaskLogs":case"showTaskDiff":case"focusTask":case"openTask":case"runChecks":case"commitTask":case"waitTask":case"listAgents":case"showAgentStatus":return e.taskId;case"showTaskPr":case"discoverTaskPr":case"linkTaskPr":case"refreshTaskPr":case"unlinkTaskPr":return e.taskId;case"addTaskLink":return e.taskId;default:return}}function wf(e,t){return t&&(e.kind==="listAgents"||e.kind==="showAgentStatus"||e.kind==="waitTask")?{...e,taskId:e.taskId??t}:e}function Tf(e,t){if(e.kind!=="waitTask")return{dispose:()=>{}};if(t)return{signal:t,dispose:()=>{}};let r=new AbortController,n=()=>r.abort();return process.once("SIGINT",n),{signal:r.signal,dispose:()=>process.removeListener("SIGINT",n)}}function yf(e){return["showTaskPr","discoverTaskPr","linkTaskPr","refreshTaskPr","unlinkTaskPr"].includes(e.kind)}function Rf(e){let t=e.CI?.trim().toLowerCase();return t!==void 0&&t!==""&&t!=="0"&&t!=="false"}import{createRequire as Wk}from"node:module";import{readFile as bf,stat as Pf}from"node:fs/promises";import Js from"node:path";var Sf=200*1024,If=500*1024,Fr="100000";async function Za(e,t,r){if(e.type==="project"&&e.repoTargets?.length)return vf(e,t,r);try{let n=je(r.selectedFilePath??null,t.filePaths),s=je(r.selectedDiffPath??null,t.diffPaths),o=s?await Xt(e.worktreePath):null,[i,a]=await Promise.all([qr(e.worktreePath,n),s?Qs(e.worktreePath,s,t.diffRows,o):Promise.resolve(Y("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 vf(e,t,r){let n=je(r.selectedFilePath??null,t.filePaths),s=je(r.selectedDiffPath??null,t.diffPaths),[o,i]=await Promise.all([tl(e,n),(async()=>{if(!s)return Y("No diff selected","No local changes found.","empty");let l=Wr(e,s),c=l?await Xt(l.target.worktreePath).catch(()=>null):null;return rl(e,s,t.diffRows,c)})()]),a=s?{[s]:i}:{};return{...t,selectedFilePath:n,selectedDiffPath:s,diffContents:a,selectedFile:o,selectedDiff:i}}async function el(e,t={}){if(e.type==="project"&&e.repoTargets?.length)return Cf(e,t);try{await K(e);let r=await Xt(e.worktreePath),[n,s]=await Promise.all([nl(e.worktreePath),sl(e.worktreePath,r)]),o=[...new Set(s.map(u=>u.path))],i=je(t.selectedFilePath??null,n),a=je(t.selectedDiffPath??null,o),[l,c]=await Promise.all([qr(e.worktreePath,i),a?Qs(e.worktreePath,a,s,r):Promise.resolve(Y("No diff selected","No local changes found.","empty"))]),d=a?{[a]:c}:{};return{taskId:e.id,fileRows:al(n),filePaths:n,diffRows:s,diffPaths:o,diffContents:d,selectedFilePath:i,selectedDiffPath:a,selectedFile:l,selectedDiff:c,error:null}}catch(r){let n=r instanceof Error?r.message:"Unable to inspect task worktree.";return{taskId:e.id,fileRows:[],filePaths:[],diffRows:[],diffPaths:[],diffContents:{},selectedFilePath:null,selectedDiffPath:null,selectedFile:Y("Files unavailable",n,"error"),selectedDiff:Y("Diff unavailable",n,"error"),error:n}}}async function Cf(e,t){let r=(e.repoTargets??[]).filter(p=>p.status==="ready"),n=await Promise.all(r.map(async p=>{let f=await Xt(p.worktreePath).catch(()=>null),[w,h]=await Promise.all([nl(p.worktreePath).catch(()=>[]),sl(p.worktreePath,f).catch(()=>[])]);return{target:p,baseRef:f,targetFiles:w,targetDiffRows:h}})),s=[],o=[];for(let{target:p,targetFiles:f,targetDiffRows:w}of n)s.push(...f.map(h=>`${p.repoId}/${h}`)),o.push(...w.map(h=>({...h,path:`${p.repoId}/${h.path}`})));let i=[...new Set(o.map(p=>p.path))].sort(),a=je(t.selectedFilePath??null,s),l=je(t.selectedDiffPath??null,i),[c,d]=await Promise.all([tl(e,a),(async()=>{if(!l)return Y("No diff selected","No local changes found.","empty");let p=Wr(e,l),f=p?n.find(w=>w.target.repoId===p.target.repoId):null;return rl(e,l,o,f?.baseRef??null)})()]),u=l?{[l]:d}:{};return{taskId:e.id,fileRows:al(s),filePaths:s,diffRows:o,diffPaths:i,diffContents:u,selectedFilePath:a,selectedDiffPath:l,selectedFile:c,selectedDiff:d,error:null}}async function tl(e,t){let r=Wr(e,t);if(!r)return Y("No file selected","No Git-visible files found.","empty");let n=await qr(r.target.worktreePath,r.relativePath);return{...n,path:t,title:t??n.title}}async function rl(e,t,r,n=null){let s=Wr(e,t);return s?{...await Qs(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}:Y(t,"Repo target is unavailable.","error",t)}function Wr(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 nl(e){let t=await I("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return ll(t.stdout)}async function sl(e,t){let[r,n,s,o]=await Promise.all([Af(e,t),Xa(e,"staged"),Xa(e,"unstaged"),Ef(e)]);return[...r,...n,...s,...o]}async function Af(e,t){if(!t)return[];let[r,n]=await Promise.all([I("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),I("git",["diff","--numstat",`${t}...HEAD`],{cwd:e})]),s=ol(r.stdout),o=il(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 Xa(e,t){let r=t==="staged"?["diff","--cached"]:["diff"],[n,s]=await Promise.all([I("git",[...r,"--name-status"],{cwd:e}),I("git",[...r,"--numstat"],{cwd:e})]),o=ol(n.stdout),i=il(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 Ef(e){let t=await I("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=ll(t.stdout);return await Promise.all(r.map(async s=>{let o=await qr(e,s),i=o.status==="ready"?xf(o.lines):null;return{group:"untracked",path:s,status:"A",additions:i,deletions:0}}))}function ol(e){return e.split(`
|
|
93
|
+
`).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 il(e){let t=new Map;for(let r of e.split(`
|
|
94
|
+
`)){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 Xt(e){return(await $("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await $("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function qr(e,t){if(!t)return Y("No file selected","No Git-visible files found.","empty");let r=Df(e,t);try{let n=await Pf(r);if(n.size>Sf)return Y(t,`File is ${n.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,n.size);let s=await bf(r);return $f(s)?Y(t,"Binary file preview is not available in Craig.","binary",t,s.byteLength):{path:t,status:"ready",title:t,lines:s.toString("utf8").split(`
|
|
95
|
+
`),byteLength:s.byteLength}}catch(n){let s=n instanceof Error?n.message:"Unable to read file.";return Y(t,s,"missing",t,null)}}async function Qs(e,t,r,n=null){if(!t)return Y("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 Xt(e);if(a){let l=await I("git",["diff","--stat","--patch",`--unified=${Fr}`,`${a}...HEAD`,"--",t],{cwd:e});l.stdout.trim().length>0&&s.push(`branch
|
|
96
|
+
${l.stdout.trimEnd()}`)}}if(o.includes("staged")){let a=await I("git",["diff","--cached","--stat","--patch",`--unified=${Fr}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`staged
|
|
97
|
+
${a.stdout.trimEnd()}`)}if(o.includes("unstaged")){let a=await I("git",["diff","--stat","--patch",`--unified=${Fr}`,"--",t],{cwd:e});a.stdout.trim().length>0&&s.push(`unstaged
|
|
98
|
+
${a.stdout.trimEnd()}`)}if(o.includes("untracked")){let a=await $("git",["diff","--no-index","--stat","--patch",`--unified=${Fr}`,"--","/dev/null",t],{cwd:e});a.stdout.trim().length>0&&s.push(`untracked
|
|
95
99
|
${a.stdout.trimEnd()}`)}let i=s.join(`
|
|
96
100
|
|
|
97
|
-
`);return i.length>
|
|
98
|
-
`):["No diff for this file."],byteLength:i.length}}function
|
|
99
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function
|
|
100
|
-
`}function
|
|
101
|
-
`)}function
|
|
102
|
-
`)}function
|
|
103
|
-
`),center:
|
|
104
|
-
`)}function
|
|
101
|
+
`);return i.length>If?Y(t,"Diff is above the 500 KB inline preview limit.","too_large",t,i.length):i.includes("\0")?Y(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(`
|
|
102
|
+
`):["No diff for this file."],byteLength:i.length}}function al(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 je(e,t){return e&&t.includes(e)?e:t[0]??null}function xf(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function ll(e){return[...new Set(e.split(`
|
|
103
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Df(e,t){let r=Js.resolve(e,t),n=Js.resolve(e);if(r!==n&&!r.startsWith(`${n}${Js.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function $f(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function Y(e,t,r,n=null,s=null){return{path:n,status:r,title:e,lines:[t],byteLength:s}}var Of=["tasks","center","inspector","actions"],cl=["agent","terminal"],dl=[],D="inspection",UI=[...cl,...dl],Xs=["commit","push","refresh-checks","close-task"],ul=["refresh-checks","close-task"],pl=["task","checks","pr","setup-run","actions","next-action"],Zs=["files","review"];function ml(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,n=Ff(e?.openInspectionKind)??r,s=g.runners.getEnabled(t);return{inputMode:qf(e?.inputMode),focusedRegion:jf(e?.focusedRegion),selectedRepoId:Ie(e?.selectedRepoId),selectedWorkspaceId:Ie(e?.selectedWorkspaceId),selectedTaskId:Ie(e?.selectedTaskId),selectedPtyTabId:Ie(e?.selectedPtyTabId),selectedLeftItemId:Hf(Ie(e?.selectedTaskId)),activeTab:r?D:Ie(e?.activeTab)??"agent",preferredPtyTabKind:Wf(e?.preferredPtyTabKind),inspectorSection:Zt(e?.inspectorSection,pl,"task"),inspectionMode:_f(e?.inspectionMode,r==="diff"?"review":"files"),openInspectionKind:n,selectedFileTreePath:Ie(e?.selectedFileTreePath),selectedFilePath:Ie(e?.selectedFilePath),selectedDiffPath:Ie(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,reviewScrollOffset:0,selectedActionId:Zt(e?.selectedActionId,Xs,"commit"),selectedProjectTargetId:null,selectedRunner:Uf(e?.selectedRunner,s,g.runners.getDefault(t)),centerTabRunner:null,actionMessage:null,footerToast:null,taskPromptInput:null,taskPromptError:null,fileSearchQuery:null,workspaceBrowser:null,terminal:Mf(),centerZoomed:!1}}function Mf(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function fl(e,t){return{...e??ur(),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 er(e,t,r={}){let n=Gf(e,t),s=to(n),o=(s?.kind==="workspace"?t.workspaces?.find(d=>d.id===s.id)??null:null)??(s?.kind==="task"?t.workspaces?.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.workspaceId)??null:null)??t.workspaces?.find(d=>d.id===e.selectedWorkspaceId)??t.workspaces?.[0]??null,a=((s?.kind==="repo"?t.repos.find(d=>d.id===s.id)??null:s?.kind==="task"?t.repos.find(d=>d.id===t.tasks.find(u=>u.id===s.id)?.repoId)??null:null)??(o?.kind==="project"?t.repos.find(d=>d.id===e.selectedRepoId&&o.discoveredRepoIds?.includes(d.id))??null:null)??(o?.kind!=="project"?t.repos.find(d=>d.id===o?.primaryRepoId)??null:null)??t.repos.find(d=>d.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,l=o?t.tasks.filter(d=>d.workspaceId===o.id):a?t.tasks.filter(d=>d.repoId===a):[],c=(s?.kind==="task"?l.find(d=>d.id===s.id)??null:null)??l.find(d=>d.id===e.selectedTaskId)??l[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:n,selectedWorkspaceId:o?.id??null,selectedRepoId:a,selectedTaskId:c?.id??null,...Bf(c,e.activeTab,e.selectedPtyTabId),selectedFilePath:Lf(e,t,c?.id??null),...Vf(e,t,c?.id??null),selectedDiffPath:Nf(e,t,c?.id??null),inspectorSection:Zt(e.inspectorSection,pl,"task")}}function ve(e,t){return{...e,terminal:t}}function gl(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function hl(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function ue(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
104
|
+
`}function kl(e){return e.length===1&&e>=" "&&e!=="\x7F"}function eo(e){return Tl(e)||Ct(e)!==null}function wl(e){return dl.includes(e)}function Tl(e){return cl.includes(e)}function yl(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[D]:[]]}function Nf(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function Lf(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedFilePath&&(t.inspection.filePaths??[]).includes(e.selectedFilePath)?e.selectedFilePath:t.inspection.selectedFilePath}function Zt(e,t,r){return t.includes(e??"")?e:r}function jf(e){return e==="tabs"?"center":Zt(e,Of,"tasks")}function _f(e,t){return e==="checks"||e==="actions"||e==="diff"||e==="review"?"review":Zt(e,Zs,t)}function Ff(e){return e==="file"||e==="diff"?e:null}function Wf(e){return e==="terminal"?"terminal":"agent"}function qf(e){return e==="terminal"?"terminal":"control"}function Uf(e,t=[...M],r="codex"){return e&&g.runners.isRunnerType(e)&&t.includes(e)?e:r}function Ur(e,t=M){let r=t.length>0?t:M,n=r.indexOf(e);return r[(n+1)%r.length]??r[0]??"codex"}function Ct(e){let t=M.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function Bf(e,t,r){if(!e)return{activeTab:t===D?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(Tl(t)){let l=e.ptyTabs.find(c=>c.kind===t)??null??s??n??e.ptyTabs[0]??null;return{activeTab:l?.id??D,selectedPtyTabId:l?.id??null}}if(t===D)return{activeTab:D,selectedPtyTabId:n?.id??s?.id??e.ptyTabs[0]?.id??null};let i=s??n??e.ptyTabs[0]??null;return{activeTab:i?.id??D,selectedPtyTabId:i?.id??null}}function Vf(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?Kf(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:n,collapsedFileTreePaths:s}}function Kf(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 Gf(e,t){let r=tt(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 tt(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 to(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 Ie(e){return typeof e=="string"?e:null}function Hf(e){return e?`task:${e}`:null}function tr(e){return typeof e=="string"&&e.startsWith("task:")}function Br(e){return typeof e=="string"&&e.startsWith("new-task:")}function Vr(e){return typeof e=="string"&&e.startsWith("new-task-workspace:")}function Rl(e){return typeof e=="string"&&e.startsWith("workspace:")}function ro(e){return Br(e)?e.slice(9):null}function no(e){return Vr(e)?e.slice(19):null}async function At(e,t,r){let n=ee(e),[s,o]=await Promise.all([G.repos.listRegisteredRepos(n),G.listWorkspaces(n,{archived:!1})]),i=await S.listTasks(n),a=so(i.tasks,t),l=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},c=a?await el(a,l):null;return{workspaceRoot:e,workspaces:o.workspaces,repos:s.repos,tasks:i.tasks,inspection:c,...r?{enabledRunnerIds:r}:{}}}function so(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function bl(e,t){return er(e,t)}import go from"node:path";import QI from"picocolors";var zf=[" \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 oo(){return[...zf]}var Kr={width:120,height:36},L={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ie(e,t){return{width:Math.max(e??Kr.width,Kr.width),height:Math.max(t??Kr.height,Kr.height)}}var Yf=["Start","Options","Exit"],Jf=["Resume","Options","Exit"],Hr=2,zr=2,Yr=2,Qf=new RegExp("\x1B\\[[0-?]*[ -/]*[@-~]","g"),Xf=new RegExp("\x1B\\[(?:0)?m","g"),Zf=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),eg=/https?:\/\/[^\s<>"']+/g,ao="\x1B[0m",lo="\x1B]8;;\x1B\\",P={panelBg:{bg:"0a0a0a",fg:"c0caf5"},panelMuted:{bg:"0a0a0a",fg:"565f89"},panelSelected:{bg:"1a1b26",fg:"c0caf5"},panelFocused:{bg:"1a1b26",fg:"7aa2f7"},divider:{bg:"0a0a0a",fg:"292e42"},rail:{bg:"0a0a0a",fg:"c0caf5"},overlay:{bg:"06060f",fg:"565f89"},overlayTitle:{bg:"06060f",fg:"565f89"},overlayLogo:{bg:"06060f",fg:"9ece6a"},overlaySubtitle:{bg:"06060f",fg:"41a6b5"},overlayMenuSelected:{bg:"06060f",fg:"7aa2f7"},accent:{fg:"7aa2f7"},success:{fg:"9ece6a"},pending:{fg:"e0af68"},error:{fg:"f7768e"},mutedfg:{fg:"565f89"},disabled:{fg:"3b4261"}},io=["3d59a1","506eb8","6386d0","7aa2f7","6386d0","506eb8"];function Il(e,t={}){return uo(e,{subtitle:"crAIg is that you?",menuItems:Yf,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}function vl(e,t={}){return uo(e,{subtitle:"Control mode is paused.",menuItems:Jf,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0,versionText:t.versionText??null,updateText:t.updateText??null})}var Gr=[" 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."],tg=["Help"],rg=5;function Xr(e,t={}){return uo(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??tg,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function Cl(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(_(" ".repeat(e.width),r,n)),o=oo(),i=Math.max(1,Math.floor((e.height-o.length-2-Gr.length)/2));for(let d=0;d<o.length&&!(i+d>=e.height);d+=1)s[i+d]=_(Ll(o[d]??"",e.width),r,P.overlayLogo);let a=Math.max(...Gr.map(d=>d.length)),l=Math.max(0,Math.floor((e.width-a)/2)),c=i+o.length+2;for(let d=0;d<Gr.length;d+=1){let u=c+d;if(u>=e.height)break;let p=Gr[d]??"";s[u]=_(ke(" ".repeat(l)+p,e.width),r,n)}return s.join(`
|
|
105
|
+
`)}function Al(e,t={}){let r=t.color??!0,n=P.overlay,s=new Array(e.height).fill(_(" ".repeat(e.width),r,n)),o="Error Log",i=t.errorLogPath??"",a=t.errorLogLines??[],l=Math.max(20,e.width-8),c=Math.max(0,Math.floor((e.width-l)/2)),d=[{text:o,tone:"selected"},{text:i,tone:"muted"},pe(),...a.length>0?a.map(f=>({text:f})):[{text:"No Craig errors have been logged.",tone:"muted"}],pe(),{text:"Esc returns to Options.",tone:"muted"}],u=rr(d,e.height-2),p=Math.max(1,Math.floor((e.height-u.length)/2));for(let f=0;f<u.length;f+=1){let w=p+f;if(w>=e.height)break;let h=u[f]??pe(),b=`${" ".repeat(c)}${Zr(h.text,l)}`,q=h.tone==="selected"?P.overlayMenuSelected:h.tone==="muted"?P.overlay:P.panelBg;s[w]=_(ke(b,e.width),r,q)}return s.join(`
|
|
106
|
+
`)}function El(e,t,r={}){let n=r.color??!0,s=L.leftWidth,o=L.rightWidth,i=r.centerOnly??!1,a=e.height-L.topRailHeight-1,l=r.focusFlashActive??!1,c={bg:P.divider.bg,fg:"9ece6a"},d=l&&(t.focusedRegion==="tasks"||t.focusedRegion==="center")?c:P.divider,u=l&&(t.focusedRegion==="center"||t.focusedRegion==="inspector")?c:P.divider,p=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent}`,f=_(ke(p,e.width),n,P.rail),w=sg(t,s-Hr-zr,a,n),h=co(e,t,{color:n,centerOnly:i}),b=ag(t,o,a,n),q=t.inputMode==="terminal",H=[],ne=[];for(let Te=0;Te<a;Te+=1)if(!i){let Ue=Jr(w[Te]??pe(),s,n,"left"),ir=_("\u2502",n,d),ar=_("\u2502",n,u),lr=Jr(b[Te]??pe(),o,n,"right");H.push(`${Ue}${ir}`),ne.push(`${ar}${lr}`)}let C=q||t.modalInput?P.panelBg:P.panelMuted,we=ng(t.footerText,t.footerToast,e.width,n,C),$t={row:1,column:1,width:e.width,rows:[f]},ot=i?null:{row:L.topRailHeight+1,column:1,width:s+L.dividerWidth,rows:H},yn=i?null:{row:L.topRailHeight+1,column:h.column+h.width,width:L.dividerWidth+o,rows:ne},m={row:e.height,column:1,width:e.width,rows:[we]},qe=i?h.rows:h.rows.map((Te,Ue)=>`${H[Ue]??""}${Te}${ne[Ue]??""}`);return{frame:[f,...qe,we].join(`
|
|
107
|
+
`),center:h,regions:{rail:$t,left:ot,center:h,right:yn,footer:m}}}function co(e,t,r={}){let n=r.color??!0,s=Dl(e,r.centerOnly??!1),o=og(t,s.width,s.rowCount,n);return{row:s.row,column:s.column,width:s.width,rows:o.map(i=>Jr(i,s.width,n,"center"))}}function xl(e,t,r,n={}){let s=t.tabs.find(c=>c.active)?.id??"";if(!eo(s)||t.centerHeader.tabLabel==="BROWSER"||t.terminal.error||t.terminal.rows.length===0||r.some(c=>c<0||c>=t.terminal.rows.length))return null;let o=n.color??!0,i=Dl(e,n.centerOnly??!1),a=$l(t,i.width,o).length,l=[...new Set(r)].map(c=>({terminalIndex:c,index:a+c})).filter(({index:c})=>c<i.rowCount).map(({terminalIndex:c,index:d})=>({index:d,row:Jr(Ol(t.terminal.rows[c]),i.width,o,"center")}));return{...i,rows:l}}function Dl(e,t){return{row:L.topRailHeight+1,column:t?1:L.leftWidth+L.dividerWidth+1,width:t?e.width:e.width-L.leftWidth-L.rightWidth-L.dividerWidth*2,rowCount:e.height-L.topRailHeight-1}}function ng(e,t,r,n,s){let o=` ${e}`;if(!t)return _(ke(o,r),n,s);let i=`${t.tone==="error"?"\u2717":"\u2713"} ${t.message}`,a=re(i),l=re(o),c=Math.max(1,r-l-a-2),d=l+c+a+2>r?Zr(o,Math.max(0,r-a-3)):o,u=Math.max(1,r-re(d)-a-2),p=t.tone==="error"?vg(i,n,s):Et(i,n,s),f=`${d}${" ".repeat(u)}${p} `;return _(ke(f,r),n,s)}function uo(e,t){let r=new Array(e.height).fill(_(" ".repeat(e.width),t.color,P.overlay)),n=oo(),s=t.menuItems.map((c,d)=>`${d===t.menuIndex?">":" "} ${c}`),o=t.optionsMessage?["",t.optionsMessage]:[],i=[...s,...o];for(;i.length<rg;)i.push("");let a=[...n,"",t.subtitle,"",...i],l=Math.max(1,Math.floor((e.height-a.length)/2));for(let c=0;c<a.length;c+=1){let d=Ll(a[c]??"",e.width);if(c<n.length){r[l+c]=_(d,t.color,P.overlayLogo);continue}if(c===n.length+1){r[l+c]=_(d,t.color,P.overlaySubtitle);continue}let u=c-(n.length+3),f=u>=0&&u<t.menuItems.length&&u===t.menuIndex?P.overlayMenuSelected:P.overlay;r[l+c]=_(d,t.color,f)}if(t.versionText){let c=t.updateText?" (update available)":"",d=`${t.versionText}${c} `,u=" ".repeat(Math.max(0,e.width-re(d)));r[e.height-1]=_(`${u}${fo(d,t.color,P.overlay)}`,t.color,P.overlay)}return r.join(`
|
|
108
|
+
`)}function sg(e,t,r,n){let s=dg(e.runners),o=1,i=e.leftTree.map(l=>cg(l,t,n));return[...rr(i,r-o),s]}function og(e,t,r,n){let s=e.tabs.find(i=>i.active)?.id??"agent",o=e.centerHeader.tabLabel==="BROWSER"||!eo(s)?e.centerTranscript.map(i=>({...i})):ig(e);return rr([...$l(e,t,n),...o],r)}function $l(e,t,r){let n=t-2,s=e.tabs.find(b=>b.active)?.label??"AGENT",o=e.inputMode==="terminal"?0:Pg(e.tabs),i=e.inputMode==="terminal"?n:s.length+1,a="\u2500".repeat(Math.max(0,i)),l=`${" ".repeat(o)}${e.inputMode==="terminal"?Et(a,r,P.panelBg):Qr(a,r,P.panelMuted)}`,c=[`${Qr(e.centerHeader.tabLabel,r,P.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),d=ug(e.tabs,r,e.focusedRegion==="center"),u=" engaged ",p=u.length+2,f=e.inputMode==="terminal"?Et(`${u}\u25CF `,r,P.panelBg):"",w=e.inputMode==="terminal"?" ".repeat(Math.max(0,n-re(d)-p)):"";return[{text:e.inputMode==="terminal"?`${d}${w}${f}`:d},{text:l,tone:"muted"},{text:c},pe()]}function ig(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},pe(),{text:e.terminal.error},pe(),{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(Ol)}function Ol(e){return{text:mo(e.segments),segments:e.segments,fullBleed:!0}}function ag(e,t,r,n){let s=e.rightInspection?lg(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):rr([{text:"CONTEXT"},pe(),...e.rightContext.map(o=>pg(o,n)),...e.actionMessage?[pe(),{text:e.actionMessage}]:[]],r);return rr(s,r)}function lg(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:Ig(o-Math.floor(s/2),0,Math.max(0,n.length-s));return[...r.map(a=>Pl(a)),...n.slice(i,i+s).map(a=>Pl(a))]}function Pl(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 cg(e,t,r){let n=" ".repeat(e.indent??0),s=e.accentDot?" \u25CF":"",o=e.status?` ${e.status}`:"",i=e.accentDot?` ${Et("\u25CF",r,e.selected?P.panelSelected:P.panelBg)}`:"",a=e.prBadge?e.prBadge.reduce((w,h)=>w+re(h.text),0):0,l=t-re(o)-re(s)-a,c=e.activity?`${e.selected?"\u25B8":" "} \u25CF `:"",d=e.selected?e.text:e.focused?Et(e.text,r,P.panelBg):e.panelHeader?Qr(e.text,r,P.panelMuted):e.text,u=ke(`${n}${c}${d}`,Math.max(0,l)),p=e.selected?"selected":e.muted?"muted":"default";if(e.activity){let w=`${n}${e.selected?"\u25B8":" "} `,h=u.slice(w.length+2),b=[{text:w},Ml(e.activity,e.activityAnimationFrame??0),{text:` ${h}${o}${i}`},...e.prBadge??[]];return{text:mo(b),segments:b,tone:p}}if(e.prBadge){let w=[{text:`${u}${o}${i}`},...e.prBadge];return{text:`${u}${o}${e.prBadge.map(b=>b.text).join("")}`,segments:w,tone:p}}return{text:`${u}${o}${i}`,tone:p}}function dg(e){let t=e.map(n=>{let s=n.health>=1,o=parseInt(n.count,10),i=o>1?` (${o})`:"";return{text:`${s?"\u25CF":"\u25CB"} ${n.name}${i}`,active:s}}),r=[];for(let n=0;n<t.length;n++){let s=t[n];n>0&&r.push({text:" "}),s.active?r.push({text:s.text,style:{fg:P.success.fg}}):r.push({text:s.text,style:{fg:P.panelMuted.fg}})}return{text:t.map(n=>n.text).join(" "),segments:r,tone:"muted"}}function ug(e,t,r){return e.map(n=>{let s=n.active?r?Et(n.label,t,P.panelBg):Qr(n.label,t,P.panelBg):fo(n.label,t,P.panelBg),o=n.activity?po(Ml(n.activity,n.activityAnimationFrame??0),t,P.panelBg):"";return`${s}${o?` ${o}`:""}`}).join(" ")}function Ml(e,t){return{text:"\u25CF",style:{fg:e==="working"?io[t%io.length]??io[0]:e==="ready"?P.success.fg:e==="error"?P.error.fg:P.panelMuted.fg}}}function pg(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?fo(e.value,t,P.panelBg):e.value}`}}function Jr(e,t,r,n){let s=mg(n,e.tone??"default"),o=fg(e,r,s);if(n==="left"){if(e.fullBleed)return _(ke(o,t),r,s);let a=t-Hr-zr;if(e.rightAlign){let c=re(o),d=Math.max(0,a-c),u=`${" ".repeat(Hr)}${" ".repeat(d)}${o}${" ".repeat(zr)}`;return _(u,r,s)}let l=`${" ".repeat(Hr)}${ke(o,a)}${" ".repeat(zr)}`;return _(l,r,s)}return n==="center"&&e.fullBleed?gg(e,t,r,s):_(ke(` ${o}`,t),r,s)}function mg(e,t){return t==="selected"||t==="focused"?P.panelSelected:t==="muted"?P.panelMuted:P.panelBg}function rr(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(pe());return r}function pe(){return{text:""}}function fg(e,t,r){return e.segments?e.segments.map(n=>po(n,t,r)).join(""):e.text}function gg(e,t,r,n){let s=" ".repeat(Yr),o=Math.max(0,t-Yr*2);if(!e.segments)return _(`${s}${ke(e.text,o)}${s}`,r,n);let i=wg(e.segments,o),a=`${s}${i.map(l=>po(l,r,n)).join("")}${s}${r?lo:""}`;return _(a,r,n)}function po(e,t,r){let n=e.href?`${Nl(e.href)}${e.text}${lo}`:hg(e.text);return!t||!e.style?n:`${nr(Rg(e.style,r))}${bg(e.style)}${n}${ao}${nr(r)}`}function hg(e){return e.replace(eg,t=>{let[r,n]=kg(t);return`${Nl(r)}${r}${lo}${n}`})}function kg(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function Nl(e){return`\x1B]8;;${e}\x1B\\`}function wg(e,t){let r=Tg(e,t);return yg(r,t)}function Tg(e,t){let r=[],n=t;for(let s of e){if(n<=0)break;let o=re(s.text);if(o<=n){r.push(s),n-=o;continue}let i=Zr(s.text,n);i.length>0&&r.push({...s,text:i}),n=0}return r}function yg(e,t){let r=re(mo(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 Rg(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 bg(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 Pg(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 Ll(e,t){let r=Math.max(0,t-re(e)),n=Math.floor(r/2),s=r-n;return`${" ".repeat(n)}${e}${" ".repeat(s)}`}function ke(e,t){let r=re(e);return r>=t?Sg(e,t):e+" ".repeat(t-r)}function Sg(e,t){if(t<=0)return"";if(re(e)<=t)return e;let r=_l(e);return Zr(r,Math.max(0,t-1))+"\u2026"}function re(e){let t=0;for(let r of Array.from(_l(e)))t+=jl(r);return t}function Zr(e,t){let r="",n=0;for(let s of Array.from(e)){let o=jl(s);if(n+o>t)break;r+=s,n+=o}return r}function jl(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 Ig(e,t,r){return Math.min(Math.max(e,t),r)}function _l(e){return e.replace(Zf,"").replace(Qf,"")}function mo(e){return e.map(t=>t.text).join("")}function _(e,t,r){if(!t)return e;let n=nr(r),s=e.replace(Xf,`${ao}${n}`);return`${n}${s}${ao}`}function nr(e){let t=[];return e.fg&&t.push(`38;2;${Sl(e.fg).join(";")}`),e.bg&&t.push(`48;2;${Sl(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function Sl(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Et(e,t,r){return en(e,t,P.success.fg,r)}function vg(e,t,r){return en(e,t,P.error.fg,r)}function Qr(e,t,r){return en(e,t,P.accent.fg,r)}function fo(e,t,r){return en(e,t,P.mutedfg.fg,r)}function en(e,t,r,n){if(!t)return e;let s=n.bg?{fg:r,bg:n.bg}:{fg:r};return`${nr(s)}${e}${nr(n)}`}function Fl(e,t,r){let n=e.tasks.find(l=>l.ptyTabs.some(c=>c.id===t))??null,s=n?.ptyTabs.find(l=>l.id===t)??null,o=n?.worktreePath??r,i=s?.kind==="agent"?Ag(s):[],a=n?{CRAIG_WORKSPACE_ROOT:r,CRAIG_TASK_ID:n.id,...s?.kind==="agent"?{CRAIG_AGENT_TAB_ID:s.id}:{}}:{};return n?.type==="project"?{cwd:o,command:i,env:{...a,GIT_CEILING_DIRECTORIES:Cg(process.env.GIT_CEILING_DIRECTORIES,o)}}:n?{cwd:o,command:i,env:a}:{cwd:o,command:i}}function Cg(e,t){let r=(e??"").split(go.delimiter).filter(n=>n.length>0);return r.includes(t)?r.join(go.delimiter):[...r,t].join(go.delimiter)}function Ag(e){return e.command.length>0?e.command:["codex"]}function Wl(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 _e(e){return{columns:Math.max(20,e.width-L.leftWidth-L.rightWidth-L.dividerWidth-Yr*2),rows:Math.max(5,e.height-L.topRailHeight-5)}}function ql(e){return e.length===1||ue(e)||e==="BACKSPACE"||e==="TAB"}function Fe(e){return typeof e=="string"&&new RegExp(`:(?:agent|${M.join("|")})(?:-\\d+)?$`).test(e)}function Ul(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 ho(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Bl(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 sr(e){return Kl.includes(e)?"SHIFT_ENTER":null}function ko(e){return Kl.some(t=>t.startsWith(e))}function Vl(e){return e==="ESCAPE"?"\x1B":e.length===1?e:null}var Kl=["\x1B[13;2u","\x1B[13;2~","\x1B[27;2;13~","\x1B[27;2;10~"];function Gl(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
105
109
|
`||r===`\r
|
|
106
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function
|
|
110
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(n=>n===t.key)}function Hl(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function zl(e,t=null){let r=t?.split(`
|
|
107
111
|
`)??[];return e.split(`
|
|
108
|
-
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function
|
|
109
|
-
`,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:""},
|
|
110
|
-
`))&&this.touchActivity(r))}writeKey(t){let r=
|
|
111
|
-
[process exited ${
|
|
112
|
+
`).map((n,s)=>r[s]===n?"":`\x1B[${s+1};1H${n}`).join("")}function tn(e,t,r,n){return e.map((s,o)=>t?.[o]===s?"":`\x1B[${r+o};${n}H${s}`).join("")}import{spawn as Xg}from"node:child_process";import{createServer as Zg,createConnection as nc}from"node:net";import{openSync as eh}from"node:fs";import{mkdir as th,readFile as So,rm as nt,writeFile as rh}from"node:fs/promises";import sn from"node:path";import{createRequire as _g}from"node:module";import Eg from"@xterm/headless";var xg=1e3,Dg=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function Jl(e){return new Eg.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:xg,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function Ql(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function To(e,t){return new Promise(r=>{e.write(t,r)})}function Xl(e,t=0){let r=e.buffer.active,n=[],s=r.getNullCell(),o=r.baseY+r.cursorY,i=Math.max(0,r.baseY-t);for(let a=0;a<e.rows;a+=1){let l=r.getLine(i+a);if(!l){n.push({segments:[]});continue}let c=[];for(let d=0;d<e.cols;d+=1){let u=l.getCell(d,s);!u||u.getWidth()===0||c.push({text:u.getChars()||" ",style:Mg(u,i+a===o&&d===r.cursorX)})}n.push({segments:$g(Og(c))})}return n}function $g(e){let t=[];for(let r of e){let n=t.at(-1);if(n&&jg(n.style,r.style)){n.text+=r.text;continue}let s={text:r.text};Zl(r.style)||(s.style=r.style),t.push(s)}return t}function Og(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!Zl(r.style))break;t-=1}return e.slice(0,t)}function Mg(e,t){let r={},n=Yl(e,"fg"),s=Yl(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 Yl(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"):Dg[s]??Ng(s)}function Ng(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(Lg).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 Lg(e){return e===0?0:55+e*40}function jg(e,t){return wo(e)===wo(t)}function wo(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function Zl(e){return wo(e)===""}var Fg=_g(import.meta.url),Wg=/^CTRL_([A-Z])$/,qg="\x1B[6n",Ug="\x1B[c",Bg="\x1B[?u",Vg={ENTER:"\r",KP_ENTER:"\r",SHIFT_ENTER:`
|
|
113
|
+
`,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:""},rn=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")yo(o),this.sessions.delete(r);else return this.attachedTabId=r,o.scrollbackLines=0,ec(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(`
|
|
114
|
+
`))&&this.touchActivity(r))}writeKey(t){let r=Kg(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&&ec(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&&(yo(r),this.sessions.delete(t)),this.removeActivity(t),this.attachedTabId===t&&(this.attachedTabId=null)}disposeAll(){for(let t of this.sessions.values())yo(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:Gg(r),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,n,s){let o=this.spawn??zg().spawn,i=Jl(n),a=s??this.resolveSessionSpec(t,r),l=Je({...this.env,...a.env??{}}),{executable:c,args:d}=Yg(this.shell,a.command,{cwd:a.cwd,env:l}),u=o(c,d,{name:"xterm-256color",cols:n.columns,rows:n.rows,cwd:a.cwd,env:Jg(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(f=>{this.touchActivity(p),Qg(u,f),To(p.terminal,f).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p.disposables.push(u.onExit(f=>{p.status="exited",p.exitCode=f.exitCode,p.lastActivityAt=Date.now(),this.notifyActivity(p),To(p.terminal,`\r
|
|
115
|
+
[process exited ${f.exitCode}]`).then(()=>{p.screenDirty=!0,this.onUpdate?.({tabId:p.tabId,kind:"full"})})})),p}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}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 Kg(e){if(e.length===1)return e;let t=Vg[e];if(t!==void 0)return t;let r=Wg.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function ec(e,t){Hg(e.pty,t),Ql(e.terminal,t),e.screenDirty=!0}function Gg(e){return(e.screenDirty||e.renderedScrollbackLines!==e.scrollbackLines)&&(e.rows=Xl(e.terminal,e.scrollbackLines),e.renderedScrollbackLines=e.scrollbackLines,e.screenDirty=!1),e.rows}function yo(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function Hg(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function zg(){return Fg("node-pty")}function Yg(e,t,r){if(t.length===0)return{executable:e,args:[]};let s=`${[Qe(t[0],r),...t.slice(1)].map(tc).join(" ")}; exec ${tc(e)} -l`;return{executable:e,args:["-lc",s]}}function tc(e){return`'${e.replaceAll("'","'\\''")}'`}function Jg(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 Qg(e,t){for(let r=0;r<Ro(t,qg);r+=1)e.write("\x1B[1;1R");for(let r=0;r<Ro(t,Ug);r+=1)e.write("\x1B[?1;2c");for(let r=0;r<Ro(t,Bg);r+=1)e.write("\x1B[?0u")}function Ro(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 sc=jr,nh=new Set([sc]),sh=16,oh=250;async function oc(e){let t=It(e.paths);await ch(t,e.paths,e.spawnDaemon);let r=await pc(t.socketPath),n=new bo(r,e);return await n.ready(),n}async function ic(e,t={}){let r=It(e);await th(e.runtimeDir,{recursive:!0}),await nt(r.socketPath,{force:!0});let n=new Po(e,t),s=Zg(o=>n.handleConnection(o));await gh(s,r.socketPath),await rh(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 nt(r.socketPath,{force:!0}),await nt(r.pidPath,{force:!0}),n.disposeAll()}async function ac(e){let t=It(e);return await on(t.socketPath)?(await dc(t.socketPath),!0):!1}var bo=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(!cc(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)}
|
|
112
116
|
`);let o=await s;if(!o.ok)throw new Error(o.error);return o}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
113
117
|
`);for(;r!==-1;){let n=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(n),r=this.buffer.indexOf(`
|
|
114
|
-
`)}}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=
|
|
118
|
+
`)}}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=lh(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)}}},Po=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 rn({...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(`
|
|
115
119
|
`);for(;o!==-1;){let i=r.slice(0,o);r=r.slice(o+1),this.handleLine(t,i),o=r.indexOf(`
|
|
116
|
-
`)}});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{
|
|
117
|
-
${o.slice(-2e3)}`:""}`)}async function
|
|
120
|
+
`)}});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{rt(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let s=this.handleRequest(t,n);rt(t,{id:n.id,ok:!0,...n.type==="ping"?{protocolVersion:sc}:{},...n.type==="getActivitySnapshots"?{activities:this.runtime.getActivitySnapshots()}:{},...s?{view:s}:{}})}catch(s){let o=s instanceof Error?s.message:String(s);rt(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 hh(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(nn)}),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(nn)}),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),rt(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)},oh))}}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&&rt(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&&rt(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)},sh))}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=ih(s,r),i=ah(s.view,r);s.view=r,s.rowKeys=r.rows.map(nn),(o.rows.length>0||i)&&rt(n,{type:"update",tabId:t,patch:o})}}};function ih(e,t){let r=[];for(let n=0;n<t.rows.length;n+=1){let s=t.rows[n];e.rowKeys[n]!==nn(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 ah(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 lh(e,t){return e.status!==t.status||e.error!==t.error||(e.scrolledBack??!1)!==t.scrolledBack||e.rows.length!==t.rowCount}function nn(e){return JSON.stringify(e)}async function ch(e,t,r){if(await dh(e.socketPath,1e3))return;await on(e.socketPath)&&(await dc(e.socketPath),await rc(e.socketPath,1e3)),await on(e.socketPath)&&(await mh(e),await rc(e.socketPath,1e3)),await ph(e);let n=t.workspaceRoot;if(r)r(n);else{let{command:i,args:a}=uh(n),l=eh(sn.join(t.runtimeDir,"pty-daemon.log"),"a");Xg(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 lc(e.socketPath))return;await Io(50)}let o=await So(sn.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${o?`
|
|
121
|
+
${o.slice(-2e3)}`:""}`)}async function lc(e){let t=await fh(e).catch(()=>null);return t?.ok===!0&&cc(t.protocolVersion)}function cc(e){return e!==void 0&&nh.has(e)}async function dh(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await lc(e))return!0;await Io(50)}return!1}function uh(e){let t=process.argv[1];if(t?.endsWith(".ts")){let n=sn.resolve(sn.dirname(t),"..","node_modules",".bin","tsx");return{command:rs("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 ph(e){let t=await So(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&mc(r))return}await nt(e.socketPath,{force:!0}),await nt(e.pidPath,{force:!0})}async function on(e){let t=await pc(e).catch(()=>null);return t?(t.end(),!0):!1}async function dc(e){await uc(e,{id:1,type:"shutdown"}).catch(()=>null)}async function mh(e){let t=await So(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!mc(r)){await nt(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await nt(e.socketPath,{force:!0})}}async function fh(e){return uc(e,{id:1,type:"ping"})}function uc(e,t){return new Promise((r,n)=>{let s=nc(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)}
|
|
118
122
|
`)),s.once("error",l=>{a(),n(l)}),s.on("data",l=>{o+=String(l);let c=o.indexOf(`
|
|
119
|
-
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function
|
|
120
|
-
`)}catch{}}function
|
|
121
|
-
`}function Bg(e){return e.length===1&&e>=" "&&e!==""}import rr from"node:path";function cc(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 dc="\u{F024B} ",uc="\u{F0DCF} ",pc="\u25CB",wo="\uEA64",mc="\uEAFE",fc="\uEBDA",ko="\u25CB",To="\u25CF",yo="\u2713",Ro="\u2715";function gc(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 hc={idle:0,working:1,ready:2,error:3};function tr(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 bo(e,t,r,n){let s=e.ptyTabs.find(i=>i.kind==="agent")?.id,o=t===s&&e.runnerSession?.lastKnownState==="failed"?"error":"idle";return tr(t,r,n,o)}function Po(e,t,r){let n="idle";for(let s of e.ptyTabs){if(s.kind!=="agent")continue;let o=bo(e,s.id,t,r);hc[o]>hc[n]&&(n=o)}return n}function wc(e,t,r){return e.some(n=>n.ptyTabs.some(s=>s.kind==="agent"&&tr(s.id,t,r)==="working"))}var en="empty",B={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Rc(e,t,r){let n=Gg(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",c=Ch(t.tasks),d=Yg(e,a),u=zg(e,a,d,r),m=u.find(b=>b.id===d)??u[0]??{id:"agent",label:"CODEX"},g=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`:Qt(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":d===x?"\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:rr.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${rr.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:w},leftTree:Vg(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(b=>vh(b,c[b])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":m.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:w},centerTranscript:Hg(d,e,s,a,e.workspaceBrowser,g,n),tabs:u,rightContext:Ih(s,a),rightInspection:lh(e,a,g)}}function Vg(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return Kg(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],c=t.tasks.filter(d=>d.workspaceId===i.id);if(c.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of c){let u=e.selectedLeftItemId===`task:${d.id}`,m=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,g={id:`task:${d.id}`,taskId:d.id,text:r?m:`${u?"\u25B8":"\u2022"} ${m}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:Po(d,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},y=Pc(d);y&&(g.prBadge=y),n.push(g)}if(i.kind==="project"){let d=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===d;n.push({id:d,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 d=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===d;n.push({id:d,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 d of l.slice(0,6)){let u=t.repos.find(m=>m.id===d);n.push({text:` \xB7 ${u?.name??d}`,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 Kg(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 m=t.selectedLeftItemId===`task:${u.id}`,g=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,y={id:`task:${u.id}`,taskId:u.id,text:s?g:`${m?"\u25B8":"\u2022"} ${g}`,indent:2,selected:m,focused:m&&t.focusedRegion==="tasks",...s?{activity:Po(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},w=Pc(u);w&&(y.prBadge=w),e.push(y)}let c=`new-task:${i.id}`,d=t.selectedLeftItemId===c;e.push({id:c,text:`+ New Task [${f.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:d,focused:d&&t.focusedRegion==="tasks",muted:!d})}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 Gg(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 Hg(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,m)=>{let g=m===s.selectedIndex?"\u25B8":" ",y=u.kind==="repo"?" [git repo]":"/";return`${g} ${u.name}${y}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return me(["Browse for a workspace to register.",s.cwd,...d?[d]:[],"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return me(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return me([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${f.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?me([`${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."]):me([`${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===x&&t.openInspectionKind==="file"?Xg(n,o,t.fileScrollOffset):e===x&&t.openInspectionKind==="diff"?Zg(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?me(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):me(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function zg(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Jg(i),...i.kind==="agent"&&n&&t?{activity:bo(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:en,label:"EMPTY",active:r===en,focused:e.focusedRegion==="center"&&r===en}];let o=e.openInspectionKind||r===x?[{id:x,label:Qg(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Yg(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===x&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??x:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??x:en}function Jg(e){return e.title.toUpperCase()}function Qg(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?rr.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Xg(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return me(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=bc(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:""},...eh(n.lines,r,s)]}function Zg(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return me(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=bc(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:""},...th(n.lines,r,s)]}function me(e){return e.map(t=>({text:t}))}function eh(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:B.lineNumber}},{text:" \u2502 ",style:{fg:B.gutter}},...So(o,r)],tone:"default"}})}function th(e,t,r){let n=rh(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>nh(o,r))}function rh(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 nh(e,t){let r=kc(e.oldNumber),n=kc(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:B.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:B.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?oh(So(e.text,t),o.bg,o.fallbackFg):So(e.text,t),l=o?{fg:B.lineNumber,bg:o.bg}:{fg:B.lineNumber},c=o?{fg:B.gutter,bg:o.bg}:{fg:B.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function kc(e){return e===null?" ":String(e).padStart(4," ")}function bc(e){let t=rr.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 So(e,t){return t==="diff"?sh(e):t==="markdown"?ih(e):t==="json"?Io(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Io(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 sh(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:B.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:B.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:B.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:B.diffMeta}}]:[{text:e}]}function oh(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function ih(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:B.markup,bold:!0}}]:Io(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Io(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:ah(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function ah(e){return e.startsWith("//")||e.startsWith("/*")?{fg:B.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:B.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:B.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:B.markup}:{fg:B.keyword}}function lh(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"?Sc(t.repoTargets??[]):s?.pullRequest??(t?A(t):null),i=[ch(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=vc(e,t),l=Co(e,r),c=fh([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...bh(e,r)]}:{title:"",rows:[...i,...Co(e,r)]}}function ch(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=vo(t),i=Ao(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Tc(e){return[{text:" "},vo(e),{text:" "},Ao(e)]}function Pc(e){if(e.type==="project"&&e.repoTargets?.length){let r=Sc(e.repoTargets);return r?Tc(r):null}let t=A(e);return t?.number?Tc(t):null}function Sc(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=uh(r);return{number:-1,status:dh(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 dh(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 uh(e){let t=e.map(r=>Ic(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 vo(e){return!e||!e.number?{text:pc,style:{fg:"565f89"}}:e.status==="merged"?{text:mc,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:fc,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:wo,style:{fg:"565f89"}}:{text:wo,style:{fg:"9ece6a"}}}function Ao(e){return e?.aggregateReadiness?yc(e.aggregateReadiness):yc(Ic(e))}function yc(e){return e==="failed"?{text:Ro,style:{fg:"f7768e"}}:e==="pending"?{text:To,style:{fg:"e0af68"}}:e==="success"?{text:yo,style:{fg:"9ece6a"}}:{text:ko,style:{fg:"565f89"}}}function Ic(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")?Cc(e)?"failed":ph(e)?"success":"pending":"pending"}function ph(e){return!!(e.mergeable&&!e.draft&&!Cc(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function Cc(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function vc(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return mh(e,t);let r=A(t),n=Ec("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 Zr=32;function mh(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,m=Zr-u.length-1,g=c.length>m?c.slice(0,m-1)+"\u2026":c,y=Zr-g.length-u.length;r.push({id:`project-review:${i.repoId}`,text:g+" ".repeat(Math.max(1,y))+u,selected:a,focused:l,muted:!0})}else{let d=vo(i.pullRequest),u=Ao(i.pullRequest),m=`${d.text} ${u.text}`,g=Zr-m.length-1,y=c.length>g?c.slice(0,g-1)+"\u2026":c,w=Zr-y.length-m.length,b=y+" ".repeat(Math.max(1,w));r.push({id:`project-review:${i.repoId}`,text:b+m,selected:a,focused:l,segments:[{text:b},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...Ec("target",o.branch,o.pullRequest))),r}function Ac(e,t,r=null){return 3+vc(e,t).length+Co(e,r).length}function Ec(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=gh(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:hh(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${xc(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(wh)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,m)=>kh(u,n(`comment:${m}`))))),s}function fh(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 gh(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function hh(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function xc(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 wh(e){let{icon:t,color:r}=yh(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," ")} ${Rh(e.status)}`,color:r,muted:!1}}function kh(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${xc(e.createdAt)}`:"",s=Th(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function Th(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 yh(e){switch(e){case"success":return{icon:yo,color:"9ece6a"};case"pending":return{icon:To,color:"e0af68"};case"failed":return{icon:Ro,color:"f7768e"};case"skipped":return{icon:ko,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Rh(e){return e==="success"?"passing":e==="failed"?"failing":e}function bh(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=Eo(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?dc:uc:cc(l.label),m=l.kind==="directory"?"7aa2f7":gc(l.label),g=" ".repeat(l.depth),y=m?{text:u,style:{fg:m}}:{text:u},w=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},b=[{text:g},y,w];return{id:l.path,text:`${g}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:b}})]}function Eo(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 Co(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(Ph(t))return Sh(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=>Dc(o,e,t))))}return r}function Ph(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Sh(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>Dc(c,e,t,s.length+1))))}}return r}function Dc(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 Ih(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:rr.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 Ch(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function vh(e,t){return{name:f.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function $c(e,t,r,n,s=null){if(s)return Ah(e,t,r,n,s);let o=Qs(e,t,{centerOnly:n});return Eh(r,o)?{output:zr(o.rows,r.rows,o.row,o.column),region:o}:null}function Ah(e,t,r,n,s){let o=wl(e,t,s,{centerOnly:n});if(!o||!xh(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:c})=>i[l]===c?"":(i[l]=c,`\x1B[${o.row+l};${o.column}H${c}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function Eh(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function xh(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}function Oc(e,t,r){let n={...e},s="";for(let o of r){let i=e[o],a=t[o];if(!Dh(i,a))return null;!i||!a||(s+=zr(a.rows,i.rows,a.row,a.column),n[o]=a)}return{output:s,regions:n}}function Dh(e,t){return!e||!t?e===t:e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}var $h=["tasks","center","inspector"];function Oh(e,t,r){if(t==="ESCAPE")return T({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return T({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return Do(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Oo({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return T({state:{...e,fileSearchQuery:n},changed:!0})}return T({state:e})}function Oo(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return nl(t)?T({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):T({state:e});if(e.fileSearchQuery!==null)return Oh(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return T({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return T({state:e,exit:!0});if(t==="ESCAPE")return T({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return T({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(Nr(e.selectedLeftItemId)||jr(e.selectedLeftItemId)))return T({state:{...e,selectedRunner:Lr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Mc(e,1);if(t==="SHIFT_TAB"||t==="[")return Mc(e,-1);if(t==="z"||t==="Z")return T({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===x?We(e,-1,r):Do(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===x?We(e,1,r):Do(e,1,r);if(t==="PAGE_UP")return We(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return We(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return We(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return We(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??O,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return T({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=qh(e,t);return T({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 T({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return T({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return T({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Qt(e.selectedLeftItemId)&&e.selectedTaskId)return T({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&ll(e.selectedLeftItemId)&&e.selectedWorkspaceId)return T({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&jc(e.activeTab,r.ptyTabIds??[]))return T({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return xo(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Lc(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return xo(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Lc(e,1)}if(ue(t)){if(e.focusedRegion==="tasks"&&(Nr(e.selectedLeftItemId)||jr(e.selectedLeftItemId))){let n=Vs(e.selectedLeftItemId),s=Ks(e.selectedLeftItemId);return T({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 T({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Qt(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return T({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Rt(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&jc(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return T({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Rt(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===x)return T({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 T({state:Nh({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return T({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:x,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?T({state:{...e,selectedDiffPath:n,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?T({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):T({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?T({state:e}):e.selectedActionId==="refresh-checks"?T({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?T({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):T({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return T({state:e})}function We(e,t,r){if(t===0)return T({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?Fc(e,t,r):e.inspectionMode==="review"?Nc(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):T({state:e});if(e.focusedRegion==="center"&&e.activeTab===x){if(e.openInspectionKind==="file")return Nc(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return jh(e,t,r)}return T({state:e})}function Mc(e,t){return tn(e,"focusedRegion",$h,t)}function xo(e,t,r){let n=tn(e,"activeTab",r&&r.length>0?r:Uh(e),t);return!n.changed||ol(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Rt(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Do(e,t,r){if(e.focusedRegion==="tasks")return Mh(e,t,r.leftItemIds);if(e.focusedRegion==="center")return xo(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Fc(e,t,r);if(r.projectTargetIds?.length){let s=$o(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=$o(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:tn(e,"selectedActionId",Xa,t)}return tn(e,"selectedActionId",Ws,t)}function Mh(e,t,r){let n=$o(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=Bs(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=Vs(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=Ks(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function Lh(e,t){if(e.inspectionMode===t)return T({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?x:e.activeTab;return T({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 Lc(e,t){return Lh(e,Wh(e.inspectionMode,qs,t))}function Fc(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return T({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=ve(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return T({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return T({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?x:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function Nh(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 Nc(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=ve(e[t]+r,0,o);return i===e[t]?T({state:e}):T({state:{...e,[t]:i,actionMessage:null},changed:!0})}function jh(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Fh(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=ve(i,0,o);return d===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=ve(i,0,o);return d===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?T({state:{...e,selectedDiffPath:d,activeTab:x,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?T({state:e}):T({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?T({state:{...e,selectedDiffPath:d,activeTab:x,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?T({state:e}):T({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=ve(i,0,o);return c===e.diffScrollOffset?T({state:e}):T({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function Fh(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=ve(e.diffScrollOffset+t,0,o),a=_h(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?T({state:e}):T({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function _h(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function tn(e,t,r,n){let s=r.indexOf(e[t]),o=ve(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?T({state:e}):T({state:{...e,[t]:i,actionMessage:null},changed:!0})}function $o(e,t,r,n,s=!1){if(r.length===0)return T({state:e});let o=r.indexOf(e[t]??r[0]??""),i=ve(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?T({state:e}):T({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function Wh(e,t,r){let n=t.indexOf(e);return t[ve(n+r,0,t.length-1)]??e}function T(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 jc(e,t){return t.includes(e)}function qh(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Rt(e.activeTab)??e.preferredPtyTabKind}function Uh(e){return[e.selectedPtyTabId,e.openInspectionKind?x:null].filter(t=>typeof t=="string")}function ve(e,t,r){return Math.min(r,Math.max(t,e))}var _c=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>E(n.paths,e.selectedTaskId,o=>{let i=t??Bh(o,e.activeTab,e.preferredPtyTabKind),a=Bc(o,i,r??void 0,n.config);return{...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id}}));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"}`}}},Wc=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={closedTab:null,nextSelectedTab:null};if(await E(t.paths,e.selectedTaskId,o=>{let i=o.ptyTabs.findIndex(l=>l.id===e.activeTab);if(i===-1)throw new Error("Only PTY tabs can be closed.");s.closedTab=o.ptyTabs[i];let a=o.ptyTabs.filter(l=>l.id!==s.closedTab.id);return s.nextSelectedTab=a[Math.min(i,a.length-1)]??null,{...o,ptyTabs:a,selectedPtyTabId:s.nextSelectedTab?.id??null}}),!s.closedTab)throw new Error("Only PTY tabs can be closed.");return{closedTab:s.closedTab,nextSelectedTab:s.nextSelectedTab}});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}`}}},qc=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{await E(t.paths,r,n=>!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab?n:{...n,selectedPtyTabId:e.activeTab})})},Uc=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{await E(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:s})}),{...e,selectedPtyTabId:r.id};let n=Bc(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{await E(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id}})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function Bh(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function Bc(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(g=>g.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),m=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...m?{runner:m}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?f.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var It=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},Vc=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();Qe(f.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new It(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},Kc=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},Gc=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 Dt(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}`}}},Hc=async(e,t)=>(await t.taskService.prs.discoverOrRefreshMany(t.paths,e),Promise.all(e.map(r=>Dt(t.paths,r.id)))),rn=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await lt.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var zc=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 Yc=async(e,t,r)=>{let n=f.runners.setRunnerEnabled(r.config,e,t);return await f.save(r.paths,n),n},Jc=async(e,t,r)=>{let n=f.runners.setRunnerPath(r.config,e,t);return await f.save(r.paths,n),n},Qc=async(e,t,r)=>{let n=f.previews.setEnabled(r.config,e,t);return await f.save(r.paths,n),n};var Vh=250;function Ae(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function nt(e,t){return Ce(t,e.ptyRuntime.getViewState(Ct(e,t)))}function Ct(e,t){let r=Ae(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 h(e,t){return nt(e,cl(t,e.model))}function Xc(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:h(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function Zc(e,t,r){return Xc(e,t,r?{tone:"success",message:r}:null)}function _(e,t,r){return Xc(e,t,{tone:"error",message:r})}function W(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return lt.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function j(e,t){if(!e.uiStateFile)return;e.runtimeState=tl(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Ee({uiStateFile:e.uiStateFile},r),()=>Ee({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function Kh(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function U(e){return{paths:e.paths,config:e.config,taskService:C,workspaceService:G,queueTaskMutation:t=>Kh(e,t)}}function Mo(e,t){let r=Ae(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?Eo(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:et(e.model),centerTabIds:al(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:Ac(t,r,s),pageRows:Math.max(5,oe(e.activeTerminal.width,e.activeTerminal.height).height-N.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function ed(e,t){await qc(t,U(e))}async function Y(e){e.model=await bt(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:h(e,e.state.shell)}:e.state={...e.state,shell:h(e,e.state.shell)}}function nn(e,t){e.model={...e.model,tasks:[...e.model.tasks.filter(r=>r.id!==t.id),t].sort((r,n)=>r.id.localeCompare(n.id))}}async function sn(e,t){let r=++e.inspectionRefreshSequence,n=Gs(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 Wa(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await bt(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,e.state.shell)},j(e,e.state.shell),e.render())}function td(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)&&sn(e,r).catch(n=>{let s=W(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Vh))}function rd(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=We(e.state.shell,r,Mo(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render(),sn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render()}},16)))}function Lo(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function No(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 sd(e){No(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,e.state.shell)},e.render())})}async function od(e,t){let r=h(e,t),n=Ae(e.model.tasks,r),s=Ct(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 Ce(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));return Ce({...r,inputMode:"control"},i)}function jo(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 Fo(e,t){try{let r=h(e,t),n=Ae(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 nd(e,n),await Y(e),s=n.selectedPtyTabId)}n&&!s&&(n=await nd(e,n),await Y(e),s=n.selectedPtyTabId);let o=h(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:Ce({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},j(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=_e(s),e.lastTerminalKey=null,e.state={mode:"main",shell:Ce({...o,inputMode:"terminal"},i)},j(e,e.state.shell)}catch(r){let n=W(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&_e(t.selectedPtyTabId)&&(await Gh(e,t.selectedTaskId,n).catch(()=>{}),await Y(e).catch(()=>{})),e.state={mode:"main",shell:_(e,rl(h(e,t),n),n)},j(e,e.state.shell)}e.render()}async function Gh(e,t,r){await Kc(t,r,U(e))}async function id(e,t,r,n){let s=h(e,t),{nextShell:o}=await _c(s,r,n,U(e));return await Y(e),h(e,{...s,...o})}async function ad(e,t){let r=h(e,t),{closedTab:n,nextShell:s}=await Wc(r,U(e));return e.ptyRuntime.disposeSession(n.id),await Y(e),h(e,{...r,...s})}async function ld(e,t){let r=h(e,t),n=et(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await Gc(r,U(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await Y(e),h(e,{...r,...i,selectedLeftItemId:Hh(n,et(e.model),s)})}async function cd(e,t){let r=h(e,t),{nextShell:n}=await zc(r,U(e));return await Y(e),h(e,{...r,...n})}async function nd(e,t){return Uc(t,U(e))}function on(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:nt(e,e.state.shell)},e.render())},16))}function Hh(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 ud(e,t,r){if(r?.aborted||e.state.mode!=="main")return;let n=dd(e),s=t.takeDueTasks(e.model.tasks,n);if(s.length!==0)try{let o=await Hc(s,U(e));if(r?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;for(let i of o)nn(e,i);t.recordSuccess(o,dd(e)),e.state={mode:"main",shell:h(e,e.state.shell)},e.render()}catch(o){if(r?.aborted)return;t.recordFailure(s,o);let i=o instanceof Error?o.message:"Background PR discovery failed.";i!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=i,rn("background PR polling",o,U(e)))}}function dd(e){return e.state.mode!=="main"?{selectedTaskId:null,reviewVisible:!1}:{selectedTaskId:e.state.shell.selectedTaskId,reviewVisible:e.state.shell.inspectionMode==="review"}}async function pd(e,t){let r=h(e,t),n=Ae(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 Y(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 Y(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${A(a)?.requiredChecks.length??0} reported`)}return h(e,{...Zc(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}var zh={pendingForegroundMs:5e3,pendingBackgroundMs:15e3,stableForegroundMs:3e4,stableBackgroundMs:6e4,discoveryForegroundMs:6e4,discoveryBackgroundMs:18e4,rateLimitBaseMs:6e4,rateLimitMaxMs:15*6e4},an=class{scheduledTasks=new Map;now;intervals;minimumIntervalMs;rateLimitFailures=0;notBefore=0;constructor(t={}){this.minimumIntervalMs=Math.max(1e3,t.minimumIntervalMs??5e3),this.intervals={...zh,...t.intervals},this.now=t.now??Date.now}takeDueTasks(t,r){let n=this.now(),s=new Set(t.map(i=>i.id));for(let i of this.scheduledTasks.keys())s.has(i)||this.scheduledTasks.delete(i);let o=[];for(let i of t){let a=this.getTaskIntervalMs(i,r);if(a===null){this.scheduledTasks.delete(i.id);continue}let l=this.scheduledTasks.get(i.id);if(!l){this.scheduledTasks.set(i.id,{intervalMs:a,nextPollAt:n}),n>=this.notBefore&&o.push(i);continue}a<l.intervalMs&&(l.nextPollAt=Math.min(l.nextPollAt,n+a)),l.intervalMs=a,n>=this.notBefore&&n>=l.nextPollAt&&o.push(i)}return o}recordSuccess(t,r){let n=this.now();this.rateLimitFailures=0,this.notBefore=0;for(let s of t){let o=this.getTaskIntervalMs(s,r);o===null?this.scheduledTasks.delete(s.id):this.scheduledTasks.set(s.id,{intervalMs:o,nextPollAt:n+o})}}recordFailure(t,r){let n=this.now(),s=r instanceof ge,o=s?Math.min(this.intervals.rateLimitBaseMs*2**this.rateLimitFailures,this.intervals.rateLimitMaxMs):Math.max(this.minimumIntervalMs,this.intervals.pendingBackgroundMs);s&&(this.rateLimitFailures+=1,this.notBefore=n+o);for(let i of t){let a=this.scheduledTasks.get(i.id);a&&(a.nextPollAt=n+o)}}getTaskIntervalMs(t,r){let n=Yh(t),s=t.id===r.selectedTaskId&&r.reviewVisible;if(n.length>0){let o=n.some(Jh);return this.withMinimum(o?s?this.intervals.pendingForegroundMs:this.intervals.pendingBackgroundMs:s?this.intervals.stableForegroundMs:this.intervals.stableBackgroundMs)}return t.status==="checked"?this.withMinimum(s?this.intervals.discoveryForegroundMs:this.intervals.discoveryBackgroundMs):null}withMinimum(t){return Math.max(t,this.minimumIntervalMs)}};function Yh(e){return e.type==="project"&&e.repoTargets?.length?e.repoTargets.map(t=>t.pullRequest).filter(t=>t.status==="open"):e.prs.filter(t=>t.status==="open")}function Jh(e){return e.requiredChecks.some(t=>t.status==="pending"||t.status==="unknown")}import tw from"node:path";import{readdir as Qh,stat as Xh}from"node:fs/promises";import md from"node:path";async function Zh(e){let t=await Qh(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=md.join(e,n.name);r.push({name:n.name,path:s,kind:await ew(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 fd(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function gd(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 ln(e,t){let r=await Zh(t);e.state.mode==="main"&&(e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function ew(e){let t=md.join(e,".git");return await Xh(t).catch(()=>null)!==null}function hd(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function wd(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function rw(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:h(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:h(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:h(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await Vc(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,U(e));n=s.task,nn(e,n);let o=h(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??vl(n,"agent"),Fe(oe(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=_e(o.selectedPtyTabId),e.state={mode:"main",shell:Ce(o,i)},j(e,e.state.shell)}catch(s){s instanceof It&&(n=s.task);let o=W(e,"create task",s,"Failed to create task.");n&&!(s instanceof It)?(await E(e.paths,n.id,i=>({...i,status:"draft",runnerSession:{...i.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o})).catch(()=>{}),await Y(e).catch(()=>{})):n&&(await E(e.paths,n.id,i=>({...i,lastFailureReason:o})).catch(()=>{}),await Y(e).catch(()=>{})),e.state={mode:"main",shell:_(e,h(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 nw(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:h(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ue(t)){rw(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:h(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:h(e,{...r,selectedRunner:Lr(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}sl(t)&&(e.state={mode:"main",shell:h(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function sw(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:h(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:h(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:h(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:h(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:h(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=fd(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:h(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:h(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"){ln(e,tw.dirname(r.cwd)).catch(s=>{let o=W(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ue(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){ln(e,s.path).catch(i=>{let a=W(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=U(e);o.addWorkspace(e.paths,s.path).then(async i=>{await Y(e);let a=i.repos[0]??null,l=h(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},j(e,e.state.shell),e.render()}).catch(i=>{let a=W(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function ow(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=ic(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;iw(e,n)}}}async function iw(e,t){let r;try{r=await lt.readRecentErrorLines(e.paths)}catch(n){let s=W(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 aw(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=lc(hd(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"?Yc(r.runner,r.enabled,U(e)):Jc(r.runner,r.path,U(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:h(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=W(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:_(e,h(e,e.state.shell),o),runnerOptions:{...hd(e),message:o}},e.render()})}function lw(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=ac(wd(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}Qc(r.feature,r.enabled,U(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=W(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:_(e,h(e,e.state.shell),s),previewOptions:{...wd(e),message:s}},e.render()})}}function kd(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){nw(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){sw(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){dw(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=Oo(e.state.shell,r,Mo(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ue(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=er(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(cw(e,r))return;e.lastTerminalKey=Al(r)?{key:r,at:Date.now()}:null;let o=El(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){on(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:h(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){ln(e,e.workspaceRoot).catch(s=>{let o=W(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:_(e,h(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){id(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Fo(e,s)}).catch(s=>{let o=W(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){ad(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){pd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=Ae(e.model.tasks,n.state),o=s?A(s)?.url??null:null;o?gd(o).catch(i=>{let a=W(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:_(e,h(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:_(e,h(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){ld(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){cd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:_(e,h(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){Fo(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:h(e,n.state)},j(e,e.state.shell),(e.state.shell.focusedRegion!=="tasks"||!e.renderTaskNavigation())&&e.render(),e.state.shell.focusedRegion==="tasks"){td(e,e.state.shell);return}sn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:_(e,h(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:h(e,n.state)},ed(e,e.state.shell).catch(()=>{}),j(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:h(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){ow(e,r);return}if(e.state.variant==="runners"){aw(e,r);return}if(e.state.variant==="previews"){lw(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ue(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"||ue(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:h(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ue(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:h(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;od(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},j(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=W(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:_(e,h(e,e.state.shell),i)},j(e,e.state.shell),e.render()})}):sd(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 Td(e,t){let r=Ml(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=er(o);if(i){Rd(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(so(o)){e.pendingTerminalKeySequence.raw=o,yd(e);return}cn(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:h(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},j(e,e.state.shell),e.render();return}let n=xl(r);if(n!==0){on(e,n);return}let s=er(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
123
|
+
`);if(c===-1)return;let d=o.slice(0,c);a(),s.end();try{r(JSON.parse(d))}catch(u){n(u instanceof Error?u:new Error(String(u)))}}),s.once("close",()=>a())})}async function rc(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await on(e))return;await Io(50)}}function pc(e){return new Promise((t,r)=>{let n=nc(e);n.once("connect",()=>t(n)),n.once("error",r)})}function gh(e,t){return new Promise((r,n)=>{e.once("error",n),e.listen(t,r)})}function rt(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
124
|
+
`)}catch{}}function mc(e){try{return process.kill(e,0),!0}catch{return!1}}function Io(e){return new Promise(t=>setTimeout(t,e))}function hh(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var vo=["Runners","Feature Previews","Error Log","Help"],gc={incrementalCenterPane:"Incremental center pane",agentActivityIndicators:"Agent activity indicators"};function Co(e,t){return M.map(r=>{let n=g.runners.getProfile(r),s=e.runners?.[r]?.enabled!==!1,o=e.runners?.[r]?.path?.trim(),i=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:o&&o.length>0?o:`default (${n.executable})`;return`${n.displayName} ${s?"enabled":"disabled"} ${i}`})}function hc(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 kc(e){return de.map(t=>`${g.previews.isEnabled(e,t)?"[x]":"[ ]"} ${gc[t]}`)}function wc(e){return e.message??"Experimental features may change or be removed. Enter toggles."}function Tc(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(vo.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:an(t)?e===0?{kind:"runners"}:e===1?{kind:"previews"}:e===2?{kind:"error-log"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function yc(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(de.length-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(!an(r))return{kind:"noop",state:e};let n=de[e.menuIndex]??de[0],s=!g.previews.isEnabled(t,n);return{kind:"save-enabled",feature:n,enabled:s,state:{...e,message:`${gc[n]} ${s?"enabled":"disabled"}.`}}}function Rc(e,t,r,n){if(e.pathEdit)return kh({...e,pathEdit:e.pathEdit},t,r);let s=Co(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=M[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:a,value:t.runners?.[a]?.path??""}}}}if(!an(r))return{kind:"noop",state:e};let o=M[e.menuIndex]??"codex",i=t.runners?.[o]?.enabled!==!1;return i&&n.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save-enabled",runner:o,enabled:!i,state:{...e,message:`${g.runners.getProfile(o).displayName} ${i?"disabled":"enabled"}.`}}}function kh(e,t,r){if(r==="ESCAPE")return{kind:"render",state:fc({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(an(r)){let n=e.pathEdit.runner,s=e.pathEdit.value.trim();return{kind:"save-path",runner:n,path:s.length>0?s:null,state:fc({...e,message:s.length>0?`${g.runners.getProfile(n).displayName} executable saved.`:`${g.runners.getProfile(n).displayName} executable reset to default.`})}}return wh(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function fc(e){let t={...e};return delete t.pathEdit,t}function an(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
125
|
+
`}function wh(e){return e.length===1&&e>=" "&&e!==""}import or from"node:path";function bc(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 Pc="\u{F024B} ",Sc="\u{F0DCF} ",Ic="\u25CB",Ao="\uEA64",vc="\uEAFE",Cc="\uEBDA",Eo="\u25CB",xo="\u25CF",Do="\u2713",$o="\u2715";function Ac(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 ln=150,Ec=6;var dn="empty",V={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function Oc(e,t,r){let n=Rh(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",c=tk(t.tasks),d=Sh(e,a),u=Ph(e,a,d,r),p=u.find(b=>b.id===d)??u[0]??{id:"agent",label:"CODEX"},f=t.inspection?.taskId===a?.id?t.inspection:null,w=s?.name??"no repo",h=a?g.runners.getDisplayName(a.runner):g.runners.getDisplayName(e.selectedRunner);return{inputMode:e.inputMode,modalInput:e.taskPromptInput!==null||e.workspaceBrowser!==null,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,footerToast:e.footerToast,terminal:e.terminal,footerText:e.workspaceBrowser!==null?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 ${g.runners.getDisplayName(e.selectedRunner)} Ctrl+R switch runner Enter create Esc cancel \u203A ${e.taskPromptInput}${e.taskPromptError?` \u2717 ${e.taskPromptError}`:""}`:e.inputMode==="terminal"?"TERMINAL \u2191\u2193/PgUp/PgDn scroll Ctrl+] return to control":e.focusedRegion==="tasks"?e.selectedLeftItemId?.startsWith("new-task:")||e.selectedLeftItemId?.startsWith("new-task-workspace:")?`r runner [${g.runners.getDisplayName(e.selectedRunner)}] Enter create task Esc pause ? help`:tr(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":d===D?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${g.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:or.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${or.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:h},leftTree:Th(e,t,r),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(b=>rk(b,c[b])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":p.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:w,agent:h},centerTranscript:bh(d,e,s,a,e.workspaceBrowser,f,n),tabs:u,rightContext:ek(s,a),rightInspection:jh(e,a,f)}}function Th(e,t,r){let n=[{text:"WORKSPACES",muted:!0,panelHeader:!0,focused:e.focusedRegion==="tasks"}];if(!t.workspaces)return yh(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],c=t.tasks.filter(d=>d.workspaceId===i.id);if(c.length===0)n.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let d of c){let u=e.selectedLeftItemId===`task:${d.id}`,p=d.title.length>28?`${d.title.slice(0,25)}\u2026`:d.title,f={id:`task:${d.id}`,taskId:d.id,text:r?p:`${u?"\u25B8":"\u2022"} ${p}`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",...r?{activity:Pt(d,r.snapshots,r.now),activityAnimationFrame:r.animationFrame}:{}},w=Nc(d);w&&(f.prBadge=w),n.push(f)}if(i.kind==="project"){let d=`new-task-workspace:${i.id}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Project Task [${g.runners.getDisplayName(e.selectedRunner)}]`,indent:2,selected:u,focused:u&&e.focusedRegion==="tasks",muted:!u})}if(i.kind==="repo"){let d=`new-task:${i.primaryRepoId}`,u=e.selectedLeftItemId===d;n.push({id:d,text:`+ New Task [${g.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 d of l.slice(0,6)){let u=t.repos.find(p=>p.id===d);n.push({text:` \xB7 ${u?.name??d}`,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 yh(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}`,f=u.title.length>28?`${u.title.slice(0,25)}\u2026`:u.title,w={id:`task:${u.id}`,taskId:u.id,text:s?f:`${p?"\u25B8":"\u2022"} ${f}`,indent:2,selected:p,focused:p&&t.focusedRegion==="tasks",...s?{activity:Pt(u,s.snapshots,s.now),activityAnimationFrame:s.animationFrame}:{}},h=Nc(u);h&&(w.prBadge=h),e.push(w)}let c=`new-task:${i.id}`,d=t.selectedLeftItemId===c;e.push({id:c,text:`+ New Task [${g.runners.getDisplayName(t.selectedRunner)}]`,indent:2,selected:d,focused:d&&t.focusedRegion==="tasks",muted:!d})}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 Rh(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 bh(e,t,r,n,s,o=null,i=null){if(s){let l=s.query?s.entries.filter(u=>u.name.toLowerCase().includes(s.query.toLowerCase())):s.entries,c=l.length===0?["No matching directories or git repos."]:l.map((u,p)=>{let f=p===s.selectedIndex?"\u25B8":" ",w=u.kind==="repo"?" [git repo]":"/";return`${f} ${u.name}${w}`}),d=s.query!==null?`Search: ${s.query}\u2588`:"";return me(["Browse for a workspace to register.",s.cwd,...d?[d]:[],"",...c,"",s.error??"Use \u2191\u2193 to move, \u2192 or Enter to open, \u2190 to go up, Enter on a git repo to add it."])}if(!r)return me(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!n){let l=i?.kind==="project",c=l?i.name??"this workspace":r.name,d=l?"Project Task":"Task";return me([`No tasks in ${c}.`,"",`Press n or choose + New ${d} to create one with ${g.runners.getDisplayName(t.selectedRunner)}.`])}let a=n.ptyTabs.find(l=>l.id===e)??null;return a?a.kind==="agent"?me([`${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."]):me([`${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===D&&t.openInspectionKind==="file"?Ch(n,o,t.fileScrollOffset):e===D&&t.openInspectionKind==="diff"?Ah(n,o,t.diffScrollOffset):n.ptyTabs.length===0&&!t.openInspectionKind?me(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):me(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function Ph(e,t,r,n){let s=t?.ptyTabs.map(i=>({id:i.id,label:Ih(i),...i.kind==="agent"&&n&&t?{activity:bt(t,i.id,n.snapshots,n.now),activityAnimationFrame:n.animationFrame}:{}}))??[];if(!t)return[{id:dn,label:"EMPTY",active:r===dn,focused:e.focusedRegion==="center"&&r===dn}];let o=e.openInspectionKind||r===D?[{id:D,label:vh(e)}]:[];return[...s,...o].map(i=>({...i,active:i.id===r,focused:e.focusedRegion==="center"&&i.id===r}))}function Sh(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===D&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??D:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??D:dn}function Ih(e){return e.title.toUpperCase()}function vh(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?or.basename(t):e.inspectionMode.toUpperCase();return e.openInspectionKind==="diff"?`${r} \u0394`:r}function Ch(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return me(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let n=t.selectedFile,s=Mc(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:""},...Eh(n.lines,r,s)]}function Ah(e,t,r){if(!e)return me(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return me(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let n=t.selectedDiff,s=Mc(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:""},...xh(n.lines,r,s)]}function me(e){return e.map(t=>({text:t}))}function Eh(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:V.lineNumber}},{text:" \u2502 ",style:{fg:V.gutter}},...Oo(o,r)],tone:"default"}})}function xh(e,t,r){let n=Dh(e),s=Math.max(0,Math.min(t,Math.max(0,n.length-1)));return n.slice(s).map(o=>$h(o,r))}function Dh(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 $h(e,t){let r=xc(e.oldNumber),n=xc(e.newNumber),s=e.kind==="delete"?r:n,o=e.kind==="delete"?{bg:"2a1111",fallbackFg:V.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:V.diffAdd}:null,i=`${s} \u2502 ${e.text}`,a=o?Mh(Oo(e.text,t),o.bg,o.fallbackFg):Oo(e.text,t),l=o?{fg:V.lineNumber,bg:o.bg}:{fg:V.lineNumber},c=o?{fg:V.gutter,bg:o.bg}:{fg:V.gutter};return{text:i,segments:[{text:s,style:l},{text:" \u2502 ",style:c},...a],fullBleed:o!==null}}function xc(e){return e===null?" ":String(e).padStart(4," ")}function Mc(e){let t=or.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 Oo(e,t){return t==="diff"?Oh(e):t==="markdown"?Nh(e):t==="json"?Mo(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Mo(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 Oh(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:V.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:V.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:V.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:V.diffMeta}}]:[{text:e}]}function Mh(e,t,r){return e.map(n=>({text:n.text,style:{...n.style??{fg:r},bg:t}}))}function Nh(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:V.markup,bold:!0}}]:Mo(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Mo(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:Lh(o)}),n=i+o.length}return n<e.length&&r.push({text:e.slice(n)}),r.length>0?r:[{text:e}]}function Lh(e){return e.startsWith("//")||e.startsWith("/*")?{fg:V.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:V.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:V.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:V.markup}:{fg:V.keyword}}function jh(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"?Lc(t.repoTargets??[]):s?.pullRequest??(t?E(t):null),i=[_h(e,o),{id:"mode-spacer",text:"",muted:!0}];if(e.inspectionMode==="review"){let a=Fc(e,t),l=No(e,r),c=Bh([{id:"review-pr-header",text:"PULL REQUEST",muted:!0},...a,{id:"review-changes-spacer",text:"",muted:!0},{id:"review-changes-header",text:"CHANGES",muted:!0},...l],e);return{title:"",rows:[...i,...c]}}return e.inspectionMode==="files"?{title:"",rows:[...i,...Qh(e,r)]}:{title:"",rows:[...i,...No(e,r)]}}function _h(e,t){let r=e.inspectionMode,n=[{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],s=[];for(let l=0;l<n.length;l++){let c=n[l];l>0&&s.push({text:" "});let d=c.active?e.focusedRegion==="inspector"||e.focusedRegion==="actions"?"9ece6a":"7aa2f7":"565f89";s.push({text:c.label,style:{fg:d}})}let o=Lo(t),i=jo(t);return s.push({text:" "},o,{text:" "},i),{id:"inspection-mode",text:s.map(l=>l.text).join(""),segments:s}}function Dc(e){return[{text:" "},Lo(e),{text:" "},jo(e)]}function Nc(e){if(e.type==="project"&&e.repoTargets?.length){let r=Lc(e.repoTargets);return r?Dc(r):null}let t=E(e);return t?.number?Dc(t):null}function Lc(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=Wh(r);return{number:-1,status:Fh(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 Fh(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 Wh(e){let t=e.map(r=>jc(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 Lo(e){return!e||!e.number?{text:Ic,style:{fg:"565f89"}}:e.status==="merged"?{text:vc,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Cc,style:{fg:"f7768e"}}:e.status==="draft"||e.draft?{text:Ao,style:{fg:"565f89"}}:{text:Ao,style:{fg:"9ece6a"}}}function jo(e){return e?.aggregateReadiness?$c(e.aggregateReadiness):$c(jc(e))}function $c(e){return e==="failed"?{text:$o,style:{fg:"f7768e"}}:e==="pending"?{text:xo,style:{fg:"e0af68"}}:e==="success"?{text:Do,style:{fg:"9ece6a"}}:{text:Eo,style:{fg:"565f89"}}}function jc(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")?_c(e)?"failed":qh(e)?"success":"pending":"pending"}function qh(e){return!!(e.mergeable&&!e.draft&&!_c(e)&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped"))}function _c(e){return e.reviewDecision==="REVIEW_REQUIRED"||e.reviewDecision==="CHANGES_REQUESTED"||e.mergeStateStatus==="REVIEW_REQUIRED"}function Fc(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];if(t.type==="project"&&t.repoTargets?.length)return Uh(e,t);let r=E(t),n=qc("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 cn=32;function Uh(e,t){let r=[],n=t.repoTargets??[],s=e.selectedProjectTargetId??n[0]?.repoId??null;for(let i of n){let a=s===i.repoId,l=e.focusedRegion==="inspector"&&a,c=i.repoId.startsWith("repo_")?i.repoId.slice(5):i.repoId;if(i.status!=="ready"){let u=i.failureReason?i.failureReason.slice(0,14):i.status,p=cn-u.length-1,f=c.length>p?c.slice(0,p-1)+"\u2026":c,w=cn-f.length-u.length;r.push({id:`project-review:${i.repoId}`,text:f+" ".repeat(Math.max(1,w))+u,selected:a,focused:l,muted:!0})}else{let d=Lo(i.pullRequest),u=jo(i.pullRequest),p=`${d.text} ${u.text}`,f=cn-p.length-1,w=c.length>f?c.slice(0,f-1)+"\u2026":c,h=cn-w.length-p.length,b=w+" ".repeat(Math.max(1,h));r.push({id:`project-review:${i.repoId}`,text:b+p,selected:a,focused:l,segments:[{text:b},{...d,text:d.text},{text:" "},{...u,text:u.text}]})}}let o=n.find(i=>i.repoId===s)??null;return o?.status==="ready"&&o.pullRequest.number&&(r.push({id:"target-detail-spacer",text:""}),r.push(...qc("target",o.branch,o.pullRequest))),r}function Wc(e,t,r=null){return 3+Fc(e,t).length+No(e,r).length}function qc(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=Vh(r.reviewDecision,r.mergeStateStatus),c=l&&l!=="review approved"?"merge blocked":r.mergeable?"merge ready":r.mergeStateStatus?`merge ${r.mergeStateStatus}`:"merge unknown";l?s.push({id:n("pr-merge"),text:`${c} \xB7 ${l}`,muted:!0,segments:[{text:c},{text:" \xB7 "},{text:l,style:{fg:Kh(r.reviewDecision,r.mergeStateStatus)}}]}):s.push({id:n("pr-merge"),text:c,muted:!0}),s.push({id:n("pr-synced"),text:`synced ${Uc(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(Gh)):s.push({id:n("checks-none"),text:r.number?"No GitHub checks reported.":"No checks \u2014 sync after creating a PR.",muted:!0});let d=r.comments??[];return d.length>0&&(s.push({id:n("comments-spacer"),text:""}),s.push({id:n("comments-header"),text:`Review comments (${d.length})`}),s.push(...d.slice(-4).flatMap((u,p)=>Hh(u,n(`comment:${p}`))))),s}function Bh(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 Vh(e,t){return e==="CHANGES_REQUESTED"?"review changes requested":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"review required":e==="APPROVED"?"review approved":null}function Kh(e,t){return e==="CHANGES_REQUESTED"?"f7768e":e==="APPROVED"?"9ece6a":e==="REVIEW_REQUIRED"||t==="REVIEW_REQUIRED"?"e0af68":"565f89"}function Uc(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 Gh(e){let{icon:t,color:r}=Yh(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," ")} ${Jh(e.status)}`,color:r,muted:!1}}function Hh(e,t){let r=e.author??"unknown",n=e.createdAt?` \xB7 ${Uc(e.createdAt)}`:"",s=zh(e.body,30),o=s.slice(0,4),i=o.length<s.length,a=[{id:`${t}:author`,text:`${r}${n}`,muted:!0},...o.map((l,c)=>({id:`${t}:body:${c}`,text:` ${i&&c===o.length-1?`${l}\u2026`:l}`,muted:!0}))];return a.push({id:`${t}:spacer`,text:"",muted:!0}),a}function zh(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 Yh(e){switch(e){case"success":return{icon:Do,color:"9ece6a"};case"pending":return{icon:xo,color:"e0af68"};case"failed":return{icon:$o,color:"f7768e"};case"skipped":return{icon:Eo,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Jh(e){return e==="success"?"passing":e==="failed"?"failing":e}function Qh(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=_o(t.fileRows,e.collapsedFileTreePaths),s=e.fileSearchQuery,o=s?n.filter(l=>l.path.toLowerCase().includes(s.toLowerCase())):n,i=s!==null?[{id:"file-search",text:`Search: ${s}\u2588`,muted:!1}]:[],a=e.selectedFileTreePath??t.selectedFilePath;return[...i,...o.map(l=>{let c=l.kind==="file"?r.get(l.path):void 0,d=c==="A"?"9ece6a":c==="M"?"e0af68":c==="D"?"f7768e":c==="??"?"565f89":void 0,u=l.kind==="directory"?e.collapsedFileTreePaths.includes(l.path)?Pc:Sc:bc(l.label),p=l.kind==="directory"?"7aa2f7":Ac(l.label),f=" ".repeat(l.depth),w=p?{text:u,style:{fg:p}}:{text:u},h=l.kind==="directory"?{text:l.label,style:{fg:"7aa2f7"}}:d?{text:l.label,style:{fg:d}}:{text:l.label},b=[{text:f},w,h];return{id:l.path,text:`${f}${u}${l.label}`,selected:l.path===a,focused:l.path===a&&e.focusedRegion==="inspector",segments:b}})]}function _o(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 No(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(Xh(t))return Zh(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=>Bc(o,e,t))))}return r}function Xh(e){return e.filePaths.some(t=>t.startsWith("repo_"))||e.diffRows.some(t=>t.path.startsWith("repo_"))}function Zh(e,t){let r=[],n=[...new Set(t.diffRows.map(s=>s.path.split("/")[0]).filter(s=>typeof s=="string"&&s.length>0))].sort();for(let s of n){let o=t.diffRows.filter(a=>a.path.startsWith(`${s}/`)),i=s.startsWith("repo_")?s.slice(5):s;r.push({id:`repo-diff:${s}`,text:i,muted:!0});for(let a of["branch","staged","unstaged","untracked"]){let l=o.filter(c=>c.group===a);l.length!==0&&(r.push({id:`repo-diff:${s}:${a}`,text:` ${a}`,muted:!0}),r.push(...l.map(c=>Bc(c,e,t,s.length+1))))}}return r}function Bc(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 ek(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:g.runners.getDisplayName(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:or.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 tk(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function rk(e,t){return{name:g.runners.getDisplayName(e).toLowerCase(),health:t>0?1:0,count:String(t)}}function Vc(e,t,r,n,s=null){if(s)return nk(e,t,r,n,s);let o=co(e,t,{centerOnly:n});return sk(r,o)?{output:tn(o.rows,r.rows,o.row,o.column),region:o}:null}function nk(e,t,r,n,s){let o=xl(e,t,s,{centerOnly:n});if(!o||!ok(r,o))return null;let i=r.rows.slice();return{output:o.rows.map(({index:l,row:c})=>i[l]===c?"":(i[l]=c,`\x1B[${o.row+l};${o.column}H${c}`)).join(""),region:{row:o.row,column:o.column,width:o.width,rows:i}}}function sk(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}function ok(e,t){return e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rowCount}function Kc(e,t,r){let n={...e},s="";for(let o of r){let i=e[o],a=t[o];if(!ik(i,a))return null;!i||!a||(s+=tn(a.rows,i.rows,a.row,a.column),n[o]=a)}return{output:s,regions:n}}function ik(e,t){return!e||!t?e===t:e.row===t.row&&e.column===t.column&&e.width===t.width&&e.rows.length===t.rows.length}var ak=["tasks","center","inspector"];function lk(e,t,r){if(t==="ESCAPE")return R({state:{...e,fileSearchQuery:null},changed:!0});if(t==="BACKSPACE"||t==="DELETE"){let n=e.fileSearchQuery??"";return R({state:{...e,fileSearchQuery:n.slice(0,-1)},changed:!0})}if(t==="UP"||t==="k"||t==="DOWN"||t==="j")return Wo(e,t==="UP"||t==="k"?-1:1,r);if(t==="ENTER")return Uo({...e,fileSearchQuery:null},t,r);if(t.length===1&&t>=" "){let n=(e.fileSearchQuery??"")+t;return R({state:{...e,fileSearchQuery:n},changed:!0})}return R({state:e})}function Uo(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return hl(t)?R({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null,focusedRegion:"center"},changed:!0,detachTerminal:!0}):R({state:e});if(e.fileSearchQuery!==null)return lk(e,t,r);if(t==="/"&&e.focusedRegion==="inspector"&&e.inspectionMode==="files")return R({state:{...e,fileSearchQuery:""},changed:!0});if(t==="q"||t==="Q")return R({state:e,exit:!0});if(t==="ESCAPE")return R({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return R({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&(Br(e.selectedLeftItemId)||Vr(e.selectedLeftItemId)))return R({state:{...e,selectedRunner:Ur(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Gc(e,1);if(t==="SHIFT_TAB"||t==="[")return Gc(e,-1);if(t==="z"||t==="Z")return R({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===D?We(e,-1,r):Wo(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===D?We(e,1,r):Wo(e,1,r);if(t==="PAGE_UP")return We(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return We(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return We(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return We(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let n=r.enabledRunnerIds??M,s=e.centerTabRunner?n.indexOf(e.centerTabRunner):-1,o=s===n.length-1?null:n[s+1];return R({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=hk(e,t);return R({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 R({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if(t==="o"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review"&&e.selectedTaskId)return R({state:e,openPrUrl:!0});if(t==="X"&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return R({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&tr(e.selectedLeftItemId)&&e.selectedTaskId)return R({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="X"&&e.focusedRegion==="tasks"&&Rl(e.selectedLeftItemId)&&e.selectedWorkspaceId)return R({state:{...e,actionMessage:null},changed:!0,removeWorkspace:!0});if(t==="x"&&e.focusedRegion==="center"&&Yc(e.activeTab,r.ptyTabIds??[]))return R({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Fo(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Hc(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Fo(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Hc(e,1)}if(ue(t)){if(e.focusedRegion==="tasks"&&(Br(e.selectedLeftItemId)||Vr(e.selectedLeftItemId))){let n=ro(e.selectedLeftItemId),s=no(e.selectedLeftItemId);return R({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 R({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&tr(e.selectedLeftItemId)&&e.selectedTaskId){let n=e.selectedPtyTabId??e.activeTab;return R({state:{...e,inputMode:"terminal",focusedRegion:"center",activeTab:n,selectedPtyTabId:n,preferredPtyTabKind:Ct(n)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0})}if(e.focusedRegion==="center"&&Yc(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return R({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Ct(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===D)return R({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 R({state:uk({...e,selectedFileTreePath:n}),changed:!0});let s=n&&(r.fileTreeFileIds??[]).includes(n)?n:e.selectedFilePath;return R({state:{...e,selectedFileTreePath:s,selectedFilePath:s,activeTab:D,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?R({state:{...e,selectedDiffPath:n,activeTab:D,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.selectedActionId==="close-task"&&!r.projectTargetIds?.length?R({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):R({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0})}return e.focusedRegion!=="actions"?R({state:e}):e.selectedActionId==="refresh-checks"?R({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?R({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):R({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return R({state:e})}function We(e,t,r){if(t===0)return R({state:e});if(e.focusedRegion==="inspector")return e.inspectionMode==="files"?Jc(e,t,r):e.inspectionMode==="review"?zc(e,"reviewScrollOffset",t,r.reviewRowCount??100,r.pageRows):R({state:e});if(e.focusedRegion==="center"&&e.activeTab===D){if(e.openInspectionKind==="file")return zc(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return pk(e,t,r)}return R({state:e})}function Gc(e,t){return un(e,"focusedRegion",ak,t)}function Fo(e,t,r){let n=un(e,"activeTab",r&&r.length>0?r:kk(e),t);return!n.changed||wl(n.state.activeTab)?n:{...n,state:{...n.state,selectedPtyTabId:n.state.activeTab,preferredPtyTabKind:Ct(n.state.activeTab)??n.state.preferredPtyTabKind}}}function Wo(e,t,r){if(e.focusedRegion==="tasks")return ck(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Fo(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Jc(e,t,r);if(r.projectTargetIds?.length){let s=qo(e,"selectedProjectTargetId",r.projectTargetIds,t);return s.changed?{...s,state:{...s.state,reviewScrollOffset:0,selectedActionId:"refresh-checks"}}:s}let n=qo(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return n.changed?{...n,state:{...n.state,activeTab:D,openInspectionKind:"diff",diffScrollOffset:0},refreshInspection:!0}:un(e,"selectedActionId",ul,t)}return un(e,"selectedActionId",Xs,t)}function ck(e,t,r){let n=qo(e,"selectedLeftItemId",r,t);if(!n.changed)return n;let s=to(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=ro(n.state.selectedLeftItemId);if(o)return{...n,state:{...n.state,selectedRepoId:o}};let i=no(n.state.selectedLeftItemId);return i?{...n,state:{...n.state,selectedWorkspaceId:i}}:n}function dk(e,t){if(e.inspectionMode===t)return R({state:e});let r=t==="files"?"file":e.openInspectionKind,n=t==="files"?D:e.activeTab;return R({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 Hc(e,t){return dk(e,gk(e.inspectionMode,Zs,t))}function Jc(e,t,r){let n=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(n.length===0)return R({state:e});let s=e.selectedFileTreePath??e.selectedFilePath??n[0]??null,o=n.indexOf(s??""),i=Ce(o===-1?0:o+t,0,n.length-1),a=n[i]??null;if(a===e.selectedFileTreePath)return R({state:e});let l=a!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(a);return R({state:{...e,selectedFileTreePath:a,selectedFilePath:l?a:e.selectedFilePath,activeTab:l?D:e.activeTab,openInspectionKind:l?"file":e.openInspectionKind,fileScrollOffset:l?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:l})}function uk(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 zc(e,t,r,n,s=10){let o=Math.max(0,n-Math.max(1,s)),i=Ce(e[t]+r,0,o);return i===e[t]?R({state:e}):R({state:{...e,[t]:i,actionMessage:null},changed:!0})}function pk(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return mk(e,t,r);let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=e.diffScrollOffset+t,a=r.diffPathIds??[];if(a.length===0||!e.selectedDiffPath){let d=Ce(i,0,o);return d===e.diffScrollOffset?R({state:e}):R({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}let l=a.indexOf(e.selectedDiffPath);if(l===-1){let d=Ce(i,0,o);return d===e.diffScrollOffset?R({state:e}):R({state:{...e,diffScrollOffset:d,actionMessage:null},changed:!0})}if(t>0&&i>o){let d=a[l+1]??null;return d?R({state:{...e,selectedDiffPath:d,activeTab:D,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===o?R({state:e}):R({state:{...e,diffScrollOffset:o,actionMessage:null},changed:!0})}if(t<0&&i<0){let d=a[l-1]??null;return d?R({state:{...e,selectedDiffPath:d,activeTab:D,openInspectionKind:"diff",diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?R({state:e}):R({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let c=Ce(i,0,o);return c===e.diffScrollOffset?R({state:e}):R({state:{...e,diffScrollOffset:c,actionMessage:null},changed:!0})}function mk(e,t,r){let n=r.diffLineCount??0,s=r.pageRows??10,o=Math.max(0,n-Math.max(1,s)),i=Ce(e.diffScrollOffset+t,0,o),a=fk(r.diffPathRanges??[],i)??e.selectedDiffPath;return i===e.diffScrollOffset&&a===e.selectedDiffPath?R({state:e}):R({state:{...e,diffScrollOffset:i,selectedDiffPath:a,actionMessage:null},changed:!0})}function fk(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function un(e,t,r,n){let s=r.indexOf(e[t]),o=Ce(s+n,0,r.length-1),i=r[o];return!i||i===e[t]?R({state:e}):R({state:{...e,[t]:i,actionMessage:null},changed:!0})}function qo(e,t,r,n,s=!1){if(r.length===0)return R({state:e});let o=r.indexOf(e[t]??r[0]??""),i=Ce(o===-1?0:o+n,0,r.length-1),a=r[i]??null;return a===e[t]?R({state:e}):R({state:{...e,[t]:a,actionMessage:null},changed:!0,refreshInspection:s})}function gk(e,t,r){let n=t.indexOf(e);return t[Ce(n+r,0,t.length-1)]??e}function R(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 Yc(e,t){return t.includes(e)}function hk(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Ct(e.activeTab)??e.preferredPtyTabKind}function kk(e){return[e.selectedPtyTabId,e.openInspectionKind?D:null].filter(t=>typeof t=="string")}function Ce(e,t,r){return Math.min(r,Math.max(t,e))}var Qc=async(e,t,r,n)=>{if(!e.selectedTaskId)throw new Error("Select a task before creating a tab.");let s=await n.queueTaskMutation(async()=>x(n.paths,e.selectedTaskId,o=>{let i=t??wk(o,e.activeTab,e.preferredPtyTabKind),a=td(o,i,r??void 0,n.config);return{...o,ptyTabs:[...o.ptyTabs,a],selectedPtyTabId:a.id}}));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"}`}}},Xc=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={closedTab:null,nextSelectedTab:null};if(await x(t.paths,e.selectedTaskId,o=>{let i=o.ptyTabs.findIndex(l=>l.id===e.activeTab);if(i===-1)throw new Error("Only PTY tabs can be closed.");s.closedTab=o.ptyTabs[i];let a=o.ptyTabs.filter(l=>l.id!==s.closedTab.id);return s.nextSelectedTab=a[Math.min(i,a.length-1)]??null,{...o,ptyTabs:a,selectedPtyTabId:s.nextSelectedTab?.id??null}}),!s.closedTab)throw new Error("Only PTY tabs can be closed.");return{closedTab:s.closedTab,nextSelectedTab:s.nextSelectedTab}});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}`}}},Zc=async(e,t)=>{let r=e.selectedTaskId;r&&await t.queueTaskMutation(async()=>{await x(t.paths,r,n=>!n.ptyTabs.some(s=>s.id===e.activeTab)||n.selectedPtyTabId===e.activeTab?n:{...n,selectedPtyTabId:e.activeTab})})},ed=async(e,t)=>{let r=e.ptyTabs.find(s=>s.kind==="agent")??null;if(r)return await t.queueTaskMutation(async()=>{await x(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:s})}),{...e,selectedPtyTabId:r.id};let n=td(e,"agent",void 0,t.config);return await t.queueTaskMutation(async()=>{await x(t.paths,e.id,s=>{let o=s.ptyTabs.find(i=>i.kind==="agent")??null;return o?{...s,selectedPtyTabId:o.id}:{...s,ptyTabs:[...s.ptyTabs,n],selectedPtyTabId:n.id}})}),{...e,ptyTabs:[...e.ptyTabs,n],selectedPtyTabId:n.id}};function wk(e,t,r){return e.ptyTabs.find(n=>n.id===t)?.kind??r}function td(e,t,r,n={}){let s=r??e.runner,o=g.runners.getProfile(s),i=t==="agent"?o.defaultAgentTitle:"Terminal",a=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,l=new Set(e.ptyTabs.map(f=>f.id)),c=1,d=a;for(;l.has(d);)c+=1,d=`${a}-${c}`;let u=new Date().toISOString(),p=r&&r!==e.runner?r:void 0;return{id:d,kind:t,...p?{runner:p}:{},title:c===1?i:`${i} ${c}`,command:t==="agent"?g.runners.buildCommand(s,void 0,n):[],createdAt:u,updatedAt:u}}var xt=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}},rd=async(e,t,r,n,s)=>{g.runners.assertEnabled(n,s.config);let o=t?await s.taskService.provisionProjectTask(s.paths,t,r,{runner:n,config:s.config}):await s.taskService.provisionTask(s.paths,e??"",r,{runner:n,config:s.config});try{let l=Je();Qe(g.runners.getConfiguredProfile(n,s.config).executable,{cwd:o.repoRoot,env:l})}catch(l){let c=l instanceof Error?l.message:"Failed to start runner.",d=await s.taskService.recordStartupFailure(s.paths,o.task.id,c);throw new xt(c,d)}let i=await s.taskService.markTaskStarted(s.paths,o.task.id),a={selectedRepoId:i.repoId,selectedWorkspaceId:i.workspaceId,selectedTaskId:i.id,selectedPtyTabId:i.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:i.selectedPtyTabId??"agent",selectedActionId:"commit"};return{task:i,nextShell:a}},nd=async(e,t,r)=>{await r.queueTaskMutation(async()=>{await r.taskService.markRunnerFailed(r.paths,e,t)})},sd=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 Lt(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}`}}},od=async(e,t)=>(await t.taskService.prs.discoverOrRefreshMany(t.paths,e),Promise.all(e.map(r=>Lt(t.paths,r.id)))),pn=async(e,t,r)=>{let n=t instanceof Error?t.message:String(t);await ct.appendErrorLogBestEffort(r.paths,{context:e,message:n,details:t instanceof Error?t.stack??t.message:String(t)})};var id=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 ad=async(e,t,r)=>{let n=g.runners.setRunnerEnabled(r.config,e,t);return await g.save(r.paths,n),n},ld=async(e,t,r)=>{let n=g.runners.setRunnerPath(r.config,e,t);return await g.save(r.paths,n),n},cd=async(e,t,r)=>{let n=g.previews.setEnabled(r.config,e,t);return await g.save(r.paths,n),n};var Tk=250;function Ae(e,t){return e.find(r=>r.id===t.selectedTaskId)??null}function st(e,t){return ve(t,e.ptyRuntime.getViewState(Dt(e,t)))}function Dt(e,t){let r=Ae(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 k(e,t){return st(e,bl(t,e.model))}function dd(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:k(e,{...e.state.shell,footerToast:null})},e.render())},600),{...t,footerToast:r}):{...t,footerToast:null}}function ud(e,t,r){return dd(e,t,r?{tone:"success",message:r}:null)}function F(e,t,r){return dd(e,t,{tone:"error",message:r})}function W(e,t,r,n){let s=r instanceof Error?r.message:n,o=r instanceof Error?r.stack??r.message:String(r);return ct.appendErrorLogBestEffort(e.paths,{context:t,message:s,details:o}),s}function j(e,t){if(!e.uiStateFile)return;e.runtimeState=fl(e.runtimeState,t);let r=e.runtimeState;e.persistQueue=e.persistQueue.then(()=>Ee({uiStateFile:e.uiStateFile},r),()=>Ee({uiStateFile:e.uiStateFile},r)),e.persistQueue.catch(()=>{})}function yk(e,t){let r=e.taskMutationQueue.then(t,t);return e.taskMutationQueue=r.then(()=>{},()=>{}),r}function B(e){return{paths:e.paths,config:e.config,taskService:S,workspaceService:G,queueTaskMutation:t=>yk(e,t)}}function Bo(e,t){let r=Ae(e.model.tasks,t),n=e.model.inspection,s=n&&n.taskId===r?.id?n:null,i=t.focusedRegion==="inspector"||t.activeTab==="inspection"?_o(s?.fileRows??[],t.collapsedFileTreePaths):[];return{leftItemIds:tt(e.model),centerTabIds:yl(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:Wc(t,r,s),pageRows:Math.max(5,ie(e.activeTerminal.width,e.activeTerminal.height).height-L.topRailHeight-9),enabledRunnerIds:e.enabledRunnerIds,projectTargetIds:r?.repoTargets?.map(a=>a.repoId)??[]}}async function pd(e,t){await Zc(t,B(e))}async function J(e){e.model=await At(e.workspaceRoot,e.state.shell,e.enabledRunnerIds),e.state.mode==="main"?e.state={mode:"main",shell:k(e,e.state.shell)}:e.state={...e.state,shell:k(e,e.state.shell)}}function mn(e,t){e.model={...e.model,tasks:[...e.model.tasks.filter(r=>r.id!==t.id),t].sort((r,n)=>r.id.localeCompare(n.id))}}async function fn(e,t){let r=++e.inspectionRefreshSequence,n=so(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 Za(n,s,a);if(r!==e.inspectionRefreshSequence)return;i={...e.model,inspection:l}}else if(i=await At(e.workspaceRoot,t,e.enabledRunnerIds),r!==e.inspectionRefreshSequence)return;e.model=i,e.state.mode==="main"&&(e.state={mode:"main",shell:k(e,e.state.shell)},j(e,e.state.shell),e.render())}function md(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)&&fn(e,r).catch(n=>{let s=W(e,"refresh inspection",n,"Failed to refresh inspection.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,actionMessage:s}),s)},e.render()})},Tk))}function fd(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=We(e.state.shell,r,Bo(e,e.state.shell));if(n.changed){if(n.refreshInspection){e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),e.render(),fn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),e.render()}},16)))}function Vo(e){e.pendingClear=!0,e.activeTerminal.fullscreen(!0)}async function Ko(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 hd(e){Ko(e).catch(()=>{}).then(()=>{e.state.mode==="main"&&(e.state={mode:"main",shell:k(e,e.state.shell)},e.render())})}async function kd(e,t){let r=k(e,t),n=Ae(e.model.tasks,r),s=Dt(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 ve(r,o);let i=await e.ptyRuntime.ensureSession(n.id,s,_e(ie(e.activeTerminal.width,e.activeTerminal.height)));return ve({...r,inputMode:"control"},i)}function Go(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 Ho(e,t){try{let r=k(e,t),n=Ae(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 gd(e,n),await J(e),s=n.selectedPtyTabId)}n&&!s&&(n=await gd(e,n),await J(e),s=n.selectedPtyTabId);let o=k(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:ve({...o,inputMode:"terminal"},e.ptyRuntime.getViewState(s))},j(e,e.state.shell);let i=await e.ptyRuntime.ensureSession(o.selectedTaskId,s,_e(ie(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Fe(s),e.lastTerminalKey=null,e.state={mode:"main",shell:ve({...o,inputMode:"terminal"},i)},j(e,e.state.shell)}catch(r){let n=W(e,"attach PTY",r,"Failed to start PTY.");t.selectedTaskId&&t.selectedPtyTabId&&Fe(t.selectedPtyTabId)&&(await Rk(e,t.selectedTaskId,n).catch(()=>{}),await J(e).catch(()=>{})),e.state={mode:"main",shell:F(e,gl(k(e,t),n),n)},j(e,e.state.shell)}e.render()}async function Rk(e,t,r){await nd(t,r,B(e))}async function wd(e,t,r,n){let s=k(e,t),{nextShell:o}=await Qc(s,r,n,B(e));return await J(e),k(e,{...s,...o})}async function Td(e,t){let r=k(e,t),{closedTab:n,nextShell:s}=await Xc(r,B(e));return e.ptyRuntime.disposeSession(n.id),await J(e),k(e,{...r,...s})}async function yd(e,t){let r=k(e,t),n=tt(e.model),s=n.indexOf(r.selectedLeftItemId??""),{closedTabIds:o,nextShell:i}=await sd(r,B(e));for(let a of o)e.ptyRuntime.disposeSession(a);return await J(e),k(e,{...r,...i,selectedLeftItemId:bk(n,tt(e.model),s)})}async function Rd(e,t){let r=k(e,t),{nextShell:n}=await id(r,B(e));return await J(e),k(e,{...r,...n})}async function gd(e,t){return ed(t,B(e))}function gn(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:st(e,e.state.shell)},e.render())},16))}function bk(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 Pd(e,t,r){if(r?.aborted||e.state.mode!=="main")return;let n=bd(e),s=t.takeDueTasks(e.model.tasks,n);if(s.length!==0)try{let o=await od(s,B(e));if(r?.aborted||(e.lastBackgroundPrPollError=null,e.state.mode!=="main"))return;for(let i of o)mn(e,i);t.recordSuccess(o,bd(e)),e.state={mode:"main",shell:k(e,e.state.shell)},e.render()}catch(o){if(r?.aborted)return;t.recordFailure(s,o);let i=o instanceof Error?o.message:"Background PR discovery failed.";i!==e.lastBackgroundPrPollError&&(e.lastBackgroundPrPollError=i,pn("background PR polling",o,B(e)))}}function bd(e){return e.state.mode!=="main"?{selectedTaskId:null,reviewVisible:!1}:{selectedTaskId:e.state.shell.selectedTaskId,reviewVisible:e.state.shell.inspectionMode==="review"}}async function Sd(e,t){let r=k(e,t),n=Ae(e.model.tasks,r),s=null,o=null;if(n?.type==="project"&&n.repoTargets?.length){let i=await S.prs.discoverOrRefreshAll(e.paths,r.selectedTaskId);await J(e);let a=i.synced+i.discovered+i.notFound;o=`Refreshed ${i.synced}/${a} targets`}else{let{disposition:i,task:a}=await S.prs.discoverOrRefresh(e.paths,r.selectedTaskId);await J(e),s=i==="not_found"?`No PR found for ${a.branch}`:null,i!=="not_found"&&(o=`Refreshed checks: ${E(a)?.requiredChecks.length??0} reported`)}return k(e,{...ud(e,r,o),focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:s})}var Pk={pendingForegroundMs:5e3,pendingBackgroundMs:15e3,stableForegroundMs:3e4,stableBackgroundMs:6e4,discoveryForegroundMs:6e4,discoveryBackgroundMs:18e4,rateLimitBaseMs:6e4,rateLimitMaxMs:15*6e4},hn=class{scheduledTasks=new Map;now;intervals;minimumIntervalMs;rateLimitFailures=0;notBefore=0;constructor(t={}){this.minimumIntervalMs=Math.max(1e3,t.minimumIntervalMs??5e3),this.intervals={...Pk,...t.intervals},this.now=t.now??Date.now}takeDueTasks(t,r){let n=this.now(),s=new Set(t.map(i=>i.id));for(let i of this.scheduledTasks.keys())s.has(i)||this.scheduledTasks.delete(i);let o=[];for(let i of t){let a=this.getTaskIntervalMs(i,r);if(a===null){this.scheduledTasks.delete(i.id);continue}let l=this.scheduledTasks.get(i.id);if(!l){this.scheduledTasks.set(i.id,{intervalMs:a,nextPollAt:n}),n>=this.notBefore&&o.push(i);continue}a<l.intervalMs&&(l.nextPollAt=Math.min(l.nextPollAt,n+a)),l.intervalMs=a,n>=this.notBefore&&n>=l.nextPollAt&&o.push(i)}return o}recordSuccess(t,r){let n=this.now();this.rateLimitFailures=0,this.notBefore=0;for(let s of t){let o=this.getTaskIntervalMs(s,r);o===null?this.scheduledTasks.delete(s.id):this.scheduledTasks.set(s.id,{intervalMs:o,nextPollAt:n+o})}}recordFailure(t,r){let n=this.now(),s=r instanceof ge,o=s?Math.min(this.intervals.rateLimitBaseMs*2**this.rateLimitFailures,this.intervals.rateLimitMaxMs):Math.max(this.minimumIntervalMs,this.intervals.pendingBackgroundMs);s&&(this.rateLimitFailures+=1,this.notBefore=n+o);for(let i of t){let a=this.scheduledTasks.get(i.id);a&&(a.nextPollAt=n+o)}}getTaskIntervalMs(t,r){let n=Sk(t),s=t.id===r.selectedTaskId&&r.reviewVisible;if(n.length>0){let o=n.some(Ik);return this.withMinimum(o?s?this.intervals.pendingForegroundMs:this.intervals.pendingBackgroundMs:s?this.intervals.stableForegroundMs:this.intervals.stableBackgroundMs)}return t.status==="checked"?this.withMinimum(s?this.intervals.discoveryForegroundMs:this.intervals.discoveryBackgroundMs):null}withMinimum(t){return Math.max(t,this.minimumIntervalMs)}};function Sk(e){return e.type==="project"&&e.repoTargets?.length?e.repoTargets.map(t=>t.pullRequest).filter(t=>t.status==="open"):e.prs.filter(t=>t.status==="open")}function Ik(e){return e.requiredChecks.some(t=>t.status==="pending"||t.status==="unknown")}import xk from"node:path";import{readdir as vk,stat as Ck}from"node:fs/promises";import Id from"node:path";async function Ak(e){let t=await vk(e,{withFileTypes:!0}),r=[];for(let n of t){if(!n.isDirectory())continue;let s=Id.join(e,n.name);r.push({name:n.name,path:s,kind:await Ek(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 vd(e){if(!e.query)return e.entries;let t=e.query.toLowerCase();return e.entries.filter(r=>r.name.toLowerCase().includes(t))}async function Cd(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 kn(e,t){let r=await Ak(t);e.state.mode==="main"&&(e.state={mode:"main",shell:k(e,{...e.state.shell,workspaceBrowser:r,activeTab:e.state.shell.selectedPtyTabId??e.state.shell.activeTab,actionMessage:null})},e.render())}async function Ek(e){let t=Id.join(e,".git");return await Ck(t).catch(()=>null)!==null}function Ad(e){let t=e.state;return t.runnerOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}function Ed(e){let t=e.state;return t.previewOptions??{menuIndex:t.menuIndex,message:t.optionsMessage}}async function Dk(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:k(e,{...t,taskPromptError:"Select a workspace first."})},e.render();return}if(r.length===0){e.state={mode:"main",shell:k(e,{...t,taskPromptError:"Task prompt cannot be empty."})},e.render();return}e.creatingTask=!0,e.state={mode:"main",shell:k(e,{...t,actionMessage:`Creating ${t.selectedRunner} task in ${t.selectedWorkspaceId??t.selectedRepoId}...`})},e.render();let n=null;try{let s=await rd(t.selectedRepoId,t.selectedWorkspaceId,r,t.selectedRunner,B(e));n=s.task,mn(e,n);let o=k(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??Wl(n,"agent"),_e(ie(e.activeTerminal.width,e.activeTerminal.height)));e.suppressTerminalEnterOnAttach=Fe(o.selectedPtyTabId),e.state={mode:"main",shell:ve(o,i)},j(e,e.state.shell)}catch(s){s instanceof xt&&(n=s.task);let o=W(e,"create task",s,"Failed to create task.");n&&!(s instanceof xt)?(await x(e.paths,n.id,i=>({...i,status:"draft",runnerSession:{...i.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:o})).catch(()=>{}),await J(e).catch(()=>{})):n&&(await x(e.paths,n.id,i=>({...i,lastFailureReason:o})).catch(()=>{}),await J(e).catch(()=>{})),e.state={mode:"main",shell:F(e,k(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 $k(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:k(e,{...r,taskPromptInput:null,taskPromptError:null,actionMessage:null})},e.render();return}if(ue(t)){Dk(e);return}if(t==="BACKSPACE"){e.state={mode:"main",shell:k(e,{...r,taskPromptInput:r.taskPromptInput.slice(0,-1),taskPromptError:null})},e.render();return}if(t==="CTRL_R"){e.state={mode:"main",shell:k(e,{...r,selectedRunner:Ur(r.selectedRunner,e.enabledRunnerIds),taskPromptError:null})},e.render();return}kl(t)&&(e.state={mode:"main",shell:k(e,{...r,taskPromptInput:`${r.taskPromptInput}${t}`,taskPromptError:null})},e.render())}}function Ok(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:k(e,{...e.state.shell,workspaceBrowser:{...r,query:null,selectedIndex:0}})},e.render();return}e.state={mode:"main",shell:k(e,{...e.state.shell,workspaceBrowser:null,actionMessage:null})},e.render();return}if(t==="/"){e.state={mode:"main",shell:k(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:k(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:k(e,{...e.state.shell,workspaceBrowser:{...r,query:s,selectedIndex:0}})},e.render();return}let n=vd(r);if(t==="UP"||t==="k"){e.state={mode:"main",shell:k(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:k(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"){kn(e,xk.dirname(r.cwd)).catch(s=>{let o=W(e,"open parent workspace directory",s,"Failed to open parent directory.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,workspaceBrowser:{...r,error:o}}),o)},e.render()});return}if(t==="RIGHT"||t==="l"||ue(t)){let s=n[r.selectedIndex]??null;if(!s)return;if((t==="RIGHT"||t==="l")&&(s.kind==="directory"||s.kind==="repo")){kn(e,s.path).catch(i=>{let a=W(e,"open workspace directory",i,"Failed to open directory.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()});return}let{workspaceService:o}=B(e);o.addWorkspace(e.paths,s.path).then(async i=>{await J(e);let a=i.repos[0]??null,l=k(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},j(e,e.state.shell),e.render()}).catch(i=>{let a=W(e,"add workspace",i,"Failed to add workspace.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,workspaceBrowser:{...r,error:a}}),a)},e.render()})}}function Mk(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="options")return;let r=Tc(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;Nk(e,n)}}}async function Nk(e,t){let r;try{r=await ct.readRecentErrorLines(e.paths)}catch(n){let s=W(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 Lk(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let r=Rc(Ad(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"?ad(r.runner,r.enabled,B(e)):ld(r.runner,r.path,B(e))).then(s=>{e.state.mode!=="overlay"||e.state.variant!=="runners"||(e.config=s,e.enabledRunnerIds=g.runners.getEnabled(e.config),e.model={...e.model,enabledRunnerIds:e.enabledRunnerIds},e.state={...e.state,shell:k(e,{...e.state.shell,selectedRunner:e.enabledRunnerIds.includes(e.state.shell.selectedRunner)?e.state.shell.selectedRunner:g.runners.getDefault(e.config)}),runnerOptions:r.state},e.render())}).catch(s=>{if(e.state.mode!=="overlay"||e.state.variant!=="runners")return;let o=W(e,"save runner option",s,"Failed to save runner option.");e.state={...e.state,shell:F(e,k(e,e.state.shell),o),runnerOptions:{...Ad(e),message:o}},e.render()})}function jk(e,t){if(e.state.mode!=="overlay"||e.state.variant!=="previews")return;let r=yc(Ed(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}cd(r.feature,r.enabled,B(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=W(e,"save feature preview",n,"Failed to save feature preview.");e.state={...e.state,shell:F(e,k(e,e.state.shell),s),previewOptions:{...Ed(e),message:s}},e.render()})}}function xd(e,t){let r=typeof t=="string"?t:"";if(e.state.mode==="main"&&e.state.shell.taskPromptInput!==null){$k(e,r);return}if(e.state.mode==="main"&&e.state.shell.workspaceBrowser!==null){Ok(e,r);return}if(e.state.mode==="main"&&e.state.shell.inputMode==="control"){if(r==="F"){Fk(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=Uo(e.state.shell,r,Bo(e,e.state.shell));if(n.exit){e.exit(0);return}if(n.detachTerminal){e.ptyRuntime.detach(),e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),e.render();return}if(e.state.shell.inputMode==="terminal"){if(n.changed){e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),e.render();return}if(e.suppressTerminalEnterOnAttach&&ue(r)){e.suppressTerminalEnterOnAttach=!1;return}e.suppressTerminalEnterOnAttach&&(e.suppressTerminalEnterOnAttach=!1);let s=sr(r);if(s){e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(_k(e,r))return;e.lastTerminalKey=ql(r)?{key:r,at:Date.now()}:null;let o=Ul(r,e.state.shell.terminal.scrolledBack??!1);if(o!==0){gn(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:k(e,n.state)},e.pendingClear=!0,e.render();return}if(n.beginTaskPrompt){e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),e.render();return}if(n.openWorkspaceBrowser){kn(e,e.workspaceRoot).catch(s=>{let o=W(e,"browse workspaces",s,"Failed to browse workspaces.");e.state={mode:"main",shell:F(e,k(e,{...n.state,workspaceBrowser:{cwd:e.workspaceRoot,entries:[],selectedIndex:0,query:null,error:o}}),o)},e.render()});return}if(n.createPtyTab){wd(e,n.state,n.createPtyTabKind,n.createPtyTabRunner).then(s=>{Ho(e,s)}).catch(s=>{let o=W(e,"create PTY tab",s,"Failed to create tab.");e.state={mode:"main",shell:F(e,k(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.closePtyTab){Td(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close PTY tab",s,"Failed to close tab.");e.state={mode:"main",shell:F(e,k(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.refreshPullRequestChecks){Sd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"refresh PR checks",s,"Failed to refresh PR checks.");e.state={mode:"main",shell:F(e,k(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.openPrUrl){let s=Ae(e.model.tasks,n.state),o=s?E(s)?.url??null:null;o?Cd(o).catch(i=>{let a=W(e,"open PR URL",i,"Failed to open PR in browser.");e.state={mode:"main",shell:F(e,k(e,n.state),a)},e.render()}):(e.state={mode:"main",shell:F(e,k(e,n.state),"No PR URL available.")},e.render());return}if(n.closeTask){yd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"close task",s,"Failed to close task.");e.state={mode:"main",shell:F(e,k(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.removeWorkspace){Rd(e,n.state).then(s=>{e.state={mode:"main",shell:s},j(e,e.state.shell),e.render()}).catch(s=>{let o=W(e,"remove workspace",s,"Failed to remove workspace.");e.state={mode:"main",shell:F(e,k(e,{...n.state,actionMessage:o}),o)},e.render()});return}if(n.attachTerminal){Ho(e,n.state);return}if(n.refreshInspection){if(e.state={mode:"main",shell:k(e,n.state)},j(e,e.state.shell),(e.state.shell.focusedRegion!=="tasks"||!e.renderTaskNavigation())&&e.render(),e.state.shell.focusedRegion==="tasks"){md(e,e.state.shell);return}fn(e,e.state.shell).catch(s=>{let o=W(e,"refresh inspection",s,"Failed to refresh inspection.");e.state={mode:"main",shell:F(e,k(e,{...e.state.shell,actionMessage:o}),o)},e.render()});return}n.changed&&(e.state={mode:"main",shell:k(e,n.state)},pd(e,e.state.shell).catch(()=>{}),j(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:k(e,e.state.shell)},e.pendingClear=!0,e.render();return}if(e.state.variant==="options"){Mk(e,r);return}if(e.state.variant==="runners"){Lk(e,r);return}if(e.state.variant==="previews"){jk(e,r);return}if(e.state.variant==="error-log"){if(r==="ESCAPE"||ue(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"||ue(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:k(e,e.state.shell)},e.pendingClear=!0,e.render());return}if(ue(r)){if(e.state.menuIndex===0){let n=e.state.variant==="boot";e.state={mode:"main",shell:k(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;kd(e,s).then(o=>{e.state.mode!=="main"||e.state.shell!==s||(e.state={mode:"main",shell:o},j(e,e.state.shell),e.render())}).catch(o=>{if(e.state.mode!=="main"||e.state.shell!==s)return;let i=W(e,"warm selected PTY",o,"Failed to start selected PTY.");e.state={mode:"main",shell:F(e,k(e,e.state.shell),i)},j(e,e.state.shell),e.render()})}):hd(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 Dd(e,t){let r=Hl(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=sr(o);if(i){Od(e),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:i,at:Date.now()},e.ptyRuntime.writeKey(i);return}if(ko(o)){e.pendingTerminalKeySequence.raw=o,$d(e);return}wn(e)}if(r.includes("")){e.ptyRuntime.detach(),e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey=null,e.state={mode:"main",shell:k(e,{...e.state.shell,inputMode:"control",actionMessage:null,focusedRegion:"center"})},j(e,e.state.shell),e.render();return}let n=Bl(r);if(n!==0){gn(e,n);return}let s=sr(r);if(s){e.suppressTerminalEnterOnAttach=!1,e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s);return}if(e.suppressTerminalEnterOnAttach&&r!=="\r"&&r!==`
|
|
122
126
|
`&&r!==`\r
|
|
123
|
-
`&&(e.suppressTerminalEnterOnAttach=!1),Ol(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function cw(e,t){if(e.pendingTerminalKeySequence){let r=Dl(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=er(n);if(s)return Rd(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(so(n))return e.pendingTerminalKeySequence.raw=n,yd(e),!0}return cn(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>cn(e),30)},!0)}function yd(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>cn(e),30))}function cn(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function Rd(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function bd(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){rd(e,no(t));return}let r=no(t);r!==0&&on(e,r)}function dw(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var dn=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=_o(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:_o(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=_o(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 _o(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var Pd=1e3,mw=pw(import.meta.url),fw=mw("terminal-kit"),gw=fw.terminal;function qo(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Sd(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function hw(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 Id(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=Z(t),n=await f.load(r),s=f.runners.getEnabled(n),o=e.uiStateFile?await it({uiStateFile:e.uiStateFile}):null,i=await bt(t,void 0,s),a=Jt(el(o,n),i);i=await bt(t,a,s);let l={current:i},c=()=>{},d=()=>{},u=()=>{},m={workspaceRoot:t,onUpdate:y=>c(y),onActivity:y=>d(y),onActivityRemoved:y=>u(y),resolveSessionSpec:(y,w)=>Cl(l.current,w,t)},g=e.ptyRuntime??await Gl({...m,paths:r,viewUpdateMode:f.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:f.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(y=>{let w=e.terminal??gw,b=null,V=null,H=null,re=null,v=null,ke=0,vt=!1,st=new Map,un=new an({minimumIntervalMs:(n.github?.watchIntervalSeconds??5)*1e3}),p,qe=new dn({resolutionMs:f.previews.isEnabled(n,"agentActivityIndicators")?150:Pd,onError:(k,L)=>rn(`heartbeat job "${k}"`,L,U(p))});p={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Jt(a,i)},get model(){return l.current},set model(k){l.current=k},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:g,resolve:y,render:()=>{},renderTaskNavigation:()=>!1,exit:k=>y(k),setAgentActivityEnabled:k=>{qe.setResolutionMs(k?150:Pd),p.ptyRuntime.setActivityEnabled?.(k)}},p.setAgentActivityEnabled(f.previews.isEnabled(n,"agentActivityIndicators")),c=k=>{p.state.mode==="main"&&(v=hw(v,k),p.ptyRenderTimer||(p.ptyRenderTimer=setTimeout(()=>{p.ptyRenderTimer=null;let L=v;if(v=null,p.state.mode==="main"){let J=nt(p,p.state.shell);if(p.state={mode:"main",shell:J},!f.previews.isEnabled(p.config,"incrementalCenterPane")||!re||!V){p.render();return}let Q=oe(w.width,w.height),At={...re,terminal:J.terminal},Be=$c(Q,At,V,J.centerZoomed,L?.kind==="rows"?L.rowIndices:null);if(!Be){p.render();return}Be.output.length>0&&w.noFormat(Be.output),re=At,V=Be.region,H&&(H={...H,center:Be.region}),b=null,w.hideCursor(!0)}},f.previews.isEnabled(p.config,"incrementalCenterPane")?0:50)))},d=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&_e(k.tabId)&&st.get(k.tabId)!==tr(k.tabId,[k],Date.now())&&p.render()},u=k=>{p.state.mode==="main"&&f.previews.isEnabled(p.config,"agentActivityIndicators")&&_e(k)&&st.get(k)!=="idle"&&p.render()};let Te=k=>{let L=oe(w.width,w.height),J=f.previews.isEnabled(p.config,"agentActivityIndicators"),ce=J?p.ptyRuntime.getActivitySnapshots?.()??[]:[],Q=Date.now(),At=Rc(h(p,k.shell),p.model,J?{snapshots:ce,now:Q,animationFrame:ke}:void 0);if(st.clear(),J)for(let vd of p.model.tasks)for(let pn of vd.ptyTabs)pn.kind==="agent"&&st.set(pn.id,tr(pn.id,ce,Q));let Be=hl(L,At,{centerOnly:k.shell.centerZoomed,focusFlashActive:p.focusFlashUntil!==null&&Date.now()<p.focusFlashUntil});return{data:At,presentation:Be}},Ue=(k,L,J,ce)=>{if(!H)return!1;let Q=Oc(H,L.regions,J);return Q?(Q.output.length>0&&w.noFormat(Q.output),re=k,H=Q.regions,V=Q.regions.center,b=ce?L.frame:null,w.hideCursor(!0),!0):!1};p.renderTaskNavigation=()=>{if(p.state.mode!=="main"||p.pendingClear||!f.previews.isEnabled(p.config,"incrementalCenterPane"))return!1;jo(p),p.ptyRuntime.setViewedTab?.(Ct(p,p.state.shell));let{data:k,presentation:L}=Te(p.state);return Ue(k,L,["rail","left","center","footer"],!1)},p.render=()=>{jo(p);let k=p.state;p.ptyRuntime.setViewedTab?.(k.mode==="main"?Ct(p,k.shell):null);let L=oe(w.width,w.height),J,ce=null;if(k.mode==="main"){let Q=Te(k);if(ce=Q.presentation,J=ce.frame,f.previews.isEnabled(p.config,"incrementalCenterPane")&&!p.pendingClear&&Ue(Q.data,ce,["rail","left","center","right","footer"],!0))return;re=Q.data,V=ce.center}else J=k.variant==="boot"?pl(L,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="pause"?ml(L,{menuIndex:k.menuIndex,optionsMessage:k.optionsMessage,versionText:p.versionText,updateText:p.updateText}):k.variant==="options"?Kr(L,{menuIndex:k.menuIndex,optionsMenuItems:go}):k.variant==="runners"?Kr(L,{menuIndex:qo(k).menuIndex,optionsMenuItems:ho(p.config,qo(k)),optionsMessage:nc(qo(k)),optionsSubtitle:"Runners"}):k.variant==="previews"?Kr(L,{menuIndex:Sd(k).menuIndex,optionsMenuItems:sc(p.config),optionsMessage:oc(Sd(k)),optionsSubtitle:"Feature Previews - Experimental"}):k.variant==="error-log"?gl(L,{errorLogPath:k.errorLog?.path??r.errorLogFile,errorLogLines:k.errorLog?.lines??[]}):fl(L),re=null,V=null,H=null;p.pendingClear&&(w.moveTo(1,1),w.eraseDisplayBelow(),p.pendingClear=!1,b=null),w.noFormat(Ll(J,b)),b=J,H=ce?.regions??null,w.hideCursor(!0)};let nr=k=>kd(p,k),sr=k=>Td(p,k),or=k=>bd(p,k),Cd=()=>{process.stdout.off("resize",Uo),process.off("SIGCONT",Bo),w.removeListener("key",nr),w.removeListener("unknown",sr),w.removeListener("mouse",or),p.scrollRenderTimer&&(clearTimeout(p.scrollRenderTimer),p.scrollRenderTimer=null),p.inspectionScrollRenderTimer&&(clearTimeout(p.inspectionScrollRenderTimer),p.inspectionScrollRenderTimer=null),p.leftNavInspectionTimer&&(clearTimeout(p.leftNavInspectionTimer),p.leftNavInspectionTimer=null),p.pendingTerminalKeySequence&&(clearTimeout(p.pendingTerminalKeySequence.timer),p.pendingTerminalKeySequence=null),p.ptyRenderTimer&&(clearTimeout(p.ptyRenderTimer),p.ptyRenderTimer=null),p.footerToastTimer&&(clearTimeout(p.footerToastTimer),p.footerToastTimer=null),p.focusFlashTimer&&(clearTimeout(p.focusFlashTimer),p.focusFlashTimer=null),qe.stop(),p.ptyRuntime.disposeAll(),w.grabInput(!1),w.hideCursor(!1),w.fullscreen(!1)};p.exit=k=>{Cd(),y(k)};let Uo=()=>{Lo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize(Fe(oe(w.width,w.height))),p.state={mode:"main",shell:nt(p,p.state.shell)}),p.render()},Bo=()=>{Lo(p),p.state.mode==="main"&&p.state.shell.inputMode==="terminal"&&(p.ptyRuntime.resize(Fe(oe(w.width,w.height))),p.state={mode:"main",shell:nt(p,p.state.shell)}),p.render()};process.stdout.on("resize",Uo),process.on("SIGCONT",Bo),w.grabInput(!0),p.inputCaptureMode="control",w.hideCursor(!0),w.fullscreen(!0),w.on("key",nr),w.on("unknown",sr),w.on("mouse",or),qe.register({id:"github.pull-requests",intervalMs:1e3,run:k=>ud(p,un,k)}),qe.register({id:"agent.activity-indicators",intervalMs:150,run:()=>{if(!f.previews.isEnabled(p.config,"agentActivityIndicators")){ke=0,vt=!1;return}let k=Date.now(),L=wc(p.model.tasks,p.ptyRuntime.getActivitySnapshots?.()??[],k);(L||vt)&&(ke=(ke+1)%6,p.state.mode==="main"&&p.render()),vt=L}}),qe.start(),f.version.checkForUpdate().then(k=>{k.updateAvailable&&k.latest&&(p.updateText=`Update available: v${k.latest}`,p.render())}),p.bootHydrationReady=No(p).catch(()=>{}),p.render()})}async function ww(){try{if(process.argv[2]==="__craig-daemon"){let e=process.argv[3]??process.cwd(),t=Z(e);return await Hl(t),0}if(process.argv[2]==="__craig-daemon-shutdown"){let e=process.argv[3]??process.cwd(),t=Z(e);return await zl(t),0}}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
124
|
-
`),1}return
|
|
127
|
+
`&&(e.suppressTerminalEnterOnAttach=!1),Gl(e.suppressTerminalEnterOnAttach,e.lastTerminalKey,r)){e.suppressTerminalEnterOnAttach=!1;return}e.ptyRuntime.write(r)}function _k(e,t){if(e.pendingTerminalKeySequence){let r=Vl(t);if(r!==null){let n=`${e.pendingTerminalKeySequence.raw}${r}`,s=sr(n);if(s)return Od(e),e.lastTerminalKey={key:s,at:Date.now()},e.ptyRuntime.writeKey(s),!0;if(ko(n))return e.pendingTerminalKeySequence.raw=n,$d(e),!0}return wn(e),!1}return t!=="ESCAPE"?!1:(e.pendingTerminalKeySequence={raw:"\x1B",timer:setTimeout(()=>wn(e),30)},!0)}function $d(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence.timer=setTimeout(()=>wn(e),30))}function wn(e){if(!e.pendingTerminalKeySequence)return;let t=e.pendingTerminalKeySequence;e.pendingTerminalKeySequence=null,clearTimeout(t.timer),e.ptyRuntime.write(t.raw)}function Od(e){e.pendingTerminalKeySequence&&(clearTimeout(e.pendingTerminalKeySequence.timer),e.pendingTerminalKeySequence=null)}function Md(e,t){if(e.state.mode!=="main")return;if(e.state.shell.inputMode==="control"){fd(e,ho(t));return}let r=ho(t);r!==0&&gn(e,r)}function Fk(e){e.focusFlashUntil=Date.now()+600,e.focusFlashTimer&&clearTimeout(e.focusFlashTimer),e.focusFlashTimer=setTimeout(()=>{e.focusFlashUntil=null,e.focusFlashTimer=null,e.render()},600)}var Tn=class{jobs=new Map;resolutionMs;now;onError;timer=null;abortController=null;constructor(t){this.resolutionMs=zo(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:zo(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=zo(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 zo(e,t){if(!Number.isFinite(e)||e<=0)throw new Error(`${t} must be a positive number.`);return e}var Nd=1e3,qk=Wk(import.meta.url),Uk=qk("terminal-kit"),Bk=Uk.terminal;function Yo(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Ld(e){return e.previewOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Vk(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 jd(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=ee(t),n=await g.load(r),s=g.runners.getEnabled(n),o=e.uiStateFile?await at({uiStateFile:e.uiStateFile}):null,i=await At(t,void 0,s),a=er(ml(o,n),i);i=await At(t,a,s);let l={current:i},c=()=>{},d=()=>{},u=()=>{},p={workspaceRoot:t,onUpdate:w=>c(w),onActivity:w=>d(w),onActivityRemoved:w=>u(w),resolveSessionSpec:(w,h)=>Fl(l.current,h,t)},f=e.ptyRuntime??await oc({...p,paths:r,viewUpdateMode:g.previews.isEnabled(n,"incrementalCenterPane")?"incremental":"snapshot",activityEnabled:g.previews.isEnabled(n,"agentActivityIndicators")});return new Promise(w=>{let h=e.terminal??Bk,b=null,q=null,H=null,ne=null,C=null,we=0,$t=!1,ot=new Map,yn=new hn({minimumIntervalMs:(n.github?.watchIntervalSeconds??5)*1e3}),m,qe=new Tn({resolutionMs:g.previews.isEnabled(n,"agentActivityIndicators")?ln:Nd,onError:(T,N)=>pn(`heartbeat job "${T}"`,N,B(m))});m={state:{mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:er(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${g.version.getCurrent()}`,updateText:null,inspectionRefreshSequence:0,pendingClear:!0,inputCaptureMode:null,runtimeState:o,persistQueue:Promise.resolve(),taskMutationQueue:Promise.resolve(),bootHydrationReady:Promise.resolve(),paths:r,workspaceRoot:t,uiStateFile:e.uiStateFile,activeTerminal:h,ptyRuntime:f,resolve:w,render:()=>{},renderTaskNavigation:()=>!1,exit:T=>w(T),setAgentActivityEnabled:T=>{qe.setResolutionMs(T?ln:Nd),m.ptyRuntime.setActivityEnabled?.(T)}},m.setAgentActivityEnabled(g.previews.isEnabled(n,"agentActivityIndicators")),c=T=>{m.state.mode==="main"&&(C=Vk(C,T),m.ptyRenderTimer||(m.ptyRenderTimer=setTimeout(()=>{m.ptyRenderTimer=null;let N=C;if(C=null,m.state.mode==="main"){let Q=st(m,m.state.shell);if(m.state={mode:"main",shell:Q},!g.previews.isEnabled(m.config,"incrementalCenterPane")||!ne||!q){m.render();return}let X=ie(h.width,h.height),Ot={...ne,terminal:Q.terminal},Be=Vc(X,Ot,q,Q.centerZoomed,N?.kind==="rows"?N.rowIndices:null);if(!Be){m.render();return}Be.output.length>0&&h.noFormat(Be.output),ne=Ot,q=Be.region,H&&(H={...H,center:Be.region}),b=null,h.hideCursor(!0)}},g.previews.isEnabled(m.config,"incrementalCenterPane")?0:50)))},d=T=>{m.state.mode==="main"&&g.previews.isEnabled(m.config,"agentActivityIndicators")&&Fe(T.tabId)&&ot.get(T.tabId)!==Ze(T.tabId,[T],Date.now())&&m.render()},u=T=>{m.state.mode==="main"&&g.previews.isEnabled(m.config,"agentActivityIndicators")&&Fe(T)&&ot.get(T)!=="idle"&&m.render()};let Te=T=>{let N=ie(h.width,h.height),Q=g.previews.isEnabled(m.config,"agentActivityIndicators"),ce=Q?m.ptyRuntime.getActivitySnapshots?.()??[]:[],X=Date.now(),Ot=Oc(k(m,T.shell),m.model,Q?{snapshots:ce,now:X,animationFrame:we}:void 0);if(ot.clear(),Q)for(let Fd of m.model.tasks)for(let Rn of Fd.ptyTabs)Rn.kind==="agent"&&ot.set(Rn.id,Ze(Rn.id,ce,X));let Be=El(N,Ot,{centerOnly:T.shell.centerZoomed,focusFlashActive:m.focusFlashUntil!==null&&Date.now()<m.focusFlashUntil});return{data:Ot,presentation:Be}},Ue=(T,N,Q,ce)=>{if(!H)return!1;let X=Kc(H,N.regions,Q);return X?(X.output.length>0&&h.noFormat(X.output),ne=T,H=X.regions,q=X.regions.center,b=ce?N.frame:null,h.hideCursor(!0),!0):!1};m.renderTaskNavigation=()=>{if(m.state.mode!=="main"||m.pendingClear||!g.previews.isEnabled(m.config,"incrementalCenterPane"))return!1;Go(m),m.ptyRuntime.setViewedTab?.(Dt(m,m.state.shell));let{data:T,presentation:N}=Te(m.state);return Ue(T,N,["rail","left","center","footer"],!1)},m.render=()=>{Go(m);let T=m.state;m.ptyRuntime.setViewedTab?.(T.mode==="main"?Dt(m,T.shell):null);let N=ie(h.width,h.height),Q,ce=null;if(T.mode==="main"){let X=Te(T);if(ce=X.presentation,Q=ce.frame,g.previews.isEnabled(m.config,"incrementalCenterPane")&&!m.pendingClear&&Ue(X.data,ce,["rail","left","center","right","footer"],!0))return;ne=X.data,q=ce.center}else Q=T.variant==="boot"?Il(N,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="pause"?vl(N,{menuIndex:T.menuIndex,optionsMessage:T.optionsMessage,versionText:m.versionText,updateText:m.updateText}):T.variant==="options"?Xr(N,{menuIndex:T.menuIndex,optionsMenuItems:vo}):T.variant==="runners"?Xr(N,{menuIndex:Yo(T).menuIndex,optionsMenuItems:Co(m.config,Yo(T)),optionsMessage:hc(Yo(T)),optionsSubtitle:"Runners"}):T.variant==="previews"?Xr(N,{menuIndex:Ld(T).menuIndex,optionsMenuItems:kc(m.config),optionsMessage:wc(Ld(T)),optionsSubtitle:"Feature Previews - Experimental"}):T.variant==="error-log"?Al(N,{errorLogPath:T.errorLog?.path??r.errorLogFile,errorLogLines:T.errorLog?.lines??[]}):Cl(N),ne=null,q=null,H=null;m.pendingClear&&(h.moveTo(1,1),h.eraseDisplayBelow(),m.pendingClear=!1,b=null),h.noFormat(zl(Q,b)),b=Q,H=ce?.regions??null,h.hideCursor(!0)};let ir=T=>xd(m,T),ar=T=>Dd(m,T),lr=T=>Md(m,T),_d=()=>{process.stdout.off("resize",Jo),process.off("SIGCONT",Qo),h.removeListener("key",ir),h.removeListener("unknown",ar),h.removeListener("mouse",lr),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),qe.stop(),m.ptyRuntime.disposeAll(),h.grabInput(!1),h.hideCursor(!1),h.fullscreen(!1)};m.exit=T=>{_d(),w(T)};let Jo=()=>{Vo(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(_e(ie(h.width,h.height))),m.state={mode:"main",shell:st(m,m.state.shell)}),m.render()},Qo=()=>{Vo(m),m.state.mode==="main"&&m.state.shell.inputMode==="terminal"&&(m.ptyRuntime.resize(_e(ie(h.width,h.height))),m.state={mode:"main",shell:st(m,m.state.shell)}),m.render()};process.stdout.on("resize",Jo),process.on("SIGCONT",Qo),h.grabInput(!0),m.inputCaptureMode="control",h.hideCursor(!0),h.fullscreen(!0),h.on("key",ir),h.on("unknown",ar),h.on("mouse",lr),qe.register({id:"github.pull-requests",intervalMs:1e3,run:T=>Pd(m,yn,T)}),qe.register({id:"agent.activity-indicators",intervalMs:ln,run:()=>{if(!g.previews.isEnabled(m.config,"agentActivityIndicators")){we=0,$t=!1;return}let T=Date.now(),N=Lr(m.model.tasks,m.ptyRuntime.getActivitySnapshots?.()??[],T);(N||$t)&&(we=(we+1)%Ec,m.state.mode==="main"&&m.render()),$t=N}}),qe.start(),g.version.checkForUpdate().then(T=>{T.updateAvailable&&T.latest&&(m.updateText=`Update available: v${T.latest}`,m.render())}),m.bootHydrationReady=Ko(m).catch(()=>{}),m.render()})}async function Kk(){try{if(process.argv[2]==="__craig-daemon"){let e=process.argv[3]??process.cwd(),t=ee(e);return await ic(t),0}if(process.argv[2]==="__craig-daemon-shutdown"){let e=process.argv[3]??process.cwd(),t=ee(e);return await ac(t),0}}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
128
|
+
`),1}return Ja({argv:process.argv.slice(2),cwd:process.cwd(),env:process.env,isInputTty:process.stdin.isTTY===!0,isOutputTty:process.stdout.isTTY===!0,writeStdout:e=>process.stdout.write(e),writeStderr:e=>process.stderr.write(e),runInteractive:e=>jd({uiStateFile:ee(e).uiStateFile,workspaceRoot:e})})}var Gk=await Kk();process.exit(Gk);
|