craig-cli 0.3.0 → 0.3.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.
- package/dist/cli.js +21 -21
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ ${P.join(`
|
|
|
25
25
|
... and ${C.length-A} more leaking disposables
|
|
26
26
|
|
|
27
27
|
`),{leaks:C,details:W}}}function s(O){return g?.trackDisposable(O),O}function f(O){g?.markAsDisposed(O)}function d(O,A){g?.setParent(O,A)}function c(O){return typeof O=="object"&&O!==null&&typeof O.dispose=="function"&&O.dispose.length===0}function u(O){if(l.Iterable.is(O)){let A=[];for(let D of O)if(D)try{D.dispose()}catch(C){A.push(C)}if(A.length===1)throw A[0];if(A.length>1)throw new AggregateError(A,"Encountered errors while disposing of store");return Array.isArray(O)?[]:O}if(O)return O.dispose(),O}function m(O){let A=s({dispose:(0,w.createSingleCallFunction)((()=>{f(A),O()}))});return A}n.DisposableTracker=_;class v{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,s(this)}dispose(){this._isDisposed||(f(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(this._toDispose.size!==0)try{u(this._toDispose)}finally{this._toDispose.clear()}}add(A){if(!A)return A;if(A===this)throw new Error("Cannot register a disposable on itself!");return d(A,this),this._isDisposed?v.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(A),A}delete(A){if(A){if(A===this)throw new Error("Cannot dispose a disposable on itself!");this._toDispose.delete(A),A.dispose()}}deleteAndLeak(A){A&&this._toDispose.has(A)&&(this._toDispose.delete(A),d(A,null))}}n.DisposableStore=v;class I{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new v,s(this),d(this._store,this)}dispose(){f(this),this._store.dispose()}_register(A){if(A===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(A)}}n.Disposable=I;class E{constructor(){this._isDisposed=!1,s(this)}get value(){return this._isDisposed?void 0:this._value}set value(A){this._isDisposed||A===this._value||(this._value?.dispose(),A&&d(A,this),this._value=A)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,f(this),this._value?.dispose(),this._value=void 0}clearAndLeak(){let A=this._value;return this._value=void 0,A&&d(A,null),A}}n.MutableDisposable=E,n.MandatoryMutableDisposable=class{constructor(O){this._disposable=new E,this._isDisposed=!1,this._disposable.value=O}get value(){return this._disposable.value}set value(O){this._isDisposed||O===this._disposable.value||(this._disposable.value=O)}dispose(){this._isDisposed=!0,this._disposable.dispose()}},n.RefCountedDisposable=class{constructor(O){this._disposable=O,this._counter=1}acquire(){return this._counter++,this}release(){return--this._counter==0&&this._disposable.dispose(),this}},n.SafeDisposable=class{constructor(){this.dispose=()=>{},this.unset=()=>{},this.isset=()=>!1,s(this)}set(O){let A=O;return this.unset=()=>A=void 0,this.isset=()=>A!==void 0,this.dispose=()=>{A&&(A(),A=void 0,f(this))},this}},n.ReferenceCollection=class{constructor(){this.references=new Map}acquire(O,...A){let D=this.references.get(O);D||(D={counter:0,object:this.createReferencedObject(O,...A)},this.references.set(O,D));let{object:C}=D,j=(0,w.createSingleCallFunction)((()=>{--D.counter==0&&(this.destroyReferencedObject(O,D.object),this.references.delete(O))}));return D.counter++,{object:C,dispose:j}}},n.AsyncReferenceCollection=class{constructor(O){this.referenceCollection=O}async acquire(O,...A){let D=this.referenceCollection.acquire(O,...A);try{return{object:await D.object,dispose:()=>D.dispose()}}catch(C){throw D.dispose(),C}}},n.ImmortalReference=class{constructor(O){this.object=O}dispose(){}};class N{constructor(){this._store=new Map,this._isDisposed=!1,s(this)}dispose(){f(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{u(this._store.values())}finally{this._store.clear()}}has(A){return this._store.has(A)}get size(){return this._store.size}get(A){return this._store.get(A)}set(A,D,C=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),C||this._store.get(A)?.dispose(),this._store.set(A,D)}deleteAndDispose(A){this._store.get(A)?.dispose(),this._store.delete(A)}deleteAndLeak(A){let D=this._store.get(A);return this._store.delete(A),D}keys(){return this._store.keys()}values(){return this._store.values()}[Symbol.iterator](){return this._store[Symbol.iterator]()}}n.DisposableMap=N},6317:(T,n)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.LinkedList=void 0;class h{static{this.Undefined=new h(void 0)}constructor(o){this.element=o,this.next=h.Undefined,this.prev=h.Undefined}}class p{constructor(){this._first=h.Undefined,this._last=h.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===h.Undefined}clear(){let o=this._first;for(;o!==h.Undefined;){let w=o.next;o.prev=h.Undefined,o.next=h.Undefined,o=w}this._first=h.Undefined,this._last=h.Undefined,this._size=0}unshift(o){return this._insert(o,!1)}push(o){return this._insert(o,!0)}_insert(o,w){let l=new h(o);if(this._first===h.Undefined)this._first=l,this._last=l;else if(w){let _=this._last;this._last=l,l.prev=_,_.next=l}else{let _=this._first;this._first=l,l.next=_,_.prev=l}this._size+=1;let g=!1;return()=>{g||(g=!0,this._remove(l))}}shift(){if(this._first!==h.Undefined){let o=this._first.element;return this._remove(this._first),o}}pop(){if(this._last!==h.Undefined){let o=this._last.element;return this._remove(this._last),o}}_remove(o){if(o.prev!==h.Undefined&&o.next!==h.Undefined){let w=o.prev;w.next=o.next,o.next.prev=w}else o.prev===h.Undefined&&o.next===h.Undefined?(this._first=h.Undefined,this._last=h.Undefined):o.next===h.Undefined?(this._last=this._last.prev,this._last.next=h.Undefined):o.prev===h.Undefined&&(this._first=this._first.next,this._first.prev=h.Undefined);this._size-=1}*[Symbol.iterator](){let o=this._first;for(;o!==h.Undefined;)yield o.element,o=o.next}}n.LinkedList=p},2608:(T,n)=>{var h;Object.defineProperty(n,"__esModule",{value:!0}),n.SetMap=n.BidirectionalMap=n.CounterSet=n.Touch=void 0,n.getOrSet=function(p,y,o){let w=p.get(y);return w===void 0&&(w=o,p.set(y,w)),w},n.mapToString=function(p){let y=[];return p.forEach(((o,w)=>{y.push(`${w} => ${o}`)})),`Map(${p.size}) {${y.join(", ")}}`},n.setToString=function(p){let y=[];return p.forEach((o=>{y.push(o)})),`Set(${p.size}) {${y.join(", ")}}`},n.mapsStrictEqualIgnoreOrder=function(p,y){if(p===y)return!0;if(p.size!==y.size)return!1;for(let[o,w]of p)if(!y.has(o)||y.get(o)!==w)return!1;for(let[o]of y)if(!p.has(o))return!1;return!0},(function(p){p[p.None=0]="None",p[p.AsOld=1]="AsOld",p[p.AsNew=2]="AsNew"})(h||(n.Touch=h={})),n.CounterSet=class{constructor(){this.map=new Map}add(p){return this.map.set(p,(this.map.get(p)||0)+1),this}delete(p){let y=this.map.get(p)||0;return y!==0&&(y--,y===0?this.map.delete(p):this.map.set(p,y),!0)}has(p){return this.map.has(p)}},n.BidirectionalMap=class{constructor(p){if(this._m1=new Map,this._m2=new Map,p)for(let[y,o]of p)this.set(y,o)}clear(){this._m1.clear(),this._m2.clear()}set(p,y){this._m1.set(p,y),this._m2.set(y,p)}get(p){return this._m1.get(p)}getKey(p){return this._m2.get(p)}delete(p){let y=this._m1.get(p);return y!==void 0&&(this._m1.delete(p),this._m2.delete(y),!0)}forEach(p,y){this._m1.forEach(((o,w)=>{p.call(y,o,w,this)}))}keys(){return this._m1.keys()}values(){return this._m1.values()}},n.SetMap=class{constructor(){this.map=new Map}add(p,y){let o=this.map.get(p);o||(o=new Set,this.map.set(p,o)),o.add(y)}delete(p,y){let o=this.map.get(p);o&&(o.delete(y),o.size===0&&this.map.delete(p))}forEach(p,y){let o=this.map.get(p);o&&o.forEach(y)}get(p){return this.map.get(p)||new Set}}},9725:(T,n)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.StopWatch=void 0;let h=globalThis.performance&&typeof globalThis.performance.now=="function";class p{static create(o){return new p(o)}constructor(o){this._now=h&&o===!1?Date.now:globalThis.performance.now.bind(globalThis.performance),this._startTime=this._now(),this._stopTime=-1}stop(){this._stopTime=this._now()}reset(){this._startTime=this._now(),this._stopTime=-1}elapsed(){return this._stopTime!==-1?this._stopTime-this._startTime:this._now()-this._startTime}}n.StopWatch=p}},t={};function r(T){var n=t[T];if(n!==void 0)return n.exports;var h=t[T]={exports:{}};return e[T].call(h.exports,h,h.exports,r),h.exports}var i={};(()=>{var T=i;Object.defineProperty(T,"__esModule",{value:!0}),T.Terminal=void 0;let n=r(5101),h=r(6097),p=r(4335),y=r(5856),o=r(3027),w=r(7150),l=["cols","rows"];class g extends w.Disposable{constructor(s){super(),this._core=this._register(new y.Terminal(s)),this._addonManager=this._register(new o.AddonManager),this._publicOptions={...this._core.options};let f=c=>this._core.options[c],d=(c,u)=>{this._checkReadonlyOptions(c),this._core.options[c]=u};for(let c in this._core.options){Object.defineProperty(this._publicOptions,c,{get:()=>this._core.options[c],set:m=>{this._checkReadonlyOptions(c),this._core.options[c]=m}});let u={get:f.bind(this,c),set:d.bind(this,c)};Object.defineProperty(this._publicOptions,c,u)}}_checkReadonlyOptions(s){if(l.includes(s))throw new Error(`Option "${s}" can only be set in the constructor`)}_checkProposedApi(){if(!this._core.optionsService.options.allowProposedApi)throw new Error("You must set the allowProposedApi option to true to use proposed API")}get onBell(){return this._core.onBell}get onBinary(){return this._core.onBinary}get onCursorMove(){return this._core.onCursorMove}get onData(){return this._core.onData}get onLineFeed(){return this._core.onLineFeed}get onResize(){return this._core.onResize}get onScroll(){return this._core.onScroll}get onTitleChange(){return this._core.onTitleChange}get onWriteParsed(){return this._core.onWriteParsed}get parser(){return this._checkProposedApi(),this._parser||(this._parser=new h.ParserApi(this._core)),this._parser}get unicode(){return this._checkProposedApi(),new p.UnicodeApi(this._core)}get rows(){return this._core.rows}get cols(){return this._core.cols}get buffer(){return this._checkProposedApi(),this._buffer||(this._buffer=this._register(new n.BufferNamespaceApi(this._core))),this._buffer}get markers(){return this._checkProposedApi(),this._core.markers}get modes(){let s=this._core.coreService.decPrivateModes,f="none";switch(this._core.coreMouseService.activeProtocol){case"X10":f="x10";break;case"VT200":f="vt200";break;case"DRAG":f="drag";break;case"ANY":f="any"}return{applicationCursorKeysMode:s.applicationCursorKeys,applicationKeypadMode:s.applicationKeypad,bracketedPasteMode:s.bracketedPasteMode,insertMode:this._core.coreService.modes.insertMode,mouseTrackingMode:f,originMode:s.origin,reverseWraparoundMode:s.reverseWraparound,sendFocusMode:s.sendFocus,synchronizedOutputMode:s.synchronizedOutput,wraparoundMode:s.wraparound}}get options(){return this._publicOptions}set options(s){for(let f in s)this._publicOptions[f]=s[f]}input(s,f=!0){this._core.input(s,f)}resize(s,f){this._verifyIntegers(s,f),this._core.resize(s,f)}registerMarker(s=0){return this._checkProposedApi(),this._verifyIntegers(s),this._core.addMarker(s)}addMarker(s){return this.registerMarker(s)}dispose(){super.dispose()}scrollLines(s){this._verifyIntegers(s),this._core.scrollLines(s)}scrollPages(s){this._verifyIntegers(s),this._core.scrollPages(s)}scrollToTop(){this._core.scrollToTop()}scrollToBottom(){this._core.scrollToBottom()}scrollToLine(s){this._verifyIntegers(s),this._core.scrollToLine(s)}clear(){this._core.clear()}write(s,f){this._core.write(s,f)}writeln(s,f){this._core.write(s),this._core.write(`\r
|
|
28
|
-
`,f)}reset(){this._core.reset()}loadAddon(s){this._addonManager.loadAddon(this,s)}_verifyIntegers(...s){for(let f of s)if(f===1/0||isNaN(f)||f%1!=0)throw new Error("This API only accepts integers")}}T.Terminal=g})();var a=on;for(var S in i)a[S]=i[S];i.__esModule&&Object.defineProperty(a,"__esModule",{value:!0})})()});var
|
|
28
|
+
`,f)}reset(){this._core.reset()}loadAddon(s){this._addonManager.loadAddon(this,s)}_verifyIntegers(...s){for(let f of s)if(f===1/0||isNaN(f)||f%1!=0)throw new Error("This API only accepts integers")}}T.Terminal=g})();var a=on;for(var S in i)a[S]=i[S];i.__esModule&&Object.defineProperty(a,"__esModule",{value:!0})})()});var ae=["codex","cursor","claude"],ho={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"}};function pe(e){return ho[e]}function ar(e,t={}){let r=pe(e),i=t.runners?.[e]?.path?.trim();return{...r,executable:i&&i.length>0?i:r.executable}}function ot(e={}){return ae.filter(t=>e.runners?.[t]?.enabled!==!1)}function Xe(e={}){let t=ot(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]}function Pt(e,t={}){if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)}function at(e){return ae.includes(e)}function hs(e){if(!e||e.length===0)return"codex";if(!at(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${ae.join(", ")}.`);return e}function De(e){return pe(e).displayName}function ge(e,t,r={}){let i=[ar(e,r).executable];return t&&t.length>0&&i.push(t),i}function fs(e){let t=[...e];for(;t[0]==="--";)t.shift();if(t.length===0)return{mode:"interactive"};if(t.length>=3&&t[0]==="repo"&&t[1]==="add"){let r=t.slice(2).join(" ").trim();if(r.length===0)throw new Error(`Repo path cannot be empty.
|
|
29
29
|
|
|
30
30
|
`+me());return{mode:"command",command:{kind:"addRepo",path:r}}}if(t.length===2&&t[0]==="repo"&&t[1]==="list")return{mode:"command",command:{kind:"listRepos"}};if(t.length===3&&t[0]==="repo"&&t[1]==="remove")return{mode:"command",command:{kind:"removeRepo",repoId:t[2].trim()}};if(t.length>=2&&t.length<=3&&t[0]==="workspace"&&t[1]==="list"){let r=t[2]==="--archived";if(t.length===3&&!r)throw new Error(`Unsupported command: ${t.join(" ")}
|
|
31
31
|
|
|
@@ -49,15 +49,15 @@ ${me()}`)}function me(){return["Craig commands:"," craig Show the
|
|
|
49
49
|
${me()}`);return t}function fo(e){let t=e.trim();if(t.length===0)throw new Error(`Repo id cannot be empty.
|
|
50
50
|
|
|
51
51
|
${me()}`);return t}import qs from"node:path";import{mkdir as po,readFile as go,writeFile as mo}from"node:fs/promises";import _o from"node:path";async function _e(e){try{let t=await go(e.configFile,"utf8"),r=JSON.parse(t);return gs(r,e.configFile)}catch(t){if(wo(t))return{};throw t instanceof SyntaxError?new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`):t}}async function ps(e,t){gs(t,e.configFile),await po(_o.dirname(e.configFile),{recursive:!0}),await mo(e.configFile,`${JSON.stringify(t,null,2)}
|
|
52
|
-
`,"utf8")}function gs(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[i,a]of Object.entries(r.runners)){if(!
|
|
53
|
-
`;await a.writeFile(S,"utf8"),await a.sync(),await a.close(),await So(i,e)}catch(S){throw await a.close().catch(()=>{}),await vo(i,{force:!0}).catch(()=>{}),S}}async function We(e,t){let r=await ko(cr(e,t),"utf8"),i=JSON.parse(r);return Co(i,cr(e,t))}async function Ye(e,t){await ae(cr(e,t.id),{...t,updatedAt:new Date().toISOString()})}function cr(e,t){return To.join(e.sessionsDir,`${t}.json`)}function Co(e,t){let r=Io(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(i=>typeof i=="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")||!Po(r.attach)||!Ro(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 Ro(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 Po(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 Io(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{readFile as Ao}from"node:fs/promises";import{readFile as xo}from"node:fs/promises";async function Re(e){let t=await xo(e.indexFile,"utf8"),r=JSON.parse(t);return lr(r,e.workspaceRoot,e.indexFile)}async function Qe(e,t){let r={...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()};await ae(e.indexFile,r)}function lr(e,t,r){if(!Eo(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}function Eo(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"}async function Se(e,t){let r=await Ao(dr(e,t),"utf8"),i=JSON.parse(r);return Do(i,dr(e,t))}async function te(e,t){let r={...t,updatedAt:new Date().toISOString()};await ae(dr(e,t.id),r)}async function ms(e,t){let r=await Re(e);r.taskIds.includes(t)||await Qe(e,{...r,taskIds:[...r.taskIds,t]})}function dr(e,t){return`${e.tasksDir}/${t}.json`}function Do(e,t){let r=Lo(e);if(!Oo(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function Lo(e){if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:ur(t.runner),repoId:typeof t.repoId=="string"?t.repoId:"legacy_repo",workspaceId:typeof t.workspaceId=="string"?t.workspaceId:"legacy_workspace",sessionId:typeof t.sessionId=="string"||t.sessionId===null?t.sessionId:null,selectedPtyTabId:typeof t.selectedPtyTabId=="string"||t.selectedPtyTabId===null?t.selectedPtyTabId:null,linkedRepoIds:Array.isArray(t.linkedRepoIds)?t.linkedRepoIds.filter(r=>typeof r=="string"):[],ptyTabs:Bo(t),runnerSession:t.runnerSession??Mo(t),checks:Ko(t),lastCommit:t.lastCommit??null,pullRequest:zo(t),artifacts:Go(t),cleanup:Xo(t)}}function Mo(e){if(typeof e.title!="string")return null;let t=ur(e.runner);return{command:ge(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}}function Oo(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"&&typeof t.status=="string"&&at(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"&&_s(t.ptyTabs)&&$o(t.runnerSession)&&No(t.prompt)&&Ho(t.checks)&&Wo(t.lastCommit)&&jo(t.pullRequest)&&Uo(t.artifacts)&&qo(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"}function Bo(e){if(_s(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 Fo(e.id,e.title,t,ur(e.runner))}function Fo(e,t,r,i){let a=pe(i);return[{id:`${e}:agent`,kind:"agent",title:a.defaultAgentTitle,command:ge(i),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]}function ur(e){return e&&at(e)?e:"codex"}function _s(e){return 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")}function $o(e){return 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)}function No(e){return typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string"}function Ho(e){return 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")}function Wo(e){return e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string"}function jo(e){return typeof e=="object"&&e!==null&&e.provider==="github"&&(typeof e.number=="number"||e.number===null)&&(typeof e.url=="string"||e.url===null)&&(typeof e.baseBranch=="string"||e.baseBranch===null)&&(typeof e.headBranch=="string"||e.headBranch===null)&&(e.status==="open"||e.status==="closed"||e.status==="merged"||e.status===null)&&typeof e.mergeable=="boolean"&&(typeof e.mergeStateStatus=="string"||e.mergeStateStatus===null)&&Array.isArray(e.requiredChecks)&&e.requiredChecks.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))&&(typeof e.lastSyncedAt=="string"||e.lastSyncedAt===null)&&(typeof e.lastSyncedHeadSha=="string"||e.lastSyncedHeadSha===null||e.lastSyncedHeadSha===void 0)}function Uo(e){return 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)}function qo(e){return 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)}function Ko(e){return e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]}}function zo(e){let t=e.pullRequest;return t?{...t,mergeStateStatus:t.mergeStateStatus??null,requiredChecks:Vo(t.requiredChecks),lastSyncedHeadSha:t.lastSyncedHeadSha??null}:{provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,mergeable:!1,mergeStateStatus:null,requiredChecks:[],lastSyncedAt:null,lastSyncedHeadSha:null}}function Vo(e){return 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})):[]}function Go(e){let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}}function Xo(e){return e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}}import{readFile as Yo}from"node:fs/promises";async function Pe(e){try{let t=await Yo(e.uiStateFile,"utf8"),r=JSON.parse(t);return Qo(r,e.uiStateFile)}catch(t){if(Zo(t))return null;throw t}}async function ve(e,t){await ae(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function Le(){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 Qo(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")||!ct(e,"inputMode")||!ct(e,"focusedRegion")||!ct(e,"activeTab")||!ct(e,"inspectorSection")||!ct(e,"inspectionMode")||!It(e,"openInspectionKind")||!It(e,"selectedFileTreePath")||!It(e,"selectedFilePath")||!It(e,"selectedDiffPath")||!Jo(e,"collapsedFileTreePaths")||!ct(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 ct(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function It(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Jo(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function Zo(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{execFile as ea}from"node:child_process";import{promisify as ta}from"node:util";var ws=ta(ea);async function J(e,t,r={}){try{let i=await ws(e,t,{cwd:r.cwd,env:r.env});return{stdout:i.stdout,stderr:i.stderr}}catch(i){if(bs(i)){let a=i.stderr?.trim()||i.stdout?.trim()||i.message;throw new Error(`${e} ${t.join(" ")} failed: ${a}`)}throw i}}async function oe(e,t,r={}){try{let i=await ws(e,t,{cwd:r.cwd,env:r.env});return{stdout:i.stdout,stderr:i.stderr,exitCode:0}}catch(i){if(bs(i))return{stdout:i.stdout??"",stderr:i.stderr??"",exitCode:typeof i.code=="number"?i.code:null};throw i}}function bs(e){return e instanceof Error}function xt(e){return`'${e.replace(/'/g,"'\\''")}'`}import{accessSync as ra,constants as sa}from"node:fs";import{homedir as ys}from"node:os";import je from"node:path";var ia=[je.join(ys(),".local","bin"),je.join(ys(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function vs(e=process.env){return oa([...(e.PATH??"").split(je.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:ia])}function Je(e=process.env){return{...e,PATH:vs(e).join(je.delimiter)}}function na(e,t={}){if(e.includes(je.sep)){let r=je.isAbsolute(e)?e:je.resolve(t.cwd??process.cwd(),e);return Ss(r)?r:null}for(let r of vs(t.env)){let i=je.join(r,e);if(Ss(i))return i}return null}function Ze(e,t={}){let r=na(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 Ss(e){try{return ra(e,sa.X_OK),!0}catch{return!1}}function oa(e){return[...new Set(e)]}import{spawn as aa}from"node:child_process";import{createHash as ca}from"node:crypto";import la from"node:path";var da="craig";async function ks(e,t,r){let i=hr(e,t),a=ha(),S=await J("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",i,"-n","runner",...a,"-c",r],{cwd:e}),T=pa(S.stdout);return await ua(e,i),T}async function ua(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 i of r)await J("tmux",i,{cwd:e})}async function Ts(e,t,r){await J("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})}async function Cs(e,t,r){await J("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})}async function Rs(e,t,r){await J("tmux",["pipe-pane","-o","-t",e,`cat >> ${xt(t)}`],{cwd:r})}async function Et(e,t,r,i){let a=i??Is(e);if(r?await J("tmux",["select-window","-t",r],{cwd:e}):await J("tmux",["select-window","-t",t],{cwd:e}),await J("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await J("tmux",["switch-client","-t",a],{cwd:e});return}await ma(e,["attach-session","-t",a])}async function Ps(e,t){await J("tmux",["kill-session","-t",t],{cwd:e})}function Is(e){let r=la.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",i=ca("sha1").update(e).digest("hex").slice(0,8);return`${da}-${r}-${i}`}function hr(e,t){return`${Is(e)}-${t.toLowerCase()}`}function ha(){let e=fa();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]}function fa(){let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,i="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof i=="number"&&i>0)return{columns:r,rows:i}}return null}function pa(e){let t=ga(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]}}function ga(e){return e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0)}async function ma(e,t){await new Promise((r,i)=>{let a=aa("tmux",t,{cwd:e,stdio:"inherit"});a.on("error",i),a.on("exit",S=>{if(S===0){r();return}i(new Error(`tmux ${t.join(" ")} failed with exit code ${S??"unknown"}.`))})})}var fr={async prepare(e,t){let r=e.runnerSession.command[0]??ge(e.runner)[0],i=Je();await J(Ze(r,{cwd:t.repoRoot,env:i}),["--help"],{cwd:t.repoRoot,env:i})},async launch(e,t){let r=e.runnerSession.command.length>0?e.runnerSession.command:ge(e.runner,e.prompt.value),i=Ze(r[0],{cwd:e.worktreePath,env:Je()});await Cs(t.session.paneId,[i,...r.slice(1)].map(a=>xt(a)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}};var pt={async create(e,t){let r=await ks(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Rs(r.paneId,t.logPath,t.repoRoot);let i=await xs({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),a={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||hr(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:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ye(e,a),a},async attach(e,t,r){let i=await pt.snapshot(t,r);if(!i.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Et(r,t.paneId,t.windowTarget,t.sessionName);let a={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:i};return await Ye(e,a),a},async resize(e,t,r,i){await Ts(i,t.sessionName,r);let a={...t,attach:{...t.attach,lastSize:r}};return await Ye(e,a),a},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 i={...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:(r.length>0,t.command)};return await Ye(e,i),i},async snapshot(e,t){return _a(e,t)}};async function _a(e,t){let r=await oe("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return xs({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(i=>i.trim()===e.paneId)})}async function xs(e){return{paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()}}import{mkdir as Us,writeFile as xa}from"node:fs/promises";import Ie from"node:path";import{readFile as wa,readdir as ba,rm as ya}from"node:fs/promises";import Es from"node:path";async function Me(e,t){let r=await wa(At(e,t),"utf8"),i=JSON.parse(r);return Sa(i,At(e,t))}async function As(e,t){await ae(At(e,t.id),{...t,updatedAt:new Date().toISOString()})}async function gt(e){let t=await ba(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>Me(e,Es.basename(i.name,".json"))))).sort((i,a)=>i.name.localeCompare(a.name)||i.id.localeCompare(a.id))}async function Ds(e,t){await ya(At(e,t),{force:!0})}function At(e,t){return Es.join(e.reposDir,`${t}.json`)}function Sa(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}import{readFile as va,readdir as ka,rm as Ta}from"node:fs/promises";import Ls from"node:path";async function Lt(e,t){let r=await va(Dt(e,t),"utf8"),i=JSON.parse(r);return Ca(i,Dt(e,t))}async function mt(e,t){await ae(Dt(e,t.id),{...t,updatedAt:new Date().toISOString()})}async function et(e){let t=await ka(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>Lt(e,Ls.basename(i.name,".json"))))).sort((i,a)=>i.id.localeCompare(a.id))}async function Ms(e,t){await Ta(Dt(e,t),{force:!0})}function Dt(e,t){return Ls.join(e.workspacesDir,`${t}.json`)}function Ca(e,t){if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.primaryRepoId!="string"||typeof e.branch!="string"||e.status!=="active"&&e.status!=="archived"||!Array.isArray(e.linkedRepoIds)||!(e.linkedRepoIds??[]).every(r=>typeof r=="string")||!(e.archivedAt===null||typeof e.archivedAt=="string")||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}async function Os(e,t){let r=await oe("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.")}async function Bs(e,t,r){if((await oe("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode!==0)throw new Error("Base branch 'main' does not exist locally.");let a=await Ra(e);await J("git",["worktree","add","-b",t,r,a],{cwd:e})}async function Ra(e){return(await oe("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await oe("git",["fetch","origin","main"],{cwd:e})).exitCode!==0?"main":(await oe("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"refs/remotes/origin/main":"main"}async function _t(e){let t=await oe("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}async function Fs(e){await J("git",["add","-A"],{cwd:e})}async function $s(e,t){await J("git",["commit","-m",t],{cwd:e})}async function Mt(e){let t=await J("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",i=""]=t.stdout.trim().split(`
|
|
54
|
-
`);if(!r||!i)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:i}}async function Ot(e){return!await _t(e)}async function Ns(e){await J("git",["remote","get-url","origin"],{cwd:e})}async function Hs(e,t){await J("git",["push","-u","origin",t],{cwd:e})}async function Ws(e,t){await J("git",["worktree","remove","--force",t],{cwd:e})}async function js(e,t){let r=await Re(e),i=Pa(new Date),a=Ia(r.taskIds,i);for(;;){let S=`task_${i}_${String(a).padStart(2,"0")}`,T=`craig/${S}`;if(!await Os(t,T))return S;a+=1}}function Pa(e){let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0");return`${t}${r}${i}`}function Ia(e,t){let r=e.filter(i=>i.startsWith(`task_${t}_`)).map(i=>Number.parseInt(i.slice(-2),10)).filter(i=>Number.isInteger(i));return r.length===0?1:Math.max(...r)+1}async function Bt(e,t,r,i={}){let a=await Me(e,t),S=await Da(e,a.id),T=await js(e,a.rootPath),n=i.sessionId??null,h=`craig/${T}`,p=Ie.join(e.worktreesDir,a.id,T),y=Ie.join(e.logsDir,`${T}.log`),o=Ie.join(e.artifactsDir,T);await Us(Ie.dirname(p),{recursive:!0}),await Us(o,{recursive:!0}),await xa(y,"","utf8");let w=Aa(e,{taskId:T,repoId:a.id,workspaceId:S.id,sessionId:n,repoRoot:a.rootPath,prompt:r,runner:i.runner??"codex",config:i.config??{},branch:h,worktreePath:p});return await te(e,w),await ms(e,T),await Bs(a.rootPath,h,p),{repoId:a.id,repoRoot:a.rootPath,sessionId:n,workspaceId:S.id,task:w}}function Ea(e,t,r,i="codex",a={}){let S=pe(i);return[{id:`${e}:agent`,kind:"agent",title:S.defaultAgentTitle,command:ge(i,void 0,a),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]}function Aa(e,t){let r=new Date().toISOString(),i=Ea(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:La(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:i[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:i,runnerSession:{command:ge(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{source:{type:"repo_config",path:Ie.relative(e.workspaceRoot,e.configFile)},lastRunAt:null,status:"not_run",commands:[],results:[]},lastCommit:null,pullRequest:{provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,mergeable:!1,mergeStateStatus:null,requiredChecks:[],lastSyncedAt:null,lastSyncedHeadSha:null},artifacts:{logPath:Ie.relative(e.workspaceRoot,Ie.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:Ie.relative(e.workspaceRoot,Ie.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:Ie.relative(e.workspaceRoot,Ie.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null},lastFailureReason:null,createdAt:r,updatedAt:r}}async function Da(e,t){let i=(await et(e)).find(a=>a.primaryRepoId===t&&a.status==="active");if(!i)throw new Error(`Repo ${t} does not have an active workspace.`);return i}function La(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}async function Ks(e,t,r,i={}){let a=r.trim(),S=await _e(e),T=i.runner??Xe(S);if(Pt(T,S),t.trim().length===0)throw new Error("Repo id cannot be empty.");if(a.length===0)throw new Error("Task prompt cannot be empty.");let n=await Bt(e,t,a,{runner:T,config:S}),h=n.task,p=ge(T,a,S),y=`session_${h.id}`,o=h.artifacts.logPath?qs.resolve(e.workspaceRoot,h.artifacts.logPath):qs.join(e.logsDir,`${h.id}.log`);try{await
|
|
52
|
+
`,"utf8")}function gs(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[i,a]of Object.entries(r.runners)){if(!ae.includes(i))throw new Error(`Craig config at ${t} is invalid. "runners.${i}" is not supported. Expected one of: ${ae.join(", ")}.`);if(typeof a!="object"||a===null||Array.isArray(a))throw new Error(`Craig config at ${t} is invalid. "runners.${i}" must be an object.`);let S=a;if(S.enabled!==void 0&&typeof S.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${i}.enabled" must be a boolean.`);if(S.path!==void 0&&(typeof S.path!="string"||S.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${i}.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(i=>typeof i=="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(i=>typeof i=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(r.github!==void 0){if(typeof r.github!="object"||r.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(r.github.mergeMethod!==void 0&&r.github.mergeMethod!=="merge"&&r.github.mergeMethod!=="rebase"&&r.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(r.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(r.github.watchIntervalSeconds)||r.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}return r}function wo(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{readFile as ko,readdir as Yu,rm as Qu}from"node:fs/promises";import To from"node:path";import{randomUUID as bo}from"node:crypto";import{open as yo,readFile as zu,rename as So,rm as vo}from"node:fs/promises";import cr from"node:path";async function ce(e,t){let r=cr.dirname(e),i=cr.join(r,`.${cr.basename(e)}.${process.pid}.${Date.now()}.${bo()}.tmp`),a=await yo(i,"w");try{let S=`${JSON.stringify(t,null,2)}
|
|
53
|
+
`;await a.writeFile(S,"utf8"),await a.sync(),await a.close(),await So(i,e)}catch(S){throw await a.close().catch(()=>{}),await vo(i,{force:!0}).catch(()=>{}),S}}async function We(e,t){let r=await ko(lr(e,t),"utf8"),i=JSON.parse(r);return Co(i,lr(e,t))}async function Ye(e,t){await ce(lr(e,t.id),{...t,updatedAt:new Date().toISOString()})}function lr(e,t){return To.join(e.sessionsDir,`${t}.json`)}function Co(e,t){let r=Io(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(i=>typeof i=="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")||!Po(r.attach)||!Ro(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 Ro(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 Po(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 Io(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{readFile as Ao}from"node:fs/promises";import{readFile as xo}from"node:fs/promises";async function Re(e){let t=await xo(e.indexFile,"utf8"),r=JSON.parse(t);return dr(r,e.workspaceRoot,e.indexFile)}async function Qe(e,t){let r={...t,workspaceRoot:e.workspaceRoot,updatedAt:new Date().toISOString()};await ce(e.indexFile,r)}function dr(e,t,r){if(!Eo(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}function Eo(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"}async function Se(e,t){let r=await Ao(ur(e,t),"utf8"),i=JSON.parse(r);return Do(i,ur(e,t))}async function te(e,t){let r={...t,updatedAt:new Date().toISOString()};await ce(ur(e,t.id),r)}async function ms(e,t){let r=await Re(e);r.taskIds.includes(t)||await Qe(e,{...r,taskIds:[...r.taskIds,t]})}function ur(e,t){return`${e.tasksDir}/${t}.json`}function Do(e,t){let r=Lo(e);if(!Oo(r))throw new Error(`Craig task record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return r}function Lo(e){if(typeof e!="object"||e===null)return e;let t=e;return{...t,runner:hr(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:Bo(t),runnerSession:t.runnerSession??Mo(t),checks:Ko(t),lastCommit:t.lastCommit??null,pullRequest:zo(t),artifacts:Go(t),cleanup:Xo(t)}}function Mo(e){if(typeof e.title!="string")return null;let t=hr(e.runner);return{command:ge(t,e.title),pid:null,startedAt:null,lastKnownState:e.status==="running"?"running":"starting",exitCode:null,exitedAt:null}}function Oo(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"&&typeof t.status=="string"&&at(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"&&_s(t.ptyTabs)&&$o(t.runnerSession)&&No(t.prompt)&&Ho(t.checks)&&Wo(t.lastCommit)&&jo(t.pullRequest)&&Uo(t.artifacts)&&qo(t.cleanup)&&(t.lastFailureReason===void 0||t.lastFailureReason===null||typeof t.lastFailureReason=="string")&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"}function Bo(e){if(_s(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 Fo(e.id,e.title,t,hr(e.runner))}function Fo(e,t,r,i){let a=pe(i);return[{id:`${e}:agent`,kind:"agent",title:a.defaultAgentTitle,command:ge(i),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]}function hr(e){return e&&at(e)?e:"codex"}function _s(e){return 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")}function $o(e){return 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)}function No(e){return typeof e=="object"&&e!==null&&(e.source==="inline"||e.source==="file")&&typeof e.value=="string"}function Ho(e){return 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")}function Wo(e){return e===null||typeof e=="object"&&e!==null&&typeof e.sha=="string"&&typeof e.message=="string"&&typeof e.committedAt=="string"}function jo(e){return typeof e=="object"&&e!==null&&e.provider==="github"&&(typeof e.number=="number"||e.number===null)&&(typeof e.url=="string"||e.url===null)&&(typeof e.baseBranch=="string"||e.baseBranch===null)&&(typeof e.headBranch=="string"||e.headBranch===null)&&(e.status==="open"||e.status==="closed"||e.status==="merged"||e.status===null)&&typeof e.mergeable=="boolean"&&(typeof e.mergeStateStatus=="string"||e.mergeStateStatus===null)&&Array.isArray(e.requiredChecks)&&e.requiredChecks.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))&&(typeof e.lastSyncedAt=="string"||e.lastSyncedAt===null)&&(typeof e.lastSyncedHeadSha=="string"||e.lastSyncedHeadSha===null||e.lastSyncedHeadSha===void 0)}function Uo(e){return 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)}function qo(e){return 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)}function Ko(e){return e.checks?{...e.checks,results:e.checks.results??[]}:{source:{type:"repo_config",path:".craig/config.json"},lastRunAt:null,status:"not_run",commands:[],results:[]}}function zo(e){let t=e.pullRequest;return t?{...t,mergeStateStatus:t.mergeStateStatus??null,requiredChecks:Vo(t.requiredChecks),lastSyncedHeadSha:t.lastSyncedHeadSha??null}:{provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,mergeable:!1,mergeStateStatus:null,requiredChecks:[],lastSyncedAt:null,lastSyncedHeadSha:null}}function Vo(e){return 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})):[]}function Go(e){let t=e.artifacts;return t?{...t,checkSummaryPath:t.checkSummaryPath??null}:{logPath:null,checkSummaryPath:null,prDraftPath:null,prStatusPath:null}}function Xo(e){return e.cleanup??{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null}}import{readFile as Yo}from"node:fs/promises";async function Pe(e){try{let t=await Yo(e.uiStateFile,"utf8"),r=JSON.parse(t);return Qo(r,e.uiStateFile)}catch(t){if(Zo(t))return null;throw t}}async function ve(e,t){await ce(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function Le(){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 Qo(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")||!ct(e,"inputMode")||!ct(e,"focusedRegion")||!ct(e,"activeTab")||!ct(e,"inspectorSection")||!ct(e,"inspectionMode")||!It(e,"openInspectionKind")||!It(e,"selectedFileTreePath")||!It(e,"selectedFilePath")||!It(e,"selectedDiffPath")||!Jo(e,"collapsedFileTreePaths")||!ct(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 ct(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function It(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Jo(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(r=>typeof r=="string"))}function Zo(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{execFile as ea}from"node:child_process";import{promisify as ta}from"node:util";var ws=ta(ea);async function J(e,t,r={}){try{let i=await ws(e,t,{cwd:r.cwd,env:r.env});return{stdout:i.stdout,stderr:i.stderr}}catch(i){if(bs(i)){let a=i.stderr?.trim()||i.stdout?.trim()||i.message;throw new Error(`${e} ${t.join(" ")} failed: ${a}`)}throw i}}async function oe(e,t,r={}){try{let i=await ws(e,t,{cwd:r.cwd,env:r.env});return{stdout:i.stdout,stderr:i.stderr,exitCode:0}}catch(i){if(bs(i))return{stdout:i.stdout??"",stderr:i.stderr??"",exitCode:typeof i.code=="number"?i.code:null};throw i}}function bs(e){return e instanceof Error}function xt(e){return`'${e.replace(/'/g,"'\\''")}'`}import{accessSync as ra,constants as sa}from"node:fs";import{homedir as ys}from"node:os";import je from"node:path";var ia=[je.join(ys(),".local","bin"),je.join(ys(),".cursor","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"];function vs(e=process.env){return oa([...(e.PATH??"").split(je.delimiter).filter(t=>t.length>0),...e.CRAIG_DISABLE_COMMAND_PATH_FALLBACKS==="1"?[]:ia])}function Je(e=process.env){return{...e,PATH:vs(e).join(je.delimiter)}}function na(e,t={}){if(e.includes(je.sep)){let r=je.isAbsolute(e)?e:je.resolve(t.cwd??process.cwd(),e);return Ss(r)?r:null}for(let r of vs(t.env)){let i=je.join(r,e);if(Ss(i))return i}return null}function Ze(e,t={}){let r=na(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 Ss(e){try{return ra(e,sa.X_OK),!0}catch{return!1}}function oa(e){return[...new Set(e)]}import{spawn as aa}from"node:child_process";import{createHash as ca}from"node:crypto";import la from"node:path";var da="craig";async function ks(e,t,r){let i=fr(e,t),a=ha(),S=await J("tmux",["new-session","-d","-P","-F","#{session_name} #{window_id} #{pane_id}","-s",i,"-n","runner",...a,"-c",r],{cwd:e}),T=pa(S.stdout);return await ua(e,i),T}async function ua(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 i of r)await J("tmux",i,{cwd:e})}async function Ts(e,t,r){await J("tmux",["resize-window","-t",t,"-x",`${r.columns}`,"-y",`${r.rows}`],{cwd:e})}async function Cs(e,t,r){await J("tmux",["send-keys","-t",e,t,"C-m"],{cwd:r})}async function Rs(e,t,r){await J("tmux",["pipe-pane","-o","-t",e,`cat >> ${xt(t)}`],{cwd:r})}async function Et(e,t,r,i){let a=i??Is(e);if(r?await J("tmux",["select-window","-t",r],{cwd:e}):await J("tmux",["select-window","-t",t],{cwd:e}),await J("tmux",["select-pane","-t",t],{cwd:e}),process.env.TMUX){await J("tmux",["switch-client","-t",a],{cwd:e});return}await ma(e,["attach-session","-t",a])}async function Ps(e,t){await J("tmux",["kill-session","-t",t],{cwd:e})}function Is(e){let r=la.basename(e).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"repo",i=ca("sha1").update(e).digest("hex").slice(0,8);return`${da}-${r}-${i}`}function fr(e,t){return`${Is(e)}-${t.toLowerCase()}`}function ha(){let e=fa();return e?["-x",`${e.columns}`,"-y",`${e.rows}`]:[]}function fa(){let e=[process.stdout,process.stderr,process.stdin];for(let t of e){let r="columns"in t?t.columns:void 0,i="rows"in t?t.rows:void 0;if(typeof r=="number"&&r>0&&typeof i=="number"&&i>0)return{columns:r,rows:i}}return null}function pa(e){let t=ga(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]}}function ga(e){return e.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0)}async function ma(e,t){await new Promise((r,i)=>{let a=aa("tmux",t,{cwd:e,stdio:"inherit"});a.on("error",i),a.on("exit",S=>{if(S===0){r();return}i(new Error(`tmux ${t.join(" ")} failed with exit code ${S??"unknown"}.`))})})}var pr={async prepare(e,t){let r=e.runnerSession.command[0]??ge(e.runner)[0],i=Je();await J(Ze(r,{cwd:t.repoRoot,env:i}),["--help"],{cwd:t.repoRoot,env:i})},async launch(e,t){let r=e.runnerSession.command.length>0?e.runnerSession.command:ge(e.runner,e.prompt.value),i=Ze(r[0],{cwd:e.worktreePath,env:Je()});await Cs(t.session.paneId,[i,...r.slice(1)].map(a=>xt(a)).join(" "),t.repoRoot)},async status(e){return e.runnerSession.lastKnownState},async stop(){},async collectArtifacts(){}};var pt={async create(e,t){let r=await ks(t.repoRoot,t.taskId,t.worktreePath);t.logPath&&await Rs(r.paneId,t.logPath,t.repoRoot);let i=await xs({paneId:r.paneId,windowTarget:r.windowTarget,alive:!0}),a={id:t.sessionId,taskId:t.taskId,repoId:t.repoId,workspaceId:t.workspaceId,substrate:"tmux",sessionName:r.sessionName||fr(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:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return await Ye(e,a),a},async attach(e,t,r){let i=await pt.snapshot(t,r);if(!i.alive)throw new Error(`Session ${t.id} is no longer live and cannot be attached.`);await Et(r,t.paneId,t.windowTarget,t.sessionName);let a={...t,status:"running",lastAttachedAt:new Date().toISOString(),snapshot:i};return await Ye(e,a),a},async resize(e,t,r,i){await Ts(i,t.sessionName,r);let a={...t,attach:{...t.attach,lastSize:r}};return await Ye(e,a),a},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 i={...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:(r.length>0,t.command)};return await Ye(e,i),i},async snapshot(e,t){return _a(e,t)}};async function _a(e,t){let r=await oe("tmux",["list-panes","-F","#{pane_id}","-t",e.paneId],{cwd:t});return xs({paneId:e.paneId,windowTarget:e.windowTarget,alive:r.exitCode===0&&r.stdout.split(/\s+/).some(i=>i.trim()===e.paneId)})}async function xs(e){return{paneId:e.paneId,windowTarget:e.windowTarget,alive:e.alive,capturedAt:new Date().toISOString()}}import{mkdir as Us,writeFile as xa}from"node:fs/promises";import Ie from"node:path";import{readFile as wa,readdir as ba,rm as ya}from"node:fs/promises";import Es from"node:path";async function Me(e,t){let r=await wa(At(e,t),"utf8"),i=JSON.parse(r);return Sa(i,At(e,t))}async function As(e,t){await ce(At(e,t.id),{...t,updatedAt:new Date().toISOString()})}async function gt(e){let t=await ba(e.reposDir,{withFileTypes:!0});return(await Promise.all(t.filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>Me(e,Es.basename(i.name,".json"))))).sort((i,a)=>i.name.localeCompare(a.name)||i.id.localeCompare(a.id))}async function Ds(e,t){await ya(At(e,t),{force:!0})}function At(e,t){return Es.join(e.reposDir,`${t}.json`)}function Sa(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}import{readFile as va,readdir as ka,rm as Ta}from"node:fs/promises";import Ls from"node:path";async function Lt(e,t){let r=await va(Dt(e,t),"utf8"),i=JSON.parse(r);return Ca(i,Dt(e,t))}async function mt(e,t){await ce(Dt(e,t.id),{...t,updatedAt:new Date().toISOString()})}async function et(e){let t=await ka(e.workspacesDir,{withFileTypes:!0});return(await Promise.all(t.filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>Lt(e,Ls.basename(i.name,".json"))))).sort((i,a)=>i.id.localeCompare(a.id))}async function Ms(e,t){await Ta(Dt(e,t),{force:!0})}function Dt(e,t){return Ls.join(e.workspacesDir,`${t}.json`)}function Ca(e,t){if(typeof e!="object"||e===null||typeof e.id!="string"||typeof e.primaryRepoId!="string"||typeof e.branch!="string"||e.status!=="active"&&e.status!=="archived"||!Array.isArray(e.linkedRepoIds)||!(e.linkedRepoIds??[]).every(r=>typeof r=="string")||!(e.archivedAt===null||typeof e.archivedAt=="string")||typeof e.createdAt!="string"||typeof e.updatedAt!="string")throw new Error(`Craig workspace record at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}async function Os(e,t){let r=await oe("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.")}async function Bs(e,t,r){if((await oe("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode!==0)throw new Error("Base branch 'main' does not exist locally.");let a=await Ra(e);await J("git",["worktree","add","-b",t,r,a],{cwd:e})}async function Ra(e){return(await oe("git",["remote","get-url","origin"],{cwd:e})).exitCode!==0||(await oe("git",["fetch","origin","main"],{cwd:e})).exitCode!==0?"main":(await oe("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"refs/remotes/origin/main":"main"}async function _t(e){let t=await oe("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}async function Fs(e){await J("git",["add","-A"],{cwd:e})}async function $s(e,t){await J("git",["commit","-m",t],{cwd:e})}async function Mt(e){let t=await J("git",["show","-s","--format=%H%n%s","HEAD"],{cwd:e}),[r="",i=""]=t.stdout.trim().split(`
|
|
54
|
+
`);if(!r||!i)throw new Error("Unable to read git HEAD commit metadata.");return{sha:r,message:i}}async function Ot(e){return!await _t(e)}async function Ns(e){await J("git",["remote","get-url","origin"],{cwd:e})}async function Hs(e,t){await J("git",["push","-u","origin",t],{cwd:e})}async function Ws(e,t){await J("git",["worktree","remove","--force",t],{cwd:e})}async function js(e,t){let r=await Re(e),i=Pa(new Date),a=Ia(r.taskIds,i);for(;;){let S=`task_${i}_${String(a).padStart(2,"0")}`,T=`craig/${S}`;if(!await Os(t,T))return S;a+=1}}function Pa(e){let t=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),i=String(e.getDate()).padStart(2,"0");return`${t}${r}${i}`}function Ia(e,t){let r=e.filter(i=>i.startsWith(`task_${t}_`)).map(i=>Number.parseInt(i.slice(-2),10)).filter(i=>Number.isInteger(i));return r.length===0?1:Math.max(...r)+1}async function Bt(e,t,r,i={}){let a=await Me(e,t),S=await Da(e,a.id),T=await js(e,a.rootPath),n=i.sessionId??null,h=`craig/${T}`,p=Ie.join(e.worktreesDir,a.id,T),y=Ie.join(e.logsDir,`${T}.log`),o=Ie.join(e.artifactsDir,T);await Us(Ie.dirname(p),{recursive:!0}),await Us(o,{recursive:!0}),await xa(y,"","utf8");let w=Aa(e,{taskId:T,repoId:a.id,workspaceId:S.id,sessionId:n,repoRoot:a.rootPath,prompt:r,runner:i.runner??"codex",config:i.config??{},branch:h,worktreePath:p});return await te(e,w),await ms(e,T),await Bs(a.rootPath,h,p),{repoId:a.id,repoRoot:a.rootPath,sessionId:n,workspaceId:S.id,task:w}}function Ea(e,t,r,i="codex",a={}){let S=pe(i);return[{id:`${e}:agent`,kind:"agent",title:S.defaultAgentTitle,command:ge(i,void 0,a),createdAt:r,updatedAt:r},{id:`${e}:terminal`,kind:"terminal",title:"Terminal",command:[],createdAt:r,updatedAt:r}]}function Aa(e,t){let r=new Date().toISOString(),i=Ea(t.taskId,t.prompt,r,t.runner,t.config);return{id:t.taskId,title:t.prompt,slug:La(t.prompt),type:"repo",status:"draft",runner:t.runner,repoId:t.repoId,workspaceId:t.workspaceId,sessionId:t.sessionId,selectedPtyTabId:i[0]?.id??null,linkedRepoIds:[],repoRoot:t.repoRoot,worktreePath:t.worktreePath,branch:t.branch,ptyTabs:i,runnerSession:{command:ge(t.runner,t.prompt,t.config),pid:null,startedAt:null,lastKnownState:"starting",exitCode:null,exitedAt:null},prompt:{source:"inline",value:t.prompt},checks:{source:{type:"repo_config",path:Ie.relative(e.workspaceRoot,e.configFile)},lastRunAt:null,status:"not_run",commands:[],results:[]},lastCommit:null,pullRequest:{provider:"github",number:null,url:null,baseBranch:null,headBranch:null,status:null,mergeable:!1,mergeStateStatus:null,requiredChecks:[],lastSyncedAt:null,lastSyncedHeadSha:null},artifacts:{logPath:Ie.relative(e.workspaceRoot,Ie.join(e.logsDir,`${t.taskId}.log`)),checkSummaryPath:Ie.relative(e.workspaceRoot,Ie.join(e.artifactsDir,t.taskId,"check-summary.json")),prDraftPath:null,prStatusPath:Ie.relative(e.workspaceRoot,Ie.join(e.artifactsDir,t.taskId,"pr-status.json"))},cleanup:{paneClosedAt:null,worktreeRemovedAt:null,preservedWorktree:!1,warning:null},lastFailureReason:null,createdAt:r,updatedAt:r}}async function Da(e,t){let i=(await et(e)).find(a=>a.primaryRepoId===t&&a.status==="active");if(!i)throw new Error(`Repo ${t} does not have an active workspace.`);return i}function La(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}async function Ks(e,t,r,i={}){let a=r.trim(),S=await _e(e),T=i.runner??Xe(S);if(Pt(T,S),t.trim().length===0)throw new Error("Repo id cannot be empty.");if(a.length===0)throw new Error("Task prompt cannot be empty.");let n=await Bt(e,t,a,{runner:T,config:S}),h=n.task,p=ge(T,a,S),y=`session_${h.id}`,o=h.artifacts.logPath?qs.resolve(e.workspaceRoot,h.artifacts.logPath):qs.join(e.logsDir,`${h.id}.log`);try{await pr.prepare(h,{repoRoot:n.repoRoot});let w=await pt.create(e,{sessionId:y,taskId:h.id,repoId:n.repoId,workspaceId:n.workspaceId,repoRoot:n.repoRoot,worktreePath:h.worktreePath,logPath:o,command:p});await pr.launch(h,{repoRoot:n.repoRoot,session:w});let l=new Date().toISOString();w={...w,status:"running",startedAt:l,command:p};let g={...h,status:"running",runner:T,sessionId:w.id,selectedPtyTabId:h.selectedPtyTabId,runnerSession:{command:w.command,pid:null,startedAt:l,lastKnownState:"running",exitCode:null,exitedAt:null}};return await te(e,g),await Ye(e,w),await ve({uiStateFile:e.uiStateFile},{...await Pe({uiStateFile:e.uiStateFile})??Le(),selectedRepoId:g.repoId,selectedWorkspaceId:g.workspaceId,selectedTaskId:g.id,selectedPtyTabId:g.selectedPtyTabId}),{kind:"createTask",taskId:g.id,repoId:g.repoId,sessionId:w.id,status:g.status,branch:g.branch,worktreePath:g.worktreePath,runner:g.runner}}catch(w){let l={...h,sessionId:null,status:"draft",runnerSession:{...h.runnerSession,lastKnownState:"failed"},lastFailureReason:w instanceof Error?w.message:"Unknown Craig error"};throw await te(e,l),w}}async function tt(e,t){let r=await Re(e),i=[],a=[];await Promise.all(r.taskIds.map(async n=>{try{i.push(await Se(e,n))}catch(h){if(Ma(h)){a.push(n);return}throw h}}));let S=t?.includeClosed?i:i.filter(n=>n.status!=="closed"),T=t?.repoId?S.filter(n=>n.repoId===t.repoId):S;return T.sort((n,h)=>n.id.localeCompare(h.id)),a.sort(),{kind:"listTasks",tasks:T,missingTaskIds:a,repoId:t?.repoId??null}}function Ma(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{access as Oa}from"node:fs/promises";import zs from"node:path";async function ie(e,t){try{return await Se(e,t)}catch(r){throw Ha(r)?new Error(`Craig task "${t}" was not found.`):r}}async function ue(e){if(!await gr(e.worktreePath))throw new Error(`Task ${e.id} worktree does not exist at ${e.worktreePath}. Repair or recreate the task before retrying.`)}function mr(e,t){return t.artifacts.logPath?zs.isAbsolute(t.artifacts.logPath)?t.artifacts.logPath:zs.join(e.workspaceRoot,t.artifacts.logPath):null}async function Vs(e,t){let r=await gr(t.worktreePath),i=mr(e,t),a=i?await gr(i):!1;return{worktreeExists:r,logExists:a,recentFailureReason:t.lastFailureReason??null,runnerCommandText:t.runnerSession.command.join(" "),checksSummary:Ba(t),lastCommitSummary:Fa(t),prSummary:$a(t),cleanupSummary:Na(t)}}async function gr(e){try{return await Oa(e),!0}catch{return!1}}function Ba(e){let t=e.checks.commands.length,r=t===1?"command":"commands",i=e.checks.lastRunAt?` at ${e.checks.lastRunAt}`:"";return`${e.checks.status} (${t} ${r})${i}`}function Fa(e){return e.lastCommit?`${e.lastCommit.sha.slice(0,7)} ${e.lastCommit.message}`:"not committed"}function $a(e){if(!e.pullRequest.number||!e.pullRequest.url)return"not linked";let t=e.pullRequest.requiredChecks.length,r=t===1?"check":"checks";return`#${e.pullRequest.number} ${e.pullRequest.status??"unknown"} mergeable=${e.pullRequest.mergeable} mergeState=${e.pullRequest.mergeStateStatus??"unknown"} (${t} ${r})`}function Na(e){return 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"}function Ha(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}async function Gs(e,t){let r=await ie(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session to attach.`);let[i,a]=await Promise.all([Me(e,r.repoId),We(e,r.sessionId)]),S=await pt.attach(e,a,i.rootPath);return{kind:"attachTask",taskId:r.id,sessionId:S.id,disposition:"attached"}}import{mkdir as Ys,readFile as Wa,writeFile as ja}from"node:fs/promises";import Ft from"node:path";import Xs from"node:path";function wt(e,t){return t?Xs.isAbsolute(t)?t:Xs.join(e.repoRoot,t):null}async function lt(e){let t=await oe("gh",["auth","status"],{cwd:e});if(t.exitCode!==0)throw new Error(t.stderr.trim()||t.stdout.trim()||"GitHub CLI auth is required.")}async function Qs(e,t){let r=wt(t,e.artifacts.prDraftPath??Ft.join(".craig","artifacts",e.id,"pr.md"));if(!r)throw new Error(`Task ${e.id} is missing a PR draft artifact path.`);await Ys(Ft.dirname(r),{recursive:!0});try{await Wa(r,"utf8")}catch{await ja(r,`## Summary
|
|
55
55
|
|
|
56
56
|
- ${e.title}
|
|
57
|
-
`,"utf8")}return e.artifacts.prDraftPath=Ft.relative(t.repoRoot,r),r}async function Js(e,t){await J("gh",["pr","create","--base","main","--head",e.branch,"--title",e.lastCommit?.message??e.title,"--body-file",t],{cwd:e.worktreePath})}async function Zs(e,t){let r=t==="merge"?"--merge":t==="rebase"?"--rebase":"--squash";await J("gh",["pr","merge",String(e.pullRequest.number),r,"--delete-branch=false"],{cwd:e.worktreePath})}async function rt(e,t){let r=await J("gh",ti(t.pullRequest.number?String(t.pullRequest.number):t.branch),{cwd:t.worktreePath}),i=JSON.parse(r.stdout);return ri(e,t,i)}async function
|
|
57
|
+
`,"utf8")}return e.artifacts.prDraftPath=Ft.relative(t.repoRoot,r),r}async function Js(e,t){await J("gh",["pr","create","--base","main","--head",e.branch,"--title",e.lastCommit?.message??e.title,"--body-file",t],{cwd:e.worktreePath})}async function Zs(e,t){let r=t==="merge"?"--merge":t==="rebase"?"--rebase":"--squash";await J("gh",["pr","merge",String(e.pullRequest.number),r,"--delete-branch=false"],{cwd:e.worktreePath})}async function rt(e,t){let r=await J("gh",ti(t.pullRequest.number?String(t.pullRequest.number):t.branch),{cwd:t.worktreePath}),i=JSON.parse(r.stdout);return ri(e,t,i)}async function _r(e,t){let r=await oe("gh",ti(t.branch),{cwd:t.worktreePath});if(r.exitCode!==0)return{discovered:!1,task:t};let i=JSON.parse(r.stdout);return await ri(e,t,i),{discovered:!0,task:t}}async function wr(e,t){let i=((await _e(e)).github?.watchIntervalSeconds??10)*1e3;for(;;){if(await rt(e,t),qa(t.pullRequest))return t;await new Promise(a=>setTimeout(a,i))}}async function br(e,t){let r=wt(e,t.artifacts.prStatusPath);r&&(await Ys(Ft.dirname(r),{recursive:!0}),await ce(r,{taskId:t.id,pullRequest:t.pullRequest}))}function ei(e){return e.requiredChecks.length===0?"no required checks":e.requiredChecks.map(t=>`${t.name}:${t.status}`).join(", ")}function st(e){return e.mergeable&&e.requiredChecks.length>0&&e.requiredChecks.every(t=>t.status==="success"||t.status==="skipped")}function Ua(e){return e.requiredChecks.some(t=>t.status==="failed")}function qa(e){return st(e)||Ua(e)||e.status==="closed"||e.status==="merged"}function Ka(e){return st(e)?"merge_ready":e.status==="merged"?"merged":e.status==="open"?"pr_open":"checked"}function ti(e){return["pr","view",e,"--json","number,url,baseRefName,headRefName,headRefOid,state,mergeable,mergeStateStatus,statusCheckRollup"]}async function ri(e,t,r){let i=za(r);return t.pullRequest=i,t.status=Ka(i),await br(e,t),await te(e,t),t}function za(e){return{provider:"github",number:e.number,url:e.url,baseBranch:e.baseRefName,headBranch:e.headRefName,status:Va(e.state),mergeable:e.mergeable==="MERGEABLE",mergeStateStatus:e.mergeStateStatus,requiredChecks:Ga(e.statusCheckRollup),lastSyncedAt:new Date().toISOString(),lastSyncedHeadSha:e.headRefOid??null}}function Va(e){return e==="OPEN"?"open":e==="MERGED"?"merged":e==="CLOSED"?"closed":null}function Ga(e){return e.map(t=>Xa(t)).filter(t=>t!==null)}function Xa(e){if(typeof e!="object"||e===null)return null;let t=e,r=t.name??t.context,i=t.state??t.status??t.conclusion;return r?{name:r,status:si(i??null,t.conclusion??null),conclusion:t.conclusion??null}:null}function si(e,t){let r=e?.toUpperCase()??null,i=t?.toUpperCase()??null;return i==="SKIPPED"||r==="SKIPPED"?"skipped":r==="SUCCESS"||i==="SUCCESS"||i==="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"||i==="FAILURE"||i==="FAILED"||i==="ERROR"||i==="TIMED_OUT"||i==="CANCELLED"||i==="ACTION_REQUIRED"||i==="STARTUP_FAILURE"?"failed":r==="COMPLETED"&&i===null?"unknown":r==="COMPLETED"&&i!==null?si(i,i):"unknown"}async function bt(e,t,r){let i=await ie(e,t);await ue(i),await Ns(i.worktreePath),await lt(i.worktreePath);let a=!!i.pullRequest.number;if(!a&&(await _r(e,i)).discovered)return r.watch&&i.pullRequest.status!=="merged"&&!st(i.pullRequest)&&await wr(e,i),ii(i,r.watch,"discovered");if(i.status!=="checked"&&i.status!=="pr_open"&&i.status!=="merge_ready")throw new Error(`Task ${i.id} cannot open a pull request from status "${i.status}".`);if(!i.lastCommit)throw new Error(`Task ${i.id} must be committed before opening a pull request.`);if(!await Ot(i.worktreePath))throw new Error(`Task ${i.id} worktree must be clean before opening a pull request.`);let S=await Qs(i,e);return await te(e,i),await Hs(i.worktreePath,i.branch),i.pullRequest.number||await Js(i,S),await rt(e,i),r.watch&&i.pullRequest.status!=="merged"&&!st(i.pullRequest)&&await wr(e,i),await br(e,i),ii(i,r.watch,a?"synced":"created")}async function ni(e,t){let r=await ie(e,t);return r.pullRequest.number&&(await lt(r.worktreePath),await rt(e,r)),r}async function yr(e,t){let r=await ie(e,t);return await ue(r),await lt(r.worktreePath),r.pullRequest.number?(await rt(e,r),{disposition:"synced",task:r}):{disposition:(await _r(e,r)).discovered?"discovered":"not_found",task:r}}function ii(e,t,r){return{kind:"openPullRequest",taskId:e.id,watch:t,disposition:r,prNumber:e.pullRequest.number??0,url:e.pullRequest.url??"",status:e.status,mergeable:e.pullRequest.mergeable,requiredChecksSummary:ei(e.pullRequest)}}async function Sr(e,t){let r=await ie(e,t);if(r.pullRequest.number)try{r=await ni(e,t)}catch{}let i=await Vs(e,r),a=r.sessionId?await We(e,r.sessionId).catch(()=>null):null;return{kind:"showTask",task:r,inspection:i,session:a}}import{access as Ya}from"node:fs/promises";async function vr(e,t){let r=await ie(e,t),i=mr(e,r);if(!i)throw new Error(`Task ${r.id} does not have a Craig-managed log path.`);try{await Ya(i)}catch{throw new Error(`Task ${r.id} log file does not exist yet at ${i}.`)}return{kind:"streamTaskLogs",taskId:r.id,logPath:i}}async function kr(e,t){let r=await ie(e,t);if(await ue(r),(await J("git",["status","--short"],{cwd:r.worktreePath})).stdout.trim().length===0)return{kind:"showTaskDiff",taskId:r.id,diffText:"",isEmpty:!0};let a=await Qa(r.worktreePath);return{kind:"showTaskDiff",taskId:r.id,diffText:a,isEmpty:!1}}async function Qa(e){let t=[],r=await J("git",["diff","--stat","--patch","HEAD"],{cwd:e});r.stdout.trim().length>0&&t.push(r.stdout.trimEnd());let i=await Ja(e);for(let a of i){let S=await oe("git",["diff","--no-index","--stat","--patch","--","/dev/null",a],{cwd:e});t.push(S.stdout.trimEnd())}return t.join(`
|
|
58
58
|
|
|
59
59
|
`)}async function Ja(e){return(await J("git",["ls-files","--others","--exclude-standard"],{cwd:e})).stdout.split(`
|
|
60
|
-
`).map(r=>r.trim()).filter(r=>r.length>0)}async function kr(e,t){let r=await ie(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let i=await We(e,r.sessionId).catch(a=>{throw Za(a)?new Error(`Task ${r.id} does not have a Craig session.`):a});if(!i.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await Et(e.repoRoot,i.paneId,i.windowTarget,i.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:i.paneId}}function Za(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{spawn as ec}from"node:child_process";async function Tr(e,t){let r=await ie(e,t);await ue(r);let a=(await _e(e)).open?.command??[];if(a.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let S=[...a,r.worktreePath];return await tc(S,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:S}}async function tc(e,t){await new Promise((r,i)=>{let[a,...S]=e,T=ec(a,S,{cwd:t,stdio:"inherit"});T.on("error",i),T.on("exit",n=>{if(n===0){r();return}i(new Error(`${e.join(" ")} failed with exit code ${n??"unknown"}.`))})})}import{mkdir as rc}from"node:fs/promises";import sc from"node:path";async function Cr(e,t){let r=await ie(e,t);if(await ue(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 _t(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 a=(await _e(e)).checks?.commands??[];if(a.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);r.checks.status="running",r.checks.commands=[...a],r.checks.results=[],await te(e,r);let S=[];for(let T of a){let n=new Date().toISOString(),h=await oe("sh",["-lc",T],{cwd:r.worktreePath}),p=new Date().toISOString(),y=h.exitCode??1;if(S.push({command:T,startedAt:n,finishedAt:p,exitCode:y}),y!==0)return r.checks.results=S,r.checks.status="failed",r.checks.lastRunAt=p,r.status="review",r.lastFailureReason=h.stderr.trim()||h.stdout.trim()||`Check command failed: ${T}`,await oi(e,r),await te(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:a}}return r.checks.results=S,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await oi(e,r),await te(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:a}}async function oi(e,t){let r=wt(e,t.artifacts.checkSummaryPath);r&&(await rc(sc.dirname(r),{recursive:!0}),await ae(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))}async function Rr(e,t){let r=await ie(e,t);await ue(r);let i=await _t(r.worktreePath);if(r.status==="running"&&i&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!i)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let a=r.prompt.value.trim();await Fs(r.worktreePath),await $s(r.worktreePath,a);let S=await Mt(r.worktreePath);return r.lastCommit={sha:S.sha,message:S.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await te(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:S.sha,message:S.message}}async function ai(e,t,r){let i=[];try{if(t.sessionId){let a=await We(e,t.sessionId);await Ps(e.repoRoot,a.sessionName),t.cleanup.paneClosedAt=new Date().toISOString()}}catch(a){i.push(a instanceof Error?a.message:"Failed to close tmux session.")}if(t.cleanup.preservedWorktree=r.preserveWorktree,!r.preserveWorktree)try{await Ws(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(a){i.push(a instanceof Error?a.message:"Failed to remove worktree.")}t.cleanup.warning=i.length>0?i.join(" "):null,await te(e,t)}async function yt(e,t,r){let i=await ie(e,t);if(await ue(i),i.status!=="pr_open"&&i.status!=="merge_ready")throw new Error(`Task ${i.id} cannot merge from status "${i.status}".`);if(!i.pullRequest.number)throw new Error(`Task ${i.id} does not have a tracked pull request.`);if(!i.lastCommit)throw new Error(`Task ${i.id} must be committed before merging.`);if(!await Ot(i.worktreePath))throw new Error(`Task ${i.id} worktree must be clean before merging.`);if((await Mt(i.worktreePath)).sha!==i.lastCommit.sha)throw new Error(`Task ${i.id} local HEAD does not match the tracked task commit. Sync or commit before merging.`);await lt(i.worktreePath),await rt(e,i);let S=ic(i);if(S.length>0)throw new Error(`Task ${i.id} pull request is not merge-ready: ${S.join("; ")}.`);let n=(await _e(e)).github?.mergeMethod??"squash";return await Zs(i,n),i.pullRequest.status="merged",i.status="merged",i.lastFailureReason=null,await te(e,i),await ai(e,i,r),{kind:"mergeTask",taskId:i.id,status:i.status,prNumber:i.pullRequest.number,preservedWorktree:r.preserveWorktree,cleanupWarning:i.cleanup.warning}}function ic(e){let t=[],r=e.pullRequest;r.status!=="open"&&t.push(`PR is ${r.status??"unknown"}`),r.mergeable||t.push(`GitHub reports merge state ${r.mergeStateStatus??"unknown"}`),r.lastSyncedHeadSha!==e.lastCommit?.sha&&t.push("local task commit is not synced to the PR head"),r.requiredChecks.length===0&&t.push("no GitHub checks reported");for(let i of["failed","pending","unknown"]){let a=r.requiredChecks.filter(S=>S.status===i).map(S=>S.name);a.length>0&&t.push(`${i} checks: ${a.join(", ")}`)}return st(r)||t.push("required checks are not passing"),[...new Set(t)]}import Pr from"node:path";import{stat as oc}from"node:fs/promises";async function ci(e,t){return{kind:"listWorkspaces",workspaces:(await et(e)).filter(i=>i.status===(t.archived?"archived":"active")),archivedOnly:t.archived}}async function li(e,t){let i={...await Lt(e,t),status:"archived",archivedAt:new Date().toISOString()};return await mt(e,i),await nc(e,t),{kind:"archiveWorkspace",workspaceId:i.id,status:i.status,branch:i.branch}}async function di(e,t){let i={...await Lt(e,t),status:"active",archivedAt:null};await mt(e,i);let a=await Pe({uiStateFile:e.uiStateFile})??null;return await ve({uiStateFile:e.uiStateFile},{...a??Le(),selectedWorkspaceId:i.id,selectedRepoId:i.primaryRepoId,selectedTaskId:null}),{kind:"restoreWorkspace",workspaceId:i.id,status:i.status,branch:i.branch}}async function ui(e,t){await Ms(e,t);let r=await Re(e);await Qe(e,{...r,workspaceIds:r.workspaceIds.filter(i=>i!==t)})}async function nc(e,t){let r=await Pe({uiStateFile:e.uiStateFile});!r||r.selectedWorkspaceId!==t||await ve({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}async function $t(e,t){let r=Pr.resolve(e.workspaceRoot,t);if(!(await oc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);await cc(r);let a=await lc(r),S=await gt(e),T=S.find(w=>w.rootPath===r);if(T)return{kind:"createRepo",repo:T,workspaceId:hi(T.id),created:!1};let n=ac(S,Pr.basename(r)),h=new Date().toISOString(),p={id:n,name:Pr.basename(r),rootPath:r,defaultBranch:a,createdAt:h,updatedAt:h},y={id:hi(n),primaryRepoId:n,branch:a,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:h,updatedAt:h};await dc(e,y),await As(e,p),await mt(e,y);let o=await Re(e);return await Qe(e,{...o,repoIds:[...o.repoIds,p.id],workspaceIds:[...o.workspaceIds,y.id]}),await ve({uiStateFile:e.uiStateFile},{...await Pe({uiStateFile:e.uiStateFile})??Le(),selectedRepoId:p.id,selectedWorkspaceId:y.id,selectedTaskId:null}),{kind:"createRepo",repo:p,workspaceId:y.id,created:!0}}async function fi(e){return{kind:"listRepos",repos:await gt(e)}}async function pi(e,t){let r=await Me(e,t),a=(await et(e)).filter(p=>p.primaryRepoId===t),S=a.filter(p=>p.status==="active"),T=await tt(e,{repoId:t});if(S.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(T.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(a.map(p=>ui(e,p.id))),await Ds(e,t);let n=await Re(e);await Qe(e,{...n,repoIds:n.repoIds.filter(p=>p!==t)});let h=await Pe({uiStateFile:e.uiStateFile});return h?.selectedRepoId===t&&await ve({uiStateFile:e.uiStateFile},{...h,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}),{kind:"removeRepo",repoId:r.id,rootPath:r.rootPath}}function ac(e,t){let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",i=`repo_${r}`,a=2;for(;e.some(S=>S.id===i);)i=`repo_${r}_${a}`,a+=1;return i}function hi(e){return`workspace_${e}`}async function cc(e){try{await J("git",["rev-parse","--show-toplevel"],{cwd:e})}catch{throw new Error(`Repo path is not a git repository: ${e}`)}}async function lc(e){let r=(await J("git",["branch","--show-current"],{cwd:e})).stdout.trim();return r.length>0?r:"HEAD"}async function dc(e,t){if((await et(e)).find(a=>a.status==="active"&&a.primaryRepoId===t.primaryRepoId&&a.branch===t.branch))throw new Error(`Workspace branch already in use for repo ${t.primaryRepoId}: ${t.branch}`)}async function gi(e,t,r){let[i,a]=await Promise.all([ie(e,t),Me(e,r)]);if(i.repoId===a.id)throw new Error(`Repo ${a.id} is already the primary repo for task ${i.id}.`);let S=i.linkedRepoIds.includes(a.id)?i.linkedRepoIds:[...i.linkedRepoIds,a.id];return await te(e,{...i,linkedRepoIds:S}),{kind:"addTaskLink",taskId:i.id,repoId:a.id,linkedRepoIds:S}}async function mi(e,t){let r=await ie(e,t),i=await Promise.all(r.linkedRepoIds.map(a=>Me(e,a)));return{kind:"listTaskLinks",taskId:r.id,repos:i}}async function _i(e,t){switch(e.kind){case"addRepo":return $t(t.paths,e.path);case"listRepos":return fi(t.paths);case"removeRepo":return pi(t.paths,e.repoId);case"listWorkspaces":return ci(t.paths,{archived:e.archived});case"archiveWorkspace":return li(t.paths,e.workspaceId);case"restoreWorkspace":return di(t.paths,e.workspaceId);case"createTask":return Ks(t.paths,e.repoId,e.prompt,e.runner?{runner:e.runner}:{});case"listTasks":return e.repoId?tt(t.paths,{repoId:e.repoId}):tt(t.paths);case"attachTask":return Gs(t.paths,e.taskId);case"addTaskLink":return gi(t.paths,e.taskId,e.repoId);case"listTaskLinks":return mi(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return yr(t.paths,e.taskId);case"showSelectedTask":return yr(t.paths,Fe(t,"show"));case"streamTaskLogs":return Sr(t.paths,e.taskId);case"streamSelectedTaskLogs":return Sr(t.paths,Fe(t,"logs"));case"showTaskDiff":return vr(t.paths,e.taskId);case"showSelectedTaskDiff":return vr(t.paths,Fe(t,"diff"));case"focusTask":return kr(t.paths,e.taskId);case"focusSelectedTask":return kr(t.paths,Fe(t,"focus"));case"openTask":return Tr(t.paths,e.taskId);case"openSelectedTask":return Tr(t.paths,Fe(t,"open"));case"runChecks":return Cr(t.paths,e.taskId);case"runSelectedTaskChecks":return Cr(t.paths,Fe(t,"check"));case"commitTask":return Rr(t.paths,e.taskId);case"commitSelectedTask":return Rr(t.paths,Fe(t,"commit"));case"openPullRequest":return bt(t.paths,e.taskId,{watch:e.watch});case"openSelectedTaskPullRequest":return bt(t.paths,Fe(t,"pr"),{watch:e.watch});case"mergeTask":return yt(t.paths,e.taskId,{preserveWorktree:e.preserveWorktree});case"mergeSelectedTask":return yt(t.paths,Fe(t,"merge"),{preserveWorktree:e.preserveWorktree});case"help":return{kind:"help",text:me()};case"exit":return{kind:"exit"};default:return uc(e)}}function uc(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Fe(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>'.`)}import{mkdir as Oe,readFile as hc}from"node:fs/promises";import we from"node:path";function $e(e){let t=we.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:we.join(t,"index.json"),reposDir:we.join(t,"repos"),workspacesDir:we.join(t,"workspaces"),sessionsDir:we.join(t,"sessions"),runtimeDir:we.join(t,"runtime"),uiStateFile:we.join(t,"runtime","ui-state.json"),tasksDir:we.join(t,"tasks"),jobsDir:we.join(t,"jobs"),logsDir:we.join(t,"logs"),artifactsDir:we.join(t,"artifacts"),worktreesDir:we.join(t,"worktrees"),configFile:we.join(t,"config.json")}}async function dt(e){let t=$e(e);await Oe(t.craigDir,{recursive:!0}),await Promise.all([Oe(t.reposDir,{recursive:!0}),Oe(t.workspacesDir,{recursive:!0}),Oe(t.sessionsDir,{recursive:!0}),Oe(t.runtimeDir,{recursive:!0}),Oe(t.tasksDir,{recursive:!0}),Oe(t.jobsDir,{recursive:!0}),Oe(t.logsDir,{recursive:!0}),Oe(t.artifactsDir,{recursive:!0}),Oe(t.worktreesDir,{recursive:!0})]);try{let a=await hc(t.indexFile,"utf8"),S=JSON.parse(a);return lr(S,e,t.indexFile)}catch(a){if(!fc(a))throw a instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):a}let r=new Date().toISOString(),i={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await ae(t.indexFile,i),i}function fc(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}function wi(e){switch(e.kind){case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
|
|
60
|
+
`).map(r=>r.trim()).filter(r=>r.length>0)}async function Tr(e,t){let r=await ie(e,t);if(!r.sessionId)throw new Error(`Task ${r.id} does not have a Craig session.`);let i=await We(e,r.sessionId).catch(a=>{throw Za(a)?new Error(`Task ${r.id} does not have a Craig session.`):a});if(!i.paneId)throw new Error(`Task ${r.id} does not have a tmux target.`);return await Et(e.repoRoot,i.paneId,i.windowTarget,i.sessionName),{kind:"focusTask",taskId:r.id,tmuxTarget:i.paneId}}function Za(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}import{spawn as ec}from"node:child_process";async function Cr(e,t){let r=await ie(e,t);await ue(r);let a=(await _e(e)).open?.command??[];if(a.length===0)return{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!1,command:null};let S=[...a,r.worktreePath];return await tc(S,e.repoRoot),{kind:"openTask",taskId:r.id,worktreePath:r.worktreePath,launched:!0,command:S}}async function tc(e,t){await new Promise((r,i)=>{let[a,...S]=e,T=ec(a,S,{cwd:t,stdio:"inherit"});T.on("error",i),T.on("exit",n=>{if(n===0){r();return}i(new Error(`${e.join(" ")} failed with exit code ${n??"unknown"}.`))})})}import{mkdir as rc}from"node:fs/promises";import sc from"node:path";async function Rr(e,t){let r=await ie(e,t);if(await ue(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 _t(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 a=(await _e(e)).checks?.commands??[];if(a.length===0)throw new Error(`Craig config at ${e.configFile} does not define any "checks.commands".`);r.checks.status="running",r.checks.commands=[...a],r.checks.results=[],await te(e,r);let S=[];for(let T of a){let n=new Date().toISOString(),h=await oe("sh",["-lc",T],{cwd:r.worktreePath}),p=new Date().toISOString(),y=h.exitCode??1;if(S.push({command:T,startedAt:n,finishedAt:p,exitCode:y}),y!==0)return r.checks.results=S,r.checks.status="failed",r.checks.lastRunAt=p,r.status="review",r.lastFailureReason=h.stderr.trim()||h.stdout.trim()||`Check command failed: ${T}`,await oi(e,r),await te(e,r),{kind:"runChecks",taskId:r.id,status:"failed",commands:a}}return r.checks.results=S,r.checks.status="passed",r.checks.lastRunAt=new Date().toISOString(),r.status="checked",r.lastFailureReason=null,await oi(e,r),await te(e,r),{kind:"runChecks",taskId:r.id,status:"passed",commands:a}}async function oi(e,t){let r=wt(e,t.artifacts.checkSummaryPath);r&&(await rc(sc.dirname(r),{recursive:!0}),await ce(r,{taskId:t.id,status:t.checks.status,lastRunAt:t.checks.lastRunAt,commands:t.checks.commands,results:t.checks.results}))}async function Pr(e,t){let r=await ie(e,t);await ue(r);let i=await _t(r.worktreePath);if(r.status==="running"&&i&&(r.status="review"),r.status!=="review"&&r.status!=="checked")throw new Error(`Task ${r.id} cannot commit from status "${r.status}".`);if(!i)throw new Error(`Task ${r.id} has no uncommitted diff to commit.`);let a=r.prompt.value.trim();await Fs(r.worktreePath),await $s(r.worktreePath,a);let S=await Mt(r.worktreePath);return r.lastCommit={sha:S.sha,message:S.message,committedAt:new Date().toISOString()},r.lastFailureReason=null,await te(e,r),{kind:"commitTask",taskId:r.id,status:r.status,commitSha:S.sha,message:S.message}}async function ai(e,t,r){let i=[];try{if(t.sessionId){let a=await We(e,t.sessionId);await Ps(e.repoRoot,a.sessionName),t.cleanup.paneClosedAt=new Date().toISOString()}}catch(a){i.push(a instanceof Error?a.message:"Failed to close tmux session.")}if(t.cleanup.preservedWorktree=r.preserveWorktree,!r.preserveWorktree)try{await Ws(e.repoRoot,t.worktreePath),t.cleanup.worktreeRemovedAt=new Date().toISOString()}catch(a){i.push(a instanceof Error?a.message:"Failed to remove worktree.")}t.cleanup.warning=i.length>0?i.join(" "):null,await te(e,t)}async function yt(e,t,r){let i=await ie(e,t);if(await ue(i),i.status!=="pr_open"&&i.status!=="merge_ready")throw new Error(`Task ${i.id} cannot merge from status "${i.status}".`);if(!i.pullRequest.number)throw new Error(`Task ${i.id} does not have a tracked pull request.`);if(!i.lastCommit)throw new Error(`Task ${i.id} must be committed before merging.`);if(!await Ot(i.worktreePath))throw new Error(`Task ${i.id} worktree must be clean before merging.`);if((await Mt(i.worktreePath)).sha!==i.lastCommit.sha)throw new Error(`Task ${i.id} local HEAD does not match the tracked task commit. Sync or commit before merging.`);await lt(i.worktreePath),await rt(e,i);let S=ic(i);if(S.length>0)throw new Error(`Task ${i.id} pull request is not merge-ready: ${S.join("; ")}.`);let n=(await _e(e)).github?.mergeMethod??"squash";return await Zs(i,n),i.pullRequest.status="merged",i.status="merged",i.lastFailureReason=null,await te(e,i),await ai(e,i,r),{kind:"mergeTask",taskId:i.id,status:i.status,prNumber:i.pullRequest.number,preservedWorktree:r.preserveWorktree,cleanupWarning:i.cleanup.warning}}function ic(e){let t=[],r=e.pullRequest;r.status!=="open"&&t.push(`PR is ${r.status??"unknown"}`),r.mergeable||t.push(`GitHub reports merge state ${r.mergeStateStatus??"unknown"}`),r.lastSyncedHeadSha!==e.lastCommit?.sha&&t.push("local task commit is not synced to the PR head"),r.requiredChecks.length===0&&t.push("no GitHub checks reported");for(let i of["failed","pending","unknown"]){let a=r.requiredChecks.filter(S=>S.status===i).map(S=>S.name);a.length>0&&t.push(`${i} checks: ${a.join(", ")}`)}return st(r)||t.push("required checks are not passing"),[...new Set(t)]}import Ir from"node:path";import{stat as oc}from"node:fs/promises";async function ci(e,t){return{kind:"listWorkspaces",workspaces:(await et(e)).filter(i=>i.status===(t.archived?"archived":"active")),archivedOnly:t.archived}}async function li(e,t){let i={...await Lt(e,t),status:"archived",archivedAt:new Date().toISOString()};return await mt(e,i),await nc(e,t),{kind:"archiveWorkspace",workspaceId:i.id,status:i.status,branch:i.branch}}async function di(e,t){let i={...await Lt(e,t),status:"active",archivedAt:null};await mt(e,i);let a=await Pe({uiStateFile:e.uiStateFile})??null;return await ve({uiStateFile:e.uiStateFile},{...a??Le(),selectedWorkspaceId:i.id,selectedRepoId:i.primaryRepoId,selectedTaskId:null}),{kind:"restoreWorkspace",workspaceId:i.id,status:i.status,branch:i.branch}}async function ui(e,t){await Ms(e,t);let r=await Re(e);await Qe(e,{...r,workspaceIds:r.workspaceIds.filter(i=>i!==t)})}async function nc(e,t){let r=await Pe({uiStateFile:e.uiStateFile});!r||r.selectedWorkspaceId!==t||await ve({uiStateFile:e.uiStateFile},{...r,selectedWorkspaceId:null,selectedRepoId:null,selectedTaskId:null})}async function $t(e,t){let r=Ir.resolve(e.workspaceRoot,t);if(!(await oc(r).catch(()=>null))?.isDirectory())throw new Error(`Repo path does not exist: ${r}`);await cc(r);let a=await lc(r),S=await gt(e),T=S.find(w=>w.rootPath===r);if(T)return{kind:"createRepo",repo:T,workspaceId:hi(T.id),created:!1};let n=ac(S,Ir.basename(r)),h=new Date().toISOString(),p={id:n,name:Ir.basename(r),rootPath:r,defaultBranch:a,createdAt:h,updatedAt:h},y={id:hi(n),primaryRepoId:n,branch:a,status:"active",linkedRepoIds:[],archivedAt:null,createdAt:h,updatedAt:h};await dc(e,y),await As(e,p),await mt(e,y);let o=await Re(e);return await Qe(e,{...o,repoIds:[...o.repoIds,p.id],workspaceIds:[...o.workspaceIds,y.id]}),await ve({uiStateFile:e.uiStateFile},{...await Pe({uiStateFile:e.uiStateFile})??Le(),selectedRepoId:p.id,selectedWorkspaceId:y.id,selectedTaskId:null}),{kind:"createRepo",repo:p,workspaceId:y.id,created:!0}}async function fi(e){return{kind:"listRepos",repos:await gt(e)}}async function pi(e,t){let r=await Me(e,t),a=(await et(e)).filter(p=>p.primaryRepoId===t),S=a.filter(p=>p.status==="active"),T=await tt(e,{repoId:t});if(S.length>0)throw new Error(`Cannot remove repo ${t} while active workspace records still reference it.`);if(T.tasks.length>0)throw new Error(`Cannot remove repo ${t} while task records still reference it.`);await Promise.all(a.map(p=>ui(e,p.id))),await Ds(e,t);let n=await Re(e);await Qe(e,{...n,repoIds:n.repoIds.filter(p=>p!==t)});let h=await Pe({uiStateFile:e.uiStateFile});return h?.selectedRepoId===t&&await ve({uiStateFile:e.uiStateFile},{...h,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null}),{kind:"removeRepo",repoId:r.id,rootPath:r.rootPath}}function ac(e,t){let r=t.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"repo",i=`repo_${r}`,a=2;for(;e.some(S=>S.id===i);)i=`repo_${r}_${a}`,a+=1;return i}function hi(e){return`workspace_${e}`}async function cc(e){try{await J("git",["rev-parse","--show-toplevel"],{cwd:e})}catch{throw new Error(`Repo path is not a git repository: ${e}`)}}async function lc(e){let r=(await J("git",["branch","--show-current"],{cwd:e})).stdout.trim();return r.length>0?r:"HEAD"}async function dc(e,t){if((await et(e)).find(a=>a.status==="active"&&a.primaryRepoId===t.primaryRepoId&&a.branch===t.branch))throw new Error(`Workspace branch already in use for repo ${t.primaryRepoId}: ${t.branch}`)}async function gi(e,t,r){let[i,a]=await Promise.all([ie(e,t),Me(e,r)]);if(i.repoId===a.id)throw new Error(`Repo ${a.id} is already the primary repo for task ${i.id}.`);let S=i.linkedRepoIds.includes(a.id)?i.linkedRepoIds:[...i.linkedRepoIds,a.id];return await te(e,{...i,linkedRepoIds:S}),{kind:"addTaskLink",taskId:i.id,repoId:a.id,linkedRepoIds:S}}async function mi(e,t){let r=await ie(e,t),i=await Promise.all(r.linkedRepoIds.map(a=>Me(e,a)));return{kind:"listTaskLinks",taskId:r.id,repos:i}}async function _i(e,t){switch(e.kind){case"addRepo":return $t(t.paths,e.path);case"listRepos":return fi(t.paths);case"removeRepo":return pi(t.paths,e.repoId);case"listWorkspaces":return ci(t.paths,{archived:e.archived});case"archiveWorkspace":return li(t.paths,e.workspaceId);case"restoreWorkspace":return di(t.paths,e.workspaceId);case"createTask":return Ks(t.paths,e.repoId,e.prompt,e.runner?{runner:e.runner}:{});case"listTasks":return e.repoId?tt(t.paths,{repoId:e.repoId}):tt(t.paths);case"attachTask":return Gs(t.paths,e.taskId);case"addTaskLink":return gi(t.paths,e.taskId,e.repoId);case"listTaskLinks":return mi(t.paths,e.taskId);case"refreshInteractiveState":throw new Error("Interactive refresh should be handled by the interactive app.");case"showTask":return Sr(t.paths,e.taskId);case"showSelectedTask":return Sr(t.paths,Fe(t,"show"));case"streamTaskLogs":return vr(t.paths,e.taskId);case"streamSelectedTaskLogs":return vr(t.paths,Fe(t,"logs"));case"showTaskDiff":return kr(t.paths,e.taskId);case"showSelectedTaskDiff":return kr(t.paths,Fe(t,"diff"));case"focusTask":return Tr(t.paths,e.taskId);case"focusSelectedTask":return Tr(t.paths,Fe(t,"focus"));case"openTask":return Cr(t.paths,e.taskId);case"openSelectedTask":return Cr(t.paths,Fe(t,"open"));case"runChecks":return Rr(t.paths,e.taskId);case"runSelectedTaskChecks":return Rr(t.paths,Fe(t,"check"));case"commitTask":return Pr(t.paths,e.taskId);case"commitSelectedTask":return Pr(t.paths,Fe(t,"commit"));case"openPullRequest":return bt(t.paths,e.taskId,{watch:e.watch});case"openSelectedTaskPullRequest":return bt(t.paths,Fe(t,"pr"),{watch:e.watch});case"mergeTask":return yt(t.paths,e.taskId,{preserveWorktree:e.preserveWorktree});case"mergeSelectedTask":return yt(t.paths,Fe(t,"merge"),{preserveWorktree:e.preserveWorktree});case"help":return{kind:"help",text:me()};case"exit":return{kind:"exit"};default:return uc(e)}}function uc(e){throw new Error(`Unsupported command: ${JSON.stringify(e)}`)}function Fe(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>'.`)}import{mkdir as Oe,readFile as hc}from"node:fs/promises";import we from"node:path";function $e(e){let t=we.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:we.join(t,"index.json"),reposDir:we.join(t,"repos"),workspacesDir:we.join(t,"workspaces"),sessionsDir:we.join(t,"sessions"),runtimeDir:we.join(t,"runtime"),uiStateFile:we.join(t,"runtime","ui-state.json"),tasksDir:we.join(t,"tasks"),jobsDir:we.join(t,"jobs"),logsDir:we.join(t,"logs"),artifactsDir:we.join(t,"artifacts"),worktreesDir:we.join(t,"worktrees"),configFile:we.join(t,"config.json")}}async function dt(e){let t=$e(e);await Oe(t.craigDir,{recursive:!0}),await Promise.all([Oe(t.reposDir,{recursive:!0}),Oe(t.workspacesDir,{recursive:!0}),Oe(t.sessionsDir,{recursive:!0}),Oe(t.runtimeDir,{recursive:!0}),Oe(t.tasksDir,{recursive:!0}),Oe(t.jobsDir,{recursive:!0}),Oe(t.logsDir,{recursive:!0}),Oe(t.artifactsDir,{recursive:!0}),Oe(t.worktreesDir,{recursive:!0})]);try{let a=await hc(t.indexFile,"utf8"),S=JSON.parse(a);return dr(S,e,t.indexFile)}catch(a){if(!fc(a))throw a instanceof SyntaxError?new Error(`Craig index at ${t.indexFile} is malformed. Remove or repair the file before rerunning Craig.`):a}let r=new Date().toISOString(),i={version:2,workspaceRoot:e,repoIds:[],workspaceIds:[],taskIds:[],jobIds:[],createdAt:r,updatedAt:r};return await ce(t.indexFile,i),i}function fc(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}function wi(e){switch(e.kind){case"createRepo":return[`${e.created?"Registered":"Already registered"} repo ${e.repo.id}`,`Path: ${e.repo.rootPath}`,`Branch: ${e.repo.defaultBranch}`,`Workspace: ${e.workspaceId}`].join(`
|
|
61
61
|
`);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(`
|
|
62
62
|
`);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 a repo with 'craig repo add <path>'.":["ID STATUS REPO BRANCH",...e.workspaces.map(t=>`${t.id} ${t.status} ${t.primaryRepoId} ${t.branch}`)].join(`
|
|
63
63
|
`);case"archiveWorkspace":return`Archived workspace ${e.workspaceId} on branch ${e.branch}`;case"restoreWorkspace":return`Restored workspace ${e.workspaceId} on branch ${e.branch}`;case"createTask":return[`Created task ${e.taskId}`,`Repo: ${e.repoId}`,`Session: ${e.sessionId}`,`Status: ${e.status}`,`Branch: ${e.branch}`,`Worktree: ${e.worktreePath}`,`Runner: ${e.runner}`].join(`
|
|
@@ -67,7 +67,7 @@ ${me()}`);return t}import qs from"node:path";import{mkdir as po,readFile as go,w
|
|
|
67
67
|
`);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(`
|
|
68
68
|
`);case"openPullRequest":return[`${pc(e.disposition,e.watch)} PR for ${e.taskId}`,`PR: #${e.prNumber} ${e.url}`,`Status: ${e.status}`,`Mergeable: ${e.mergeable}`,`Checks: ${e.requiredChecksSummary}`].join(`
|
|
69
69
|
`);case"mergeTask":return[`Merged task ${e.taskId} from PR #${e.prNumber}`,`Status: ${e.status}`,`Preserved worktree: ${e.preservedWorktree}`,`Cleanup warning: ${e.cleanupWarning??"none"}`].join(`
|
|
70
|
-
`);default:return mc(e)}}function pc(e,t){return t?"Watched":e==="created"?"Created":e==="discovered"?"Discovered":"Synced"}function gc(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 mc(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function _c(e){return e.checks.status}function wc(e){return e.pullRequest.number?`#${e.pullRequest.number}:${e.pullRequest.status??"unknown"}`:"-"}import{createRequire as fu}from"node:module";import{readdir as pu,stat as gu}from"node:fs/promises";import os from"node:path";import{readFile as bc,stat as yc}from"node:fs/promises";import
|
|
70
|
+
`);default:return mc(e)}}function pc(e,t){return t?"Watched":e==="created"?"Created":e==="discovered"?"Discovered":"Synced"}function gc(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 mc(e){throw new Error(`Unsupported result: ${JSON.stringify(e)}`)}function _c(e){return e.checks.status}function wc(e){return e.pullRequest.number?`#${e.pullRequest.number}:${e.pullRequest.status??"unknown"}`:"-"}import{createRequire as fu}from"node:module";import{readdir as pu,stat as gu}from"node:fs/promises";import os from"node:path";import{readFile as bc,stat as yc}from"node:fs/promises";import xr from"node:path";var Sc=200*1024,vc=500*1024,Nt="100000";async function Si(e,t={}){try{await ue(e);let[r,i]=await Promise.all([kc(e.worktreePath),Tc(e.worktreePath)]),a=[...new Set(i.map(o=>o.path))],S=yi(t.selectedFilePath??null,r),T=yi(t.selectedDiffPath??null,a),[n,h]=await Promise.all([Ti(e.worktreePath,S),Promise.all(a.map(async o=>[o,await xc(e.worktreePath,o,i)]))]),p=Object.fromEntries(h),y=T?p[T]??xe("No diff selected","No local changes found.","empty"):xe("No diff selected","No local changes found.","empty");return{taskId:e.id,fileRows:Ec(r),filePaths:r,diffRows:i,diffPaths:a,diffContents:p,selectedFilePath:S,selectedDiffPath:T,selectedFile:n,selectedDiff:y,error:null}}catch(r){let i=r instanceof Error?r.message:"Unable to inspect task worktree.";return{taskId:e.id,fileRows:[],filePaths:[],diffRows:[],diffPaths:[],diffContents:{},selectedFilePath:null,selectedDiffPath:null,selectedFile:xe("Files unavailable",i,"error"),selectedDiff:xe("Diff unavailable",i,"error"),error:i}}}async function kc(e){let t=await J("git",["ls-files","--cached","--others","--exclude-standard"],{cwd:e});return Ci(t.stdout)}async function Tc(e){let[t,r,i,a]=await Promise.all([Cc(e),bi(e,"staged"),bi(e,"unstaged"),Rc(e)]);return[...t,...r,...i,...a]}async function Cc(e){let t=await ki(e);if(!t)return[];let r=await J("git",["diff","--name-status",`${t}...HEAD`],{cwd:e}),i=vi(r.stdout);return(await Promise.all(i.map(async S=>{let T=await Ic(e,t,S.path);return{group:"branch",path:S.path,status:S.status,additions:T.additions,deletions:T.deletions}}))).sort((S,T)=>S.path.localeCompare(T.path))}async function bi(e,t){let i=await J("git",t==="staged"?["diff","--cached","--name-status"]:["diff","--name-status"],{cwd:e}),a=vi(i.stdout);return(await Promise.all(a.map(async T=>{let n=await Pc(e,t,T.path);return{group:t,path:T.path,status:T.status,additions:n.additions,deletions:n.deletions}}))).sort((T,n)=>T.path.localeCompare(n.path))}async function Rc(e){let t=await J("git",["ls-files","--others","--exclude-standard"],{cwd:e}),r=Ci(t.stdout);return await Promise.all(r.map(async a=>{let S=await Ti(e,a),T=S.status==="ready"?Ac(S.lines):null;return{group:"untracked",path:a,status:"A",additions:T,deletions:0}}))}function vi(e){return e.split(`
|
|
71
71
|
`).map(t=>t.trim()).filter(t=>t.length>0).map(t=>{let[r="M",...i]=t.split(" ");return{status:r,path:i.at(-1)??""}}).filter(t=>t.path.length>0)}async function Pc(e,t,r){let a=await J("git",t==="staged"?["diff","--cached","--numstat","--",r]:["diff","--numstat","--",r],{cwd:e}),[S="-",T="-"]=(a.stdout.split(`
|
|
72
72
|
`)[0]??"").split(" ");return{additions:S==="-"?null:Number(S),deletions:T==="-"?null:Number(T)}}async function Ic(e,t,r){let i=await J("git",["diff","--numstat",`${t}...HEAD`,"--",r],{cwd:e}),[a="-",S="-"]=(i.stdout.split(`
|
|
73
73
|
`)[0]??"").split(" ");return{additions:a==="-"?null:Number(a),deletions:S==="-"?null:Number(S)}}async function ki(e){return(await oe("git",["show-ref","--verify","--quiet","refs/remotes/origin/main"],{cwd:e})).exitCode===0?"origin/main":(await oe("git",["show-ref","--verify","--quiet","refs/heads/main"],{cwd:e})).exitCode===0?"main":null}async function Ti(e,t){if(!t)return xe("No file selected","No Git-visible files found.","empty");let r=Dc(e,t);try{let i=await yc(r);if(i.size>Sc)return xe(t,`File is ${i.size} bytes, above the 200 KB inline preview limit.`,"too_large",t,i.size);let a=await bc(r);return Lc(a)?xe(t,"Binary file preview is not available in Craig.","binary",t,a.byteLength):{path:t,status:"ready",title:t,lines:a.toString("utf8").split(`
|
|
@@ -79,25 +79,25 @@ ${T.stdout.trimEnd()}`)}let S=i.join(`
|
|
|
79
79
|
|
|
80
80
|
`);return S.length>vc?xe(t,"Diff is above the 500 KB inline preview limit.","too_large",t,S.length):S.includes("\0")?xe(t,"Binary diff preview is not available in Craig.","binary",t,S.length):{path:t,status:S.length>0?"ready":"empty",title:t,lines:S.length>0?S.split(`
|
|
81
81
|
`):["No diff for this file."],byteLength:S.length}}function Ec(e){let t=[],r=new Set;for(let i of e){let a=i.split("/");for(let S=0;S<a.length-1;S+=1){let T=a.slice(0,S+1).join("/");r.has(T)||(r.add(T),t.push({kind:"directory",path:T,depth:S,label:a[S]??T}))}t.push({kind:"file",path:i,depth:a.length-1,label:a.at(-1)??i})}return t}function yi(e,t){return e&&t.includes(e)?e:t[0]??null}function Ac(e){return e.length===1&&e[0]===""?0:e.at(-1)===""?e.length-1:e.length}function Ci(e){return[...new Set(e.split(`
|
|
82
|
-
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Dc(e,t){let r=Ir.resolve(e,t),i=Ir.resolve(e);if(r!==i&&!r.startsWith(`${i}${Ir.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Lc(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function xe(e,t,r,i=null,a=null){return{path:i,status:r,title:e,lines:[t],byteLength:a}}import{access as Mc}from"node:fs/promises";async function Ri(e,t){let r=await ie(e,t),i=await Oc(r.worktreePath),a={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:i&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await te(e,a),a}async function Oc(e){try{return await Mc(e),!0}catch{return!1}}import kt from"node:path";function Pi(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 Ii="\u{F024B} ",xi="\u{F0DCF} ",Ei="\u25CB",Ai="\uEA64",Di="\uEAFE",Li="\uEBDA",xr="\u25CB",Er="\u25CF",Ar="\u2713",Dr="\u2715";function Mi(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 Bc=["tasks","center","inspector","actions"],Ni=["agent","terminal"],Hi=[],ne="inspection",Lg=[...Ni,...Hi],Wi=["commit","push","create-pr","refresh-checks","merge","close-task"],Fc=["refresh-checks","close-task"],ji=["task","checks","pr","setup-run","actions","next-action"],Ui=["diff","files","review"];function qi(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,i=Zc(e?.openInspectionKind)??r,a=ot(t);return{inputMode:tl(e?.inputMode),focusedRegion:Qc(e?.focusedRegion),selectedRepoId:Ue(e?.selectedRepoId),selectedTaskId:Ue(e?.selectedTaskId),selectedPtyTabId:Ue(e?.selectedPtyTabId),selectedLeftItemId:dl(Ue(e?.selectedTaskId)),activeTab:r?ne:Ue(e?.activeTab)??"agent",preferredPtyTabKind:el(e?.preferredPtyTabKind),inspectorSection:St(e?.inspectorSection,ji,"task"),inspectionMode:Jc(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:i,selectedFileTreePath:Ue(e?.selectedFileTreePath),selectedFilePath:Ue(e?.selectedFilePath),selectedDiffPath:Ue(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,selectedActionId:St(e?.selectedActionId,Wi,"commit"),selectedRunner:rl(e?.selectedRunner,a,Xe(t)),centerTabRunner:null,actionMessage:null,taskPromptInput:null,taskPromptError:null,workspaceBrowser:null,terminal:$c(),centerZoomed:!1}}function $c(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Ki(e,t){return{...e??Le(),selectedRepoId:t.selectedRepoId,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 jt(e,t,r={}){let i=cl(e,t),a=Zi(i),T=((a?.kind==="repo"?t.repos.find(p=>p.id===a.id)??null:a?.kind==="task"?t.repos.find(p=>p.id===t.tasks.find(y=>y.id===a.id)?.repoId)??null:null)??t.repos.find(p=>p.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,n=T?t.tasks.filter(p=>p.repoId===T):[],h=(a?.kind==="task"?n.find(p=>p.id===a.id)??null:null)??n.find(p=>p.id===e.selectedTaskId)??n[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:i,selectedRepoId:T,selectedTaskId:h?.id??null,...il(h,e.activeTab,e.selectedPtyTabId),selectedFilePath:t.inspection&&t.inspection.taskId===h?.id?t.inspection.selectedFilePath:e.selectedFilePath,...nl(e,t,h?.id??null),selectedDiffPath:Gc(e,t,h?.id??null),inspectorSection:St(e.inspectorSection,ji,"task")}}function zi(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Nc(t)?X({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null},changed:!0,detachTerminal:!0}):X({state:e});if(t==="q"||t==="Q")return X({state:e,exit:!0});if(t==="ESCAPE")return X({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return X({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&Mr(e.selectedLeftItemId))return X({state:{...e,selectedRunner:Br(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Oi(e,1);if(t==="SHIFT_TAB"||t==="[")return Oi(e,-1);if(t==="z"||t==="Z")return X({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===ne?qe(e,-1,r):Bi(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===ne?qe(e,1,r):Bi(e,1,r);if(t==="PAGE_UP")return qe(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return qe(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return qe(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return qe(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let i=r.enabledRunnerIds??de,a=e.centerTabRunner?i.indexOf(e.centerTabRunner):-1,S=a===i.length-1?null:i[a+1];return X({state:{...e,centerTabRunner:S,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let i=sl(e,t);return X({state:{...e,preferredPtyTabKind:i,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:i,createPtyTabRunner:i==="agent"?e.centerTabRunner:null})}if((t==="R"||t==="r")&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return X({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if((t==="X"||t==="x")&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return X({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if((t==="X"||t==="x")&&e.focusedRegion==="tasks"&&Wt(e.selectedLeftItemId)&&e.selectedTaskId)return X({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="x"&&e.focusedRegion==="center"&&$i(e.activeTab,r.ptyTabIds??[]))return X({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Lr(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fi(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Lr(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fi(e,1)}if(Ke(t)){if(e.focusedRegion==="tasks"&&Mr(e.selectedLeftItemId)){let i=en(e.selectedLeftItemId);return X({state:{...e,selectedRepoId:i??e.selectedRepoId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return X({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Wt(e.selectedLeftItemId)&&e.selectedTaskId)return X({state:{...e,inputMode:"terminal",activeTab:e.selectedPtyTabId??e.activeTab,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&$i(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return X({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Fr(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===ne)return X({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let i=e.selectedFileTreePath??e.selectedFilePath;if(i&&(r.fileTreeDirectoryIds??[]).includes(i))return X({state:qc({...e,selectedFileTreePath:i}),changed:!0});let a=i&&(r.fileTreeFileIds??[]).includes(i)?i:e.selectedFilePath;return X({state:{...e,selectedFileTreePath:a,selectedFilePath:a,activeTab:ne,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?X({state:{...e,activeTab:ne,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="refresh-checks"?X({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?X({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):X({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?X({state:e}):e.selectedActionId==="create-pr"?X({state:{...e,actionMessage:null},changed:!0,syncPullRequest:!0}):e.selectedActionId==="refresh-checks"?X({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="merge"?X({state:{...e,actionMessage:null},changed:!0,mergeTask:!0}):e.selectedActionId==="close-task"?X({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):X({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return X({state:e})}function vt(e,t){return{...e,terminal:t}}function Vi(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Nc(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function Ke(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
83
|
-
`}function Gi(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Xi(e){return Yi(e)||/:(?:agent|terminal)(?:-\d+)?$/.test(e)}function Hc(e){return Hi.includes(e)}function Yi(e){return Ni.includes(e)}function Qi(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[ne]:[]]}var Wc=["tasks","center","inspector"];function Oi(e,t){return Ht(e,"focusedRegion",Wc,t)}function Lr(e,t,r){let i=Ht(e,"activeTab",r&&r.length>0?r:al(e),t);return!i.changed||Hc(i.state.activeTab)?i:{...i,state:{...i.state,selectedPtyTabId:i.state.activeTab,preferredPtyTabKind:Fr(i.state.activeTab)??i.state.preferredPtyTabKind}}}function Bi(e,t,r){if(e.focusedRegion==="tasks")return jc(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Lr(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ji(e,t,r);if(e.inspectionMode==="diff"){let i=Or(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return i.changed?{...i,state:{...i.state,diffScrollOffset:0}}:i}return Ht(e,"selectedActionId",Fc,t)}return Ht(e,"selectedActionId",Wi,t)}function jc(e,t,r){let i=Or(e,"selectedLeftItemId",r,t);if(!i.changed)return i;let a=Zi(i.state.selectedLeftItemId);if(a?.kind==="task")return{...i,state:{...i.state,selectedTaskId:a.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0},refreshInspection:!0};if(a?.kind==="repo")return{...i,state:{...i.state,selectedRepoId:a.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0},refreshInspection:!0};let S=en(i.state.selectedLeftItemId);return S?{...i,state:{...i.state,selectedRepoId:S}}:i}function qe(e,t,r){if(t===0)return X({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ji(e,t,r);if(e.inspectionMode==="diff"){let i=Or(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return i.changed?{...i,state:{...i.state,diffScrollOffset:0}}:i}return X({state:e})}if(e.focusedRegion==="center"&&e.activeTab===ne){if(e.openInspectionKind==="file")return Kc(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return zc(e,t,r)}return X({state:e})}function Uc(e,t){if(e.inspectionMode===t)return X({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,i=t==="diff"||t==="files"?ne:e.activeTab;return X({state:{...e,inspectionMode:t,activeTab:i,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Fi(e,t){return Uc(e,Yc(e.inspectionMode,Ui,t))}function Ji(e,t,r){let i=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(i.length===0)return X({state:e});let a=e.selectedFileTreePath??e.selectedFilePath??i[0]??null,S=i.indexOf(a??""),T=Ne(S===-1?0:S+t,0,i.length-1),n=i[T]??null;if(n===e.selectedFileTreePath)return X({state:e});let h=n!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(n);return X({state:{...e,selectedFileTreePath:n,selectedFilePath:h?n:e.selectedFilePath,fileScrollOffset:h?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:h})}function qc(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,i)=>r.localeCompare(i)),actionMessage:null}}function Kc(e,t,r,i,a=10){let S=Math.max(0,i-Math.max(1,a)),T=Ne(e[t]+r,0,S);return T===e[t]?X({state:e}):X({state:{...e,[t]:T,actionMessage:null},changed:!0})}function zc(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Vc(e,t,r);let i=r.diffLineCount??0,a=r.pageRows??10,S=Math.max(0,i-Math.max(1,a)),T=e.diffScrollOffset+t,n=r.diffPathIds??[];if(n.length===0||!e.selectedDiffPath){let y=Ne(T,0,S);return y===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:y,actionMessage:null},changed:!0})}let h=n.indexOf(e.selectedDiffPath);if(h===-1){let y=Ne(T,0,S);return y===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:y,actionMessage:null},changed:!0})}if(t>0&&T>S){let y=n[h+1]??null;return y?X({state:{...e,selectedDiffPath:y,diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===S?X({state:e}):X({state:{...e,diffScrollOffset:S,actionMessage:null},changed:!0})}if(t<0&&T<0){let y=n[h-1]??null;return y?X({state:{...e,selectedDiffPath:y,diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?X({state:e}):X({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let p=Ne(T,0,S);return p===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:p,actionMessage:null},changed:!0})}function Vc(e,t,r){let i=r.diffLineCount??0,a=r.pageRows??10,S=Math.max(0,i-Math.max(1,a)),T=Ne(e.diffScrollOffset+t,0,S),n=Xc(r.diffPathRanges??[],T)??e.selectedDiffPath;return T===e.diffScrollOffset&&n===e.selectedDiffPath?X({state:e}):X({state:{...e,diffScrollOffset:T,selectedDiffPath:n,actionMessage:null},changed:!0})}function Gc(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function Xc(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Ht(e,t,r,i){let a=r.indexOf(e[t]),S=Ne(a+i,0,r.length-1),T=r[S];return!T||T===e[t]?X({state:e}):X({state:{...e,[t]:T,actionMessage:null},changed:!0})}function Or(e,t,r,i,a=!1){if(r.length===0)return X({state:e});let S=r.indexOf(e[t]??r[0]??""),T=Ne(S===-1?0:S+i,0,r.length-1),n=r[T]??null;return n===e[t]?X({state:e}):X({state:{...e,[t]:n,actionMessage:null},changed:!0,refreshInspection:a})}function Yc(e,t,r){let i=t.indexOf(e);return t[Ne(i+r,0,t.length-1)]??e}function X(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,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,syncPullRequest:e.syncPullRequest??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,mergeTask:e.mergeTask??!1,closeTask:e.closeTask??!1,refreshInspection:e.refreshInspection??!1}}function St(e,t,r){return t.includes(e??"")?e:r}function Qc(e){return e==="tabs"?"center":St(e,Bc,"tasks")}function Jc(e,t){return e==="checks"||e==="actions"||e==="review"?"review":St(e,Ui,t)}function Zc(e){return e==="file"||e==="diff"?e:null}function el(e){return e==="terminal"?"terminal":"agent"}function tl(e){return e==="terminal"?"terminal":"control"}function rl(e,t=[...de],r="codex"){return e&&at(e)&&t.includes(e)?e:r}function Br(e,t=de){let r=t.length>0?t:de,i=r.indexOf(e);return r[(i+1)%r.length]??r[0]??"codex"}function Fr(e){return/:agent(?:-\d+)?$/.test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function sl(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Fr(e.activeTab)??e.preferredPtyTabKind}function il(e,t,r){if(!e)return{activeTab:t===ne?t:"agent",selectedPtyTabId:null};let i=e.ptyTabs.find(n=>n.id===r)??null,a=e.selectedPtyTabId?e.ptyTabs.find(n=>n.id===e.selectedPtyTabId)??null:null,S=e.ptyTabs.find(n=>n.id===t)??null;if(S)return{activeTab:S.id,selectedPtyTabId:S.id};if(Yi(t)){let h=e.ptyTabs.find(p=>p.kind===t)??null??a??i??e.ptyTabs[0]??null;return{activeTab:h?.id??ne,selectedPtyTabId:h?.id??null}}if(t===ne)return{activeTab:ne,selectedPtyTabId:i?.id??a?.id??e.ptyTabs[0]?.id??null};let T=a??i??e.ptyTabs[0]??null;return{activeTab:T?.id??ne,selectedPtyTabId:T?.id??null}}function nl(e,t,r){if(!t.inspection||t.inspection.taskId!==r)return{selectedFileTreePath:e.selectedFileTreePath,collapsedFileTreePaths:e.collapsedFileTreePaths};let i=e.selectedFileTreePath??t.inspection.selectedFilePath,a=e.selectedFileTreePath===null&&e.collapsedFileTreePaths.length===0?ol(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:i,collapsedFileTreePaths:a}}function ol(e,t){let r=new Set;if(t){let i=t.split("/");for(let a=1;a<i.length;a+=1)r.add(i.slice(0,a).join("/"))}return e.filter(i=>i.kind==="directory"&&!i.path.includes("/")&&!r.has(i.path)).map(i=>i.path).sort((i,a)=>i.localeCompare(a))}function al(e){return[e.selectedPtyTabId,e.openInspectionKind?ne:null].filter(t=>typeof t=="string")}function $i(e,t){return t.includes(e)}function cl(e,t){let r=ll(t);return e.selectedLeftItemId&&r.includes(e.selectedLeftItemId)?e.selectedLeftItemId:e.selectedTaskId&&r.includes(`task:${e.selectedTaskId}`)?`task:${e.selectedTaskId}`:e.selectedRepoId&&r.includes(`repo:${e.selectedRepoId}`)?`repo:${e.selectedRepoId}`:r[0]??null}function ll(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 Zi(e){return e?e.startsWith("repo:")?{kind:"repo",id:e.slice(5)}:e.startsWith("task:")?{kind:"task",id:e.slice(5)}:null:null}function Ue(e){return typeof e=="string"?e:null}function dl(e){return e?`task:${e}`:null}function Wt(e){return typeof e=="string"&&e.startsWith("task:")}function Mr(e){return typeof e=="string"&&e.startsWith("new-task:")}function en(e){return Mr(e)?e.slice(9):null}function Ne(e,t,r){return Math.min(r,Math.max(t,e))}var Ut="empty",ce={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function rn(e,t){let r=t.repos.find(w=>w.id===e.selectedRepoId)??t.repos[0]??null,i=r?t.tasks.filter(w=>w.repoId===r.id):[],a=i.find(w=>w.id===e.selectedTaskId)??i[0]??null,S=Kl(t.tasks),T=pl(e,a),n=fl(e,a,T),h=n.find(w=>w.id===T)??n[0]??{id:"agent",label:"CODEX"},p=t.inspection?.taskId===a?.id?t.inspection:null,y=r?.name??"no repo",o=a?De(a.runner):De(e.selectedRunner);return{inputMode:e.inputMode,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,terminal:e.terminal,footerText:e.workspaceBrowser!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${r?`[${r.name}]`:"[no repo]"} \xB7 ${De(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:")?`r runner [${De(e.selectedRunner)}] Enter create task Esc pause ? help`:Wt(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?a===null?"n new task Tab tasks Esc pause ? help":T===ne?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${De(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?"R sync PR X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?"\u2191\u2193 navigate Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:kt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${kt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:o,liveLabel:a?.status==="running"?"live":"idle"},leftTree:ul(e,t.repos,t.tasks),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(w=>zl(w,S[w])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":h.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:o},centerTranscript:hl(T,e,r,a,e.workspaceBrowser,p),tabs:n,rightContext:ql(r,a),rightInspection:Il(e,a,p)}}function ul(e,t,r){let i=[{text:"WORKSPACES",muted:!0,focused:e.focusedRegion==="tasks"}];if(t.length===0)i.push({text:"No repos registered.",indent:2,muted:!0});else for(let S of t){let T=e.selectedLeftItemId===`repo:${S.id}`;i.push({id:`repo:${S.id}`,text:`\u25BE ${S.name}`,selected:T,focused:T&&e.focusedRegion==="tasks"});let n=r.filter(y=>y.repoId===S.id);if(n.length===0)i.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let y of n){let o=e.selectedLeftItemId===`task:${y.id}`,w=o?"\u25B8":"\u2022",l={id:`task:${y.id}`,taskId:y.id,text:`${w} ${y.id} [${y.runner}]`,indent:2,selected:o,focused:o&&e.focusedRegion==="tasks",accentDot:y.status==="running"};o&&(l.status=y.status),i.push(l)}let h=`new-task:${S.id}`,p=e.selectedLeftItemId===h;i.push({id:h,text:`+ New Task [${De(e.selectedRunner)}]`,indent:2,selected:p,focused:p&&e.focusedRegion==="tasks",muted:!p})}let a=e.selectedLeftItemId==="new-workspace";return i.push({text:"",muted:!0}),i.push({id:"new-workspace",text:"+ New Workspace",selected:a,focused:a&&e.focusedRegion==="tasks"}),i}function hl(e,t,r,i,a,S=null){if(a){let n=a.entries.length===0?["No directories or git repos here."]:a.entries.map((h,p)=>{let y=p===a.selectedIndex?"\u25B8":" ",o=h.kind==="repo"?" [git repo]":"/";return`${y} ${h.name}${o}`});return ke(["Browse for a workspace to register.",a.cwd,"",...n,"",a.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 ke(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!i)return ke([`No tasks in ${r.name}.`,"",`Press n or choose + New Task to create one with ${De(t.selectedRunner)}.`]);let T=i.ptyTabs.find(n=>n.id===e)??null;return T?T.kind==="agent"?ke([`${T.title} tab ready for ${i.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."]):ke([`${T.title} tab ready for ${i.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===ne&&t.openInspectionKind==="file"?_l(i,S,t.fileScrollOffset):e===ne&&t.openInspectionKind==="diff"?wl(i,S,t.diffScrollOffset):i.ptyTabs.length===0&&!t.openInspectionKind?ke(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):ke(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function fl(e,t,r){let i=t?.ptyTabs.map(S=>({id:S.id,label:gl(S)}))??[];if(!t)return[{id:Ut,label:"EMPTY",active:r===Ut,focused:e.focusedRegion==="center"&&r===Ut}];let a=e.openInspectionKind?[{id:ne,label:ml(e)}]:[];return[...i,...a].map(S=>({...S,active:S.id===r,focused:e.focusedRegion==="center"&&S.id===r}))}function pl(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===ne&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??ne:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??ne:Ut}function gl(e){return e.title.toUpperCase()}function ml(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?kt.basename(t):"Inspect";return e.openInspectionKind==="diff"?`${r} \u0394`:r}function _l(e,t,r){if(!e)return ke(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return ke(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let i=t.selectedFile,a=nn(i.path??i.title);return[{text:i.title},{text:`${i.byteLength===null?"size unknown":`${i.byteLength} bytes`} \xB7 ${i.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...yl(i.lines,r,a)]}function wl(e,t,r){if(!e)return ke(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return ke(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let i=bl(t),a=Math.max(0,Math.min(r,Math.max(0,i.length-1)));return[{text:"All changes"},{text:`${t.diffPaths.length} files \xB7 ${i.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...i.slice(a)]}function Hr(e){if(!e)return[];let t=0;return e.diffPaths.map(r=>{let a=1+(e.diffContents[r]??e.selectedDiff).lines.length+1,S={path:r,start:t,end:t+a};return t+=a,S})}function sn(e){return Hr(e).at(-1)?.end??0}function bl(e){let t=[];for(let r of e.diffPaths){let i=e.diffContents[r]??e.selectedDiff,a=nn(i.path??i.title);t.push({text:i.title,tone:"muted"}),t.push(...Sl(i.lines,0,a)),t.push({text:""})}return t.length>0?t:ke(["No local changes."])}function ke(e){return e.map(t=>({text:t}))}function yl(e,t,r){let i=Math.max(3,String(e.length).length),a=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(a).map((S,T)=>{let n=a+T+1;return{text:`${`${String(n).padStart(i," ")} \u2502 `}${S}`,segments:[{text:String(n).padStart(i," "),style:{fg:ce.lineNumber}},{text:" \u2502 ",style:{fg:ce.gutter}},...$r(S,r)],tone:"default"}})}function Sl(e,t,r){let i=vl(e),a=Math.max(0,Math.min(t,Math.max(0,i.length-1)));return i.slice(a).map(S=>kl(S,r))}function vl(e){let t=[],r=0,i=0;for(let a of e){let S=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(a);if(S){r=Number.parseInt(S[1]??"0",10),i=Number.parseInt(S[2]??"0",10);continue}if(!(a.startsWith("diff --git")||a.startsWith("index ")||a.startsWith("+++ ")||a.startsWith("--- "))&&!(a==="staged"||a==="unstaged"||a==="untracked")){if(a.startsWith("-")&&!a.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:a.slice(1),kind:"delete"}),r+=1;continue}if(a.startsWith("+")&&!a.startsWith("+++")){t.push({oldNumber:null,newNumber:i,marker:"+",text:a.slice(1),kind:"add"}),i+=1;continue}if(a.startsWith(" ")){if(r===0&&i===0)continue;t.push({oldNumber:r,newNumber:i,marker:" ",text:a.slice(1),kind:"context"}),r+=1,i+=1;continue}}}return t}function kl(e,t){let r=tn(e.oldNumber),i=tn(e.newNumber),a=e.kind==="delete"?r:i,S=e.kind==="delete"?{bg:"2a1111",fallbackFg:ce.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:ce.diffAdd}:null,T=`${a} \u2502 ${e.text}`,n=S?Cl($r(e.text,t),S.bg,S.fallbackFg):$r(e.text,t),h=S?{fg:ce.lineNumber,bg:S.bg}:{fg:ce.lineNumber},p=S?{fg:ce.gutter,bg:S.bg}:{fg:ce.gutter};return{text:T,segments:[{text:a,style:h},{text:" \u2502 ",style:p},...n],fullBleed:S!==null}}function tn(e){return e===null?" ":String(e).padStart(4," ")}function nn(e){let t=kt.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 $r(e,t){return t==="diff"?Tl(e):t==="markdown"?Rl(e):t==="json"?Nr(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Nr(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 Tl(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:ce.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:ce.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:ce.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:ce.diffMeta}}]:[{text:e}]}function Cl(e,t,r){return e.map(i=>({text:i.text,style:{...i.style??{fg:r},bg:t}}))}function Rl(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:ce.markup,bold:!0}}]:Nr(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Nr(e,t){let r=[],i=0;for(let a of e.matchAll(t)){let S=a[0],T=a.index??0;T>i&&r.push({text:e.slice(i,T)}),r.push({text:S,style:Pl(S)}),i=T+S.length}return i<e.length&&r.push({text:e.slice(i)}),r.length>0?r:[{text:e}]}function Pl(e){return e.startsWith("//")||e.startsWith("/*")?{fg:ce.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:ce.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:ce.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:ce.markup}:{fg:ce.keyword}}function Il(e,t,r){let i=[xl(e,t),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...Dl(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Hl(e,r)]}:{title:"",rows:[...i,...jl(e,r)]}}function xl(e,t){let r=e.inspectionMode,i=[{label:"CHANGES",active:r==="diff"},{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],a=[];for(let h=0;h<i.length;h++){let p=i[h];h>0&&a.push({text:" "}),a.push({text:p.label,style:{fg:p.active?"7aa2f7":"565f89"}})}let S=El(t?.pullRequest??null),T=Al(t?.pullRequest?.requiredChecks??null);return a.push({text:" "},S,{text:" "},T),{id:"inspection-mode",text:a.map(h=>h.text).join(""),segments:a}}function El(e){return!e||!e.number?{text:Ei,style:{fg:"565f89"}}:e.status==="merged"?{text:Di,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Li,style:{fg:"f7768e"}}:{text:Ai,style:{fg:"9ece6a"}}}function Al(e){return!e||e.length===0?{text:xr,style:{fg:"565f89"}}:e.some(t=>t.status==="failed")?{text:Dr,style:{fg:"f7768e"}}:e.every(t=>t.status==="success")?{text:Ar,style:{fg:"9ece6a"}}:{text:Er,style:{fg:"e0af68"}}}function Dl(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];let r=t.pullRequest;return[{id:"review-title",text:"PR",muted:!0},r.number?{id:"pr-number",text:`#${r.number} ${r.status??"unknown"}`}:{id:"pr-number",text:"No PR linked.",muted:!0},Ll(r.url),{id:"pr-base",text:`base ${r.baseBranch??"unknown"}`,muted:r.baseBranch===null},{id:"pr-head",text:`head ${r.headBranch??t.branch}`,muted:r.headBranch===null},{id:"pr-merge",text:`merge ${r.mergeable?"ready":r.mergeStateStatus??"unknown"}`},{id:"pr-synced",text:`synced ${$l(r.lastSyncedAt)}`,muted:r.lastSyncedAt===null},{id:"pr-sha",text:`sha ${Nl(r.lastSyncedHeadSha)}`,muted:r.lastSyncedHeadSha===null},{id:"review-spacer",text:""},{id:"review-checks",text:"Checks",muted:!0},...Ml(t)]}function Ll(e){if(!e)return{id:"pr-url",text:"not created",muted:!0};let t="Open in GitHub \u2197";return{id:"pr-url",text:t,segments:[{text:t,href:e,style:{fg:"7aa2f7",underline:!0}}]}}function Ml(e){return e.pullRequest.number?e.pullRequest.requiredChecks.length===0?[{id:"pr-checks-empty",text:"No GitHub checks reported.",muted:!0}]:e.pullRequest.requiredChecks.map(Ol):[{id:"pr-checks-none",text:"No checks \u2014 sync after creating a PR.",muted:!0}]}function Ol(e){let{icon:t,color:r}=Bl(e.status),i=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${i.padEnd(16," ")} ${Fl(e.status)}`,color:r,muted:!1}}function Bl(e){switch(e){case"success":return{icon:Ar,color:"9ece6a"};case"pending":return{icon:Er,color:"e0af68"};case"failed":return{icon:Dr,color:"f7768e"};case"skipped":return{icon:xr,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Fl(e){return e==="success"?"passing":e==="failed"?"failing":e}function $l(e){return e??"--"}function Nl(e){return e?e.slice(0,7):"--"}function Hl(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(S=>[S.path,S.status])),i=Wl(t.fileRows,e.collapsedFileTreePaths),a=e.selectedFileTreePath??t.selectedFilePath;return i.map(S=>{let T=S.kind==="file"?r.get(S.path):void 0,n=T==="A"?"9ece6a":T==="M"?"e0af68":T==="D"?"f7768e":T==="??"?"565f89":void 0,h=S.kind==="directory"?e.collapsedFileTreePaths.includes(S.path)?Ii:xi:Pi(S.label),p=S.kind==="file"?Mi(S.label):void 0,y=" ".repeat(S.depth),o=p?{text:h,style:{fg:p}}:{text:h},w=n?{text:S.label,style:{fg:n}}:{text:S.label},l=[{text:y},o,w];return{id:S.path,text:`${y}${h}${S.label}`,selected:S.path===a,focused:S.path===a&&e.focusedRegion==="inspector",muted:S.kind==="directory",segments:l}})}function Wl(e,t){let r=new Set(t);return e.filter(i=>{let a=i.path.split("/");for(let S=1;S<a.length;S+=1)if(r.has(a.slice(0,S).join("/")))return!1;return!0})}function jl(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:"No local changes.",muted:!0}];let r=[];for(let i of["branch","staged","unstaged","untracked"]){let a=t.diffRows.filter(S=>S.group===i);a.length!==0&&(r.push({id:i,text:i.toUpperCase(),muted:!0}),r.push(...a.map(S=>Ul(S,e,t))))}return r}function Ul(e,t,r){let i=e.additions===null?"-":`+${e.additions}`,a=e.deletions===null?"-":`-${e.deletions}`,S=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68";return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${e.path} ${i}/${a}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:S}}function ql(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:De(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:kt.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 Kl(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function zl(e,t){return{name:De(e).toLowerCase(),health:t>0?1:0,count:String(t)}}var qt={width:120,height:36},Ee={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ut(e,t){return{width:Math.max(e??qt.width,qt.width),height:Math.max(t??qt.height,qt.height)}}import{spawn as wd}from"node:child_process";import{createHash as bd}from"node:crypto";import{createServer as yd,createConnection as _n}from"node:net";import{openSync as Sd}from"node:fs";import{mkdir as vd,readFile as zr,rm as nt,writeFile as kd}from"node:fs/promises";import{tmpdir as Td}from"node:os";import ht from"node:path";import{createRequire as td}from"node:module";var ln=uo(an(),1),Vl=1e3,Gl=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function dn(e){return new ln.default.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:Vl,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function un(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function jr(e,t){return new Promise(r=>{e.write(t,r)})}function hn(e,t=0){let r=e.buffer.active,i=[],a=r.getNullCell(),S=r.baseY+r.cursorY,T=Math.max(0,r.baseY-t);for(let n=0;n<e.rows;n+=1){let h=r.getLine(T+n);if(!h){i.push({segments:[]});continue}let p=[];for(let y=0;y<e.cols;y+=1){let o=h.getCell(y,a);!o||o.getWidth()===0||p.push({text:o.getChars()||" ",style:Ql(o,T+n===S&&y===r.cursorX)})}i.push({segments:Xl(Yl(p))})}return i}function Xl(e){let t=[];for(let r of e){let i=t.at(-1);if(i&&ed(i.style,r.style)){i.text+=r.text;continue}let a={text:r.text};fn(r.style)||(a.style=r.style),t.push(a)}return t}function Yl(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!fn(r.style))break;t-=1}return e.slice(0,t)}function Ql(e,t){let r={},i=cn(e,"fg"),a=cn(e,"bg");return i&&(r.fg=i),a&&(r.bg=a),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 cn(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let i=t==="fg"?e.isFgRGB():e.isBgRGB(),a=t==="fg"?e.getFgColor():e.getBgColor();return i?a.toString(16).padStart(6,"0"):Gl[a]??Jl(a)}function Jl(e){if(e>=16&&e<=231){let t=e-16,r=Math.floor(t/36),i=Math.floor(t%36/6),a=t%6;return[r,i,a].map(Zl).map(S=>S.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 Zl(e){return e===0?0:55+e*40}function ed(e,t){return Wr(e)===Wr(t)}function Wr(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function fn(e){return Wr(e)===""}var rd=td(import.meta.url),sd=/^CTRL_([A-Z])$/,id="\x1B[6n",nd="\x1B[c",od="\x1B[?u",ad="\x1B]10;?\x1B\\",cd="\x1B]10;?\x07",ld="\x1B]11;?\x1B\\",dd="\x1B]11;?\x07",ud={ENTER:"\r",KP_ENTER:"\r",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:""},Kt=class{sessions=new Map;shell;env;spawn;onUpdate;resolveSessionSpec;attachedTabId=null;constructor(t){this.shell=t.shell??process.env.SHELL??"/bin/zsh",this.env=t.env??process.env,this.spawn=t.spawn,this.onUpdate=t.onUpdate,this.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,i,a){let S=this.sessions.get(r);if(S)if(S.status!=="running")Ur(S),this.sessions.delete(r);else return this.attachedTabId=r,S.scrollbackLines=0,pn(S,i),this.getViewState(r);let T=this.createSession(t,r,i,a);return this.sessions.set(r,T),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||r.pty.write(t)}writeKey(t){let r=hd(t);r!==null&&this.write(r)}scrollViewport(t){let r=this.getAttachedSession();if(!r||t===0)return;let i=r.terminal.buffer.active.baseY;r.scrollbackLines=Math.max(0,Math.min(i,r.scrollbackLines-t))}resize(t){let r=this.getAttachedSession();r&&pn(r,t)}detach(){this.attachedTabId=null}disposeSession(t){let r=this.sessions.get(t);r&&(Ur(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())Ur(t);this.sessions.clear(),this.attachedTabId=null}getViewState(t){if(!t)return{status:"idle",rows:[],error:null,scrolledBack:!1};let r=this.sessions.get(t);return r?{status:r.status,rows:hn(r.terminal,r.scrollbackLines),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,i,a){let S=this.spawn??pd().spawn,T=dn(i),n=a??this.resolveSessionSpec(t,r),h=Je(this.env),{executable:p,args:y}=gd(this.shell,n.command,{cwd:n.cwd,env:h}),o=S(p,y,{name:"xterm-256color",cols:i.columns,rows:i.rows,cwd:n.cwd,env:md(h)}),w={taskId:t,tabId:r,pty:o,terminal:T,status:"running",error:null,disposables:[],scrollbackLines:0};return w.disposables.push(o.onData(l=>{_d(o,l),jr(w.terminal,l).then(()=>{this.onUpdate?.(w.tabId)})})),w.disposables.push(o.onExit(l=>{w.status="exited",jr(w.terminal,`\r
|
|
84
|
-
[process exited ${l.exitCode}]`).then(()=>{this.onUpdate?.(w.tabId)})})),w}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function hd(e){if(e.length===1)return e;let t=ud[e];if(t!==void 0)return t;let r=sd.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function pn(e,t){fd(e.pty,t),un(e.terminal,t)}function Ur(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function fd(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function pd(){return rd("node-pty")}function gd(e,t,r){if(t.length===0)return{executable:e,args:[]};let a=`${[Ze(t[0],r),...t.slice(1)].map(gn).join(" ")}; exec ${gn(e)} -l`;return{executable:e,args:["-lc",a]}}function gn(e){return`'${e.replaceAll("'","'\\''")}'`}function md(e){let t={};for(let[r,i]of Object.entries(e))typeof i=="string"&&(t[r]=i);return t.TERM=t.TERM??"xterm-256color",t}function _d(e,t){for(let a=0;a<it(t,id);a+=1)e.write("\x1B[1;1R");for(let a=0;a<it(t,nd);a+=1)e.write("\x1B[?1;2c");for(let a=0;a<it(t,od);a+=1)e.write("\x1B[?0u");let r=it(t,ad)+it(t,cd);for(let a=0;a<r;a+=1)e.write("\x1B]10;rgb:e6e6/e6e6/e6e6\x1B\\");let i=it(t,ld)+it(t,dd);for(let a=0;a<i;a+=1)e.write("\x1B]11;rgb:0a0a/0a0a/0a0a\x1B\\")}function it(e,t){if(t.length===0)return 0;let r=0,i=e.indexOf(t);for(;i!==-1;)r+=1,i=e.indexOf(t,i+t.length);return r}var Vr=3;async function wn(e){let t=Gr(e.paths);await Cd(t,e.paths,e.spawnDaemon);let r=await Tn(t.socketPath),i=new qr(r,e);return await i.ready(),i}async function bn(e,t={}){let r=Gr(e);await vd(e.runtimeDir,{recursive:!0}),await nt(r.socketPath,{force:!0});let i=new Kr(e,t),a=yd(S=>i.handleConnection(S));await Ad(a,r.socketPath),await kd(r.pidPath,String(process.pid),"utf8"),await new Promise(S=>{let T=()=>{i.closeClients(),a.close(()=>S())};i.onShutdown=T,process.once("SIGTERM",T),process.once("SIGINT",T)}),await nt(r.socketPath,{force:!0}),await nt(r.pidPath,{force:!0}),i.disposeAll()}async function yn(e){let t=Gr(e);return await
|
|
82
|
+
`).map(t=>t.trim()).filter(t=>t.length>0))].sort((t,r)=>t.localeCompare(r))}function Dc(e,t){let r=xr.resolve(e,t),i=xr.resolve(e);if(r!==i&&!r.startsWith(`${i}${xr.sep}`))throw new Error(`File path escapes task worktree: ${t}`);return r}function Lc(e){return e.subarray(0,Math.min(e.byteLength,8e3)).includes(0)}function xe(e,t,r,i=null,a=null){return{path:i,status:r,title:e,lines:[t],byteLength:a}}import{access as Mc}from"node:fs/promises";async function Ri(e,t){let r=await ie(e,t),i=await Oc(r.worktreePath),a={...r,status:"closed",cleanup:{...r.cleanup,preservedWorktree:i&&r.cleanup.worktreeRemovedAt===null,warning:null},lastFailureReason:null};return await te(e,a),a}async function Oc(e){try{return await Mc(e),!0}catch{return!1}}import kt from"node:path";function Pi(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 Ii="\u{F024B} ",xi="\u{F0DCF} ",Ei="\u25CB",Ai="\uEA64",Di="\uEAFE",Li="\uEBDA",Er="\u25CB",Ar="\u25CF",Dr="\u2713",Lr="\u2715";function Mi(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 Bc=["tasks","center","inspector","actions"],Ni=["agent","terminal"],Hi=[],ne="inspection",Lg=[...Ni,...Hi],Wi=["commit","push","create-pr","refresh-checks","merge","close-task"],Fc=["refresh-checks","close-task"],ji=["task","checks","pr","setup-run","actions","next-action"],Ui=["diff","files","review"];function qi(e,t={}){let r=e?.activeTab==="files"?"file":e?.activeTab==="diff"?"diff":null,i=Zc(e?.openInspectionKind)??r,a=ot(t);return{inputMode:tl(e?.inputMode),focusedRegion:Qc(e?.focusedRegion),selectedRepoId:Ue(e?.selectedRepoId),selectedTaskId:Ue(e?.selectedTaskId),selectedPtyTabId:Ue(e?.selectedPtyTabId),selectedLeftItemId:dl(Ue(e?.selectedTaskId)),activeTab:r?ne:Ue(e?.activeTab)??"agent",preferredPtyTabKind:el(e?.preferredPtyTabKind),inspectorSection:St(e?.inspectorSection,ji,"task"),inspectionMode:Jc(e?.inspectionMode,r==="diff"?"diff":"files"),openInspectionKind:i,selectedFileTreePath:Ue(e?.selectedFileTreePath),selectedFilePath:Ue(e?.selectedFilePath),selectedDiffPath:Ue(e?.selectedDiffPath),collapsedFileTreePaths:Array.isArray(e?.collapsedFileTreePaths)?e.collapsedFileTreePaths:[],fileScrollOffset:0,diffScrollOffset:0,selectedActionId:St(e?.selectedActionId,Wi,"commit"),selectedRunner:rl(e?.selectedRunner,a,Xe(t)),centerTabRunner:null,actionMessage:null,taskPromptInput:null,taskPromptError:null,workspaceBrowser:null,terminal:$c(),centerZoomed:!1}}function $c(){return{status:"idle",rows:[],error:null,scrolledBack:!1}}function Ki(e,t){return{...e??Le(),selectedRepoId:t.selectedRepoId,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 jt(e,t,r={}){let i=cl(e,t),a=Zi(i),T=((a?.kind==="repo"?t.repos.find(p=>p.id===a.id)??null:a?.kind==="task"?t.repos.find(p=>p.id===t.tasks.find(y=>y.id===a.id)?.repoId)??null:null)??t.repos.find(p=>p.id===e.selectedRepoId)??t.repos[0]??null)?.id??null,n=T?t.tasks.filter(p=>p.repoId===T):[],h=(a?.kind==="task"?n.find(p=>p.id===a.id)??null:null)??n.find(p=>p.id===e.selectedTaskId)??n[0]??null;return{...e,inputMode:r.resetInputMode?"control":e.inputMode,selectedLeftItemId:i,selectedRepoId:T,selectedTaskId:h?.id??null,...il(h,e.activeTab,e.selectedPtyTabId),selectedFilePath:t.inspection&&t.inspection.taskId===h?.id?t.inspection.selectedFilePath:e.selectedFilePath,...nl(e,t,h?.id??null),selectedDiffPath:Gc(e,t,h?.id??null),inspectorSection:St(e.inspectorSection,ji,"task")}}function zi(e,t,r={leftItemIds:[]}){if(e.inputMode==="terminal")return Nc(t)?X({state:{...e,inputMode:"control",centerZoomed:!1,actionMessage:null},changed:!0,detachTerminal:!0}):X({state:e});if(t==="q"||t==="Q")return X({state:e,exit:!0});if(t==="ESCAPE")return X({state:{...e,actionMessage:null},changed:e.actionMessage!==null,pause:!0});if(t==="n"||t==="N")return X({state:{...e,focusedRegion:"tasks",actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0});if((t==="r"||t==="R")&&e.focusedRegion==="tasks"&&Or(e.selectedLeftItemId))return X({state:{...e,selectedRunner:Fr(e.selectedRunner,r.enabledRunnerIds),actionMessage:null,taskPromptError:null},changed:!0});if(t==="TAB"||t==="]")return Oi(e,1);if(t==="SHIFT_TAB"||t==="[")return Oi(e,-1);if(t==="z"||t==="Z")return X({state:{...e,centerZoomed:!e.centerZoomed,actionMessage:null},changed:!0});if(t==="UP"||t==="k")return e.focusedRegion==="center"&&e.activeTab===ne?qe(e,-1,r):Bi(e,-1,r);if(t==="DOWN"||t==="j")return e.focusedRegion==="center"&&e.activeTab===ne?qe(e,1,r):Bi(e,1,r);if(t==="PAGE_UP")return qe(e,-(r.pageRows??10),r);if(t==="PAGE_DOWN")return qe(e,r.pageRows??10,r);if(t==="MOUSE_WHEEL_UP")return qe(e,-3,r);if(t==="MOUSE_WHEEL_DOWN")return qe(e,3,r);if(t==="r"&&e.focusedRegion==="center"&&e.selectedTaskId){let i=r.enabledRunnerIds??ae,a=e.centerTabRunner?i.indexOf(e.centerTabRunner):-1,S=a===i.length-1?null:i[a+1];return X({state:{...e,centerTabRunner:S,actionMessage:null},changed:!0})}if((t==="+"||t==="a"||t==="A"||t==="t"||t==="T")&&e.focusedRegion==="center"&&e.selectedTaskId){let i=sl(e,t);return X({state:{...e,preferredPtyTabKind:i,actionMessage:null},changed:!0,createPtyTab:!0,createPtyTabKind:i,createPtyTabRunner:i==="agent"?e.centerTabRunner:null})}if((t==="R"||t==="r")&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return X({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0});if((t==="X"||t==="x")&&e.focusedRegion==="inspector"&&e.inspectionMode==="review")return X({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if((t==="X"||t==="x")&&e.focusedRegion==="tasks"&&Wt(e.selectedLeftItemId)&&e.selectedTaskId)return X({state:{...e,selectedActionId:"close-task",actionMessage:null},changed:!0,closeTask:!0});if(t==="x"&&e.focusedRegion==="center"&&$i(e.activeTab,r.ptyTabIds??[]))return X({state:{...e,actionMessage:null},changed:!0,closePtyTab:!0});if(t==="LEFT"||t==="h"){if(e.focusedRegion==="center")return Mr(e,-1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fi(e,-1)}if(t==="RIGHT"||t==="l"){if(e.focusedRegion==="center")return Mr(e,1,r.centerTabIds);if(e.focusedRegion==="inspector")return Fi(e,1)}if(Ke(t)){if(e.focusedRegion==="tasks"&&Or(e.selectedLeftItemId)){let i=en(e.selectedLeftItemId);return X({state:{...e,selectedRepoId:i??e.selectedRepoId,actionMessage:null,taskPromptInput:"",taskPromptError:null},changed:!0,beginTaskPrompt:!0})}if(e.focusedRegion==="tasks"&&e.selectedLeftItemId==="new-workspace")return X({state:{...e,actionMessage:null},changed:!0,openWorkspaceBrowser:!0});if(e.focusedRegion==="tasks"&&Wt(e.selectedLeftItemId)&&e.selectedTaskId)return X({state:{...e,inputMode:"terminal",activeTab:e.selectedPtyTabId??e.activeTab,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&$i(e.activeTab,r.ptyTabIds??[])&&e.selectedTaskId)return X({state:{...e,inputMode:"terminal",selectedPtyTabId:e.activeTab,preferredPtyTabKind:Ut(e.activeTab)??e.preferredPtyTabKind,actionMessage:null},changed:!0,attachTerminal:!0});if(e.focusedRegion==="center"&&e.activeTab===ne)return X({state:{...e,actionMessage:null},changed:!0,refreshInspection:!0});if(e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="files"){let i=e.selectedFileTreePath??e.selectedFilePath;if(i&&(r.fileTreeDirectoryIds??[]).includes(i))return X({state:qc({...e,selectedFileTreePath:i}),changed:!0});let a=i&&(r.fileTreeFileIds??[]).includes(i)?i:e.selectedFilePath;return X({state:{...e,selectedFileTreePath:a,selectedFilePath:a,activeTab:ne,openInspectionKind:"file",fileScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0})}return e.focusedRegion==="inspector"&&e.selectedTaskId&&e.inspectionMode==="diff"?X({state:{...e,activeTab:ne,openInspectionKind:"diff",diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.focusedRegion==="inspector"&&e.inspectionMode==="review"?e.selectedActionId==="refresh-checks"?X({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="close-task"?X({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):X({state:{...e,selectedActionId:"refresh-checks",actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.focusedRegion!=="actions"?X({state:e}):e.selectedActionId==="create-pr"?X({state:{...e,actionMessage:null},changed:!0,syncPullRequest:!0}):e.selectedActionId==="refresh-checks"?X({state:{...e,actionMessage:null},changed:!0,refreshPullRequestChecks:!0}):e.selectedActionId==="merge"?X({state:{...e,actionMessage:null},changed:!0,mergeTask:!0}):e.selectedActionId==="close-task"?X({state:{...e,actionMessage:null},changed:!0,closeTask:!0}):X({state:{...e,actionMessage:`Action queued: ${e.selectedActionId} (inspection surfaces land in phase 4.1).`},changed:!0})}return X({state:e})}function vt(e,t){return{...e,terminal:t}}function Vi(e,t){return{...e,inputMode:"control",terminal:{status:"failed",rows:[],error:t}}}function Nc(e){return e===""||e==="CTRL_]"||e==="CTRL_RIGHT_BRACKET"}function Ke(e){return e==="ENTER"||e==="KP_ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
83
|
+
`}function Gi(e){return e.length===1&&e>=" "&&e!=="\x7F"}function Xi(e){return Yi(e)||Ut(e)!==null}function Hc(e){return Hi.includes(e)}function Yi(e){return Ni.includes(e)}function Qi(e,t){return[...e?.ptyTabs.map(r=>r.id)??[],...t?.openInspectionKind?[ne]:[]]}var Wc=["tasks","center","inspector"];function Oi(e,t){return Ht(e,"focusedRegion",Wc,t)}function Mr(e,t,r){let i=Ht(e,"activeTab",r&&r.length>0?r:al(e),t);return!i.changed||Hc(i.state.activeTab)?i:{...i,state:{...i.state,selectedPtyTabId:i.state.activeTab,preferredPtyTabKind:Ut(i.state.activeTab)??i.state.preferredPtyTabKind}}}function Bi(e,t,r){if(e.focusedRegion==="tasks")return jc(e,t,r.leftItemIds);if(e.focusedRegion==="center")return Mr(e,t,r.centerTabIds);if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ji(e,t,r);if(e.inspectionMode==="diff"){let i=Br(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return i.changed?{...i,state:{...i.state,diffScrollOffset:0}}:i}return Ht(e,"selectedActionId",Fc,t)}return Ht(e,"selectedActionId",Wi,t)}function jc(e,t,r){let i=Br(e,"selectedLeftItemId",r,t);if(!i.changed)return i;let a=Zi(i.state.selectedLeftItemId);if(a?.kind==="task")return{...i,state:{...i.state,selectedTaskId:a.id,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0},refreshInspection:!0};if(a?.kind==="repo")return{...i,state:{...i.state,selectedRepoId:a.id,selectedTaskId:null,selectedPtyTabId:null,selectedFilePath:null,selectedFileTreePath:null,selectedDiffPath:null,fileScrollOffset:0,diffScrollOffset:0},refreshInspection:!0};let S=en(i.state.selectedLeftItemId);return S?{...i,state:{...i.state,selectedRepoId:S}}:i}function qe(e,t,r){if(t===0)return X({state:e});if(e.focusedRegion==="inspector"){if(e.inspectionMode==="files")return Ji(e,t,r);if(e.inspectionMode==="diff"){let i=Br(e,"selectedDiffPath",r.diffPathIds??[],t,!0);return i.changed?{...i,state:{...i.state,diffScrollOffset:0}}:i}return X({state:e})}if(e.focusedRegion==="center"&&e.activeTab===ne){if(e.openInspectionKind==="file")return Kc(e,"fileScrollOffset",t,r.fileLineCount??0,r.pageRows);if(e.openInspectionKind==="diff")return zc(e,t,r)}return X({state:e})}function Uc(e,t){if(e.inspectionMode===t)return X({state:e});let r=t==="diff"?"diff":t==="files"?"file":e.openInspectionKind,i=t==="diff"||t==="files"?ne:e.activeTab;return X({state:{...e,inspectionMode:t,activeTab:i,openInspectionKind:r,fileScrollOffset:t==="files"?0:e.fileScrollOffset,diffScrollOffset:t==="diff"?0:e.diffScrollOffset,actionMessage:null},changed:!0,refreshInspection:!0})}function Fi(e,t){return Uc(e,Yc(e.inspectionMode,Ui,t))}function Ji(e,t,r){let i=r.fileTreeRowIds&&r.fileTreeRowIds.length>0?r.fileTreeRowIds:r.filePathIds??[];if(i.length===0)return X({state:e});let a=e.selectedFileTreePath??e.selectedFilePath??i[0]??null,S=i.indexOf(a??""),T=Ne(S===-1?0:S+t,0,i.length-1),n=i[T]??null;if(n===e.selectedFileTreePath)return X({state:e});let h=n!==null&&(r.fileTreeFileIds??r.filePathIds??[]).includes(n);return X({state:{...e,selectedFileTreePath:n,selectedFilePath:h?n:e.selectedFilePath,fileScrollOffset:h?0:e.fileScrollOffset,actionMessage:null},changed:!0,refreshInspection:h})}function qc(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,i)=>r.localeCompare(i)),actionMessage:null}}function Kc(e,t,r,i,a=10){let S=Math.max(0,i-Math.max(1,a)),T=Ne(e[t]+r,0,S);return T===e[t]?X({state:e}):X({state:{...e,[t]:T,actionMessage:null},changed:!0})}function zc(e,t,r){if(r.diffPathRanges&&r.diffPathRanges.length>0)return Vc(e,t,r);let i=r.diffLineCount??0,a=r.pageRows??10,S=Math.max(0,i-Math.max(1,a)),T=e.diffScrollOffset+t,n=r.diffPathIds??[];if(n.length===0||!e.selectedDiffPath){let y=Ne(T,0,S);return y===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:y,actionMessage:null},changed:!0})}let h=n.indexOf(e.selectedDiffPath);if(h===-1){let y=Ne(T,0,S);return y===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:y,actionMessage:null},changed:!0})}if(t>0&&T>S){let y=n[h+1]??null;return y?X({state:{...e,selectedDiffPath:y,diffScrollOffset:0,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===S?X({state:e}):X({state:{...e,diffScrollOffset:S,actionMessage:null},changed:!0})}if(t<0&&T<0){let y=n[h-1]??null;return y?X({state:{...e,selectedDiffPath:y,diffScrollOffset:Number.MAX_SAFE_INTEGER,actionMessage:null},changed:!0,refreshInspection:!0}):e.diffScrollOffset===0?X({state:e}):X({state:{...e,diffScrollOffset:0,actionMessage:null},changed:!0})}let p=Ne(T,0,S);return p===e.diffScrollOffset?X({state:e}):X({state:{...e,diffScrollOffset:p,actionMessage:null},changed:!0})}function Vc(e,t,r){let i=r.diffLineCount??0,a=r.pageRows??10,S=Math.max(0,i-Math.max(1,a)),T=Ne(e.diffScrollOffset+t,0,S),n=Xc(r.diffPathRanges??[],T)??e.selectedDiffPath;return T===e.diffScrollOffset&&n===e.selectedDiffPath?X({state:e}):X({state:{...e,diffScrollOffset:T,selectedDiffPath:n,actionMessage:null},changed:!0})}function Gc(e,t,r){return!t.inspection||t.inspection.taskId!==r||e.selectedDiffPath&&(t.inspection.diffPaths??[]).includes(e.selectedDiffPath)?e.selectedDiffPath:t.inspection.selectedDiffPath}function Xc(e,t){return e.find(r=>t>=r.start&&t<r.end)?.path??e.at(-1)?.path??null}function Ht(e,t,r,i){let a=r.indexOf(e[t]),S=Ne(a+i,0,r.length-1),T=r[S];return!T||T===e[t]?X({state:e}):X({state:{...e,[t]:T,actionMessage:null},changed:!0})}function Br(e,t,r,i,a=!1){if(r.length===0)return X({state:e});let S=r.indexOf(e[t]??r[0]??""),T=Ne(S===-1?0:S+i,0,r.length-1),n=r[T]??null;return n===e[t]?X({state:e}):X({state:{...e,[t]:n,actionMessage:null},changed:!0,refreshInspection:a})}function Yc(e,t,r){let i=t.indexOf(e);return t[Ne(i+r,0,t.length-1)]??e}function X(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,createPtyTab:e.createPtyTab??!1,createPtyTabKind:e.createPtyTabKind??null,createPtyTabRunner:e.createPtyTabRunner??null,closePtyTab:e.closePtyTab??!1,syncPullRequest:e.syncPullRequest??!1,refreshPullRequestChecks:e.refreshPullRequestChecks??!1,mergeTask:e.mergeTask??!1,closeTask:e.closeTask??!1,refreshInspection:e.refreshInspection??!1}}function St(e,t,r){return t.includes(e??"")?e:r}function Qc(e){return e==="tabs"?"center":St(e,Bc,"tasks")}function Jc(e,t){return e==="checks"||e==="actions"||e==="review"?"review":St(e,Ui,t)}function Zc(e){return e==="file"||e==="diff"?e:null}function el(e){return e==="terminal"?"terminal":"agent"}function tl(e){return e==="terminal"?"terminal":"control"}function rl(e,t=[...ae],r="codex"){return e&&at(e)&&t.includes(e)?e:r}function Fr(e,t=ae){let r=t.length>0?t:ae,i=r.indexOf(e);return r[(i+1)%r.length]??r[0]??"codex"}function Ut(e){let t=ae.join("|");return new RegExp(`:(?:agent|${t})(?:-\\d+)?$`).test(e)?"agent":/:terminal(?:-\d+)?$/.test(e)?"terminal":null}function sl(e,t){return t==="a"||t==="A"?"agent":t==="t"||t==="T"?"terminal":Ut(e.activeTab)??e.preferredPtyTabKind}function il(e,t,r){if(!e)return{activeTab:t===ne?t:"agent",selectedPtyTabId:null};let i=e.ptyTabs.find(n=>n.id===r)??null,a=e.selectedPtyTabId?e.ptyTabs.find(n=>n.id===e.selectedPtyTabId)??null:null,S=e.ptyTabs.find(n=>n.id===t)??null;if(S)return{activeTab:S.id,selectedPtyTabId:S.id};if(Yi(t)){let h=e.ptyTabs.find(p=>p.kind===t)??null??a??i??e.ptyTabs[0]??null;return{activeTab:h?.id??ne,selectedPtyTabId:h?.id??null}}if(t===ne)return{activeTab:ne,selectedPtyTabId:i?.id??a?.id??e.ptyTabs[0]?.id??null};let T=a??i??e.ptyTabs[0]??null;return{activeTab:T?.id??ne,selectedPtyTabId:T?.id??null}}function nl(e,t,r){if(!t.inspection||t.inspection.taskId!==r)return{selectedFileTreePath:e.selectedFileTreePath,collapsedFileTreePaths:e.collapsedFileTreePaths};let i=e.selectedFileTreePath??t.inspection.selectedFilePath,a=e.selectedFileTreePath===null&&e.collapsedFileTreePaths.length===0?ol(t.inspection.fileRows??[],t.inspection.selectedFilePath):e.collapsedFileTreePaths;return{selectedFileTreePath:i,collapsedFileTreePaths:a}}function ol(e,t){let r=new Set;if(t){let i=t.split("/");for(let a=1;a<i.length;a+=1)r.add(i.slice(0,a).join("/"))}return e.filter(i=>i.kind==="directory"&&!i.path.includes("/")&&!r.has(i.path)).map(i=>i.path).sort((i,a)=>i.localeCompare(a))}function al(e){return[e.selectedPtyTabId,e.openInspectionKind?ne:null].filter(t=>typeof t=="string")}function $i(e,t){return t.includes(e)}function cl(e,t){let r=ll(t);return e.selectedLeftItemId&&r.includes(e.selectedLeftItemId)?e.selectedLeftItemId:e.selectedTaskId&&r.includes(`task:${e.selectedTaskId}`)?`task:${e.selectedTaskId}`:e.selectedRepoId&&r.includes(`repo:${e.selectedRepoId}`)?`repo:${e.selectedRepoId}`:r[0]??null}function ll(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 Zi(e){return e?e.startsWith("repo:")?{kind:"repo",id:e.slice(5)}:e.startsWith("task:")?{kind:"task",id:e.slice(5)}:null:null}function Ue(e){return typeof e=="string"?e:null}function dl(e){return e?`task:${e}`:null}function Wt(e){return typeof e=="string"&&e.startsWith("task:")}function Or(e){return typeof e=="string"&&e.startsWith("new-task:")}function en(e){return Or(e)?e.slice(9):null}function Ne(e,t,r){return Math.min(r,Math.max(t,e))}var qt="empty",le={lineNumber:"3b4261",gutter:"3b4261",keyword:"9d7cd8",string:"9ece6a",literal:"ff9e64",comment:"565f89",markup:"f7768e",diffAdd:"9ece6a",diffDelete:"f7768e",diffMeta:"565f89",diffHunk:"565f89"};function rn(e,t){let r=t.repos.find(w=>w.id===e.selectedRepoId)??t.repos[0]??null,i=r?t.tasks.filter(w=>w.repoId===r.id):[],a=i.find(w=>w.id===e.selectedTaskId)??i[0]??null,S=Kl(t.tasks),T=pl(e,a),n=fl(e,a,T),h=n.find(w=>w.id===T)??n[0]??{id:"agent",label:"CODEX"},p=t.inspection?.taskId===a?.id?t.inspection:null,y=r?.name??"no repo",o=a?De(a.runner):De(e.selectedRunner);return{inputMode:e.inputMode,focusedRegion:e.focusedRegion,actionMessage:e.actionMessage,terminal:e.terminal,footerText:e.workspaceBrowser!==null?`BROWSE WORKSPACE ${e.workspaceBrowser.cwd} \u2191\u2193 move \u2192 open \u2190 up Enter add repo Esc cancel`:e.taskPromptInput!==null?`NEW TASK ${r?`[${r.name}]`:"[no repo]"} \xB7 ${De(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:")?`r runner [${De(e.selectedRunner)}] Enter create task Esc pause ? help`:Wt(e.selectedLeftItemId)?"n new task Enter attach X close task Esc pause ? help":"n new task Enter select Esc pause ? help":e.focusedRegion==="center"?a===null?"n new task Tab tasks Esc pause ? help":T===ne?"\u2191\u2193/wheel/PgUp/PgDn scroll \u2190/\u2192 switch Tab inspector Esc pause ? help":`+ new tab a ${De(e.centerTabRunner??a?.runner??e.selectedRunner)} r runner t terminal x close Enter attach Esc pause ? help`:e.inspectionMode==="review"?"R sync PR X close task \u2190/\u2192 mode Esc pause ? help":e.inspectionMode==="files"?"\u2191\u2193 navigate Enter open file \u2190/\u2192 mode Esc pause ? help":"\u2191\u2193 navigate \u2190/\u2192 mode Esc pause ? help",topRail:{workspacePath:kt.relative(process.env.HOME??"",t.workspaceRoot).length>0?`~/${kt.relative(process.env.HOME??"",t.workspaceRoot)}`:t.workspaceRoot,agent:o,liveLabel:a?.status==="running"?"live":"idle"},leftTree:ul(e,t.repos,t.tasks),runners:(t.enabledRunnerIds??["codex","cursor","claude"]).map(w=>zl(w,S[w])),centerHeader:{tabLabel:e.workspaceBrowser?"BROWSER":h.label,taskId:e.workspaceBrowser?"new workspace":a?.id??"no task",repo:y,agent:o},centerTranscript:hl(T,e,r,a,e.workspaceBrowser,p),tabs:n,rightContext:ql(r,a),rightInspection:Il(e,a,p)}}function ul(e,t,r){let i=[{text:"WORKSPACES",muted:!0,focused:e.focusedRegion==="tasks"}];if(t.length===0)i.push({text:"No repos registered.",indent:2,muted:!0});else for(let S of t){let T=e.selectedLeftItemId===`repo:${S.id}`;i.push({id:`repo:${S.id}`,text:`\u25BE ${S.name}`,selected:T,focused:T&&e.focusedRegion==="tasks"});let n=r.filter(y=>y.repoId===S.id);if(n.length===0)i.push({text:" \xB7 no tasks yet",indent:0,muted:!0});else for(let y of n){let o=e.selectedLeftItemId===`task:${y.id}`,w=o?"\u25B8":"\u2022",l={id:`task:${y.id}`,taskId:y.id,text:`${w} ${y.id} [${y.runner}]`,indent:2,selected:o,focused:o&&e.focusedRegion==="tasks",accentDot:y.status==="running"};o&&(l.status=y.status),i.push(l)}let h=`new-task:${S.id}`,p=e.selectedLeftItemId===h;i.push({id:h,text:`+ New Task [${De(e.selectedRunner)}]`,indent:2,selected:p,focused:p&&e.focusedRegion==="tasks",muted:!p})}let a=e.selectedLeftItemId==="new-workspace";return i.push({text:"",muted:!0}),i.push({id:"new-workspace",text:"+ New Workspace",selected:a,focused:a&&e.focusedRegion==="tasks"}),i}function hl(e,t,r,i,a,S=null){if(a){let n=a.entries.length===0?["No directories or git repos here."]:a.entries.map((h,p)=>{let y=p===a.selectedIndex?"\u25B8":" ",o=h.kind==="repo"?" [git repo]":"/";return`${y} ${h.name}${o}`});return ke(["Browse for a workspace to register.",a.cwd,"",...n,"",a.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 ke(["No repos registered yet.","","Run `craig repo add <path>` in command mode, then reopen the shell."]);if(!i)return ke([`No tasks in ${r.name}.`,"",`Press n or choose + New Task to create one with ${De(t.selectedRunner)}.`]);let T=i.ptyTabs.find(n=>n.id===e)??null;return T?T.kind==="agent"?ke([`${T.title} tab ready for ${i.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."]):ke([`${T.title} tab ready for ${i.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===ne&&t.openInspectionKind==="file"?_l(i,S,t.fileScrollOffset):e===ne&&t.openInspectionKind==="diff"?wl(i,S,t.diffScrollOffset):i.ptyTabs.length===0&&!t.openInspectionKind?ke(["No task tabs open.","","Press a to create an agent tab, t to create a Terminal tab, or + to create the preferred tab kind."]):ke(["No center tab selected.","","Choose a task PTY tab or open an inspection item from the right panel."])}function fl(e,t,r){let i=t?.ptyTabs.map(S=>({id:S.id,label:gl(S)}))??[];if(!t)return[{id:qt,label:"EMPTY",active:r===qt,focused:e.focusedRegion==="center"&&r===qt}];let a=e.openInspectionKind?[{id:ne,label:ml(e)}]:[];return[...i,...a].map(S=>({...S,active:S.id===r,focused:e.focusedRegion==="center"&&S.id===r}))}function pl(e,t){return t?t.ptyTabs.some(r=>r.id===e.activeTab)||e.activeTab===ne&&e.openInspectionKind?e.activeTab:e.activeTab==="agent"||e.activeTab==="terminal"?t.ptyTabs.find(r=>r.kind===e.activeTab)?.id??t.ptyTabs[0]?.id??ne:e.selectedPtyTabId&&t.ptyTabs.some(r=>r.id===e.selectedPtyTabId)?e.selectedPtyTabId:t.ptyTabs[0]?.id??ne:qt}function gl(e){return e.title.toUpperCase()}function ml(e){let t=e.openInspectionKind==="diff"?e.selectedDiffPath:e.selectedFilePath,r=t?kt.basename(t):"Inspect";return e.openInspectionKind==="diff"?`${r} \u0394`:r}function _l(e,t,r){if(!e)return ke(["No task selected.","","Select or create a task to inspect files."]);if(!t||t.error)return ke(["Files unavailable.","",t?.error??"Craig has not loaded file inspection for this task yet."]);let i=t.selectedFile,a=nn(i.path??i.title);return[{text:i.title},{text:`${i.byteLength===null?"size unknown":`${i.byteLength} bytes`} \xB7 ${i.lines.length} lines \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...yl(i.lines,r,a)]}function wl(e,t,r){if(!e)return ke(["No task selected.","","Select or create a task to inspect diffs."]);if(!t||t.error)return ke(["Diff unavailable.","",t?.error??"Craig has not loaded diff inspection for this task yet."]);let i=bl(t),a=Math.max(0,Math.min(r,Math.max(0,i.length-1)));return[{text:"All changes"},{text:`${t.diffPaths.length} files \xB7 ${i.length} rows \xB7 PgUp/PgDn or wheel scroll`,tone:"muted"},{text:""},...i.slice(a)]}function Hr(e){if(!e)return[];let t=0;return e.diffPaths.map(r=>{let a=1+(e.diffContents[r]??e.selectedDiff).lines.length+1,S={path:r,start:t,end:t+a};return t+=a,S})}function sn(e){return Hr(e).at(-1)?.end??0}function bl(e){let t=[];for(let r of e.diffPaths){let i=e.diffContents[r]??e.selectedDiff,a=nn(i.path??i.title);t.push({text:i.title,tone:"muted"}),t.push(...Sl(i.lines,0,a)),t.push({text:""})}return t.length>0?t:ke(["No local changes."])}function ke(e){return e.map(t=>({text:t}))}function yl(e,t,r){let i=Math.max(3,String(e.length).length),a=Math.max(0,Math.min(t,Math.max(0,e.length-1)));return e.slice(a).map((S,T)=>{let n=a+T+1;return{text:`${`${String(n).padStart(i," ")} \u2502 `}${S}`,segments:[{text:String(n).padStart(i," "),style:{fg:le.lineNumber}},{text:" \u2502 ",style:{fg:le.gutter}},...$r(S,r)],tone:"default"}})}function Sl(e,t,r){let i=vl(e),a=Math.max(0,Math.min(t,Math.max(0,i.length-1)));return i.slice(a).map(S=>kl(S,r))}function vl(e){let t=[],r=0,i=0;for(let a of e){let S=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(a);if(S){r=Number.parseInt(S[1]??"0",10),i=Number.parseInt(S[2]??"0",10);continue}if(!(a.startsWith("diff --git")||a.startsWith("index ")||a.startsWith("+++ ")||a.startsWith("--- "))&&!(a==="staged"||a==="unstaged"||a==="untracked")){if(a.startsWith("-")&&!a.startsWith("---")){t.push({oldNumber:r,newNumber:null,marker:"-",text:a.slice(1),kind:"delete"}),r+=1;continue}if(a.startsWith("+")&&!a.startsWith("+++")){t.push({oldNumber:null,newNumber:i,marker:"+",text:a.slice(1),kind:"add"}),i+=1;continue}if(a.startsWith(" ")){if(r===0&&i===0)continue;t.push({oldNumber:r,newNumber:i,marker:" ",text:a.slice(1),kind:"context"}),r+=1,i+=1;continue}}}return t}function kl(e,t){let r=tn(e.oldNumber),i=tn(e.newNumber),a=e.kind==="delete"?r:i,S=e.kind==="delete"?{bg:"2a1111",fallbackFg:le.diffDelete}:e.kind==="add"?{bg:"10210f",fallbackFg:le.diffAdd}:null,T=`${a} \u2502 ${e.text}`,n=S?Cl($r(e.text,t),S.bg,S.fallbackFg):$r(e.text,t),h=S?{fg:le.lineNumber,bg:S.bg}:{fg:le.lineNumber},p=S?{fg:le.gutter,bg:S.bg}:{fg:le.gutter};return{text:T,segments:[{text:a,style:h},{text:" \u2502 ",style:p},...n],fullBleed:S!==null}}function tn(e){return e===null?" ":String(e).padStart(4," ")}function nn(e){let t=kt.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 $r(e,t){return t==="diff"?Tl(e):t==="markdown"?Rl(e):t==="json"?Nr(e,/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|-?\b\d+(?:\.\d+)?\b/g):t==="javascript"||t==="css"?Nr(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 Tl(e){return e.startsWith("+")&&!e.startsWith("+++")?[{text:e,style:{fg:le.diffAdd}}]:e.startsWith("-")&&!e.startsWith("---")?[{text:e,style:{fg:le.diffDelete}}]:e.startsWith("@@")?[{text:e,style:{fg:le.diffHunk}}]:e.startsWith("diff --git")||e.startsWith("index ")||e.startsWith("+++ ")||e.startsWith("--- ")?[{text:e,style:{fg:le.diffMeta}}]:[{text:e}]}function Cl(e,t,r){return e.map(i=>({text:i.text,style:{...i.style??{fg:r},bg:t}}))}function Rl(e){return/^#{1,6}\s/.test(e)?[{text:e,style:{fg:le.markup,bold:!0}}]:Nr(e,/(`[^`]+`)|(\*\*[^*]+\*\*)|(\[[^\]]+\]\([^)]+\))/g)}function Nr(e,t){let r=[],i=0;for(let a of e.matchAll(t)){let S=a[0],T=a.index??0;T>i&&r.push({text:e.slice(i,T)}),r.push({text:S,style:Pl(S)}),i=T+S.length}return i<e.length&&r.push({text:e.slice(i)}),r.length>0?r:[{text:e}]}function Pl(e){return e.startsWith("//")||e.startsWith("/*")?{fg:le.comment,italic:!0}:e.startsWith('"')||e.startsWith("'")||e.startsWith("`")?{fg:le.string}:/^-?\d/.test(e)||e==="true"||e==="false"||e==="null"||e==="undefined"?{fg:le.literal}:e.startsWith("**")||e.startsWith("[")||e.startsWith("`")?{fg:le.markup}:{fg:le.keyword}}function Il(e,t,r){let i=[xl(e,t),{id:"mode-spacer",text:"",muted:!0}];return e.inspectionMode==="review"?{title:"",rows:[...i,...Dl(e,t)]}:e.inspectionMode==="files"?{title:"",rows:[...i,...Hl(e,r)]}:{title:"",rows:[...i,...jl(e,r)]}}function xl(e,t){let r=e.inspectionMode,i=[{label:"CHANGES",active:r==="diff"},{label:"FILES",active:r==="files"},{label:"REVIEW",active:r==="review"}],a=[];for(let h=0;h<i.length;h++){let p=i[h];h>0&&a.push({text:" "}),a.push({text:p.label,style:{fg:p.active?"7aa2f7":"565f89"}})}let S=El(t?.pullRequest??null),T=Al(t?.pullRequest?.requiredChecks??null);return a.push({text:" "},S,{text:" "},T),{id:"inspection-mode",text:a.map(h=>h.text).join(""),segments:a}}function El(e){return!e||!e.number?{text:Ei,style:{fg:"565f89"}}:e.status==="merged"?{text:Di,style:{fg:"9d7cd8"}}:e.status==="closed"?{text:Li,style:{fg:"f7768e"}}:{text:Ai,style:{fg:"9ece6a"}}}function Al(e){return!e||e.length===0?{text:Er,style:{fg:"565f89"}}:e.some(t=>t.status==="failed")?{text:Lr,style:{fg:"f7768e"}}:e.every(t=>t.status==="success")?{text:Dr,style:{fg:"9ece6a"}}:{text:Ar,style:{fg:"e0af68"}}}function Dl(e,t){if(!t)return[{id:"review-empty",text:"No task selected.",muted:!0}];let r=t.pullRequest;return[{id:"review-title",text:"PR",muted:!0},r.number?{id:"pr-number",text:`#${r.number} ${r.status??"unknown"}`}:{id:"pr-number",text:"No PR linked.",muted:!0},Ll(r.url),{id:"pr-base",text:`base ${r.baseBranch??"unknown"}`,muted:r.baseBranch===null},{id:"pr-head",text:`head ${r.headBranch??t.branch}`,muted:r.headBranch===null},{id:"pr-merge",text:`merge ${r.mergeable?"ready":r.mergeStateStatus??"unknown"}`},{id:"pr-synced",text:`synced ${$l(r.lastSyncedAt)}`,muted:r.lastSyncedAt===null},{id:"pr-sha",text:`sha ${Nl(r.lastSyncedHeadSha)}`,muted:r.lastSyncedHeadSha===null},{id:"review-spacer",text:""},{id:"review-checks",text:"Checks",muted:!0},...Ml(t)]}function Ll(e){if(!e)return{id:"pr-url",text:"not created",muted:!0};let t="Open in GitHub \u2197";return{id:"pr-url",text:t,segments:[{text:t,href:e,style:{fg:"7aa2f7",underline:!0}}]}}function Ml(e){return e.pullRequest.number?e.pullRequest.requiredChecks.length===0?[{id:"pr-checks-empty",text:"No GitHub checks reported.",muted:!0}]:e.pullRequest.requiredChecks.map(Ol):[{id:"pr-checks-none",text:"No checks \u2014 sync after creating a PR.",muted:!0}]}function Ol(e){let{icon:t,color:r}=Bl(e.status),i=e.name.length>16?`${e.name.slice(0,15)}\u2026`:e.name;return{id:`pr-check:${e.name}`,text:`${t} ${i.padEnd(16," ")} ${Fl(e.status)}`,color:r,muted:!1}}function Bl(e){switch(e){case"success":return{icon:Dr,color:"9ece6a"};case"pending":return{icon:Ar,color:"e0af68"};case"failed":return{icon:Lr,color:"f7768e"};case"skipped":return{icon:Er,color:"565f89"};default:return{icon:"?",color:"565f89"}}}function Fl(e){return e==="success"?"passing":e==="failed"?"failing":e}function $l(e){return e??"--"}function Nl(e){return e?e.slice(0,7):"--"}function Hl(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(S=>[S.path,S.status])),i=Wl(t.fileRows,e.collapsedFileTreePaths),a=e.selectedFileTreePath??t.selectedFilePath;return i.map(S=>{let T=S.kind==="file"?r.get(S.path):void 0,n=T==="A"?"9ece6a":T==="M"?"e0af68":T==="D"?"f7768e":T==="??"?"565f89":void 0,h=S.kind==="directory"?e.collapsedFileTreePaths.includes(S.path)?Ii:xi:Pi(S.label),p=S.kind==="file"?Mi(S.label):void 0,y=" ".repeat(S.depth),o=p?{text:h,style:{fg:p}}:{text:h},w=n?{text:S.label,style:{fg:n}}:{text:S.label},l=[{text:y},o,w];return{id:S.path,text:`${y}${h}${S.label}`,selected:S.path===a,focused:S.path===a&&e.focusedRegion==="inspector",muted:S.kind==="directory",segments:l}})}function Wl(e,t){let r=new Set(t);return e.filter(i=>{let a=i.path.split("/");for(let S=1;S<a.length;S+=1)if(r.has(a.slice(0,S).join("/")))return!1;return!0})}function jl(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:"No local changes.",muted:!0}];let r=[];for(let i of["branch","staged","unstaged","untracked"]){let a=t.diffRows.filter(S=>S.group===i);a.length!==0&&(r.push({id:i,text:i.toUpperCase(),muted:!0}),r.push(...a.map(S=>Ul(S,e,t))))}return r}function Ul(e,t,r){let i=e.additions===null?"-":`+${e.additions}`,a=e.deletions===null?"-":`-${e.deletions}`,S=e.status==="A"||e.group==="untracked"?"9ece6a":e.status==="D"?"f7768e":"e0af68";return{id:`${e.group}:${e.path}`,text:` ${e.status.padEnd(2," ")} ${e.path} ${i}/${a}`,selected:e.path===(t.selectedDiffPath??r.selectedDiffPath),focused:e.path===(t.selectedDiffPath??r.selectedDiffPath)&&t.focusedRegion==="inspector",color:S}}function ql(e,t){return e?t?[{label:"Task",value:t.id},{label:"Repo",value:e.name},{label:"Agent",value:De(t.runner)},{label:"Branch",value:t.branch},{label:"Status",value:t.status},{label:"Worktree",value:kt.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 Kl(e){return e.reduce((t,r)=>(t[r.runner]+=1,t),{codex:0,cursor:0,claude:0})}function zl(e,t){return{name:De(e).toLowerCase(),health:t>0?1:0,count:String(t)}}var Kt={width:120,height:36},Ee={leftWidth:42,rightWidth:36,dividerWidth:1,topRailHeight:1};function ut(e,t){return{width:Math.max(e??Kt.width,Kt.width),height:Math.max(t??Kt.height,Kt.height)}}import{spawn as wd}from"node:child_process";import{createHash as bd}from"node:crypto";import{createServer as yd,createConnection as _n}from"node:net";import{openSync as Sd}from"node:fs";import{mkdir as vd,readFile as zr,rm as nt,writeFile as kd}from"node:fs/promises";import{tmpdir as Td}from"node:os";import ht from"node:path";import{createRequire as td}from"node:module";var ln=uo(an(),1),Vl=1e3,Gl=["000000","cd3131","0dbc79","e5e510","2472c8","bc3fbc","11a8cd","e5e5e5","666666","f14c4c","23d18b","f5f543","3b8eea","d670d6","29b8db","ffffff"];function dn(e){return new ln.default.Terminal({allowProposedApi:!0,cols:e.columns,rows:e.rows,scrollback:Vl,theme:{foreground:"#e6e6e6",background:"#0a0a0a"}})}function un(e,t){(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function jr(e,t){return new Promise(r=>{e.write(t,r)})}function hn(e,t=0){let r=e.buffer.active,i=[],a=r.getNullCell(),S=r.baseY+r.cursorY,T=Math.max(0,r.baseY-t);for(let n=0;n<e.rows;n+=1){let h=r.getLine(T+n);if(!h){i.push({segments:[]});continue}let p=[];for(let y=0;y<e.cols;y+=1){let o=h.getCell(y,a);!o||o.getWidth()===0||p.push({text:o.getChars()||" ",style:Ql(o,T+n===S&&y===r.cursorX)})}i.push({segments:Xl(Yl(p))})}return i}function Xl(e){let t=[];for(let r of e){let i=t.at(-1);if(i&&ed(i.style,r.style)){i.text+=r.text;continue}let a={text:r.text};fn(r.style)||(a.style=r.style),t.push(a)}return t}function Yl(e){let t=e.length;for(;t>0;){let r=e[t-1];if(!r||r.text!==" "||!fn(r.style))break;t-=1}return e.slice(0,t)}function Ql(e,t){let r={},i=cn(e,"fg"),a=cn(e,"bg");return i&&(r.fg=i),a&&(r.bg=a),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 cn(e,t){if(t==="fg"?e.isFgDefault():e.isBgDefault())return;let i=t==="fg"?e.isFgRGB():e.isBgRGB(),a=t==="fg"?e.getFgColor():e.getBgColor();return i?a.toString(16).padStart(6,"0"):Gl[a]??Jl(a)}function Jl(e){if(e>=16&&e<=231){let t=e-16,r=Math.floor(t/36),i=Math.floor(t%36/6),a=t%6;return[r,i,a].map(Zl).map(S=>S.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 Zl(e){return e===0?0:55+e*40}function ed(e,t){return Wr(e)===Wr(t)}function Wr(e){return e?[e.fg??"",e.bg??"",e.bold?"b":"",e.dim?"d":"",e.italic?"i":"",e.underline?"u":"",e.inverse?"v":""].join("|"):""}function fn(e){return Wr(e)===""}var rd=td(import.meta.url),sd=/^CTRL_([A-Z])$/,id="\x1B[6n",nd="\x1B[c",od="\x1B[?u",ad="\x1B]10;?\x1B\\",cd="\x1B]10;?\x07",ld="\x1B]11;?\x1B\\",dd="\x1B]11;?\x07",ud={ENTER:"\r",KP_ENTER:"\r",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:""},zt=class{sessions=new Map;shell;env;spawn;onUpdate;resolveSessionSpec;attachedTabId=null;constructor(t){this.shell=t.shell??process.env.SHELL??"/bin/zsh",this.env=t.env??process.env,this.spawn=t.spawn,this.onUpdate=t.onUpdate,this.resolveSessionSpec=t.resolveSessionSpec??(()=>({cwd:t.workspaceRoot,command:[]}))}ensureSession(t,r,i,a){let S=this.sessions.get(r);if(S)if(S.status!=="running")Ur(S),this.sessions.delete(r);else return this.attachedTabId=r,S.scrollbackLines=0,pn(S,i),this.getViewState(r);let T=this.createSession(t,r,i,a);return this.sessions.set(r,T),this.attachedTabId=r,this.getViewState(r)}write(t){let r=this.getAttachedSession();!r||r.status!=="running"||r.pty.write(t)}writeKey(t){let r=hd(t);r!==null&&this.write(r)}scrollViewport(t){let r=this.getAttachedSession();if(!r||t===0)return;let i=r.terminal.buffer.active.baseY;r.scrollbackLines=Math.max(0,Math.min(i,r.scrollbackLines-t))}resize(t){let r=this.getAttachedSession();r&&pn(r,t)}detach(){this.attachedTabId=null}disposeSession(t){let r=this.sessions.get(t);r&&(Ur(r),this.sessions.delete(t),this.attachedTabId===t&&(this.attachedTabId=null))}disposeAll(){for(let t of this.sessions.values())Ur(t);this.sessions.clear(),this.attachedTabId=null}getViewState(t){if(!t)return{status:"idle",rows:[],error:null,scrolledBack:!1};let r=this.sessions.get(t);return r?{status:r.status,rows:hn(r.terminal,r.scrollbackLines),error:r.error,scrolledBack:r.scrollbackLines>0}:{status:"idle",rows:[],error:null,scrolledBack:!1}}createSession(t,r,i,a){let S=this.spawn??pd().spawn,T=dn(i),n=a??this.resolveSessionSpec(t,r),h=Je(this.env),{executable:p,args:y}=gd(this.shell,n.command,{cwd:n.cwd,env:h}),o=S(p,y,{name:"xterm-256color",cols:i.columns,rows:i.rows,cwd:n.cwd,env:md(h)}),w={taskId:t,tabId:r,pty:o,terminal:T,status:"running",error:null,disposables:[],scrollbackLines:0};return w.disposables.push(o.onData(l=>{_d(o,l),jr(w.terminal,l).then(()=>{this.onUpdate?.(w.tabId)})})),w.disposables.push(o.onExit(l=>{w.status="exited",jr(w.terminal,`\r
|
|
84
|
+
[process exited ${l.exitCode}]`).then(()=>{this.onUpdate?.(w.tabId)})})),w}getAttachedSession(){return this.attachedTabId?this.sessions.get(this.attachedTabId)??null:null}};function hd(e){if(e.length===1)return e;let t=ud[e];if(t!==void 0)return t;let r=sd.exec(e);return r?.[1]?String.fromCharCode(r[1].charCodeAt(0)-64):null}function pn(e,t){fd(e.pty,t),un(e.terminal,t)}function Ur(e){for(let t of e.disposables)t.dispose();e.terminal.dispose(),e.pty.kill()}function fd(e,t){t.columns>0&&t.rows>0&&(e.cols!==t.columns||e.rows!==t.rows)&&e.resize(t.columns,t.rows)}function pd(){return rd("node-pty")}function gd(e,t,r){if(t.length===0)return{executable:e,args:[]};let a=`${[Ze(t[0],r),...t.slice(1)].map(gn).join(" ")}; exec ${gn(e)} -l`;return{executable:e,args:["-lc",a]}}function gn(e){return`'${e.replaceAll("'","'\\''")}'`}function md(e){let t={};for(let[r,i]of Object.entries(e))typeof i=="string"&&(t[r]=i);return t.TERM=t.TERM??"xterm-256color",t}function _d(e,t){for(let a=0;a<it(t,id);a+=1)e.write("\x1B[1;1R");for(let a=0;a<it(t,nd);a+=1)e.write("\x1B[?1;2c");for(let a=0;a<it(t,od);a+=1)e.write("\x1B[?0u");let r=it(t,ad)+it(t,cd);for(let a=0;a<r;a+=1)e.write("\x1B]10;rgb:e6e6/e6e6/e6e6\x1B\\");let i=it(t,ld)+it(t,dd);for(let a=0;a<i;a+=1)e.write("\x1B]11;rgb:0a0a/0a0a/0a0a\x1B\\")}function it(e,t){if(t.length===0)return 0;let r=0,i=e.indexOf(t);for(;i!==-1;)r+=1,i=e.indexOf(t,i+t.length);return r}var Vr=3;async function wn(e){let t=Gr(e.paths);await Cd(t,e.paths,e.spawnDaemon);let r=await Tn(t.socketPath),i=new qr(r,e);return await i.ready(),i}async function bn(e,t={}){let r=Gr(e);await vd(e.runtimeDir,{recursive:!0}),await nt(r.socketPath,{force:!0});let i=new Kr(e,t),a=yd(S=>i.handleConnection(S));await Ad(a,r.socketPath),await kd(r.pidPath,String(process.pid),"utf8"),await new Promise(S=>{let T=()=>{i.closeClients(),a.close(()=>S())};i.onShutdown=T,process.once("SIGTERM",T),process.once("SIGINT",T)}),await nt(r.socketPath,{force:!0}),await nt(r.pidPath,{force:!0}),i.disposeAll()}async function yn(e){let t=Gr(e);return await Gt(t.socketPath)?(await vn(t.socketPath),!0):!1}var qr=class{constructor(t,r){this.socket=t;this.options=r,t.setEncoding("utf8"),t.on("data",i=>this.handleData(String(i))),t.on("error",i=>this.rejectAll(i instanceof Error?i:new Error(String(i)))),t.on("close",()=>{this.closed=!0,this.rejectAll(new Error("Craig PTY daemon connection closed."))})}socket;nextRequestId=1;pending=new Map;viewCache=new Map;attachedTabId=null;buffer="";closed=!1;options;async ready(){if((await this.send({type:"ping"})).protocolVersion!==Vr)throw new Error("Craig PTY daemon protocol mismatch.")}async ensureSession(t,r,i){let a=await this.send({type:"ensureSession",taskId:t,tabId:r,size:i,spec:this.options.resolveSessionSpec?.(t,r)??{cwd:this.options.workspaceRoot,command:[]}});this.attachedTabId=r;let S=a.view??{status:"idle",rows:[],error:null};return this.viewCache.set(r,S),S}async hydrateSessions(t){for(let r of t)try{let i=await this.send({type:"hydrateSession",tabId:r});i.view&&this.viewCache.set(r,i.view)}catch(i){let a=i instanceof Error?i.message:String(i);this.viewCache.set(r,{status:"failed",rows:[],error:a})}}write(t){this.send({type:"write",input:t}).catch(()=>{})}writeKey(t){this.send({type:"writeKey",key:t}).catch(()=>{})}scrollViewport(t){this.send({type:"scrollViewport",lines:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}resize(t){this.send({type:"resize",size:t}).then(r=>{this.attachedTabId&&r.view&&this.viewCache.set(this.attachedTabId,r.view)}).catch(()=>{})}detach(){this.attachedTabId=null,this.send({type:"detach"}).catch(()=>{})}disposeSession(t){this.viewCache.delete(t),this.attachedTabId===t&&(this.attachedTabId=null),this.send({type:"disposeSession",tabId:t}).catch(()=>{})}disposeAll(){this.attachedTabId=null,!this.closed&&(this.socket.end(),this.closed=!0)}getViewState(t){return t?this.viewCache.get(t)??{status:"idle",rows:[],error:null,scrolledBack:!1}:{status:"idle",rows:[],error:null,scrolledBack:!1}}async requestShutdown(){await this.send({type:"shutdown"})}async send(t){if(this.closed)throw new Error("Craig PTY daemon connection is closed.");let r=this.nextRequestId;this.nextRequestId+=1;let i={...t,id:r},a=new Promise((T,n)=>{this.pending.set(r,{resolve:T,reject:n})});if(this.socket.destroyed)throw this.pending.delete(r),new Error("Craig PTY daemon connection is closed.");this.socket.write(`${JSON.stringify(i)}
|
|
85
85
|
`);let S=await a;if(!S.ok)throw new Error(S.error);return S}handleData(t){this.buffer+=t;let r=this.buffer.indexOf(`
|
|
86
86
|
`);for(;r!==-1;){let i=this.buffer.slice(0,r);this.buffer=this.buffer.slice(r+1),this.handleMessage(i),r=this.buffer.indexOf(`
|
|
87
|
-
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let i=this.pending.get(r.id);if(!i)return;this.pending.delete(r.id),i.resolve(r);return}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},Kr=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new
|
|
87
|
+
`)}}handleMessage(t){if(t.trim().length===0)return;let r;try{r=JSON.parse(t)}catch{return}if("id"in r){let i=this.pending.get(r.id);if(!i)return;this.pending.delete(r.id),i.resolve(r);return}r.type==="update"&&(r.tabId&&this.viewCache.set(r.tabId,r.view),this.options.onUpdate?.(r.tabId??""))}rejectAll(t){for(let r of this.pending.values())r.reject(t);this.pending.clear()}},Kr=class{onShutdown=null;clients=new Set;runtime;attachedTabId=null;constructor(t,r){this.runtime=new zt({...r,workspaceRoot:t.workspaceRoot,onUpdate:i=>this.broadcastUpdate(i)})}handleConnection(t){let r="";this.clients.add(t),t.setEncoding("utf8"),t.on("data",i=>{r+=String(i);let a=r.indexOf(`
|
|
88
88
|
`);for(;a!==-1;){let S=r.slice(0,a);r=r.slice(a+1),this.handleLine(t,S),a=r.indexOf(`
|
|
89
|
-
`)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let i;try{i=JSON.parse(r)}catch{
|
|
90
|
-
${S.slice(-2e3)}`:""}`)}async function Sn(e){let t=await Ed(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===Vr}async function Rd(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Sn(e))return!0;await Xr(50)}return!1}function Pd(e){let t=process.argv[1];if(t?.endsWith(".ts"))return{command:ht.resolve(ht.dirname(t),"..","node_modules",".bin","tsx"),args:[t,"__craig-daemon",e]};let r=process.argv.slice(1);return{command:process.execPath,args:[...process.execArgv,...r,"__craig-daemon",e]}}async function Id(e){let t=await zr(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Cn(r))return}await nt(e.socketPath,{force:!0}),await nt(e.pidPath,{force:!0})}async function
|
|
89
|
+
`)}}),t.on("close",()=>this.clients.delete(t)),t.on("error",()=>this.clients.delete(t))}disposeAll(){this.runtime.disposeAll()}closeClients(){for(let t of this.clients)t.destroy();this.clients.clear()}async handleLine(t,r){if(r.trim().length===0)return;let i;try{i=JSON.parse(r)}catch{Vt(t,{id:-1,ok:!1,error:"Malformed daemon request."});return}try{let a=this.handleRequest(i);Vt(t,{id:i.id,ok:!0,...i.type==="ping"?{protocolVersion:Vr}:{},...a?{view:a}:{}})}catch(a){let S=a instanceof Error?a.message:String(a);Vt(t,{id:i.id,ok:!1,error:S})}}handleRequest(t){switch(t.type){case"ping":return null;case"ensureSession":return this.attachedTabId=t.tabId,this.runtime.ensureSession(t.taskId,t.tabId,t.size,t.spec);case"hydrateSession":return this.runtime.getViewState(t.tabId);case"write":return this.runtime.write(t.input),null;case"writeKey":return this.runtime.writeKey(t.key),null;case"scrollViewport":return this.runtime.scrollViewport(t.lines),this.runtime.getViewState(this.attachedTabId);case"resize":return this.runtime.resize(t.size),this.runtime.getViewState(this.attachedTabId);case"detach":return this.runtime.detach(),this.attachedTabId=null,null;case"disposeSession":return this.runtime.disposeSession(t.tabId),this.attachedTabId===t.tabId&&(this.attachedTabId=null),null;case"getViewState":return this.runtime.getViewState(t.tabId);case"shutdown":return setTimeout(()=>this.onShutdown?.(),0),null;default:return Dd(t)}}broadcastUpdate(t){let r=this.runtime.getViewState(t);for(let i of this.clients)Vt(i,{type:"update",tabId:t,view:r})}};function Gr(e){let t=bd("sha256").update(e.workspaceRoot).digest("hex").slice(0,16);return{socketPath:ht.join(Td(),`craig-${t}.sock`),pidPath:ht.join(e.runtimeDir,"pty-daemon.pid")}}async function Cd(e,t,r){if(await Rd(e.socketPath,1e3))return;await Gt(e.socketPath)&&(await vn(e.socketPath),await mn(e.socketPath,1e3)),await Gt(e.socketPath)&&(await xd(e),await mn(e.socketPath,1e3)),await Id(e);let i=t.workspaceRoot;if(r)r(i);else{let{command:T,args:n}=Pd(i),h=Sd(ht.join(t.runtimeDir,"pty-daemon.log"),"a");wd(T,n,{cwd:i,detached:!0,stdio:["ignore",h,h],env:process.env}).unref()}let a=Date.now();for(;Date.now()-a<5e3;){if(await Sn(e.socketPath))return;await Xr(50)}let S=await zr(ht.join(t.runtimeDir,"pty-daemon.log"),"utf8").catch(()=>"");throw new Error(`Craig PTY daemon did not start.${S?`
|
|
90
|
+
${S.slice(-2e3)}`:""}`)}async function Sn(e){let t=await Ed(e).catch(()=>null);return t?.ok===!0&&t.protocolVersion===Vr}async function Rd(e,t){let r=Date.now();for(;Date.now()-r<t;){if(await Sn(e))return!0;await Xr(50)}return!1}function Pd(e){let t=process.argv[1];if(t?.endsWith(".ts"))return{command:ht.resolve(ht.dirname(t),"..","node_modules",".bin","tsx"),args:[t,"__craig-daemon",e]};let r=process.argv.slice(1);return{command:process.execPath,args:[...process.execArgv,...r,"__craig-daemon",e]}}async function Id(e){let t=await zr(e.pidPath,"utf8").catch(()=>null);if(t){let r=Number(t.trim());if(Number.isInteger(r)&&r>0&&Cn(r))return}await nt(e.socketPath,{force:!0}),await nt(e.pidPath,{force:!0})}async function Gt(e){let t=await Tn(e).catch(()=>null);return t?(t.end(),!0):!1}async function vn(e){await kn(e,{id:1,type:"shutdown"}).catch(()=>null)}async function xd(e){let t=await zr(e.pidPath,"utf8").catch(()=>null),r=Number(t?.trim());if(!Number.isInteger(r)||r<=0||!Cn(r)){await nt(e.socketPath,{force:!0});return}try{process.kill(r,"SIGTERM")}catch{await nt(e.socketPath,{force:!0})}}async function Ed(e){return kn(e,{id:1,type:"ping"})}function kn(e,t){return new Promise((r,i)=>{let a=_n(e),S="",T=setTimeout(()=>{a.destroy(),i(new Error("Craig PTY daemon request timed out."))},500),n=()=>clearTimeout(T);a.setEncoding("utf8"),a.once("connect",()=>a.write(`${JSON.stringify(t)}
|
|
91
91
|
`)),a.once("error",h=>{n(),i(h)}),a.on("data",h=>{S+=String(h);let p=S.indexOf(`
|
|
92
|
-
`);if(p===-1)return;let y=S.slice(0,p);n(),a.end();try{r(JSON.parse(y))}catch(o){i(o instanceof Error?o:new Error(String(o)))}}),a.once("close",()=>n())})}async function mn(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await
|
|
93
|
-
`)}catch{}}function Cn(e){try{return process.kill(e,0),!0}catch{return!1}}function Xr(e){return new Promise(t=>setTimeout(t,e))}function Dd(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var Ld=[" \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 Yr(){return[...Ld]}var Md=["Start","Options","Exit"],Od=["Resume","Options","Exit"],
|
|
94
|
-
`)}function Dn(e,t,r={}){let i=r.color??!0,a=Ee.leftWidth,S=Ee.rightWidth,T=Ee.dividerWidth,n=r.centerOnly??!1,h=n?e.width:e.width-a-S-T*2,p=e.height-Ee.topRailHeight-1,y=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent} ${Nn(`\u25CF ${t.topRail.liveLabel}`,i,se.rail)}`,o=
|
|
95
|
-
`)}function Zr(e,t){let r=new Array(e.height).fill(
|
|
96
|
-
`)}function Wd(e,t,r,i){let a=Vd(e.runners),S=1,T=e.leftTree.map(h=>zd(h,t,i));return[...
|
|
97
|
-
`}function hu(e){return e.length===1&&e>=" "&&e!=="\x7F"}var mu=fu(import.meta.url),_u=mu("terminal-kit"),wu=_u.terminal;async function Vn(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),S=e.uiStateFile?await Pe({uiStateFile:e.uiStateFile}):null,T=Promise.resolve(),n=Promise.resolve(),h=await Ct(t,void 0,a),p=jt(qi(S,i),h);h=await Ct(t,p,a);let y=()=>{},o={workspaceRoot:t,onUpdate:()=>y(),resolveSessionSpec:(g,_)=>ku(h,_,t)},w=e.ptyRuntime??await wn({...o,paths:r}),l=g=>{if(!e.uiStateFile)return;S=Ki(S,g);let _=S;T=T.then(()=>ve({uiStateFile:e.uiStateFile},_),()=>ve({uiStateFile:e.uiStateFile},_)),T.catch(()=>{})};return new Promise(g=>{let _=e.terminal??wu,s={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:jt(p,h)},f=!1,d=!1,c=null,u=0,m=0,v=null,I=null,E=null,N=null,O=!1,A=!0,D=null,C=()=>{},j=w;y=()=>{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(yu($,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=Su(H?.fileRows??[],$.collapsedFileTreePaths);return{leftItemIds:vu(h),centerTabIds:Qi(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:Hr(H),fileLineCount:H?.selectedFile.lines.length??0,diffLineCount:sn(H),pageRows:Math.max(5,ut(_.width,_.height).height-Ee.topRailHeight-9),enabledRunnerIds:a}}async function R($){await ps(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:Xe(i)})}:s={...s,shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Xe(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($)}),l(s.shell),C()}async function K($){let M=await Du($);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))},l(s.shell);let re=await j.ensureSession(V.selectedTaskId,H,is(ut(_.width,_.height)));d=ns(H),c=null,s={mode:"main",shell:vt({...V,inputMode:"terminal"},re)},l(s.shell)}catch(M){let L=M instanceof Error?M.message:"Failed to start PTY.";$.selectedTaskId&&$.selectedPtyTabId&&ns($.selectedPtyTabId)&&(await x($.selectedTaskId,L).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:Vi(W($),L)},l(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??Cu(re,H.activeTab,H.preferredPtyTabKind),Ce=Kn(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(nr=>nr.id===M.activeTab);if(re===-1)throw new Error("Only PTY tabs can be closed.");let be=V.ptyTabs[re],Ce=V.ptyTabs.filter(nr=>nr.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 br(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 br(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 Ri(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=Kn($,"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=()=>{Ge();let $=ut(_.width,_.height),M=s.mode==="main"?Dn($,rn(W(s.shell),h),{centerOnly:s.shell.centerZoomed}):s.variant==="boot"?xn($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="pause"?En($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="options"?Jr($,{menuIndex:s.menuIndex,optionsMenuItems:ts}):s.variant==="runners"?Jr($,{menuIndex:Rt(s).menuIndex,optionsMenuItems:rs(i,Rt(s)),optionsMessage:jn(Rt(s)),optionsSubtitle:"Runners"}):An($);_.moveTo(1,1),A&&(_.eraseDisplayBelow(),A=!1),_.noFormat(M),_.hideCursor(!0)};function Ge(){let $=s.mode==="main"&&s.shell.inputMode==="terminal"?"terminal":"control";$!==D&&(D=$,_.grabInput($==="terminal"?{mouse:"button"}:!0))}let Xn=()=>{process.stdout.off("resize",ds),_.removeListener("key",as),_.removeListener("unknown",cs),_.removeListener("mouse",ls),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)},sr=$=>{Xn(),g($)},Yn=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 Ru(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??Gn(L,"agent"),is(ut(_.width,_.height)));d=ns(H.selectedPtyTabId),s={mode:"main",shell:vt(H,V)},l(s.shell)}catch(H){H instanceof tr&&(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()}},Qn=$=>{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($)){Yn();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:Br(M.selectedRunner,a),taskPromptError:null})},C();return}Gi($)&&(s={mode:"main",shell:W({...M,taskPromptInput:`${M.taskPromptInput}${$}`,taskPromptError:null})},C())}},Jn=$=>{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(os.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}`})},l(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()})}}},as=$=>{let M=typeof $=="string"?$:"";if(s.mode==="main"&&s.shell.taskPromptInput!==null){Qn(M);return}if(s.mode==="main"&&s.shell.workspaceBrowser!==null){Jn(M);return}if(s.mode==="main"){let L=zi(s.shell,M,k(s.shell));if(L.exit){sr(0);return}if(L.detachTerminal){j.detach(),s={mode:"main",shell:W(L.state)},l(s.shell),C();return}if(s.shell.inputMode==="terminal"){if(L.changed){s={mode:"main",shell:W(L.state)},l(s.shell),C();return}if(d&&Ke(M)){d=!1;return}d&&(d=!1),c=Iu(M)?{key:M,at:Date.now()}:null;let H=xu(M,s.shell.terminal.scrolledBack??!1);if(H!==0){ir(H);return}j.writeKey(M);return}if(M==="CTRL_C"){sr(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)},l(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},l(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},l(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},l(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},l(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},l(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(()=>{}),l(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"){Zn(M);return}if(s.variant==="runners"){eo(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}sr(0)}};function Zn($){if(s.mode!=="overlay"||s.variant!=="options")return;let M=Un(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 eo($){if(s.mode!=="overlay"||s.variant!=="runners")return;let M=qn(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 cs=$=>{let M=Pu($);if(s.mode!=="main"||s.shell.inputMode!=="terminal"||M.length===0)return;if(M.includes("")){j.detach(),d=!1,c=null,s={mode:"main",shell:W({...s.shell,inputMode:"control",actionMessage:null})},l(s.shell),C();return}let L=Eu(M);if(L!==0){ir(L);return}if(d&&M!=="\r"&&M!==`
|
|
92
|
+
`);if(p===-1)return;let y=S.slice(0,p);n(),a.end();try{r(JSON.parse(y))}catch(o){i(o instanceof Error?o:new Error(String(o)))}}),a.once("close",()=>n())})}async function mn(e,t){let r=Date.now();for(;Date.now()-r<t;){if(!await Gt(e))return;await Xr(50)}}function Tn(e){return new Promise((t,r)=>{let i=_n(e);i.once("connect",()=>t(i)),i.once("error",r)})}function Ad(e,t){return new Promise((r,i)=>{e.once("error",i),e.listen(t,r)})}function Vt(e,t){if(!e.destroyed)try{e.write(`${JSON.stringify(t)}
|
|
93
|
+
`)}catch{}}function Cn(e){try{return process.kill(e,0),!0}catch{return!1}}function Xr(e){return new Promise(t=>setTimeout(t,e))}function Dd(e){throw new Error(`Unhandled daemon request: ${JSON.stringify(e)}`)}var Ld=[" \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 Yr(){return[...Ld]}var Md=["Start","Options","Exit"],Od=["Resume","Options","Exit"],Qt=2,Jt=2,Zt=2,Bd=new RegExp("\x1B\\[[0-9;]*m","g"),Fd=new RegExp("\x1B\\[(?:0)?m","g"),$d=new RegExp("\x1B\\]8;;[^\x1B]*\x1B\\\\","g"),Nd=/https?:\/\/[^\s<>"']+/g,Qr="\x1B[0m",In="\x1B]8;;\x1B\\",se={panelBg:{bg:"0a0a0a",fg:"c0caf5"},panelMuted:{bg:"0a0a0a",fg:"565f89"},panelSelected:{bg:"1a1b26",fg:"c0caf5"},panelFocused:{bg:"1a1b26",fg:"7aa2f7"},divider:{bg:"0a0a0a",fg:"292e42"},rail:{bg:"0a0a0a",fg:"c0caf5"},overlay:{bg:"06060f",fg:"565f89"},overlayTitle:{bg:"06060f",fg:"565f89"},overlayLogo:{bg:"06060f",fg:"9ece6a"},overlaySubtitle:{bg:"06060f",fg:"41a6b5"},overlayMenuSelected:{bg:"06060f",fg:"7aa2f7"},accent:{fg:"7aa2f7"},success:{fg:"9ece6a"},pending:{fg:"e0af68"},error:{fg:"f7768e"},mutedfg:{fg:"565f89"},disabled:{fg:"3b4261"}};function xn(e,t={}){return Zr(e,{subtitle:"crAIg is that you?",menuItems:Md,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function En(e,t={}){return Zr(e,{subtitle:"Control mode is paused.",menuItems:Od,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}var Xt=[" 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."],Hd=["Help"];function Jr(e,t={}){return Zr(e,{subtitle:t.optionsSubtitle??"Configuration",menuItems:t.optionsMenuItems??Hd,menuIndex:t.menuIndex??0,optionsMessage:t.optionsMessage??null,color:t.color??!0})}function An(e,t={}){let r=t.color??!0,i=se.overlay,a=new Array(e.height).fill(de(" ".repeat(e.width),r,i)),S=Yr(),T=Math.max(1,Math.floor((e.height-S.length-2-Xt.length)/2));for(let y=0;y<S.length&&!(T+y>=e.height);y+=1)a[T+y]=de(Bn(S[y]??"",e.width),r,se.overlayLogo);let n=Math.max(...Xt.map(y=>y.length)),h=Math.max(0,Math.floor((e.width-n)/2)),p=T+S.length+2;for(let y=0;y<Xt.length;y+=1){let o=p+y;if(o>=e.height)break;let w=Xt[y]??"";a[o]=de(ze(" ".repeat(h)+w,e.width),r,i)}return a.join(`
|
|
94
|
+
`)}function Dn(e,t,r={}){let i=r.color??!0,a=Ee.leftWidth,S=Ee.rightWidth,T=Ee.dividerWidth,n=r.centerOnly??!1,h=n?e.width:e.width-a-S-T*2,p=e.height-Ee.topRailHeight-1,y=`CRAIG | ${t.topRail.workspacePath} | ${t.topRail.agent} ${Nn(`\u25CF ${t.topRail.liveLabel}`,i,se.rail)}`,o=de(ze(y,e.width),i,se.rail),w=Wd(t,a-Qt-Jt,p,i),l=jd(t,h,p,i),g=qd(t,S,p,i),_=[];for(let f=0;f<p;f+=1){if(n){_.push(Yt(l[f]??Be(),h,i,"center"));continue}let d=Yt(w[f]??Be(),a,i,"left"),c=de("\u2502",i,se.divider),u=Yt(l[f]??Be(),h,i,"center"),m=de("\u2502",i,se.divider),v=Yt(g[f]??Be(),S,i,"right");_.push(`${d}${c}${u}${m}${v}`)}let s=de(ze(` ${t.footerText}`,e.width),i,se.panelMuted);return[o,..._,s].join(`
|
|
95
|
+
`)}function Zr(e,t){let r=new Array(e.height).fill(de(" ".repeat(e.width),t.color,se.overlay)),i=Yr(),a=Math.max(...t.menuItems.map(p=>p.length)),S=t.menuItems.map((p,y)=>`${y===t.menuIndex?">":" "} ${p.padEnd(a)}`),T=t.optionsMessage?["",t.optionsMessage]:[],n=[...i,"",t.subtitle,"",...S,...T],h=Math.max(1,Math.floor((e.height-n.length)/2));for(let p=0;p<n.length;p+=1){let y=Bn(n[p]??"",e.width);if(p<i.length){r[h+p]=de(y,t.color,se.overlayLogo);continue}if(p===i.length+1){r[h+p]=de(y,t.color,se.overlaySubtitle);continue}let o=p-(i.length+3),l=o>=0&&o<t.menuItems.length&&o===t.menuIndex?se.overlayMenuSelected:se.overlay;r[h+p]=de(y,t.color,l)}return r.join(`
|
|
96
|
+
`)}function Wd(e,t,r,i){let a=Vd(e.runners),S=1,T=e.leftTree.map(h=>zd(h,t,i));return[...er(T,r-S),a]}function jd(e,t,r,i){let a=e.tabs.find(o=>o.active)?.label??"AGENT",S=ou(e.tabs),T=`${" ".repeat(S)}${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"||!Xi(h)?e.centerTranscript.map(o=>({...o})):Ud(e),y=[{text:Gd(e.tabs,i)},{text:T,tone:"muted"},{text:n},Be(),...p];return er(y,r)}function Ud(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:$n(i.segments),segments:i.segments,fullBleed:!0}))}function qd(e,t,r,i){let a=e.rightInspection?Kd(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:Ln("CONTEXT",e.focusedRegion==="tasks",i,se.panelBg)},Be(),...e.rightContext.map(S=>Xd(S,i)),...e.actionMessage?[Be(),{text:e.actionMessage}]:[]],r);return er(a,r)}function Kd(e,t){let r=e.slice(0,2),i=e.slice(2),a=Math.max(0,t-r.length),S=i.findIndex(n=>n.focused||n.selected),T=S===-1?0:cu(S-Math.floor(a/2),0,Math.max(0,i.length-a));return[...r.map(n=>Rn(n)),...i.slice(T,T+a).map(n=>Rn(n))]}function Rn(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(" "),S=a===-1?e.text:e.text.slice(0,a),T=a===-1?"":e.text.slice(a);return{text:i,segments:[{text:t},{text:S,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 zd(e,t,r){let i=" ".repeat(e.indent??0),a=e.accentDot?" \u25CF":"",S=e.status?` ${e.status}`:"",T=e.accentDot?` ${Nn("\u25CF",r,e.selected?se.panelSelected:se.panelBg)}`:"",n=t-Ve(S)-Ve(a),h=e.focused&&!e.selected?Ln(e.text,!0,r,se.panelBg):e.text,y=`${ze(`${i}${h}`,Math.max(0,n))}${S}${T}`;return e.selected?{text:y,tone:"selected"}:e.muted?{text:y,tone:"muted"}:{text:y}}function Vd(e){let t=e.map(i=>{let a=i.health>=1,S=parseInt(i.count,10),T=S>1?` (${S})`:"";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 Gd(e,t){return e.map(r=>r.active?tr(r.label,t,se.panelBg):Hn(r.label,t,se.panelBg)).join(" ")}function Xd(e,t){return{text:`${e.label.padEnd(8," ")} ${e.mutedValue?Hn(e.value,t,se.panelBg):e.value}`}}function Ln(e,t,r,i){return t?tr(e,r,i):e}function Yt(e,t,r,i){let a=Yd(i,e.tone??"default"),S=Qd(e,r,a);if(i==="left"){if(e.fullBleed)return de(ze(S,t),r,a);let n=t-Qt-Jt;if(e.rightAlign){let p=Ve(S),y=Math.max(0,n-p),o=`${" ".repeat(Qt)}${" ".repeat(y)}${S}${" ".repeat(Jt)}`;return de(o,r,a)}let h=`${" ".repeat(Qt)}${ze(S,n)}${" ".repeat(Jt)}`;return de(h,r,a)}return i==="center"&&e.fullBleed?Jd(e,t,r,a):de(ze(` ${S}`,t),r,a)}function Yd(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 Qd(e,t,r){return e.segments?e.segments.map(i=>Mn(i,t,r)).join(""):e.text}function Jd(e,t,r,i){let a=" ".repeat(Zt),S=Math.max(0,t-Zt*2);if(!e.segments)return de(`${a}${ze(e.text,S)}${a}`,r,i);let T=tu(e.segments,S),n=`${a}${T.map(h=>Mn(h,r,i)).join("")}${a}`;return de(n,r,i)}function Mn(e,t,r){let i=e.href?`${On(e.href)}${e.text}${In}`:Zd(e.text);return!t||!e.style?i:`${Tt(iu(e.style,r))}${nu(e.style)}${i}${Qr}${Tt(r)}`}function Zd(e){return e.replace(Nd,t=>{let[r,i]=eu(t);return`${On(r)}${r}${In}${i}`})}function eu(e){let t=e.length;for(;t>0&&".,;:!?)]}".includes(e[t-1]??"");)t-=1;return[e.slice(0,t),e.slice(t)]}function On(e){return`\x1B]8;;${e}\x1B\\`}function tu(e,t){let r=ru(e,t);return su(r,t)}function ru(e,t){let r=[],i=t;for(let a of e){if(i<=0)break;let S=Ve(a.text);if(S<=i){r.push(a),i-=S;continue}r.push({...a,text:a.text.slice(0,i)}),i=0}return r}function su(e,t){let r=Ve($n(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 iu(e,t){let r=e.inverse?e.bg??t.bg:e.fg,i=e.inverse?e.fg??t.fg:e.bg,a={},S=r??t.fg,T=i??t.bg;return S&&(a.fg=S),T&&(a.bg=T),a}function nu(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 ou(e){let t=0;for(let r of e){if(r.active)return t;t+=r.label.length+3}return 0}function Bn(e,t){let r=Math.max(0,t-Ve(e)),i=Math.floor(r/2),a=r-i;return`${" ".repeat(i)}${e}${" ".repeat(a)}`}function ze(e,t){let r=Ve(e);return r>=t?au(e,t):e+" ".repeat(t-r)}function au(e,t){return Ve(e)<=t?e:Fn(e).slice(0,Math.max(0,t-1))+"\u2026"}function Ve(e){return Fn(e).length}function cu(e,t,r){return Math.min(Math.max(e,t),r)}function Fn(e){return e.replace($d,"").replace(Bd,"")}function $n(e){return e.map(t=>t.text).join("")}function de(e,t,r){if(!t)return e;let i=Tt(r),a=e.replace(Fd,`${Qr}${i}`);return`${i}${a}${Qr}`}function Tt(e){let t=[];return e.fg&&t.push(`38;2;${Pn(e.fg).join(";")}`),e.bg&&t.push(`48;2;${Pn(e.bg).join(";")}`),`\x1B[${t.join(";")}m`}function Pn(e){return[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}function Nn(e,t,r){return es(e,t,se.success.fg,r)}function tr(e,t,r){return es(e,t,se.accent.fg,r)}function Hn(e,t,r){return es(e,t,se.mutedfg.fg,r)}function es(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 ts=["Runners","Help"];function rs(e,t){return ae.map(r=>{let i=pe(r),a=e.runners?.[r]?.enabled!==!1,S=e.runners?.[r]?.path?.trim(),T=t.pathEdit?.runner===r?`${t.pathEdit.value}_`:S&&S.length>0?S:`default (${i.executable})`;return`${i.displayName} ${a?"enabled":"disabled"} ${T}`})}function jn(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 Un(e,t){return t==="UP"||t==="k"?{kind:"render",menuIndex:Math.max(0,e-1)}:t==="DOWN"||t==="j"?{kind:"render",menuIndex:Math.min(ts.length-1,e+1)}:t==="ESCAPE"?{kind:"back"}:ss(t)?e===0?{kind:"runners"}:{kind:"help"}:{kind:"noop",menuIndex:e}}function qn(e,t,r,i){if(e.pathEdit)return lu({...e,pathEdit:e.pathEdit},t,r);let a=rs(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=ae[e.menuIndex]??"codex";return{kind:"render",state:{...e,message:null,pathEdit:{runner:n,value:t.runners?.[n]?.path??""}}}}if(!ss(r))return{kind:"noop",state:e};let S=ae[e.menuIndex]??"codex",T=t.runners?.[S]?.enabled!==!1;return T&&i.length<=1?{kind:"render",state:{...e,message:"At least one runner must stay enabled."}}:{kind:"save",config:du(t,S,!T),state:{...e,message:`${pe(S).displayName} ${T?"disabled":"enabled"}.`}}}function lu(e,t,r){if(r==="ESCAPE")return{kind:"render",state:Wn({...e,message:null})};if(r==="BACKSPACE")return{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:e.pathEdit.value.slice(0,-1)}}};if(ss(r)){let i=e.pathEdit.runner,a=e.pathEdit.value.trim();return{kind:"save",config:uu(t,i,a.length>0?a:null),state:Wn({...e,message:a.length>0?`${pe(i).displayName} executable saved.`:`${pe(i).displayName} executable reset to default.`})}}return hu(r)?{kind:"render",state:{...e,pathEdit:{...e.pathEdit,value:`${e.pathEdit.value}${r}`}}}:{kind:"noop",state:e}}function du(e,t,r){return{...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:r}}}}function uu(e,t,r){let i={...e.runners?.[t]??{},...r?{path:r}:{}};return r||delete i.path,{...e,runners:{...e.runners??{},[t]:i}}}function Wn(e){let t={...e};return delete t.pathEdit,t}function ss(e){return e==="ENTER"||e==="RETURN"||e==="CTRL_M"||e==="\r"||e===`
|
|
97
|
+
`}function hu(e){return e.length===1&&e>=" "&&e!=="\x7F"}var mu=fu(import.meta.url),_u=mu("terminal-kit"),wu=_u.terminal;async function Vn(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),S=e.uiStateFile?await Pe({uiStateFile:e.uiStateFile}):null,T=Promise.resolve(),n=Promise.resolve(),h=await Ct(t,void 0,a),p=jt(qi(S,i),h);h=await Ct(t,p,a);let y=()=>{},o={workspaceRoot:t,onUpdate:()=>y(),resolveSessionSpec:(g,_)=>ku(h,_,t)},w=e.ptyRuntime??await wn({...o,paths:r}),l=g=>{if(!e.uiStateFile)return;S=Ki(S,g);let _=S;T=T.then(()=>ve({uiStateFile:e.uiStateFile},_),()=>ve({uiStateFile:e.uiStateFile},_)),T.catch(()=>{})};return new Promise(g=>{let _=e.terminal??wu,s={mode:"overlay",variant:"boot",menuIndex:0,optionsMessage:null,shell:jt(p,h)},f=!1,d=!1,c=null,u=0,m=0,v=null,I=null,E=null,N=null,O=!1,A=!0,D=null,C=()=>{},j=w;y=()=>{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(yu($,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=Su(H?.fileRows??[],$.collapsedFileTreePaths);return{leftItemIds:vu(h),centerTabIds:Qi(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:Hr(H),fileLineCount:H?.selectedFile.lines.length??0,diffLineCount:sn(H),pageRows:Math.max(5,ut(_.width,_.height).height-Ee.topRailHeight-9),enabledRunnerIds:a}}async function R($){await ps(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:Xe(i)})}:s={...s,shell:W({...s.shell,selectedRunner:a.includes(s.shell.selectedRunner)?s.shell.selectedRunner:Xe(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($)}),l(s.shell),C()}async function K($){let M=await Du($);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))},l(s.shell);let re=await j.ensureSession(V.selectedTaskId,H,is(ut(_.width,_.height)));d=ns(H),c=null,s={mode:"main",shell:vt({...V,inputMode:"terminal"},re)},l(s.shell)}catch(M){let L=M instanceof Error?M.message:"Failed to start PTY.";$.selectedTaskId&&$.selectedPtyTabId&&ns($.selectedPtyTabId)&&(await x($.selectedTaskId,L).catch(()=>{}),await B().catch(()=>{})),s={mode:"main",shell:Vi(W($),L)},l(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??Cu(re,H.activeTab,H.preferredPtyTabKind),Ce=Kn(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 Ri(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=Kn($,"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=()=>{Ge();let $=ut(_.width,_.height),M=s.mode==="main"?Dn($,rn(W(s.shell),h),{centerOnly:s.shell.centerZoomed}):s.variant==="boot"?xn($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="pause"?En($,{menuIndex:s.menuIndex,optionsMessage:s.optionsMessage}):s.variant==="options"?Jr($,{menuIndex:s.menuIndex,optionsMenuItems:ts}):s.variant==="runners"?Jr($,{menuIndex:Rt(s).menuIndex,optionsMenuItems:rs(i,Rt(s)),optionsMessage:jn(Rt(s)),optionsSubtitle:"Runners"}):An($);_.moveTo(1,1),A&&(_.eraseDisplayBelow(),A=!1),_.noFormat(M),_.hideCursor(!0)};function Ge(){let $=s.mode==="main"&&s.shell.inputMode==="terminal"?"terminal":"control";$!==D&&(D=$,_.grabInput($==="terminal"?{mouse:"button"}:!0))}let Xn=()=>{process.stdout.off("resize",ds),_.removeListener("key",as),_.removeListener("unknown",cs),_.removeListener("mouse",ls),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=$=>{Xn(),g($)},Yn=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 Ru(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??Gn(L,"agent"),is(ut(_.width,_.height)));d=ns(H.selectedPtyTabId),s={mode:"main",shell:vt(H,V)},l(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()}},Qn=$=>{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($)){Yn();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}Gi($)&&(s={mode:"main",shell:W({...M,taskPromptInput:`${M.taskPromptInput}${$}`,taskPromptError:null})},C())}},Jn=$=>{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(os.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}`})},l(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()})}}},as=$=>{let M=typeof $=="string"?$:"";if(s.mode==="main"&&s.shell.taskPromptInput!==null){Qn(M);return}if(s.mode==="main"&&s.shell.workspaceBrowser!==null){Jn(M);return}if(s.mode==="main"){let L=zi(s.shell,M,k(s.shell));if(L.exit){ir(0);return}if(L.detachTerminal){j.detach(),s={mode:"main",shell:W(L.state)},l(s.shell),C();return}if(s.shell.inputMode==="terminal"){if(L.changed){s={mode:"main",shell:W(L.state)},l(s.shell),C();return}if(d&&Ke(M)){d=!1;return}d&&(d=!1),c=Iu(M)?{key:M,at:Date.now()}:null;let H=xu(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)},l(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},l(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},l(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},l(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},l(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},l(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(()=>{}),l(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"){Zn(M);return}if(s.variant==="runners"){eo(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 Zn($){if(s.mode!=="overlay"||s.variant!=="options")return;let M=Un(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 eo($){if(s.mode!=="overlay"||s.variant!=="runners")return;let M=qn(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 cs=$=>{let M=Pu($);if(s.mode!=="main"||s.shell.inputMode!=="terminal"||M.length===0)return;if(M.includes("")){j.detach(),d=!1,c=null,s={mode:"main",shell:W({...s.shell,inputMode:"control",actionMessage:null})},l(s.shell),C();return}let L=Eu(M);if(L!==0){nr(L);return}if(d&&M!=="\r"&&M!==`
|
|
98
98
|
`&&M!==`\r
|
|
99
|
-
`&&(d=!1),Au(d,c,M)){d=!1;return}j.write(M)},ls=$=>{if(s.mode!=="main")return;if(s.shell.inputMode==="control"){ro(zn($));return}let M=zn($);M!==0&&
|
|
99
|
+
`&&(d=!1),Au(d,c,M)){d=!1;return}j.write(M)},ls=$=>{if(s.mode!=="main")return;if(s.shell.inputMode==="control"){ro(zn($));return}let M=zn($);M!==0&&nr(M)};function nr($){u+=$,!v&&(v=setTimeout(()=>{v=null;let M=u;u=0,M!==0&&(to(M),C())},16))}function to($){j.scrollViewport($),s={mode:"main",shell:z(s.shell)}}function ro($){$!==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)},l(s.shell),C()}},16)))}let ds=()=>{A=!0,s.mode==="main"&&s.shell.inputMode==="terminal"&&(j.resize(is(ut(_.width,_.height))),s={mode:"main",shell:z(s.shell)}),C()};process.stdout.on("resize",ds),_.grabInput(!0),D="control",_.hideCursor(!0),_.fullscreen(!0),_.on("key",as),_.on("unknown",cs),_.on("mouse",ls),N=setInterval(()=>{fe()},(i.github?.watchIntervalSeconds??10)*1e3),C()})}async function Ct(e,t,r){let i=$e(e),[a,S]=await Promise.all([gt(i),tt(i)]),T=bu(S.tasks,t),n=t?{selectedFilePath:t.selectedFilePath,selectedDiffPath:t.selectedDiffPath}:{},h=T?await Si(T,n):null;return{workspaceRoot:e,repos:a,tasks:S.tasks,inspection:h,...r?{enabledRunnerIds:r}:{}}}function bu(e,t){return t?.selectedTaskId?e.find(r=>r.id===t.selectedTaskId)??null:null}function yu(e,t){return jt(e,t)}function Su(e,t){let r=new Set(t);return e.filter(i=>{let a=i.path.split("/");for(let S=1;S<a.length;S+=1)if(r.has(a.slice(0,S).join("/")))return!1;return!0})}function vu(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 ku(e,t,r){let i=e.tasks.find(S=>S.ptyTabs.some(T=>T.id===t))??null,a=i?.ptyTabs.find(S=>S.id===t)??null;return{cwd:i?.worktreePath??r,command:a?.kind==="agent"?Tu(a):[]}}function Tu(e){return e.command.length>0?e.command:["codex"]}function Rt(e){return e.runnerOptions??{menuIndex:e.menuIndex,message:e.optionsMessage}}function Cu(e,t,r){return e.ptyTabs.find(i=>i.id===t)?.kind??r}function Kn(e,t,r,i={}){let a=r??e.runner,S=pe(a),T=t==="agent"?S.defaultAgentTitle:"Terminal",n=t==="agent"&&r&&r!==e.runner?`${e.id}:${r}`:`${e.id}:${t}`,h=new Set(e.ptyTabs.map(l=>l.id)),p=1,y=n;for(;h.has(y);)p+=1,y=`${n}-${p}`;let o=new Date().toISOString(),w=r&&r!==e.runner?r:void 0;return{id:y,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 Ru(e,t,r,i){let a=await _e(e);Pt(i,a);let S=await Bt(e,t,r,{runner:i,config:a});try{let h=Je();await J(Ze(ar(i,a).executable,{cwd:S.repoRoot,env:h}),["--help"],{cwd:S.repoRoot,env:h})}catch(h){let p=h instanceof Error?h.message:"Failed to start runner.",y={...S.task,status:"draft",runnerSession:{...S.task.runnerSession,lastKnownState:"failed",exitedAt:new Date().toISOString()},lastFailureReason:p};throw await te(e,y),new rr(p,y)}let T=Gn(S.task,"agent"),n={...S.task,status:"running",selectedPtyTabId:T,runnerSession:{...S.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 Gn(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 is(e){return{columns:Math.max(20,e.width-Ee.leftWidth-Ee.rightWidth-Ee.dividerWidth-Zt*2),rows:Math.max(5,e.height-Ee.topRailHeight-5)}}function Pu(e){return typeof e=="string"?e:Buffer.isBuffer(e)?e.toString("utf8"):""}function Iu(e){return e.length===1||Ke(e)||e==="BACKSPACE"||e==="TAB"}function ns(e){return typeof e=="string"&&new RegExp(`:(?:agent|${ae.join("|")})(?:-\\d+)?$`).test(e)}function xu(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 zn(e){return e==="MOUSE_WHEEL_UP"?-3:e==="MOUSE_WHEEL_DOWN"?3:0}function Eu(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 Au(e,t,r){return r.length===0?!1:e&&(r==="\r"||r===`
|
|
100
100
|
`||r===`\r
|
|
101
|
-
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(i=>i===t.key)}async function Du(e){let t=await pu(e,{withFileTypes:!0}),r=[];for(let i of t){if(!i.isDirectory())continue;let a=os.join(e,i.name);r.push({name:i.name,path:a,kind:await Lu(a)?"repo":"directory"})}return r.sort((i,a)=>i.kind!==a.kind?i.kind==="repo"?-1:1:i.name.localeCompare(a.name)),{cwd:e,entries:r,selectedIndex:0,error:null}}async function Lu(e){let t=os.join(e,".git");return await gu(t).catch(()=>null)!==null}function
|
|
101
|
+
`)?!0:!t||Date.now()-t.at>=30?!1:r===t.key?!0:r.length<=4&&r.split("").every(i=>i===t.key)}async function Du(e){let t=await pu(e,{withFileTypes:!0}),r=[];for(let i of t){if(!i.isDirectory())continue;let a=os.join(e,i.name);r.push({name:i.name,path:a,kind:await Lu(a)?"repo":"directory"})}return r.sort((i,a)=>i.kind!==a.kind?i.kind==="repo"?-1:1:i.name.localeCompare(a.name)),{cwd:e,entries:r,selectedIndex:0,error:null}}async function Lu(e){let t=os.join(e,".git");return await gu(t).catch(()=>null)!==null}function sr(){return process.cwd()}async function Mu(){try{if(process.argv[2]==="__craig-daemon"){let n=process.argv[3]??sr(),h=$e(n);return await dt(n),await bn(h),0}if(process.argv[2]==="__craig-daemon-shutdown"){let n=process.argv[3]??sr(),h=$e(n);return await dt(n),await yn(h),0}let e=fs(process.argv.slice(2)),t=sr(),r=$e(t),i=await dt(t),a={paths:r};if(e.mode==="interactive")return await Vn({uiStateFile:r.uiStateFile,workspaceRoot:r.workspaceRoot});if(!e.command)throw new Error("Command mode requires a command.");let S=await _i(e.command,a),T=wi(S);return T.length>0&&process.stdout.write(`${T}
|
|
102
102
|
`),0}catch(e){let t=e instanceof Error?e.message:"Unknown Craig error";return process.stderr.write(`${t}
|
|
103
103
|
`),1}}var Ou=await Mu();process.exit(Ou);
|