craig-cli 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +117 -15
  2. package/dist/cli.js +1 -1
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -1,6 +1,23 @@
1
+ <div align="center">
2
+ <pre>
3
+ ▄████▄ ██▀███ ▄▄▄ ██▓ ▄████
4
+ ▒██▀ ▀█ ▓██ ▒ ██▒▒████▄ ▓██▒ ██▒ ▀█▒
5
+ ▒▓█ ▄ ▓██ ░▄█ ▒▒██ ▀█▄ ▒██▒▒██░▄▄▄░
6
+ ▒▓▓▄ ▄██▒▒██▀▀█▄ ░██▄▄▄▄██ ░██░░▓█ ██▓
7
+ ▒ ▓███▀ ░░██▓ ▒██▒ ▓█ ▓██▒░██░░▒▓███▀▒
8
+ ░ ░▒ ▒ ░░ ▒▓ ░▒▓░ ▒▒ ▓▒█░░▓ ░▒ ▒
9
+ ░ ▒ ░▒ ░ ▒░ ▒ ▒▒ ░ ▒ ░ ░ ░
10
+ ░ ░░ ░ ░ ▒ ▒ ░░ ░ ░
11
+ ░ ░ ░ ░ ░ ░ ░
12
+ ░
13
+
14
+ crAIg is that you?
15
+ </pre>
16
+ </div>
17
+
1
18
  # Craig
2
19
 
3
- Craig is a local terminal control plane for repo-backed agent work.
20
+ Craig is a local terminal control plane for repo-backed agent work. The primary interface is the full-screen terminal UI launched with `craig`; command-mode entry points are available for automation and debugging.
4
21
 
5
22
  ## Install
6
23
 
@@ -10,42 +27,105 @@ npm install -g craig-cli
10
27
 
11
28
  Craig requires Node 22 or newer.
12
29
 
13
- ## Setup
30
+ External tools:
31
+
32
+ - `git` for repo, branch, and worktree operations
33
+ - `gh` authenticated with GitHub for PR, check, and merge flows
34
+ - an agent CLI such as Codex, Cursor, or Claude
35
+
36
+ ## Start Craig
14
37
 
15
- Run Craig from a git workspace:
38
+ Run Craig from the workspace where you want `.craig/` state to live:
16
39
 
17
40
  ```bash
18
- cd path/to/your/repo
41
+ cd path/to/your/workspace
19
42
  craig
20
43
  ```
21
44
 
22
- Craig stores local workspace state under `.craig/` in the workspace where you run it. That state includes task records, worktrees, runtime UI state, logs, and review metadata.
23
-
24
- ## External Tools
25
-
26
- Craig does not bundle agent CLIs. Install and authenticate the agent CLIs you want to use separately, such as Codex, Cursor, or Claude.
27
-
28
- Craig also expects:
45
+ The TUI opens with a boot overlay, then a workspace shell with task navigation, center work tabs, and an inspector panel.
46
+
47
+ Craig stores task records, worktrees, runtime UI state, logs, and review metadata under `.craig/`.
48
+
49
+ ## TUI Workflow
50
+
51
+ 1. Launch `craig`.
52
+ 2. Add or select a workspace/repo from the left side. You can also pre-register one with `craig repo add <path>`.
53
+ 3. Press `n` to create a task from the TUI.
54
+ 4. Type the task prompt and press `Enter`.
55
+ 5. Craig creates the branch, task worktree, and agent tab.
56
+ 6. Press `Enter` on an agent or terminal tab to attach the live PTY.
57
+ 7. Use `Ctrl+]` to return from terminal mode to Craig control mode.
58
+ 8. Use the Files, Changes, and Review inspector modes to inspect work without leaving Craig.
59
+
60
+ ## TUI Keys
61
+
62
+ ```text
63
+ Global
64
+ ? help
65
+ Esc pause / back
66
+ Tab, ] next panel
67
+ Shift+Tab, [ previous panel
68
+ q quit
69
+
70
+ Navigation
71
+ Up/Down, j/k move selection
72
+ Left/Right,
73
+ h/l switch tabs or inspector mode
74
+
75
+ Tasks
76
+ n new task
77
+ Enter attach selected task PTY
78
+ X close selected task
79
+
80
+ Center panel
81
+ Enter attach PTY
82
+ + new tab
83
+ a new agent tab
84
+ t new terminal tab
85
+ x close tab
86
+ z zoom center panel
87
+
88
+ Review
89
+ R sync PR / refresh checks
90
+ X close task
91
+
92
+ Terminal mode
93
+ Ctrl+] return to control mode
94
+ Wheel,
95
+ PgUp/PgDn scroll terminal
96
+ ```
29
97
 
30
- - `git` for workspace, branch, and worktree operations
31
- - `gh` authenticated with GitHub for PR, check, and merge flows
98
+ ## Command Mode
32
99
 
33
- ## Commands
100
+ Use command mode when scripting, debugging, or working outside the TUI.
34
101
 
35
102
  ```bash
36
103
  craig
104
+
37
105
  craig repo add <path>
38
106
  craig repo list
39
107
  craig repo remove <repo-id>
108
+
40
109
  craig workspace list
41
- craig task new --repo <repo-id> "<task>"
110
+ craig workspace list --archived
111
+ craig workspace archive <workspace-id>
112
+ craig workspace restore <workspace-id>
113
+
114
+ craig task new --repo <repo-id> [--runner codex|cursor|claude] "<task>"
42
115
  craig task list
116
+ craig task list --repo <repo-id>
43
117
  craig task show <task-id>
118
+ craig task attach <task-id>
119
+ craig task open <task-id>
44
120
  craig task logs <task-id>
45
121
  craig task diff <task-id>
46
122
  craig task check <task-id>
123
+ craig task commit <task-id>
47
124
  craig task pr <task-id> [--watch]
48
125
  craig task merge <task-id> [--preserve-worktree]
126
+
127
+ craig link add <task-id> <repo-id>
128
+ craig link list <task-id>
49
129
  ```
50
130
 
51
131
  ## Configuration
@@ -68,3 +148,25 @@ Craig reads optional workspace-local config from `.craig/config.json`.
68
148
  }
69
149
  }
70
150
  ```
151
+
152
+ `checks.commands` defines commands for `craig task check`. `runners.<id>` controls whether Codex, Cursor, or Claude appears as a task runner and can override that runner's executable path. Runner path changes apply to newly created task sessions.
153
+
154
+ ## Local State
155
+
156
+ Craig writes local state under `.craig/`:
157
+
158
+ ```text
159
+ .craig/
160
+ artifacts/
161
+ logs/
162
+ runtime/
163
+ tasks/
164
+ workspaces/
165
+ worktrees/
166
+ ```
167
+
168
+ Treat `.craig/` as private developer state. It can contain task prompts, logs, local paths, PR metadata, and worktrees.
169
+
170
+ ## License
171
+
172
+ Craig is proprietary software. All rights reserved.
package/dist/cli.js CHANGED
@@ -94,7 +94,7 @@ ${y.slice(-2e3)}`:""}`)}async function Tn(e){let t=await Ld(e).catch(()=>null);r
94
94
  `)}function On(e,t,r={}){let i=r.color??!0,a=Ee.leftWidth,y=Ee.rightWidth,T=Ee.dividerWidth,n=r.centerOnly??!1,h=n?e.width:e.width-a-y-T*2,p=e.height-Ee.topRailHeight,S=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent} ${jn(`\u25CF ${t.topRail.liveLabel}`,i,se.rail)}`,o=le(nt(S,e.width),i,se.rail),w=qd(t,a-Qt-Jt,p,i),c=Kd(t,h,p,i),g=Vd(t,y,p,i),_=[];for(let s=0;s<p;s+=1){if(n){let v=s===p-1?{text:t.footerText,tone:"muted",fullBleed:!0}:c[s]??Be();_.push(Yt(v,h,i,"center"));continue}let f=Yt(w[s]??Be(),a,i,"left"),d=le("\u2502",i,se.divider),l=Yt(c[s]??Be(),h,i,"center"),u=le("\u2502",i,se.divider),m=Yt(g[s]??Be(),y,i,"right");_.push(`${f}${d}${l}${u}${m}`)}return[o,..._].join(`
95
95
  `)}function es(e,t){let r=new Array(e.height).fill(le(" ".repeat(e.width),t.color,se.overlay)),i=Qr(),a=Math.max(...t.menuItems.map(p=>p.length)),y=t.menuItems.map((p,S)=>`${S===t.menuIndex?">":" "} ${p.padEnd(a)}`),T=t.optionsMessage?["",t.optionsMessage]:[],n=[...i,"",t.subtitle,"",...y,...T],h=Math.max(1,Math.floor((e.height-n.length)/2));for(let p=0;p<n.length;p+=1){let S=Nn(n[p]??"",e.width);if(p<i.length){r[h+p]=le(S,t.color,se.overlayLogo);continue}if(p===i.length+1){r[h+p]=le(S,t.color,se.overlaySubtitle);continue}let o=p-(i.length+3),c=o>=0&&o<t.menuItems.length&&o===t.menuIndex?se.overlayMenuSelected:se.overlay;r[h+p]=le(S,t.color,c)}return r.join(`
96
96
  `)}function qd(e,t,r,i){let a=Yd(e.runners),y=2,T=e.leftTree.map(h=>Xd(h,t,i));return[...er(T,r-y),a,{text:e.footerText,tone:"muted",fullBleed:!0}]}function Kd(e,t,r,i){let a=e.tabs.find(o=>o.active)?.label??"AGENT",y=lu(e.tabs),T=`${" ".repeat(y)}${tr("\u2500".repeat(a.length+1),i,se.panelMuted)}`,n=[`${tr(e.centerHeader.tabLabel,i,se.panelBg)} ${e.centerHeader.taskId}`,e.centerHeader.repo].join(" \xB7 "),h=e.tabs.find(o=>o.active)?.id??"agent",p=e.centerHeader.tabLabel==="BROWSER"||!Yi(h)?e.centerTranscript.map(o=>({...o})):zd(e),S=[{text:Qd(e.tabs,i)},{text:T,tone:"muted"},{text:n},Be(),...p];return er(S,r)}function zd(e){if(e.terminal.error)return[{text:"terminal \u25B8 PTY unavailable"},Be(),{text:e.terminal.error},Be(),{text:"Fix the native dependency setup, then re-enter terminal mode."}];let t=e.tabs.find(i=>i.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(i=>({text:Wn(i.segments),segments:i.segments,fullBleed:!0}))}function Vd(e,t,r,i){let a=e.rightInspection?Gd(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):er([{text:Bn("CONTEXT",e.focusedRegion==="tasks",i,se.panelBg)},Be(),...e.rightContext.map(y=>Jd(y,i)),...e.actionMessage?[Be(),{text:e.actionMessage}]:[]],r);return er(a,r)}function Gd(e,t){let r=e.slice(0,2),i=e.slice(2),a=Math.max(0,t-r.length),y=i.findIndex(n=>n.focused||n.selected),T=y===-1?0:uu(y-Math.floor(a/2),0,Math.max(0,i.length-a));return[...r.map(n=>xn(n)),...i.slice(T,T+a).map(n=>xn(n))]}function xn(e){let t=e.focused?"\u25B8 ":e.selected?"\u2022 ":" ",r=e.focused||e.selected?"selected":e.muted?"muted":"default",i=`${t}${e.text}`;if(e.segments)return{text:i,segments:[{text:t},...e.segments],tone:r};if(e.accentPrefix&&!e.muted){let a=e.text.indexOf(" "),y=a===-1?e.text:e.text.slice(0,a),T=a===-1?"":e.text.slice(a);return{text:i,segments:[{text:t},{text:y,style:{fg:"7aa2f7"}},{text:T}],tone:r}}return e.color?{text:i,segments:[{text:t},{text:e.text,style:{fg:e.color}}],tone:r}:{text:i,tone:r}}function Xd(e,t,r){let i=" ".repeat(e.indent??0),a=e.accentDot?" \u25CF":"",y=e.status?` ${e.status}`:"",T=e.accentDot?` ${jn("\u25CF",r,e.selected?se.panelSelected:se.panelBg)}`:"",n=t-ze(y)-ze(a),h=e.focused&&!e.selected?Bn(e.text,!0,r,se.panelBg):e.text,S=`${nt(`${i}${h}`,Math.max(0,n))}${y}${T}`;return e.selected?{text:S,tone:"selected"}:e.muted?{text:S,tone:"muted"}:{text:S}}function Yd(e){let t=e.map(i=>{let a=i.health>=1,y=parseInt(i.count,10),T=y>1?` (${y})`:"";return{text:`${a?"\u25CF":"\u25CB"} ${i.name}${T}`,active:a}}),r=[];for(let i=0;i<t.length;i++){let a=t[i];i>0&&r.push({text:" "}),a.active?r.push({text:a.text,style:{fg:se.success.fg}}):r.push({text:a.text,style:{fg:se.panelMuted.fg}})}return{text:t.map(i=>i.text).join(" "),segments:r,tone:"muted"}}function Qd(e,t){return e.map(r=>r.active?tr(r.label,t,se.panelBg):Un(r.label,t,se.panelBg)).join(" ")}function Jd(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Un(e.value,t,se.panelBg):e.value}`}}function Bn(e,t,r,i){return t?tr(e,r,i):e}function Yt(e,t,r,i){let a=Zd(i,e.tone??"default"),y=eu(e,r,a);if(i==="left"){if(e.fullBleed)return le(nt(y,t),r,a);let n=t-Qt-Jt;if(e.rightAlign){let p=ze(y),S=Math.max(0,n-p),o=`${" ".repeat(Qt)}${" ".repeat(S)}${y}${" ".repeat(Jt)}`;return le(o,r,a)}let h=`${" ".repeat(Qt)}${nt(y,n)}${" ".repeat(Jt)}`;return le(h,r,a)}return i==="center"&&e.fullBleed?tu(e,t,r,a):le(nt(` ${y}`,t),r,a)}function Zd(e,t){return t==="selected"||t==="focused"?se.panelSelected:t==="muted"?se.panelMuted:se.panelBg}function er(e,t){let r=e.slice(0,t);for(;r.length<t;)r.push(Be());return r}function Be(){return{text:""}}function eu(e,t,r){return e.segments?e.segments.map(i=>Fn(i,t,r)).join(""):e.text}function tu(e,t,r,i){let a=" ".repeat(Zt),y=Math.max(0,t-Zt*2);if(!e.segments)return le(`${a}${nt(e.text,y)}${a}`,r,i);let T=iu(e.segments,y),n=`${a}${T.map(h=>Fn(h,r,i)).join("")}${a}`;return le(n,r,i)}function Fn(e,t,r){let i=e.href?`${$n(e.href)}${e.text}${An}`:ru(e.text);return!t||!e.style?i:`${Tt(au(e.style,r))}${cu(e.style)}${i}${Jr}${Tt(r)}`}function ru(e){return e.replace(jd,t=>{let[r,i]=su(t);return`${$n(r)}${r}${An}${i}`})}function su(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function $n(e){return`\x1B]8;;${e}\x1B\\`}function iu(e,t){let r=nu(e,t);return ou(r,t)}function nu(e,t){let r=[],i=t;for(let a of e){if(i<=0)break;let y=ze(a.text);if(y<=i){r.push(a),i-=y;continue}r.push({...a,text:a.text.slice(0,i)}),i=0}return r}function ou(e,t){let r=ze(Wn(e));if(r>=t)return e;let i=e.at(-1)?.style;return i?.bg?[...e,{text:" ".repeat(t-r),style:i}]:[...e,{text:" ".repeat(t-r)}]}function au(e,t){let r=e.inverse?e.bg??t.bg:e.fg,i=e.inverse?e.fg??t.fg:e.bg,a={},y=r??t.fg,T=i??t.bg;return y&&(a.fg=y),T&&(a.bg=T),a}function cu(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 lu(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function Nn(e,t){let r=Math.max(0,t-ze(e)),i=Math.floor(r/2),a=r-i;return`${" ".repeat(i)}${e}${" ".repeat(a)}`}function nt(e,t){let r=ze(e);return r>=t?du(e,t):e+" ".repeat(t-r)}function du(e,t){return ze(e)<=t?e:Hn(e).slice(0,Math.max(0,t-1))+"\u2026"}function ze(e){return Hn(e).length}function uu(e,t,r){return Math.min(Math.max(e,t),r)}function Hn(e){return e.replace(Wd,"").replace(Nd,"")}function Wn(e){return e.map(t=>t.text).join("")}function le(e,t,r){if(!t)return e;let i=Tt(r),a=e.replace(Hd,`${Jr}${i}`);return`${i}${a}${Jr}`}function Tt(e){let t=[];return e.fg&&t.push(`38;2;${En(e.fg).join(";")}`),e.bg&&t.push(`48;2;${En(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function En(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function jn(e,t,r){return ts(e,t,se.success.fg,r)}function tr(e,t,r){return ts(e,t,se.accent.fg,r)}function Un(e,t,r){return ts(e,t,se.mutedfg.fg,r)}function ts(e,t,r,i){if(!t)return e;let a=i.bg?{fg:r,bg:i.bg}:{fg:r};return`${Tt(a)}${e}${Tt(i)}`}var rs=["Runners","Help"];function ss(e,t){return de.map(r=>{let i=pe(r),a=e.runners?.[r]?.enabled!==!1,y=e.runners?.[r]?.path?.trim(),T=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:y&&y.length>0?y:`default (${i.executable})`;return`${i.displayName} ${a?"enabled":"disabled"} ${T}`})}function Kn(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 zn(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(rs.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:is(t)?e===0?{kind:"runners"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function Vn(e,t,r,i){if(e.pathEdit)return hu({...e,pathEdit:e.pathEdit},t,r);let a=ss(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(a-1,e.menuIndex+1),message:null}};if(r==="ESCAPE")return{kind:"back",state:e};if(r==="e"){let n=de[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:n,value:t.runners?.[n]?.path??""}}}}if(!is(r))return{kind:"noop",state:e};let y=de[e.menuIndex]??"codex",T=t.runners?.[y]?.enabled!==!1;return T&&i.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save",config:fu(t,y,!T),state:{...e,message:`${pe(y).displayName} ${T?"disabled":"enabled"}.`}}}function hu(e,t,r){if(r==="ESCAPE")return{kind:"render",state:qn({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(is(r)){let i=e.pathEdit.runner,a=e.pathEdit.value.trim();return{kind:"save",config:pu(t,i,a.length>0?a:null),state:qn({...e,message:a.length>0?`${pe(i).displayName} executable saved.`:`${pe(i).displayName} executable reset to default.`})}}return gu(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function fu(e,t,r){return{...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}}}function pu(e,t,r){let i={...e.runners?.[t]??{},...r?{path:r}:{}};return r||delete i.path,{...e,runners:{...e.runners??{},[t]:i}}}function qn(e){let t={...e};return delete t.pathEdit,t}function is(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
97
- `}function gu(e){return e.length===1&&e>=" "&&e!=="\x7F"}var bu=mu(import.meta.url),yu=bu("terminal-kit"),Su=yu.terminal;async function Yn(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=$e(t);await dt(t);let i=await _e(r),a=ot(i),y=e.uiStateFile?await Pe({uiStateFile:e.uiStateFile}):null,T=Promise.resolve(),n=Promise.resolve(),h=await Ct(t,void 0,a),p=Ut(Ki(y,i),h);h=await Ct(t,p,a);let S=()=>{},o={workspaceRoot:t,onUpdate:()=>S(),resolveSessionSpec:(g,_)=>Ru(h,_,t)},w=e.ptyRuntime??await Sn({...o,paths:r}),c=g=>{if(!e.uiStateFile)return;y=zi(y,g);let _=y;T=T.then(()=>ve({uiStateFile:e.uiStateFile},_),()=>ve({uiStateFile:e.uiStateFile},_)),T.catch(()=>{})};return new Promise(g=>{let _=e.terminal??Su,s={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Ut(p,h)},f=!1,d=!1,l=null,u=0,m=0,v=null,I=null,E=null,N=null,O=!1,A=!0,D=null,C=()=>{},j=w;S=()=>{s.mode==="main"&&(s={mode:"main",shell:z(s.shell)},E||(E=setTimeout(()=>{E=null,s.mode==="main"&&C()},50)))};function z($){return vt($,j.getViewState($.selectedPtyTabId))}function W($){return z(ku($,h))}function G($){return h.tasks.find(M=>M.id===$.selectedTaskId)??null}async function q(){await j.hydrateSessions?.(h.tasks.flatMap($=>$.ptyTabs.map(M=>M.id)))}function b(){q().catch(()=>{}).then(()=>{s.mode==="main"&&(s={mode:"main",shell:z(s.shell)},C())})}function P($){let M=n.then($,$);return n=M.then(()=>{},()=>{}),M}function k($){let M=G($),L=h.inspection,H=L&&L.taskId===M?.id?L:null,V=Tu(H?.fileRows??[],$.collapsedFileTreePaths);return{leftItemIds:Cu(h),centerTabIds:Ji(M,$),ptyTabIds:M?.ptyTabs.map(re=>re.id)??[],filePathIds:H?.filePaths??[],fileTreeRowIds:V.map(re=>re.path),fileTreeFileIds:V.filter(re=>re.kind==="file").map(re=>re.path),fileTreeDirectoryIds:V.filter(re=>re.kind==="directory").map(re=>re.path),diffPathIds:H?.diffPaths??[],diffPathRanges:Wr(H),fileLineCount:H?.selectedFile.lines.length??0,diffLineCount:an(H),pageRows:Math.max(5,ut(_.width,_.height).height-Ee.topRailHeight-8),enabledRunnerIds:a}}async function R($){await gs(r,$),i=$,a=ot(i),h={...h,enabledRunnerIds:a},s.mode==="main"?s={mode:"main",shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Ge(i)})}:s={...s,shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Ge(i)})}}async function F($){let M=$.selectedTaskId;M&&await P(async()=>{let L=await Se(r,M);!L.ptyTabs.some(H=>H.id===$.activeTab)||L.selectedPtyTabId===$.activeTab||await te(r,{...L,selectedPtyTabId:$.activeTab})})}async function B(){let $=(s.mode==="main",s.shell);h=await Ct(t,$,a),s.mode==="main"?s={mode:"main",shell:W(s.shell)}:s={...s,shell:W(s.shell)}}async function U($){h=await Ct(t,$,a),s.mode==="main"&&(s={mode:"main",shell:W($)}),c(s.shell),C()}async function K($){let M=await Ou($);s.mode==="main"&&(s={mode:"main",shell:W({...s.shell,workspaceBrowser:M,activeTab:s.shell.selectedPtyTabId??s.shell.activeTab,actionMessage:null})},C())}async function ee($){try{let M=W($),L=G(M),H=M.selectedPtyTabId;if(L&&M.focusedRegion==="tasks"){let be=L.ptyTabs.find(Ce=>Ce.kind==="agent")??null;be?H=be.id:(L=await Ae(L),await B(),H=L.selectedPtyTabId)}L&&!H&&(L=await Ae(L),await B(),H=L.selectedPtyTabId);let V=W({...M,activeTab:H??M.activeTab,selectedPtyTabId:H});if(!V.selectedTaskId||!H){s={mode:"main",shell:V},C();return}s={mode:"main",shell:vt({...V,inputMode:"terminal"},j.getViewState(H))},c(s.shell);let re=await j.ensureSession(V.selectedTaskId,H,ns(ut(_.width,_.height)));d=os(H),l=null,s={mode:"main",shell:vt({...V,inputMode:"terminal"},re)},c(s.shell)}catch(M){let L=M instanceof Error?M.message:"Failed to start PTY.";$.selectedTaskId&&$.selectedPtyTabId&&os($.selectedPtyTabId)&&(await x($.selectedTaskId,L).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:Gi(W($),L)},c(s.shell)}C()}async function x($,M){await P(async()=>{let L=await Se(r,$);await te(r,{...L,status:L.status==="running"?"draft":L.status,runnerSession:{...L.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:M})})}async function Q($,M,L){let H=W($);if(!H.selectedTaskId)throw new Error("Select a task before creating a tab.");let V=await P(async()=>{let re=await Se(r,H.selectedTaskId),be=M??Iu(re,H.activeTab,H.preferredPtyTabKind),Ce=Gn(re,be,L??void 0,i),ft={...re,ptyTabs:[...re.ptyTabs,Ce],selectedPtyTabId:Ce.id};return await te(r,ft),ft});return await B(),W({...H,activeTab:V.selectedPtyTabId??H.activeTab,selectedPtyTabId:V.selectedPtyTabId,preferredPtyTabKind:V.ptyTabs.at(-1)?.kind??H.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${V.ptyTabs.at(-1)?.title??"tab"}`})}async function Y($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:L,nextSelectedTab:H}=await P(async()=>{let V=await Se(r,M.selectedTaskId),re=V.ptyTabs.findIndex(or=>or.id===M.activeTab);if(re===-1)throw new Error("Only PTY tabs can be closed.");let be=V.ptyTabs[re],Ce=V.ptyTabs.filter(or=>or.id!==be.id),ft=Ce[Math.min(re,Ce.length-1)]??Ce[re-1]??null;return await te(r,{...V,ptyTabs:Ce,selectedPtyTabId:ft?.id??null}),{closedTab:be,nextSelectedTab:ft}});return j.disposeSession(L.id),await B(),W({...M,activeTab:H?.id??(M.openInspectionKind?"inspection":M.activeTab),selectedPtyTabId:H?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${L.title}`})}async function Z($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before creating or syncing a PR.");let L=await bt(r,M.selectedTaskId,{watch:!1});await B();let H=L.disposition==="created"?"Created PR":L.disposition==="discovered"?"Discovered PR":"Synced PR";return W({...M,focusedRegion:"inspector",inspectionMode:"review",actionMessage:`${H}: #${L.prNumber} ${L.url}`})}async function he($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before refreshing PR checks.");let{disposition:L,task:H}=await yr(r,M.selectedTaskId);await B();let V=L==="not_found"?`No PR found for ${H.branch}`:L==="discovered"?`Discovered PR: #${H.pullRequest.number} ${H.pullRequest.url??""}`:`Refreshed checks: ${H.pullRequest.requiredChecks.length} reported`;return W({...M,focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:V})}async function fe(){if(O||s.mode!=="main"||!s.shell.selectedTaskId)return;let $=s.shell.selectedTaskId,L=!!(h.tasks.find(H=>H.id===$)??null)?.pullRequest.number;O=!0;try{let{disposition:H,task:V}=await yr(r,$);if(s.mode!=="main"||s.shell.selectedTaskId!==$)return;h=await Ct(t,s.shell,a),s={mode:"main",shell:W({...s.shell,actionMessage:H==="discovered"&&!L?`Discovered PR: #${V.pullRequest.number} ${V.pullRequest.url??""}`:s.shell.actionMessage})},C()}catch{}finally{O=!1}}async function He($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before merging a PR.");let L=await yt(r,M.selectedTaskId,{preserveWorktree:!0});return await B(),W({...M,focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"merge",actionMessage:`Merged PR #${L.prNumber}; worktree preserved`})}async function Te($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before closing it.");let L=await Se(r,M.selectedTaskId),H=await Pi(r,M.selectedTaskId);for(let V of L.ptyTabs)j.disposeSession(V.id);return await B(),W({...M,selectedActionId:"close-task",actionMessage:H.cleanup.preservedWorktree?`Archived task ${H.id}; worktree preserved`:`Archived task ${H.id}`})}async function Ae($){let M=$.ptyTabs.find(V=>V.kind==="agent")??null;if(M){let V={...$,selectedPtyTabId:M.id};return await P(async()=>{let re=await Se(r,$.id),be=re.ptyTabs.find(Ce=>Ce.kind==="agent")??null;be&&await te(r,{...re,selectedPtyTabId:be.id})}),V}let L=Gn($,"agent",void 0,i),H={...$,ptyTabs:[...$.ptyTabs,L],selectedPtyTabId:L.id};return await P(async()=>{let V=await Se(r,$.id),re=V.ptyTabs.find(be=>be.kind==="agent")??null;if(re){await te(r,{...V,selectedPtyTabId:re.id});return}await te(r,{...V,ptyTabs:[...V.ptyTabs,L],selectedPtyTabId:L.id})}),H}C=()=>{Ve();let $=ut(_.width,_.height),M=s.mode==="main"?On($,on(W(s.shell),h),{centerOnly:s.shell.centerZoomed}):s.variant==="boot"?Dn($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="pause"?Ln($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="options"?Zr($,{menuIndex:s.menuIndex,optionsMenuItems:rs}):s.variant==="runners"?Zr($,{menuIndex:Rt(s).menuIndex,optionsMenuItems:ss(i,Rt(s)),optionsMessage:Kn(Rt(s)),optionsSubtitle:"Runners"}):Mn($);_.moveTo(1,1),A&&(_.eraseDisplayBelow(),A=!1),_.noFormat(M)};function Ve(){let $=s.mode==="main"&&s.shell.inputMode==="terminal"?"terminal":"control";$!==D&&(D=$,_.grabInput($==="terminal"?{mouse:"button"}:!0))}let Jn=()=>{process.stdout.off("resize",us),_.removeListener("key",cs),_.removeListener("unknown",ls),_.removeListener("mouse",ds),v&&(clearTimeout(v),v=null),I&&(clearTimeout(I),I=null),E&&(clearTimeout(E),E=null),N&&(clearInterval(N),N=null),j.disposeAll(),_.grabInput(!1),_.hideCursor(!1),_.fullscreen(!1)},ir=$=>{Jn(),g($)},Zn=async()=>{if(s.mode!=="main"||f)return;let $=s.shell,M=$.taskPromptInput?.trim()??"";if(!$.selectedRepoId){s={mode:"main",shell:W({...$,taskPromptError:"Select a repo first."})},C();return}if(M.length===0){s={mode:"main",shell:W({...$,taskPromptError:"Task prompt cannot be empty."})},C();return}f=!0,s={mode:"main",shell:W({...$,actionMessage:`Creating ${$.selectedRunner} task in ${$.selectedRepoId}...`})},C();let L=null;try{L=await xu(r,$.selectedRepoId,M,$.selectedRunner),await B();let H=W({...s.shell,selectedRepoId:L.repoId,selectedTaskId:L.id,selectedPtyTabId:L.selectedPtyTabId,selectedLeftItemId:`task:${L.id}`,activeTab:L.selectedPtyTabId??"agent",inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),V=await j.ensureSession(L.id,H.selectedPtyTabId??Qn(L,"agent"),ns(ut(_.width,_.height)));d=os(H.selectedPtyTabId),s={mode:"main",shell:vt(H,V)},c(s.shell)}catch(H){H instanceof rr&&(L=H.task);let V=H instanceof Error?H.message:"Failed to create task.";L&&(await te(r,{...L,status:"draft",runnerSession:{...L.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:V}).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:W({...s.shell,inputMode:"control",selectedTaskId:L?.id??s.shell.selectedTaskId,selectedPtyTabId:L?.selectedPtyTabId??s.shell.selectedPtyTabId,selectedLeftItemId:L?`task:${L.id}`:s.shell.selectedLeftItemId,activeTab:L?.selectedPtyTabId??s.shell.activeTab,taskPromptInput:L?null:"",taskPromptError:V,actionMessage:null})}}finally{f=!1,C()}},eo=$=>{if(s.mode!=="main")return;let M=s.shell;if(M.taskPromptInput!==null){if($==="ESCAPE"){s={mode:"main",shell:W({...M,taskPromptInput:null,taskPromptError:null,actionMessage:null})},C();return}if(Ke($)){Zn();return}if($==="BACKSPACE"){s={mode:"main",shell:W({...M,taskPromptInput:M.taskPromptInput.slice(0,-1),taskPromptError:null})},C();return}if($==="CTRL_R"){s={mode:"main",shell:W({...M,selectedRunner:Fr(M.selectedRunner,a),taskPromptError:null})},C();return}Xi($)&&(s={mode:"main",shell:W({...M,taskPromptInput:`${M.taskPromptInput}${$}`,taskPromptError:null})},C())}},to=$=>{if(s.mode!=="main")return;let M=s.shell.workspaceBrowser;if(M){if($==="ESCAPE"){s={mode:"main",shell:W({...s.shell,workspaceBrowser:null,actionMessage:null})},C();return}if($==="UP"||$==="k"){s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,selectedIndex:Math.max(0,M.selectedIndex-1),error:null}})},C();return}if($==="DOWN"||$==="j"){let L=Math.max(0,M.entries.length-1);s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,selectedIndex:Math.min(L,M.selectedIndex+1),error:null}})},C();return}if($==="LEFT"||$==="h"){K(as.dirname(M.cwd)).catch(L=>{let H=L instanceof Error?L.message:"Failed to open parent directory.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:H}})},C()});return}if($==="RIGHT"||$==="l"||Ke($)){let L=M.entries[M.selectedIndex]??null;if(!L)return;if(L.kind==="directory"||($==="RIGHT"||$==="l")&&L.kind==="repo"){K(L.path).catch(H=>{let V=H instanceof Error?H.message:"Failed to open directory.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:V}})},C()});return}$t(r,L.path).then(async H=>{await B(),s={mode:"main",shell:W({...s.shell,workspaceBrowser:null,selectedLeftItemId:`repo:${H.repo.id}`,selectedRepoId:H.repo.id,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${H.repo.name}`})},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to add workspace.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:V}})},C()})}}},cs=$=>{let M=typeof $=="string"?$:"";if(s.mode==="main"&&s.shell.taskPromptInput!==null){eo(M);return}if(s.mode==="main"&&s.shell.workspaceBrowser!==null){to(M);return}if(s.mode==="main"){let L=Vi(s.shell,M,k(s.shell));if(L.exit){ir(0);return}if(L.detachTerminal){j.detach(),s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(s.shell.inputMode==="terminal"){if(L.changed){s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(d&&Ke(M)){d=!1;return}d&&(d=!1),l=Au(M)?{key:M,at:Date.now()}:null;let H=Du(M,s.shell.terminal.scrolledBack??!1);if(H!==0){nr(H);return}j.writeKey(M);return}if(M==="CTRL_C"){ir(0);return}if(M==="?"&&s.shell.inputMode==="control"){s={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:s.shell},A=!0,C();return}if(L.pause){s={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:W(L.state)},A=!0,C();return}if(L.beginTaskPrompt){s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(L.openWorkspaceBrowser){K(t).catch(H=>{let V=H instanceof Error?H.message:"Failed to browse workspaces.";s={mode:"main",shell:W({...L.state,workspaceBrowser:{cwd:t,entries:[],selectedIndex:0,error:V}})},C()});return}if(L.createPtyTab){Q(L.state,L.createPtyTabKind,L.createPtyTabRunner).then(H=>{ee(H)}).catch(H=>{let V=H instanceof Error?H.message:"Failed to create tab.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.closePtyTab){Y(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to close tab.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.syncPullRequest){Z(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to create or sync PR.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.refreshPullRequestChecks){he(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to refresh PR checks.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.mergeTask){He(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to merge PR.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.closeTask){Te(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to close task.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.attachTerminal){ee(L.state);return}if(L.refreshInspection){U(L.state).catch(H=>{let V=H instanceof Error?H.message:"Failed to refresh inspection.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}L.changed&&(s={mode:"main",shell:W(L.state)},F(s.shell).catch(()=>{}),c(s.shell),C());return}if(s.variant==="help"){s.viaOptions&&s.parentVariant?s={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:s.shell,parentVariant:s.parentVariant}:s.parentVariant?s={mode:"overlay",variant:s.parentVariant,menuIndex:1,optionsMessage:null,shell:s.shell}:s={mode:"main",shell:W(s.shell)},A=!0,C();return}if(s.variant==="options"){ro(M);return}if(s.variant==="runners"){so(M);return}if(s.optionsMessage){(M==="ESCAPE"||Ke(M))&&(s={...s,optionsMessage:null},C());return}if(M==="UP"||M==="k"){s={...s,menuIndex:Math.max(0,s.menuIndex-1)},C();return}if(M==="DOWN"||M==="j"){s={...s,menuIndex:Math.min(2,s.menuIndex+1)},C();return}if(M==="ESCAPE"){s.variant==="pause"&&(s={mode:"main",shell:W(s.shell)},A=!0,C());return}if(Ke(M)){if(s.menuIndex===0){s={mode:"main",shell:W({...s.shell,inputMode:"control"})},A=!0,C(),b();return}if(s.menuIndex===1){let L=s.variant==="boot"||s.variant==="pause"?s.variant:void 0;s={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}ir(0)}};function ro($){if(s.mode!=="overlay"||s.variant!=="options")return;let M=zn(s.menuIndex,$);if(M.kind!=="noop"){if(M.kind==="render"){s={...s,menuIndex:M.menuIndex},C();return}if(M.kind==="back"){s.parentVariant&&(s={mode:"overlay",variant:s.parentVariant,menuIndex:1,optionsMessage:null,shell:s.shell},A=!0,C());return}if(M.kind==="help"){let L=s.parentVariant;s={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:s.shell,viaOptions:!0,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}if(M.kind==="runners"){let L=s.parentVariant;s={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C()}}}function so($){if(s.mode!=="overlay"||s.variant!=="runners")return;let M=Vn(Rt(s),i,$,a);if(M.kind!=="noop"){if(M.kind==="back"){let L=s.parentVariant;s={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}if(M.kind==="render"){s={...s,runnerOptions:M.state},C();return}R(M.config).then(()=>{s.mode!=="overlay"||s.variant!=="runners"||(s={...s,runnerOptions:M.state},C())}).catch(L=>{if(s.mode!=="overlay"||s.variant!=="runners")return;let H=L instanceof Error?L.message:"Failed to save runner option.";s={...s,runnerOptions:{...Rt(s),message:H}},C()})}}let ls=$=>{let M=Eu($);if(s.mode!=="main"||s.shell.inputMode!=="terminal"||M.length===0)return;if(M.includes("")){j.detach(),d=!1,l=null,s={mode:"main",shell:W({...s.shell,inputMode:"control",actionMessage:null})},c(s.shell),C();return}let L=Lu(M);if(L!==0){nr(L);return}if(d&&M!=="\r"&&M!==`
97
+ `}function gu(e){return e.length===1&&e>=" "&&e!=="\x7F"}var bu=mu(import.meta.url),yu=bu("terminal-kit"),Su=yu.terminal;async function Yn(e={}){if(!process.stdin.isTTY||!process.stdout.isTTY)throw new Error("Craig terminal shell requires a TTY.");let t=e.workspaceRoot??process.cwd(),r=$e(t);await dt(t);let i=await _e(r),a=ot(i),y=e.uiStateFile?await Pe({uiStateFile:e.uiStateFile}):null,T=Promise.resolve(),n=Promise.resolve(),h=await Ct(t,void 0,a),p=Ut(Ki(y,i),h);h=await Ct(t,p,a);let S=()=>{},o={workspaceRoot:t,onUpdate:()=>S(),resolveSessionSpec:(g,_)=>Ru(h,_,t)},w=e.ptyRuntime??await Sn({...o,paths:r}),c=g=>{if(!e.uiStateFile)return;y=zi(y,g);let _=y;T=T.then(()=>ve({uiStateFile:e.uiStateFile},_),()=>ve({uiStateFile:e.uiStateFile},_)),T.catch(()=>{})};return new Promise(g=>{let _=e.terminal??Su,s={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:Ut(p,h)},f=!1,d=!1,l=null,u=0,m=0,v=null,I=null,E=null,N=null,O=!1,A=!0,D=null,C=()=>{},j=w;S=()=>{s.mode==="main"&&(s={mode:"main",shell:z(s.shell)},E||(E=setTimeout(()=>{E=null,s.mode==="main"&&C()},50)))};function z($){return vt($,j.getViewState($.selectedPtyTabId))}function W($){return z(ku($,h))}function G($){return h.tasks.find(M=>M.id===$.selectedTaskId)??null}async function q(){await j.hydrateSessions?.(h.tasks.flatMap($=>$.ptyTabs.map(M=>M.id)))}function b(){q().catch(()=>{}).then(()=>{s.mode==="main"&&(s={mode:"main",shell:z(s.shell)},C())})}function P($){let M=n.then($,$);return n=M.then(()=>{},()=>{}),M}function k($){let M=G($),L=h.inspection,H=L&&L.taskId===M?.id?L:null,V=Tu(H?.fileRows??[],$.collapsedFileTreePaths);return{leftItemIds:Cu(h),centerTabIds:Ji(M,$),ptyTabIds:M?.ptyTabs.map(re=>re.id)??[],filePathIds:H?.filePaths??[],fileTreeRowIds:V.map(re=>re.path),fileTreeFileIds:V.filter(re=>re.kind==="file").map(re=>re.path),fileTreeDirectoryIds:V.filter(re=>re.kind==="directory").map(re=>re.path),diffPathIds:H?.diffPaths??[],diffPathRanges:Wr(H),fileLineCount:H?.selectedFile.lines.length??0,diffLineCount:an(H),pageRows:Math.max(5,ut(_.width,_.height).height-Ee.topRailHeight-8),enabledRunnerIds:a}}async function R($){await gs(r,$),i=$,a=ot(i),h={...h,enabledRunnerIds:a},s.mode==="main"?s={mode:"main",shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Ge(i)})}:s={...s,shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Ge(i)})}}async function F($){let M=$.selectedTaskId;M&&await P(async()=>{let L=await Se(r,M);!L.ptyTabs.some(H=>H.id===$.activeTab)||L.selectedPtyTabId===$.activeTab||await te(r,{...L,selectedPtyTabId:$.activeTab})})}async function B(){let $=(s.mode==="main",s.shell);h=await Ct(t,$,a),s.mode==="main"?s={mode:"main",shell:W(s.shell)}:s={...s,shell:W(s.shell)}}async function U($){h=await Ct(t,$,a),s.mode==="main"&&(s={mode:"main",shell:W($)}),c(s.shell),C()}async function K($){let M=await Ou($);s.mode==="main"&&(s={mode:"main",shell:W({...s.shell,workspaceBrowser:M,activeTab:s.shell.selectedPtyTabId??s.shell.activeTab,actionMessage:null})},C())}async function ee($){try{let M=W($),L=G(M),H=M.selectedPtyTabId;if(L&&M.focusedRegion==="tasks"){let be=L.ptyTabs.find(Ce=>Ce.kind==="agent")??null;be?H=be.id:(L=await Ae(L),await B(),H=L.selectedPtyTabId)}L&&!H&&(L=await Ae(L),await B(),H=L.selectedPtyTabId);let V=W({...M,activeTab:H??M.activeTab,selectedPtyTabId:H});if(!V.selectedTaskId||!H){s={mode:"main",shell:V},C();return}s={mode:"main",shell:vt({...V,inputMode:"terminal"},j.getViewState(H))},c(s.shell);let re=await j.ensureSession(V.selectedTaskId,H,ns(ut(_.width,_.height)));d=os(H),l=null,s={mode:"main",shell:vt({...V,inputMode:"terminal"},re)},c(s.shell)}catch(M){let L=M instanceof Error?M.message:"Failed to start PTY.";$.selectedTaskId&&$.selectedPtyTabId&&os($.selectedPtyTabId)&&(await x($.selectedTaskId,L).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:Gi(W($),L)},c(s.shell)}C()}async function x($,M){await P(async()=>{let L=await Se(r,$);await te(r,{...L,status:L.status==="running"?"draft":L.status,runnerSession:{...L.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:M})})}async function Q($,M,L){let H=W($);if(!H.selectedTaskId)throw new Error("Select a task before creating a tab.");let V=await P(async()=>{let re=await Se(r,H.selectedTaskId),be=M??Iu(re,H.activeTab,H.preferredPtyTabKind),Ce=Gn(re,be,L??void 0,i),ft={...re,ptyTabs:[...re.ptyTabs,Ce],selectedPtyTabId:Ce.id};return await te(r,ft),ft});return await B(),W({...H,activeTab:V.selectedPtyTabId??H.activeTab,selectedPtyTabId:V.selectedPtyTabId,preferredPtyTabKind:V.ptyTabs.at(-1)?.kind??H.preferredPtyTabKind,focusedRegion:"center",actionMessage:`Created tab: ${V.ptyTabs.at(-1)?.title??"tab"}`})}async function Y($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before closing a tab.");let{closedTab:L,nextSelectedTab:H}=await P(async()=>{let V=await Se(r,M.selectedTaskId),re=V.ptyTabs.findIndex(or=>or.id===M.activeTab);if(re===-1)throw new Error("Only PTY tabs can be closed.");let be=V.ptyTabs[re],Ce=V.ptyTabs.filter(or=>or.id!==be.id),ft=Ce[Math.min(re,Ce.length-1)]??Ce[re-1]??null;return await te(r,{...V,ptyTabs:Ce,selectedPtyTabId:ft?.id??null}),{closedTab:be,nextSelectedTab:ft}});return j.disposeSession(L.id),await B(),W({...M,activeTab:H?.id??(M.openInspectionKind?"inspection":M.activeTab),selectedPtyTabId:H?.id??null,focusedRegion:"center",actionMessage:`Closed tab: ${L.title}`})}async function Z($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before creating or syncing a PR.");let L=await bt(r,M.selectedTaskId,{watch:!1});await B();let H=L.disposition==="created"?"Created PR":L.disposition==="discovered"?"Discovered PR":"Synced PR";return W({...M,focusedRegion:"inspector",inspectionMode:"review",actionMessage:`${H}: #${L.prNumber} ${L.url}`})}async function he($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before refreshing PR checks.");let{disposition:L,task:H}=await yr(r,M.selectedTaskId);await B();let V=L==="not_found"?`No PR found for ${H.branch}`:L==="discovered"?`Discovered PR: #${H.pullRequest.number} ${H.pullRequest.url??""}`:`Refreshed checks: ${H.pullRequest.requiredChecks.length} reported`;return W({...M,focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"refresh-checks",actionMessage:V})}async function fe(){if(O||s.mode!=="main"||!s.shell.selectedTaskId)return;let $=s.shell.selectedTaskId,L=!!(h.tasks.find(H=>H.id===$)??null)?.pullRequest.number;O=!0;try{let{disposition:H,task:V}=await yr(r,$);if(s.mode!=="main"||s.shell.selectedTaskId!==$)return;h=await Ct(t,s.shell,a),s={mode:"main",shell:W({...s.shell,actionMessage:H==="discovered"&&!L?`Discovered PR: #${V.pullRequest.number} ${V.pullRequest.url??""}`:s.shell.actionMessage})},C()}catch{}finally{O=!1}}async function He($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before merging a PR.");let L=await yt(r,M.selectedTaskId,{preserveWorktree:!0});return await B(),W({...M,focusedRegion:"inspector",inspectionMode:"review",selectedActionId:"merge",actionMessage:`Merged PR #${L.prNumber}; worktree preserved`})}async function Te($){let M=W($);if(!M.selectedTaskId)throw new Error("Select a task before closing it.");let{taskBeforeClose:L,task:H}=await P(async()=>{let V=await Se(r,M.selectedTaskId),re=await Pi(r,M.selectedTaskId);return{taskBeforeClose:V,task:re}});for(let V of L.ptyTabs)j.disposeSession(V.id);return await B(),W({...M,selectedActionId:"close-task",actionMessage:H.cleanup.preservedWorktree?`Archived task ${H.id}; worktree preserved`:`Archived task ${H.id}`})}async function Ae($){let M=$.ptyTabs.find(V=>V.kind==="agent")??null;if(M){let V={...$,selectedPtyTabId:M.id};return await P(async()=>{let re=await Se(r,$.id),be=re.ptyTabs.find(Ce=>Ce.kind==="agent")??null;be&&await te(r,{...re,selectedPtyTabId:be.id})}),V}let L=Gn($,"agent",void 0,i),H={...$,ptyTabs:[...$.ptyTabs,L],selectedPtyTabId:L.id};return await P(async()=>{let V=await Se(r,$.id),re=V.ptyTabs.find(be=>be.kind==="agent")??null;if(re){await te(r,{...V,selectedPtyTabId:re.id});return}await te(r,{...V,ptyTabs:[...V.ptyTabs,L],selectedPtyTabId:L.id})}),H}C=()=>{Ve();let $=ut(_.width,_.height),M=s.mode==="main"?On($,on(W(s.shell),h),{centerOnly:s.shell.centerZoomed}):s.variant==="boot"?Dn($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="pause"?Ln($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="options"?Zr($,{menuIndex:s.menuIndex,optionsMenuItems:rs}):s.variant==="runners"?Zr($,{menuIndex:Rt(s).menuIndex,optionsMenuItems:ss(i,Rt(s)),optionsMessage:Kn(Rt(s)),optionsSubtitle:"Runners"}):Mn($);_.moveTo(1,1),A&&(_.eraseDisplayBelow(),A=!1),_.noFormat(M)};function Ve(){let $=s.mode==="main"&&s.shell.inputMode==="terminal"?"terminal":"control";$!==D&&(D=$,_.grabInput($==="terminal"?{mouse:"button"}:!0))}let Jn=()=>{process.stdout.off("resize",us),_.removeListener("key",cs),_.removeListener("unknown",ls),_.removeListener("mouse",ds),v&&(clearTimeout(v),v=null),I&&(clearTimeout(I),I=null),E&&(clearTimeout(E),E=null),N&&(clearInterval(N),N=null),j.disposeAll(),_.grabInput(!1),_.hideCursor(!1),_.fullscreen(!1)},ir=$=>{Jn(),g($)},Zn=async()=>{if(s.mode!=="main"||f)return;let $=s.shell,M=$.taskPromptInput?.trim()??"";if(!$.selectedRepoId){s={mode:"main",shell:W({...$,taskPromptError:"Select a repo first."})},C();return}if(M.length===0){s={mode:"main",shell:W({...$,taskPromptError:"Task prompt cannot be empty."})},C();return}f=!0,s={mode:"main",shell:W({...$,actionMessage:`Creating ${$.selectedRunner} task in ${$.selectedRepoId}...`})},C();let L=null;try{L=await xu(r,$.selectedRepoId,M,$.selectedRunner),await B();let H=W({...s.shell,selectedRepoId:L.repoId,selectedTaskId:L.id,selectedPtyTabId:L.selectedPtyTabId,selectedLeftItemId:`task:${L.id}`,activeTab:L.selectedPtyTabId??"agent",inputMode:"terminal",taskPromptInput:null,taskPromptError:null,actionMessage:null}),V=await j.ensureSession(L.id,H.selectedPtyTabId??Qn(L,"agent"),ns(ut(_.width,_.height)));d=os(H.selectedPtyTabId),s={mode:"main",shell:vt(H,V)},c(s.shell)}catch(H){H instanceof rr&&(L=H.task);let V=H instanceof Error?H.message:"Failed to create task.";L&&(await te(r,{...L,status:"draft",runnerSession:{...L.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:V}).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:W({...s.shell,inputMode:"control",selectedTaskId:L?.id??s.shell.selectedTaskId,selectedPtyTabId:L?.selectedPtyTabId??s.shell.selectedPtyTabId,selectedLeftItemId:L?`task:${L.id}`:s.shell.selectedLeftItemId,activeTab:L?.selectedPtyTabId??s.shell.activeTab,taskPromptInput:L?null:"",taskPromptError:V,actionMessage:null})}}finally{f=!1,C()}},eo=$=>{if(s.mode!=="main")return;let M=s.shell;if(M.taskPromptInput!==null){if($==="ESCAPE"){s={mode:"main",shell:W({...M,taskPromptInput:null,taskPromptError:null,actionMessage:null})},C();return}if(Ke($)){Zn();return}if($==="BACKSPACE"){s={mode:"main",shell:W({...M,taskPromptInput:M.taskPromptInput.slice(0,-1),taskPromptError:null})},C();return}if($==="CTRL_R"){s={mode:"main",shell:W({...M,selectedRunner:Fr(M.selectedRunner,a),taskPromptError:null})},C();return}Xi($)&&(s={mode:"main",shell:W({...M,taskPromptInput:`${M.taskPromptInput}${$}`,taskPromptError:null})},C())}},to=$=>{if(s.mode!=="main")return;let M=s.shell.workspaceBrowser;if(M){if($==="ESCAPE"){s={mode:"main",shell:W({...s.shell,workspaceBrowser:null,actionMessage:null})},C();return}if($==="UP"||$==="k"){s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,selectedIndex:Math.max(0,M.selectedIndex-1),error:null}})},C();return}if($==="DOWN"||$==="j"){let L=Math.max(0,M.entries.length-1);s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,selectedIndex:Math.min(L,M.selectedIndex+1),error:null}})},C();return}if($==="LEFT"||$==="h"){K(as.dirname(M.cwd)).catch(L=>{let H=L instanceof Error?L.message:"Failed to open parent directory.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:H}})},C()});return}if($==="RIGHT"||$==="l"||Ke($)){let L=M.entries[M.selectedIndex]??null;if(!L)return;if(L.kind==="directory"||($==="RIGHT"||$==="l")&&L.kind==="repo"){K(L.path).catch(H=>{let V=H instanceof Error?H.message:"Failed to open directory.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:V}})},C()});return}$t(r,L.path).then(async H=>{await B(),s={mode:"main",shell:W({...s.shell,workspaceBrowser:null,selectedLeftItemId:`repo:${H.repo.id}`,selectedRepoId:H.repo.id,selectedTaskId:null,selectedPtyTabId:null,actionMessage:`Registered workspace: ${H.repo.name}`})},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to add workspace.";s={mode:"main",shell:W({...s.shell,workspaceBrowser:{...M,error:V}})},C()})}}},cs=$=>{let M=typeof $=="string"?$:"";if(s.mode==="main"&&s.shell.taskPromptInput!==null){eo(M);return}if(s.mode==="main"&&s.shell.workspaceBrowser!==null){to(M);return}if(s.mode==="main"){let L=Vi(s.shell,M,k(s.shell));if(L.exit){ir(0);return}if(L.detachTerminal){j.detach(),s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(s.shell.inputMode==="terminal"){if(L.changed){s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(d&&Ke(M)){d=!1;return}d&&(d=!1),l=Au(M)?{key:M,at:Date.now()}:null;let H=Du(M,s.shell.terminal.scrolledBack??!1);if(H!==0){nr(H);return}j.writeKey(M);return}if(M==="CTRL_C"){ir(0);return}if(M==="?"&&s.shell.inputMode==="control"){s={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:s.shell},A=!0,C();return}if(L.pause){s={mode:"overlay",variant:"pause",menuIndex:0,optionsMessage:null,shell:W(L.state)},A=!0,C();return}if(L.beginTaskPrompt){s={mode:"main",shell:W(L.state)},c(s.shell),C();return}if(L.openWorkspaceBrowser){K(t).catch(H=>{let V=H instanceof Error?H.message:"Failed to browse workspaces.";s={mode:"main",shell:W({...L.state,workspaceBrowser:{cwd:t,entries:[],selectedIndex:0,error:V}})},C()});return}if(L.createPtyTab){Q(L.state,L.createPtyTabKind,L.createPtyTabRunner).then(H=>{ee(H)}).catch(H=>{let V=H instanceof Error?H.message:"Failed to create tab.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.closePtyTab){Y(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to close tab.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.syncPullRequest){Z(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to create or sync PR.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.refreshPullRequestChecks){he(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to refresh PR checks.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.mergeTask){He(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to merge PR.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.closeTask){Te(L.state).then(H=>{s={mode:"main",shell:H},c(s.shell),C()}).catch(H=>{let V=H instanceof Error?H.message:"Failed to close task.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}if(L.attachTerminal){ee(L.state);return}if(L.refreshInspection){U(L.state).catch(H=>{let V=H instanceof Error?H.message:"Failed to refresh inspection.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}L.changed&&(s={mode:"main",shell:W(L.state)},F(s.shell).catch(()=>{}),c(s.shell),C());return}if(s.variant==="help"){s.viaOptions&&s.parentVariant?s={mode:"overlay",variant:"options",menuIndex:1,optionsMessage:null,shell:s.shell,parentVariant:s.parentVariant}:s.parentVariant?s={mode:"overlay",variant:s.parentVariant,menuIndex:1,optionsMessage:null,shell:s.shell}:s={mode:"main",shell:W(s.shell)},A=!0,C();return}if(s.variant==="options"){ro(M);return}if(s.variant==="runners"){so(M);return}if(s.optionsMessage){(M==="ESCAPE"||Ke(M))&&(s={...s,optionsMessage:null},C());return}if(M==="UP"||M==="k"){s={...s,menuIndex:Math.max(0,s.menuIndex-1)},C();return}if(M==="DOWN"||M==="j"){s={...s,menuIndex:Math.min(2,s.menuIndex+1)},C();return}if(M==="ESCAPE"){s.variant==="pause"&&(s={mode:"main",shell:W(s.shell)},A=!0,C());return}if(Ke(M)){if(s.menuIndex===0){s={mode:"main",shell:W({...s.shell,inputMode:"control"})},A=!0,C(),b();return}if(s.menuIndex===1){let L=s.variant==="boot"||s.variant==="pause"?s.variant:void 0;s={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}ir(0)}};function ro($){if(s.mode!=="overlay"||s.variant!=="options")return;let M=zn(s.menuIndex,$);if(M.kind!=="noop"){if(M.kind==="render"){s={...s,menuIndex:M.menuIndex},C();return}if(M.kind==="back"){s.parentVariant&&(s={mode:"overlay",variant:s.parentVariant,menuIndex:1,optionsMessage:null,shell:s.shell},A=!0,C());return}if(M.kind==="help"){let L=s.parentVariant;s={mode:"overlay",variant:"help",menuIndex:0,optionsMessage:null,shell:s.shell,viaOptions:!0,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}if(M.kind==="runners"){let L=s.parentVariant;s={mode:"overlay",variant:"runners",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C()}}}function so($){if(s.mode!=="overlay"||s.variant!=="runners")return;let M=Vn(Rt(s),i,$,a);if(M.kind!=="noop"){if(M.kind==="back"){let L=s.parentVariant;s={mode:"overlay",variant:"options",menuIndex:0,optionsMessage:null,shell:s.shell,...L!==void 0?{parentVariant:L}:{}},A=!0,C();return}if(M.kind==="render"){s={...s,runnerOptions:M.state},C();return}R(M.config).then(()=>{s.mode!=="overlay"||s.variant!=="runners"||(s={...s,runnerOptions:M.state},C())}).catch(L=>{if(s.mode!=="overlay"||s.variant!=="runners")return;let H=L instanceof Error?L.message:"Failed to save runner option.";s={...s,runnerOptions:{...Rt(s),message:H}},C()})}}let ls=$=>{let M=Eu($);if(s.mode!=="main"||s.shell.inputMode!=="terminal"||M.length===0)return;if(M.includes("")){j.detach(),d=!1,l=null,s={mode:"main",shell:W({...s.shell,inputMode:"control",actionMessage:null})},c(s.shell),C();return}let L=Lu(M);if(L!==0){nr(L);return}if(d&&M!=="\r"&&M!==`
98
98
  `&&M!==`\r
99
99
  `&&(d=!1),Mu(d,l,M)){d=!1;return}j.write(M)},ds=$=>{if(s.mode!=="main")return;if(s.shell.inputMode==="control"){no(Xn($));return}let M=Xn($);M!==0&&nr(M)};function nr($){u+=$,!v&&(v=setTimeout(()=>{v=null;let M=u;u=0,M!==0&&(io(M),C())},16))}function io($){j.scrollViewport($),s={mode:"main",shell:z(s.shell)}}function no($){$!==0&&(m+=$,!I&&(I=setTimeout(()=>{I=null;let M=m;if(m=0,M===0||s.mode!=="main"||s.shell.inputMode!=="control")return;let L=qe(s.shell,M,k(s.shell));if(L.changed){if(L.refreshInspection){U(L.state).catch(H=>{let V=H instanceof Error?H.message:"Failed to refresh inspection.";s={mode:"main",shell:W({...L.state,actionMessage:V})},C()});return}s={mode:"main",shell:W(L.state)},c(s.shell),C()}},16)))}let us=()=>{A=!0,s.mode==="main"&&s.shell.inputMode==="terminal"&&(j.resize(ns(ut(_.width,_.height))),s={mode:"main",shell:z(s.shell)}),C()};process.stdout.on("resize",us),_.grabInput(!0),D="control",_.hideCursor(!0),_.fullscreen(!0),_.on("key",cs),_.on("unknown",ls),_.on("mouse",ds),N=setInterval(()=>{fe()},(i.github?.watchIntervalSeconds??10)*1e3),C()})}async function Ct(e,t,r){let i=$e(e),[a,y]=await Promise.all([gt(i),et(i)]),T=vu(y.tasks,t),n=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},h=T?await vi(T,n):null;return{workspaceRoot:e,repos:a,tasks:y.tasks,inspection:h,...r?{enabledRunnerIds:r}:{}}}function vu(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function ku(e,t){return Ut(e,t)}function Tu(e,t){let r=new Set(t);return e.filter(i=>{let a=i.path.split("/");for(let y=1;y<a.length;y+=1)if(r.has(a.slice(0,y).join("/")))return!1;return!0})}function Cu(e){let t=[];for(let r of e.repos){t.push(`repo:${r.id}`);for(let i of e.tasks.filter(a=>a.repoId===r.id))t.push(`task:${i.id}`);t.push(`new-task:${r.id}`)}return t.push("new-workspace"),t}function Ru(e,t,r){let i=e.tasks.find(y=>y.ptyTabs.some(T=>T.id===t))??null,a=i?.ptyTabs.find(y=>y.id===t)??null;return{cwd:i?.worktreePath??r,command:a?.kind==="agent"?Pu(a):[]}}function Pu(e){return e.command.length>0?e.command:["codex"]}function Rt(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Iu(e,t,r){return e.ptyTabs.find(i=>i.id===t)?.kind??r}function Gn(e,t,r,i={}){let a=r??e.runner,y=pe(a),T=t==="agent"?y.defaultAgentTitle:"Terminal",n=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,h=new Set(e.ptyTabs.map(c=>c.id)),p=1,S=n;for(;h.has(S);)p+=1,S=`${n}-${p}`;let o=new Date().toISOString(),w=r&&r!==e.runner?r:void 0;return{id:S,kind:t,...w?{runner:w}:{},title:p===1?T:`${T} ${p}`,command:t==="agent"?ge(a,void 0,i):[],createdAt:o,updatedAt:o}}async function xu(e,t,r,i){let a=await _e(e);Pt(i,a);let y=await Bt(e,t,r,{runner:i,config:a});try{let h=Qe();await J(Je(ar(i,a).executable,{cwd:y.repoRoot,env:h}),["--help"],{cwd:y.repoRoot,env:h})}catch(h){let p=h instanceof Error?h.message:"Failed to start runner.",S={...y.task,status:"draft",runnerSession:{...y.task.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:p};throw await te(e,S),new rr(p,S)}let T=Qn(y.task,"agent"),n={...y.task,status:"running",selectedPtyTabId:T,runnerSession:{...y.task.runnerSession,startedAt:new Date().toISOString(),lastKnownState:"running"}};return await te(e,n),await ve({uiStateFile:e.uiStateFile},{...await Pe({uiStateFile:e.uiStateFile})??Le(),version:1,selectedRepoId:n.repoId,selectedWorkspaceId:n.workspaceId,selectedTaskId:n.id,selectedPtyTabId:n.selectedPtyTabId,inputMode:"control",focusedRegion:"center",activeTab:n.selectedPtyTabId??"agent",selectedActionId:"commit",updatedAt:new Date().toISOString()}),n}var rr=class extends Error{task;constructor(t,r){super(t),this.name="InteractiveTaskStartupError",this.task=r}};function Qn(e,t){let r=e.ptyTabs.find(i=>i.kind===t);if(!r)throw new Error(`Task ${e.id} is missing its ${t} PTY tab.`);return r.id}function ns(e){return{columns:Math.max(20,e.width-Ee.leftWidth-Ee.rightWidth-Ee.dividerWidth-Zt*2),rows:Math.max(5,e.height-Ee.topRailHeight-4)}}function Eu(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Au(e){return e.length===1||Ke(e)||e==="BACKSPACE"||e==="TAB"}function os(e){return typeof e=="string"&&/:agent(?:-\d+)?$/.test(e)}function Du(e,t){return e==="UP"&&t?-3:e==="DOWN"&&t?3:e==="PAGE_UP"?-5:e==="PAGE_DOWN"?5:e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Xn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Lu(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 Mu(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
100
100
  `||r===`\r
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "craig-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Craig local control plane CLI",
5
+ "license": "UNLICENSED",
5
6
  "type": "module",
6
7
  "bin": {
7
8
  "craig": "dist/cli.js"