@wular/coder 0.2.2 → 0.2.3

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.
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- var T$=Object.defineProperty;var Y1=($,W)=>{for(var q in W)T$($,q,{get:W[q],enumerable:!0,configurable:!0,set:(Z)=>W[q]=()=>Z})};import u from"node:fs";import W1 from"node:net";import r from"node:path";import L from"node:process";function e($,W={}){let q=new Set(W.valueOptions??[]),Z=new Set(W.booleanOptions??[]),K=W.aliasMap??{},z={},Q=[],G=!1;for(let X=0;X<$.length;X+=1){let M=$[X];if(G){Q.push(M);continue}if(M==="--"){G=!0;continue}if(!M.startsWith("-")||M==="-"){Q.push(M);continue}if(M.startsWith("--")){let[J,A]=M.slice(2).split("=",2),P=K[J]??J;if(Z.has(P)){z[P]=A===void 0?!0:A!=="false";continue}if(q.has(P)){let S=A??$[X+1];if(S===void 0)throw Error(`Missing value for --${J}`);if(z[P]=S,A===void 0)X+=1;continue}throw Error(`Unknown option --${J} (use -- to pass literal text starting with -)`)}let y=M.slice(1),R=K[y]??y;if(Z.has(R)){z[R]=!0;continue}if(q.has(R)){let J=$[X+1];if(J===void 0)throw Error(`Missing value for -${y}`);z[R]=J,X+=1;continue}throw Error(`Unknown option -${y} (use -- to pass literal text starting with -)`)}return{options:z,positionals:Q}}import r$ from"node:net";import h from"node:process";import{spawn as o$}from"node:child_process";import s$ from"node:readline";import $$ from"node:path";import A$ from"node:process";function P$($){return String($??"").replace(/[^A-Za-z0-9._-]/g,"-").replace(/^-+|-+$/g,"")}function W$($,W=A$.platform){if(W==="win32")return`pipe:\\\\.\\pipe\\${P$(`${$$.win32.basename($)}-codex-app-server`)}`;return`unix:${$$.join($,"broker.sock")}`}function _($){if(typeof $!=="string"||$.length===0)throw Error("Missing broker endpoint.");if($.startsWith("pipe:")){let W=$.slice(5);if(!W)throw Error("Broker pipe endpoint is missing its path.");return{kind:"pipe",path:W}}if($.startsWith("unix:")){let W=$.slice(5);if(!W)throw Error("Broker Unix socket endpoint is missing its path.");return{kind:"unix",path:W}}throw Error(`Unsupported broker endpoint: ${$}`)}import O from"node:fs";import F$ from"node:net";import v$ from"node:os";import E from"node:path";import c from"node:process";import{spawn as w$}from"node:child_process";import{fileURLToPath as j$}from"node:url";import{execFileSync as Z$}from"node:child_process";import V from"node:fs";import f$ from"node:os";import N from"node:path";var _$=["completed","failed","cancelled"],U1=["queued","running"];var B$="CODER_HOME";function K$(){return N.resolve(process.env[B$]||N.join(f$.homedir(),".coder"))}var q$=new Map;function x1($){let W=q$.get($);if(W!==void 0)return W;let q;try{q=Z$("git",["rev-parse","--show-toplevel"],{cwd:$,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{q=$}return q$.set($,q),q}var Q$="global";function w($){return N.join(K$(),"state",Q$)}var v=null;function Y$(){if(v)return v;let $=N.join(K$(),"state"),W=[];try{W=V.readdirSync($,{withFileTypes:!0})}catch{}return v=W.filter((q)=>q.isDirectory()&&q.name!==Q$).map((q)=>N.join($,q.name)),v}function z$($){return N.join(w($),"jobs")}function f($,W){let q=N.join(z$($),W);if(V.existsSync(N.join(q,"job.json")))return q;for(let Z of Y$()){let K=N.join(Z,"jobs",W);if(V.existsSync(N.join(K,"job.json")))return K}return q}function L1(){let $=Math.random().toString(36).slice(2,8);return`coder-${Date.now().toString(36)}-${$}`}function E$($,W,q){let Z=f($,W);V.mkdirSync(Z,{recursive:!0});let K=N.join(Z,"job.json"),Q={...C$($,W)??{id:W,createdAt:new Date().toISOString(),status:"queued"},...q,updatedAt:new Date().toISOString()};return V.writeFileSync(K,`${JSON.stringify(Q,null,2)}
3
- `,"utf8"),Q}function C$($,W){let q=N.join(f($,W),"job.json");if(!V.existsSync(q))return null;try{return JSON.parse(V.readFileSync(q,"utf8"))}catch{return null}}function T1($,W){let q=f($,W);if(!V.existsSync(q))return!1;return V.rmSync(q,{recursive:!0,force:!0}),!0}function u$($){if(!$)return!1;try{return process.kill($,0),!0}catch(W){return W.code==="EPERM"}}function k$($){try{let W=Z$("ps",["-o","lstart=","-p",String($)],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim(),q=W?Date.parse(W):NaN;return Number.isFinite(q)?q:null}catch{return null}}function I$($,W){if(!u$($))return!1;let q=k$($),Z=Date.parse(W.createdAt??"");if(q===null||!Number.isFinite(Z))return!0;return q<=Z+60000}var h$=60000;function S$($,W){if(W.status!=="running"&&W.status!=="queued")return W;let q;if(W.pid)q=!I$(W.pid,W);else{let Z=Date.parse(W.updatedAt??W.createdAt??"");q=Number.isFinite(Z)&&Date.now()-Z>h$}if(q)return E$($,W.id,{status:"failed",error:"worker exited without finishing",completedAt:new Date().toISOString()});return W}function D$($){let W=[z$($),...Y$().map((K)=>N.join(K,"jobs"))],q=new Set,Z=[];for(let K of W){let z=[];try{z=V.readdirSync(K)}catch{continue}for(let Q of z){if(q.has(Q))continue;let G=N.join(K,Q,"job.json");try{let X=JSON.parse(V.readFileSync(G,"utf8"));q.add(Q),Z.push(X)}catch{}}}return Z.map((K)=>S$($,K)).sort((K,z)=>String(z.updatedAt??"").localeCompare(String(K.updatedAt??"")))}function A1($,W){let q=D$($);if(!W)return q[0]??null;let Z=q.find((z)=>z.id===W);if(Z)return Z;let K=q.filter((z)=>z.id.startsWith(W));if(K.length===1)return K[0];if(K.length>1)throw Error(`Job reference "${W}" is ambiguous. Use a longer id.`);return null}function P1($,W){let q=f($,W);try{V.mkdirSync(q,{recursive:!0}),V.writeFileSync(N.join(q,"heartbeat"),"","utf8")}catch{}}function _1($,W){let q=f($,W.id),Z=Date.parse(W.updatedAt??"")||0;for(let K of["log.jsonl","heartbeat"])try{Z=Math.max(Z,V.statSync(N.join(q,K)).mtimeMs)}catch{}return Z?new Date(Z).toISOString():void 0}function f1($,W,q){let Z=f($,W);V.mkdirSync(Z,{recursive:!0}),V.appendFileSync(N.join(Z,"log.jsonl"),`${JSON.stringify({at:new Date().toISOString(),...q})}
4
- `,"utf8")}function B1($,W,q=40){let Z=N.join(f($,W),"log.jsonl");if(!V.existsSync(Z))return[];return V.readFileSync(Z,"utf8").split(/\r?\n/).filter(Boolean).slice(-q).map((z)=>{try{return JSON.parse(z)}catch{return{message:z}}})}import m from"node:fs";import{fileURLToPath as p}from"node:url";var k1=p(import.meta.url);function X$(){try{return JSON.parse(m.readFileSync(p(new URL("../package.json",import.meta.url)),"utf8")).version??"unknown"}catch{return"unknown"}}function I1($){try{return JSON.parse(m.readFileSync($,"utf8")).version??null}catch{return null}}function h1(){return p(new URL("..",import.meta.url))}var b$="broker.json";function g$($="coder-"){return O.mkdtempSync(E.join(v$.tmpdir(),$))}function m$($){let W=_($);return F$.createConnection({path:W.path})}async function G$($,W=2000){let q=Date.now();while(Date.now()-q<W){if(await new Promise((K)=>{let z=m$($);z.on("connect",()=>{z.end(),K(!0)}),z.on("error",()=>K(!1))}))return!0;await new Promise((K)=>setTimeout(K,50))}return!1}function p$({scriptPath:$,cwd:W,endpoint:q,pidFile:Z,logFile:K,env:z=c.env}){let Q=O.openSync(K,"a"),G=w$(c.execPath,[$,"serve","--endpoint",q,"--cwd",W,"--pid-file",Z],{cwd:W,env:z,detached:!0,stdio:["ignore",Q,Q]});return G.unref(),O.closeSync(Q),G}function c$(){let $=[new URL("./lib/broker.js",import.meta.url),new URL("./broker.js",import.meta.url)];for(let W of $){let q=j$(W);if(O.existsSync(q))return q}throw Error("Coder broker script not found next to the runtime. Rebuild with `bun run build`.")}function n($){return E.join(w($),b$)}function l($){let W=n($);if(!O.existsSync(W))return null;try{return JSON.parse(O.readFileSync(W,"utf8"))}catch{return null}}function n$($,W){let q=w($);O.mkdirSync(q,{recursive:!0}),O.writeFileSync(n($),`${JSON.stringify(W,null,2)}
5
- `,"utf8")}function l$($){let W=n($);if(O.existsSync(W))O.unlinkSync(W)}async function a$($){if(!$)return!1;try{return await G$($,150)}catch{return!1}}async function M$($,W={}){let q=W.scriptPath??c$(),Z=X$(),K=l($),z=K?.version===Z&&K?.scriptPath===q;if(K&&z&&await a$(K.endpoint))return K;if(K)H$({endpoint:K.endpoint??null,pidFile:K.pidFile??null,logFile:K.logFile??null,sessionDir:K.sessionDir??null,pid:K.pid??null,killProcess:W.killProcess??null}),l$($);let Q=g$(),X=(W.createBrokerEndpoint??W$)(Q,W.platform),M=E.join(Q,"broker.pid"),y=E.join(Q,"broker.log"),R=p$({scriptPath:q,cwd:$,endpoint:X,pidFile:M,logFile:y,env:W.env??c.env});if(!await G$(X,W.timeoutMs??2000))return H$({endpoint:X,pidFile:M,logFile:y,sessionDir:Q,pid:R.pid??null,killProcess:W.killProcess??null}),null;let A={endpoint:X,pidFile:M,logFile:y,sessionDir:Q,pid:R.pid??null,version:Z,scriptPath:q};return n$($,A),A}function H$({endpoint:$=null,pidFile:W,logFile:q,sessionDir:Z=null,pid:K=null,killProcess:z=null}){if(Number.isFinite(K)&&z)try{z(K)}catch{}if(W&&O.existsSync(W))O.unlinkSync(W);if(q&&O.existsSync(q))O.unlinkSync(q);if($)try{let G=_($);if(G.kind==="unix"&&O.existsSync(G.path))O.unlinkSync(G.path)}catch{}let Q=Z??(W?E.dirname(W):q?E.dirname(q):null);if(Q&&O.existsSync(Q))try{O.rmdirSync(Q)}catch{}}import{spawnSync as i$}from"node:child_process";import I from"node:process";function j($,W=[],q={}){let Z=i$($,W,{cwd:q.cwd,env:q.env,encoding:"utf8",input:q.input,maxBuffer:q.maxBuffer,stdio:q.stdio??"pipe",shell:I.platform==="win32"?I.env.SHELL||!0:!1,windowsHide:!0});return{command:$,args:W,status:Z.status??0,signal:Z.signal??null,stdout:Z.stdout??"",stderr:Z.stderr??"",error:Z.error??null}}function i1($,W=["--version"],q={}){let Z=j($,W,q);if(Z.error&&Z.error.code==="ENOENT")return{available:!1,detail:"not found"};if(Z.error)return{available:!1,detail:Z.error.message};if(Z.status!==0)return{available:!1,detail:Z.stderr.trim()||Z.stdout.trim()||`exit ${Z.status}`};return{available:!0,detail:Z.stdout.trim()||Z.stderr.trim()||"ok"}}function t$($){return/not found|no running instance|cannot find|does not exist|no such process/i.test($)}function U$($,W={}){if(!Number.isFinite($))return{attempted:!1,delivered:!1,method:null};let q=$,Z=W.platform??I.platform,K=W.runCommandImpl??j,z=W.killImpl??I.kill.bind(I);if(Z==="win32"){let Q=K("taskkill",["/PID",String(q),"/T","/F"],{cwd:W.cwd,env:W.env});if(!Q.error&&Q.status===0)return{attempted:!0,delivered:!0,method:"taskkill",result:Q};let G=`${Q.stderr}
6
- ${Q.stdout}`.trim();if(!Q.error&&t$(G))return{attempted:!0,delivered:!1,method:"taskkill",result:Q};if(Q.error?.code==="ENOENT")try{return z(q),{attempted:!0,delivered:!0,method:"kill"}}catch(X){if(X?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"kill"};throw X}if(Q.error)throw Q.error;throw Error(d$(Q))}try{return z(-q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process-group"}}catch(Q){if(Q?.code!=="ESRCH")try{return z(q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process"}}catch(G){if(G?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"process"};throw G}return{attempted:!0,delivered:!1,method:"process-group"}}}function d$($){let W=[`${$.command} ${$.args.join(" ")}`.trim()];if($.signal)W.push(`signal=${$.signal}`);else W.push(`exit=${$.status}`);let q=($.stderr||"").trim(),Z=($.stdout||"").trim();if(q)W.push(q);else if(Z)W.push(Z);return W.join(": ")}var N$="CODER_APP_SERVER_ENDPOINT",O$=-32001,e$="0.144.1",a;function $1(){if(a===void 0){let $=j("codex",["--version"]),W=/(\d+\.\d+\.\d+(?:-[\w.]+)?)/.exec(`${$.stdout} ${$.stderr}`);a=W?W[1]:e$}return a}function y$(){return{title:"Coder",name:"coder",version:$1()}}var J$={experimentalApi:!1,requestAttestation:!1,optOutNotificationMethods:["item/agentMessage/delta","item/reasoning/summaryTextDelta","item/reasoning/summaryPartAdded","item/reasoning/textDelta"]};function V$($,W,q){return q===void 0?{code:$,message:W}:{code:$,message:W,data:q}}function i($,W){let q=Error($);if(q.data=W,W?.code!==void 0)q.rpcCode=W.code;return q}class t{cwd;options;pending;nextId;stderr;closed;exitError;notificationHandler;serverRequestHandler;lineBuffer;transport;exitPromise;exitResolved;resolveExit;handleServerRequest;constructor($,W={}){this.cwd=$,this.options=W,this.pending=new Map,this.nextId=1,this.stderr="",this.closed=!1,this.exitError=null,this.notificationHandler=null,this.serverRequestHandler=null,this.lineBuffer="",this.transport="unknown",this.handleServerRequest=(q)=>this.defaultHandleServerRequest(q),this.exitPromise=new Promise((q)=>{this.resolveExit=q})}setNotificationHandler($){this.notificationHandler=$}setServerRequestHandler($){this.serverRequestHandler=$}request($,W){if(this.closed)throw Error("codex app-server client is closed.");let q=this.nextId;return this.nextId+=1,new Promise((Z,K)=>{this.pending.set(q,{resolve:Z,reject:K,method:$}),this.sendMessage({id:q,method:$,params:W})})}notify($,W={}){if(this.closed)return;this.sendMessage({method:$,params:W})}handleChunk($){this.lineBuffer+=$;let W=this.lineBuffer.indexOf(`
2
+ var A$=Object.defineProperty;var X1=($,W)=>{for(var q in W)A$($,q,{get:W[q],enumerable:!0,configurable:!0,set:(Z)=>W[q]=()=>Z})};import u from"node:fs";import q1 from"node:net";import r from"node:path";import L from"node:process";function e($,W={}){let q=new Set(W.valueOptions??[]),Z=new Set(W.booleanOptions??[]),K=W.aliasMap??{},X={},Q=[],G=!1;for(let z=0;z<$.length;z+=1){let M=$[z];if(G){Q.push(M);continue}if(M==="--"){G=!0;continue}if(!M.startsWith("-")||M==="-"){Q.push(M);continue}if(M.startsWith("--")){let[R,A]=M.slice(2).split("=",2),P=K[R]??R;if(Z.has(P)){X[P]=A===void 0?!0:A!=="false";continue}if(q.has(P)){let S=A??$[z+1];if(S===void 0)throw Error(`Missing value for --${R}`);if(X[P]=S,A===void 0)z+=1;continue}throw Error(`Unknown option --${R} (use -- to pass literal text starting with -)`)}let y=M.slice(1),J=K[y]??y;if(Z.has(J)){X[J]=!0;continue}if(q.has(J)){let R=$[z+1];if(R===void 0)throw Error(`Missing value for -${y}`);X[J]=R,z+=1;continue}throw Error(`Unknown option -${y} (use -- to pass literal text starting with -)`)}return{options:X,positionals:Q}}import s$ from"node:net";import h from"node:process";import{spawn as o$}from"node:child_process";import e$ from"node:readline";import $$ from"node:path";import P$ from"node:process";function _$($){return String($??"").replace(/[^A-Za-z0-9._-]/g,"-").replace(/^-+|-+$/g,"")}function W$($,W=P$.platform){if(W==="win32")return`pipe:\\\\.\\pipe\\${_$(`${$$.win32.basename($)}-codex-app-server`)}`;return`unix:${$$.join($,"broker.sock")}`}function _($){if(typeof $!=="string"||$.length===0)throw Error("Missing broker endpoint.");if($.startsWith("pipe:")){let W=$.slice(5);if(!W)throw Error("Broker pipe endpoint is missing its path.");return{kind:"pipe",path:W}}if($.startsWith("unix:")){let W=$.slice(5);if(!W)throw Error("Broker Unix socket endpoint is missing its path.");return{kind:"unix",path:W}}throw Error(`Unsupported broker endpoint: ${$}`)}import O from"node:fs";import v$ from"node:net";import w$ from"node:os";import E from"node:path";import c from"node:process";import{spawn as j$}from"node:child_process";import{fileURLToPath as g$}from"node:url";import{execFileSync as Z$}from"node:child_process";import V from"node:fs";import B$ from"node:os";import N from"node:path";var f$=["completed","failed","cancelled"],N1=["queued","running"];var E$="CODER_HOME";function K$(){return N.resolve(process.env[E$]||N.join(B$.homedir(),".coder"))}var q$=new Map;function L1($){let W=q$.get($);if(W!==void 0)return W;let q;try{q=Z$("git",["rev-parse","--show-toplevel"],{cwd:$,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{q=$}return q$.set($,q),q}var Q$="global";function w($){return N.join(K$(),"state",Q$)}var v=null;function Y$(){if(v)return v;let $=N.join(K$(),"state"),W=[];try{W=V.readdirSync($,{withFileTypes:!0})}catch{}return v=W.filter((q)=>q.isDirectory()&&q.name!==Q$).map((q)=>N.join($,q.name)),v}function X$($){return N.join(w($),"jobs")}function f($,W){let q=N.join(X$($),W);if(V.existsSync(N.join(q,"job.json")))return q;for(let Z of Y$()){let K=N.join(Z,"jobs",W);if(V.existsSync(N.join(K,"job.json")))return K}return q}function T1(){let $=Math.random().toString(36).slice(2,8);return`coder-${Date.now().toString(36)}-${$}`}function C$($,W,q){let Z=f($,W);V.mkdirSync(Z,{recursive:!0});let K=N.join(Z,"job.json"),Q={...u$($,W)??{id:W,createdAt:new Date().toISOString(),status:"queued"},...q,updatedAt:new Date().toISOString()};return V.writeFileSync(K,`${JSON.stringify(Q,null,2)}
3
+ `,"utf8"),Q}function z$($){if(!$.engine&&($.agent==="codex"||$.agent==="claude"))$.engine=$.agent;return $}function u$($,W){let q=N.join(f($,W),"job.json");if(!V.existsSync(q))return null;try{return z$(JSON.parse(V.readFileSync(q,"utf8")))}catch{return null}}function A1($,W){let q=f($,W);if(!V.existsSync(q))return!1;return V.rmSync(q,{recursive:!0,force:!0}),!0}function k$($){if(!$)return!1;try{return process.kill($,0),!0}catch(W){return W.code==="EPERM"}}function I$($){try{let W=Z$("ps",["-o","lstart=","-p",String($)],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim(),q=W?Date.parse(W):NaN;return Number.isFinite(q)?q:null}catch{return null}}function h$($,W){if(!k$($))return!1;let q=I$($),Z=Date.parse(W.createdAt??"");if(q===null||!Number.isFinite(Z))return!0;return q<=Z+60000}var S$=60000;function D$($,W){if(W.status!=="running"&&W.status!=="queued")return W;let q;if(W.pid)q=!h$(W.pid,W);else{let Z=Date.parse(W.updatedAt??W.createdAt??"");q=Number.isFinite(Z)&&Date.now()-Z>S$}if(q)return C$($,W.id,{status:"failed",error:"worker exited without finishing",completedAt:new Date().toISOString()});return W}function F$($){let W=[X$($),...Y$().map((K)=>N.join(K,"jobs"))],q=new Set,Z=[];for(let K of W){let X=[];try{X=V.readdirSync(K)}catch{continue}for(let Q of X){if(q.has(Q))continue;let G=N.join(K,Q,"job.json");try{let z=z$(JSON.parse(V.readFileSync(G,"utf8")));q.add(Q),Z.push(z)}catch{}}}return Z.map((K)=>D$($,K)).sort((K,X)=>String(X.updatedAt??"").localeCompare(String(K.updatedAt??"")))}function P1($,W){let q=F$($);if(!W)return q[0]??null;let Z=q.find((X)=>X.id===W);if(Z)return Z;let K=q.filter((X)=>X.id.startsWith(W));if(K.length===1)return K[0];if(K.length>1)throw Error(`Job reference "${W}" is ambiguous. Use a longer id.`);return null}function _1($,W){let q=f($,W);try{V.mkdirSync(q,{recursive:!0}),V.writeFileSync(N.join(q,"heartbeat"),"","utf8")}catch{}}function f1($,W){let q=f($,W.id),Z=Date.parse(W.updatedAt??"")||0;for(let K of["log.jsonl","heartbeat"])try{Z=Math.max(Z,V.statSync(N.join(q,K)).mtimeMs)}catch{}return Z?new Date(Z).toISOString():void 0}function B1($,W,q){let Z=f($,W);V.mkdirSync(Z,{recursive:!0}),V.appendFileSync(N.join(Z,"log.jsonl"),`${JSON.stringify({at:new Date().toISOString(),...q})}
4
+ `,"utf8")}function E1($,W,q=40){let Z=N.join(f($,W),"log.jsonl");if(!V.existsSync(Z))return[];return V.readFileSync(Z,"utf8").split(/\r?\n/).filter(Boolean).slice(-q).map((X)=>{try{return JSON.parse(X)}catch{return{message:X}}})}import m from"node:fs";import{fileURLToPath as p}from"node:url";var I1=p(import.meta.url);function H$(){try{return JSON.parse(m.readFileSync(p(new URL("../package.json",import.meta.url)),"utf8")).version??"unknown"}catch{return"unknown"}}function h1($){try{return JSON.parse(m.readFileSync($,"utf8")).version??null}catch{return null}}function S1(){return p(new URL("..",import.meta.url))}var b$="broker.json";function m$($="coder-"){return O.mkdtempSync(E.join(w$.tmpdir(),$))}function p$($){let W=_($);return v$.createConnection({path:W.path})}async function M$($,W=2000){let q=Date.now();while(Date.now()-q<W){if(await new Promise((K)=>{let X=p$($);X.on("connect",()=>{X.end(),K(!0)}),X.on("error",()=>K(!1))}))return!0;await new Promise((K)=>setTimeout(K,50))}return!1}function c$({scriptPath:$,cwd:W,endpoint:q,pidFile:Z,logFile:K,env:X=c.env}){let Q=O.openSync(K,"a"),G=j$(c.execPath,[$,"serve","--endpoint",q,"--cwd",W,"--pid-file",Z],{cwd:W,env:X,detached:!0,stdio:["ignore",Q,Q]});return G.unref(),O.closeSync(Q),G}function n$(){let $=[new URL("./lib/broker.js",import.meta.url),new URL("./broker.js",import.meta.url)];for(let W of $){let q=g$(W);if(O.existsSync(q))return q}throw Error("Coder broker script not found next to the runtime. Rebuild with `bun run build`.")}function n($){return E.join(w($),b$)}function l($){let W=n($);if(!O.existsSync(W))return null;try{return JSON.parse(O.readFileSync(W,"utf8"))}catch{return null}}function l$($,W){let q=w($);O.mkdirSync(q,{recursive:!0}),O.writeFileSync(n($),`${JSON.stringify(W,null,2)}
5
+ `,"utf8")}function a$($){let W=n($);if(O.existsSync(W))O.unlinkSync(W)}async function i$($){if(!$)return!1;try{return await M$($,150)}catch{return!1}}async function U$($,W={}){let q=W.scriptPath??n$(),Z=H$(),K=l($),X=K?.version===Z&&K?.scriptPath===q;if(K&&X&&await i$(K.endpoint))return K;if(K)G$({endpoint:K.endpoint??null,pidFile:K.pidFile??null,logFile:K.logFile??null,sessionDir:K.sessionDir??null,pid:K.pid??null,killProcess:W.killProcess??null}),a$($);let Q=m$(),z=(W.createBrokerEndpoint??W$)(Q,W.platform),M=E.join(Q,"broker.pid"),y=E.join(Q,"broker.log"),J=c$({scriptPath:q,cwd:$,endpoint:z,pidFile:M,logFile:y,env:W.env??c.env});if(!await M$(z,W.timeoutMs??2000))return G$({endpoint:z,pidFile:M,logFile:y,sessionDir:Q,pid:J.pid??null,killProcess:W.killProcess??null}),null;let A={endpoint:z,pidFile:M,logFile:y,sessionDir:Q,pid:J.pid??null,version:Z,scriptPath:q};return l$($,A),A}function G$({endpoint:$=null,pidFile:W,logFile:q,sessionDir:Z=null,pid:K=null,killProcess:X=null}){if(Number.isFinite(K)&&X)try{X(K)}catch{}if(W&&O.existsSync(W))O.unlinkSync(W);if(q&&O.existsSync(q))O.unlinkSync(q);if($)try{let G=_($);if(G.kind==="unix"&&O.existsSync(G.path))O.unlinkSync(G.path)}catch{}let Q=Z??(W?E.dirname(W):q?E.dirname(q):null);if(Q&&O.existsSync(Q))try{O.rmdirSync(Q)}catch{}}import{spawnSync as t$}from"node:child_process";import I from"node:process";function j($,W=[],q={}){let Z=t$($,W,{cwd:q.cwd,env:q.env,encoding:"utf8",input:q.input,maxBuffer:q.maxBuffer,stdio:q.stdio??"pipe",shell:I.platform==="win32"?I.env.SHELL||!0:!1,windowsHide:!0});return{command:$,args:W,status:Z.status??0,signal:Z.signal??null,stdout:Z.stdout??"",stderr:Z.stderr??"",error:Z.error??null}}function t1($,W=["--version"],q={}){let Z=j($,W,q);if(Z.error&&Z.error.code==="ENOENT")return{available:!1,detail:"not found"};if(Z.error)return{available:!1,detail:Z.error.message};if(Z.status!==0)return{available:!1,detail:Z.stderr.trim()||Z.stdout.trim()||`exit ${Z.status}`};return{available:!0,detail:Z.stdout.trim()||Z.stderr.trim()||"ok"}}function d$($){return/not found|no running instance|cannot find|does not exist|no such process/i.test($)}function N$($,W={}){if(!Number.isFinite($))return{attempted:!1,delivered:!1,method:null};let q=$,Z=W.platform??I.platform,K=W.runCommandImpl??j,X=W.killImpl??I.kill.bind(I);if(Z==="win32"){let Q=K("taskkill",["/PID",String(q),"/T","/F"],{cwd:W.cwd,env:W.env});if(!Q.error&&Q.status===0)return{attempted:!0,delivered:!0,method:"taskkill",result:Q};let G=`${Q.stderr}
6
+ ${Q.stdout}`.trim();if(!Q.error&&d$(G))return{attempted:!0,delivered:!1,method:"taskkill",result:Q};if(Q.error?.code==="ENOENT")try{return X(q),{attempted:!0,delivered:!0,method:"kill"}}catch(z){if(z?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"kill"};throw z}if(Q.error)throw Q.error;throw Error(r$(Q))}try{return X(-q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process-group"}}catch(Q){if(Q?.code!=="ESRCH")try{return X(q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process"}}catch(G){if(G?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"process"};throw G}return{attempted:!0,delivered:!1,method:"process-group"}}}function r$($){let W=[`${$.command} ${$.args.join(" ")}`.trim()];if($.signal)W.push(`signal=${$.signal}`);else W.push(`exit=${$.status}`);let q=($.stderr||"").trim(),Z=($.stdout||"").trim();if(q)W.push(q);else if(Z)W.push(Z);return W.join(": ")}var V$="CODER_APP_SERVER_ENDPOINT",y$=-32001,$1="0.144.1",a;function W1(){if(a===void 0){let $=j("codex",["--version"]),W=/(\d+\.\d+\.\d+(?:-[\w.]+)?)/.exec(`${$.stdout} ${$.stderr}`);a=W?W[1]:$1}return a}function R$(){return{title:"Coder",name:"coder",version:W1()}}var J$={experimentalApi:!1,requestAttestation:!1,optOutNotificationMethods:["item/agentMessage/delta","item/reasoning/summaryTextDelta","item/reasoning/summaryPartAdded","item/reasoning/textDelta"]};function O$($,W,q){return q===void 0?{code:$,message:W}:{code:$,message:W,data:q}}function i($,W){let q=Error($);if(q.data=W,W?.code!==void 0)q.rpcCode=W.code;return q}class t{cwd;options;pending;nextId;stderr;closed;exitError;notificationHandler;serverRequestHandler;lineBuffer;transport;exitPromise;exitResolved;resolveExit;handleServerRequest;constructor($,W={}){this.cwd=$,this.options=W,this.pending=new Map,this.nextId=1,this.stderr="",this.closed=!1,this.exitError=null,this.notificationHandler=null,this.serverRequestHandler=null,this.lineBuffer="",this.transport="unknown",this.handleServerRequest=(q)=>this.defaultHandleServerRequest(q),this.exitPromise=new Promise((q)=>{this.resolveExit=q})}setNotificationHandler($){this.notificationHandler=$}setServerRequestHandler($){this.serverRequestHandler=$}request($,W){if(this.closed)throw Error("codex app-server client is closed.");let q=this.nextId;return this.nextId+=1,new Promise((Z,K)=>{this.pending.set(q,{resolve:Z,reject:K,method:$}),this.sendMessage({id:q,method:$,params:W})})}notify($,W={}){if(this.closed)return;this.sendMessage({method:$,params:W})}handleChunk($){this.lineBuffer+=$;let W=this.lineBuffer.indexOf(`
7
7
  `);while(W!==-1){let q=this.lineBuffer.slice(0,W);this.lineBuffer=this.lineBuffer.slice(W+1),this.handleLine(q),W=this.lineBuffer.indexOf(`
8
- `)}}handleLine($){if(!$.trim())return;let W;try{W=JSON.parse($)}catch(q){this.handleExit(i(`Failed to parse codex app-server JSONL: ${q instanceof Error?q.message:String(q)}`,{line:$}));return}if(W.id!==void 0&&W.method){this.handleServerRequest(W);return}if(W.id!==void 0){let q=this.pending.get(W.id);if(!q)return;if(this.pending.delete(W.id),W.error)q.reject(i(W.error.message??`codex app-server ${q.method} failed.`,W.error));else q.resolve(W.result??{});return}if(W.method&&this.notificationHandler)this.notificationHandler(W)}defaultHandleServerRequest($){let W=this.serverRequestHandler;if(!W){this.sendMessage({id:$.id,error:V$(-32601,`Unsupported server request: ${$.method}`)});return}Promise.resolve().then(()=>W($.method,$.params??{})).then((q)=>{this.sendMessage({id:$.id,result:q??{}})}).catch((q)=>{this.sendMessage({id:$.id,error:V$(-32000,q instanceof Error?q.message:String(q))})})}handleExit($){if(this.exitResolved)return;this.exitResolved=!0,this.exitError=$??null;for(let W of this.pending.values())W.reject(this.exitError??Error("codex app-server connection closed."));this.pending.clear(),this.resolveExit(void 0)}sendMessage($){throw Error("sendMessage must be implemented by subclasses.")}}class R$ extends t{proc;readline;constructor($,W={}){super($,W);this.transport="direct"}async initialize(){this.proc=o$("codex",["-c","sandbox_workspace_write.network_access=false","app-server","--disable","plugins"],{cwd:this.cwd,env:this.options.env??h.env,stdio:["pipe","pipe","pipe"],shell:h.platform==="win32"?h.env.SHELL||!0:!1,windowsHide:!0});let $=this.proc.stdout,W=this.proc.stderr;if(!$||!W)throw Error("codex app-server did not expose stdio streams.");$.setEncoding("utf8"),W.setEncoding("utf8"),W.on("data",(q)=>{this.stderr+=q}),this.proc.on("error",(q)=>{this.handleExit(q)}),this.proc.on("exit",(q,Z)=>{let K=this.stderr.trim(),z=q===0?null:i(`codex app-server exited unexpectedly (${Z?`signal ${Z}`:`exit ${q}`}).${K?`
9
- ${K}`:""}`);this.handleExit(z)}),this.readline=s$.createInterface({input:$}),this.readline.on("line",(q)=>{this.handleLine(q)}),await this.request("initialize",{clientInfo:this.options.clientInfo??y$(),capabilities:this.options.capabilities??J$}),this.notify("initialized",{})}async close(){if(this.closed){await this.exitPromise;return}if(this.closed=!0,this.readline)this.readline.close();if(this.proc&&!this.proc.killed)this.proc.stdin?.end(),setTimeout(()=>{if(this.proc&&!this.proc.killed&&this.proc.exitCode===null)if(h.platform==="win32")try{U$(this.proc.pid)}catch{}else this.proc.kill("SIGTERM")},50).unref?.();await this.exitPromise}sendMessage($){let W=`${JSON.stringify($)}
10
- `,q=this.proc?.stdin;if(!q)throw Error("codex app-server stdin is not available.");q.write(W)}}class x$ extends t{endpoint;socket;constructor($,W={}){super($,W);this.transport="broker",this.endpoint=W.brokerEndpoint}async initialize(){await new Promise(($,W)=>{let q=_(this.endpoint);this.socket=r$.createConnection({path:q.path}),this.socket.setEncoding("utf8"),this.socket.on("connect",$),this.socket.on("data",(Z)=>{this.handleChunk(Z)}),this.socket.on("error",(Z)=>{if(!this.exitResolved)W(Z);this.handleExit(Z)}),this.socket.on("close",()=>{this.handleExit(this.exitError)})}),await this.request("initialize",{clientInfo:this.options.clientInfo??y$(),capabilities:this.options.capabilities??J$}),this.notify("initialized",{})}async close(){if(this.closed){await this.exitPromise;return}if(this.closed=!0,this.socket)this.socket.end();await this.exitPromise}sendMessage($){let W=`${JSON.stringify($)}
11
- `,q=this.socket;if(!q)throw Error("codex app-server broker connection is not connected.");q.write(W)}}class d{static async connect($,W={}){let q=null;if(!W.disableBroker){if(q=W.brokerEndpoint??W.env?.[N$]??h.env[N$]??null,!q&&W.reuseExistingBroker)q=l($)?.endpoint??null;if(!q&&!W.reuseExistingBroker)q=(await M$($,{env:W.env}))?.endpoint??null}let Z=q?new x$($,{...W,brokerEndpoint:q}):new R$($,W);return await Z.initialize(),Z}}var q1=new Set(["turn/start","review/start","thread/compact/start"]);function L$($,W,q){let Z=new Set;if(W?.threadId)Z.add(W.threadId);if($==="review/start"&&q?.reviewThreadId)Z.add(q.reviewThreadId);return Z}function C($,W,q){return q===void 0?{code:$,message:W}:{code:$,message:W,data:q}}function T($,W){if($.destroyed)return;$.write(`${JSON.stringify(W)}
12
- `)}function Z1($){return $?.method==="turn/interrupt"}function K1($){if(!$)return;u.mkdirSync(r.dirname($),{recursive:!0}),u.writeFileSync($,`${L.pid}
13
- `,"utf8")}async function Q1(){let[$,...W]=L.argv.slice(2);if($!=="serve")throw Error("Usage: node src/lib/broker.mjs serve --endpoint <value> [--cwd <path>] [--pid-file <path>]");let{options:q}=e(W,{valueOptions:["cwd","pid-file","endpoint"]});if(!q.endpoint)throw Error("Missing required --endpoint.");let Z=q.cwd?r.resolve(L.cwd(),q.cwd):L.cwd(),K=String(q.endpoint),z=_(K),Q=q["pid-file"]?r.resolve(q["pid-file"]):null;K1(Q);let G=await d.connect(Z,{disableBroker:!0}),X=null,M=null,y=null,R=new Set,J=new Map;function A(Y){for(let[U,B]of J)if(B===Y)J.delete(U),G.sendMessage({id:U,error:C(-32000,"Broker client disconnected before answering the server request.")})}function P(Y){if(A(Y),X===Y)X=null;if(M===Y)M=null,y=null}function S(Y){let U=X??M;if(!U)return;if(T(U,Y),Y.method==="turn/completed"&&M===U){let B=Y.params?.threadId??null;if(!B||!y||y.has(B)){if(M=null,y=null,X===U)X=null}}}async function b(Y){for(let U of R)U.end();if(await G.close().catch(()=>{}),await new Promise((U)=>Y.close(U)),z.kind==="unix"&&u.existsSync(z.path))u.unlinkSync(z.path);if(Q&&u.existsSync(Q))u.unlinkSync(Q)}G.setNotificationHandler(S),G.handleServerRequest=(Y)=>{let U=M??X;if(!U||U.destroyed){G.sendMessage({id:Y.id,error:C(-32601,`No broker client available to answer ${Y.method}.`)});return}J.set(Y.id,U),T(U,Y)};let D=W1.createServer((Y)=>{R.add(Y),Y.setEncoding("utf8");let U="";Y.on("data",async(B)=>{U+=B;let F=U.indexOf(`
14
- `);while(F!==-1){let o=U.slice(0,F);if(U=U.slice(F+1),F=U.indexOf(`
15
- `),!o.trim())continue;let H;try{H=JSON.parse(o)}catch(x){T(Y,{id:null,error:C(-32700,`Invalid JSON: ${x instanceof Error?x.message:String(x)}`)});continue}if(H.id!==void 0&&!H.method&&J.has(H.id)){J.delete(H.id),G.sendMessage(H);continue}if(H.id!==void 0&&H.method==="initialize"){T(Y,{id:H.id,result:{userAgent:"coder-broker"}});continue}if(H.method==="initialized"&&H.id===void 0)continue;if(H.id!==void 0&&H.method==="broker/shutdown")T(Y,{id:H.id,result:{}}),await b(D),L.exit(0);if(H.id===void 0||!H.method)continue;let s=Z1(H)&&M&&M!==Y&&!X;if((X&&X!==Y||M&&M!==Y)&&!s){T(Y,{id:H.id,error:C(O$,"Shared Codex broker is busy.")});continue}if(s){try{let x=await G.request(H.method,H.params??{});T(Y,{id:H.id,result:x})}catch(x){let k=x;T(Y,{id:H.id,error:C(k.rpcCode??-32000,k.message)})}continue}let g=q1.has(H.method);if(X=Y,g)M=Y,y=L$(H.method,H.params??{},null);try{let x=await G.request(H.method,H.params??{});if(T(Y,{id:H.id,result:x}),g)y=L$(H.method,H.params??{},x);if(X===Y)X=null}catch(x){let k=x;if(T(Y,{id:H.id,error:C(k.rpcCode??-32000,k.message)}),X===Y)X=null;if(M===Y&&g)M=null,y=null}}}),Y.on("close",()=>{R.delete(Y),P(Y)}),Y.on("error",()=>{R.delete(Y),P(Y)})});L.on("SIGTERM",async()=>{await b(D),L.exit(0)}),L.on("SIGINT",async()=>{await b(D),L.exit(0)}),D.listen(z.path)}Q1().catch(($)=>{L.stderr.write(`${$ instanceof Error?$.message:String($)}
8
+ `)}}handleLine($){if(!$.trim())return;let W;try{W=JSON.parse($)}catch(q){this.handleExit(i(`Failed to parse codex app-server JSONL: ${q instanceof Error?q.message:String(q)}`,{line:$}));return}if(W.id!==void 0&&W.method){this.handleServerRequest(W);return}if(W.id!==void 0){let q=this.pending.get(W.id);if(!q)return;if(this.pending.delete(W.id),W.error)q.reject(i(W.error.message??`codex app-server ${q.method} failed.`,W.error));else q.resolve(W.result??{});return}if(W.method&&this.notificationHandler)this.notificationHandler(W)}defaultHandleServerRequest($){let W=this.serverRequestHandler;if(!W){this.sendMessage({id:$.id,error:O$(-32601,`Unsupported server request: ${$.method}`)});return}Promise.resolve().then(()=>W($.method,$.params??{})).then((q)=>{this.sendMessage({id:$.id,result:q??{}})}).catch((q)=>{this.sendMessage({id:$.id,error:O$(-32000,q instanceof Error?q.message:String(q))})})}handleExit($){if(this.exitResolved)return;this.exitResolved=!0,this.exitError=$??null;for(let W of this.pending.values())W.reject(this.exitError??Error("codex app-server connection closed."));this.pending.clear(),this.resolveExit(void 0)}sendMessage($){throw Error("sendMessage must be implemented by subclasses.")}}class x$ extends t{proc;readline;constructor($,W={}){super($,W);this.transport="direct"}async initialize(){this.proc=o$("codex",["-c","sandbox_workspace_write.network_access=false","app-server","--disable","plugins"],{cwd:this.cwd,env:this.options.env??h.env,stdio:["pipe","pipe","pipe"],shell:h.platform==="win32"?h.env.SHELL||!0:!1,windowsHide:!0});let $=this.proc.stdout,W=this.proc.stderr;if(!$||!W)throw Error("codex app-server did not expose stdio streams.");$.setEncoding("utf8"),W.setEncoding("utf8"),W.on("data",(q)=>{this.stderr+=q}),this.proc.on("error",(q)=>{this.handleExit(q)}),this.proc.on("exit",(q,Z)=>{let K=this.stderr.trim(),X=q===0?null:i(`codex app-server exited unexpectedly (${Z?`signal ${Z}`:`exit ${q}`}).${K?`
9
+ ${K}`:""}`);this.handleExit(X)}),this.readline=e$.createInterface({input:$}),this.readline.on("line",(q)=>{this.handleLine(q)}),await this.request("initialize",{clientInfo:this.options.clientInfo??R$(),capabilities:this.options.capabilities??J$}),this.notify("initialized",{})}async close(){if(this.closed){await this.exitPromise;return}if(this.closed=!0,this.readline)this.readline.close();if(this.proc&&!this.proc.killed)this.proc.stdin?.end(),setTimeout(()=>{if(this.proc&&!this.proc.killed&&this.proc.exitCode===null)if(h.platform==="win32")try{N$(this.proc.pid)}catch{}else this.proc.kill("SIGTERM")},50).unref?.();await this.exitPromise}sendMessage($){let W=`${JSON.stringify($)}
10
+ `,q=this.proc?.stdin;if(!q)throw Error("codex app-server stdin is not available.");q.write(W)}}class L$ extends t{endpoint;socket;constructor($,W={}){super($,W);this.transport="broker",this.endpoint=W.brokerEndpoint}async initialize(){await new Promise(($,W)=>{let q=_(this.endpoint);this.socket=s$.createConnection({path:q.path}),this.socket.setEncoding("utf8"),this.socket.on("connect",$),this.socket.on("data",(Z)=>{this.handleChunk(Z)}),this.socket.on("error",(Z)=>{if(!this.exitResolved)W(Z);this.handleExit(Z)}),this.socket.on("close",()=>{this.handleExit(this.exitError)})}),await this.request("initialize",{clientInfo:this.options.clientInfo??R$(),capabilities:this.options.capabilities??J$}),this.notify("initialized",{})}async close(){if(this.closed){await this.exitPromise;return}if(this.closed=!0,this.socket)this.socket.end();await this.exitPromise}sendMessage($){let W=`${JSON.stringify($)}
11
+ `,q=this.socket;if(!q)throw Error("codex app-server broker connection is not connected.");q.write(W)}}class d{static async connect($,W={}){let q=null;if(!W.disableBroker){if(q=W.brokerEndpoint??W.env?.[V$]??h.env[V$]??null,!q&&W.reuseExistingBroker)q=l($)?.endpoint??null;if(!q&&!W.reuseExistingBroker)q=(await U$($,{env:W.env}))?.endpoint??null}let Z=q?new L$($,{...W,brokerEndpoint:q}):new x$($,W);return await Z.initialize(),Z}}var Z1=new Set(["turn/start","review/start","thread/compact/start"]);function T$($,W,q){let Z=new Set;if(W?.threadId)Z.add(W.threadId);if($==="review/start"&&q?.reviewThreadId)Z.add(q.reviewThreadId);return Z}function C($,W,q){return q===void 0?{code:$,message:W}:{code:$,message:W,data:q}}function T($,W){if($.destroyed)return;$.write(`${JSON.stringify(W)}
12
+ `)}function K1($){return $?.method==="turn/interrupt"}function Q1($){if(!$)return;u.mkdirSync(r.dirname($),{recursive:!0}),u.writeFileSync($,`${L.pid}
13
+ `,"utf8")}async function Y1(){let[$,...W]=L.argv.slice(2);if($!=="serve")throw Error("Usage: node src/lib/broker.mjs serve --endpoint <value> [--cwd <path>] [--pid-file <path>]");let{options:q}=e(W,{valueOptions:["cwd","pid-file","endpoint"]});if(!q.endpoint)throw Error("Missing required --endpoint.");let Z=q.cwd?r.resolve(L.cwd(),q.cwd):L.cwd(),K=String(q.endpoint),X=_(K),Q=q["pid-file"]?r.resolve(q["pid-file"]):null;Q1(Q);let G=await d.connect(Z,{disableBroker:!0}),z=null,M=null,y=null,J=new Set,R=new Map;function A(Y){for(let[U,B]of R)if(B===Y)R.delete(U),G.sendMessage({id:U,error:C(-32000,"Broker client disconnected before answering the server request.")})}function P(Y){if(A(Y),z===Y)z=null;if(M===Y)M=null,y=null}function S(Y){let U=z??M;if(!U)return;if(T(U,Y),Y.method==="turn/completed"&&M===U){let B=Y.params?.threadId??null;if(!B||!y||y.has(B)){if(M=null,y=null,z===U)z=null}}}async function g(Y){for(let U of J)U.end();if(await G.close().catch(()=>{}),await new Promise((U)=>Y.close(U)),X.kind==="unix"&&u.existsSync(X.path))u.unlinkSync(X.path);if(Q&&u.existsSync(Q))u.unlinkSync(Q)}G.setNotificationHandler(S),G.handleServerRequest=(Y)=>{let U=M??z;if(!U||U.destroyed){G.sendMessage({id:Y.id,error:C(-32601,`No broker client available to answer ${Y.method}.`)});return}R.set(Y.id,U),T(U,Y)};let D=q1.createServer((Y)=>{J.add(Y),Y.setEncoding("utf8");let U="";Y.on("data",async(B)=>{U+=B;let F=U.indexOf(`
14
+ `);while(F!==-1){let s=U.slice(0,F);if(U=U.slice(F+1),F=U.indexOf(`
15
+ `),!s.trim())continue;let H;try{H=JSON.parse(s)}catch(x){T(Y,{id:null,error:C(-32700,`Invalid JSON: ${x instanceof Error?x.message:String(x)}`)});continue}if(H.id!==void 0&&!H.method&&R.has(H.id)){R.delete(H.id),G.sendMessage(H);continue}if(H.id!==void 0&&H.method==="initialize"){T(Y,{id:H.id,result:{userAgent:"coder-broker"}});continue}if(H.method==="initialized"&&H.id===void 0)continue;if(H.id!==void 0&&H.method==="broker/shutdown")T(Y,{id:H.id,result:{}}),await g(D),L.exit(0);if(H.id===void 0||!H.method)continue;let o=K1(H)&&M&&M!==Y&&!z;if((z&&z!==Y||M&&M!==Y)&&!o){T(Y,{id:H.id,error:C(y$,"Shared Codex broker is busy.")});continue}if(o){try{let x=await G.request(H.method,H.params??{});T(Y,{id:H.id,result:x})}catch(x){let k=x;T(Y,{id:H.id,error:C(k.rpcCode??-32000,k.message)})}continue}let b=Z1.has(H.method);if(z=Y,b)M=Y,y=T$(H.method,H.params??{},null);try{let x=await G.request(H.method,H.params??{});if(T(Y,{id:H.id,result:x}),b)y=T$(H.method,H.params??{},x);if(z===Y)z=null}catch(x){let k=x;if(T(Y,{id:H.id,error:C(k.rpcCode??-32000,k.message)}),z===Y)z=null;if(M===Y&&b)M=null,y=null}}}),Y.on("close",()=>{J.delete(Y),P(Y)}),Y.on("error",()=>{J.delete(Y),P(Y)})});L.on("SIGTERM",async()=>{await g(D),L.exit(0)}),L.on("SIGINT",async()=>{await g(D),L.exit(0)}),D.listen(X.path)}Y1().catch(($)=>{L.stderr.write(`${$ instanceof Error?$.message:String($)}
16
16
  `),L.exit(1)});
@@ -6,35 +6,41 @@ Point Coder at any OpenAI-compatible URL, like Ollama or llama.cpp on your lapto
6
6
 
7
7
  ```bash
8
8
  # local Ollama model, no key
9
- coder setup-model qwen --base-url http://localhost:11434/v1 --model qwen2.5-coder:32b
9
+ coder model add qwen --base-url http://localhost:11434/v1 --model qwen2.5-coder:32b
10
10
 
11
11
  # third-party provider via OpenRouter
12
- coder setup-model kimi --base-url https://openrouter.ai/api/v1 --model moonshotai/kimi-k2 --env-key OPENROUTER_API_KEY
12
+ coder model add kimi --base-url https://openrouter.ai/api/v1 --model moonshotai/kimi-k2 --env-key OPENROUTER_API_KEY
13
13
  ```
14
14
 
15
- `setup-model` saves the entry, probes the endpoint, and reports anything missing (unreachable URL, unset key env var, no codex). Flags:
15
+ `model add` saves the entry, probes the endpoint, and reports anything missing (unreachable URL, unset key env var, no codex). Change one later with `coder model update <name>`, drop it with `coder model remove <name>`. Flags:
16
16
 
17
17
  | Flag | Meaning |
18
18
  | --- | --- |
19
19
  | `--base-url <url>` | OpenAI-compatible API base (e.g. `http://localhost:11434/v1`) |
20
20
  | `--model <id>` | the provider's model id (e.g. `qwen2.5-coder:32b`) |
21
21
  | `--env-key <VAR>` | env var holding the API key; omit for keyless local endpoints |
22
- | `--remove <name>` | delete a configured model |
23
22
  | `--workspace` | write to `<repo>/coder.config.json` instead of the user file |
24
23
 
25
24
  ## Use it
26
25
 
27
- Anywhere a model name goes:
26
+ Anywhere a model name goes; together they form the `custom` agent:
28
27
 
29
28
  ```bash
30
29
  coder run --model qwen "explain this repo" # per task
31
- coder config set agents.codex.model qwen # as the default
32
- coder setup-model # list models + probe their endpoints
30
+ coder run --agent custom "explain this repo" # the custom agent (its default model, or the only one)
31
+ coder config set agents.custom.model qwen # default model for --agent custom
32
+ coder model list # list models + probe their endpoints
33
+ ```
34
+
35
+ Add `custom` to the fallback chain to make your models a fallback tier, e.g. a local model that takes over when the hosted engines are out of quota:
36
+
37
+ ```bash
38
+ coder config set chain '["codex", "claude", "custom"]'
33
39
  ```
34
40
 
35
41
  ## Config shape
36
42
 
37
- `setup-model` writes the `models` section of the [config](../README.md#configuration):
43
+ `coder model add` writes the `models` section of the [config](../README.md#configuration):
38
44
 
39
45
  ```json
40
46
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wular/coder",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Delegating coding-agent runtime",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,6 +7,10 @@ description: Use Coder for any coding, implementation, or investigation task - f
7
7
 
8
8
  You dispatch coding tasks through the `coder` runtime instead of implementing them yourself. By default the runtime picks the engine from its configured chain; flags like `--agent`/`--model`/`--effort` override it.
9
9
 
10
+ Coder delegates coding to supervised subagents of any model, from your favorite harness. It is a local supervisor runtime (npm: `@wular/coder`): it spawns engine CLIs (OpenAI Codex, Anthropic Claude) as sandboxed workers, keeps task state in `~/.coder`, enforces its own permission/approval policy, and falls back down the configured chain when an engine can't start. Beyond the built-in models it runs **custom models** - any OpenAI-compatible endpoint, local (Ollama, vLLM, ...) or hosted (OpenRouter, ...) - added with `coder model add` and dispatched with `--model <name>` or `--agent custom` (they currently run on the codex engine; no login needed).
11
+
12
+ ## Setup
13
+
10
14
  If `coder` is not on PATH, install it yourself without asking (`npm install -g @wular/coder`). Assume nothing about setup state - the user may or may not have run setup. When a dispatch fails because engines are missing or logged out, run `coder setup-host` and follow its output: it checks engines and auth, seeds the config, refreshes this skill, auto-updates codex when too old for the default model, and prints the exact fix for anything not ready (safe to re-run anytime). Ask the user before installing an engine CLI or changing auth; if setup updated codex, tell the user to restart their codex session.
11
15
 
12
16
  ## Dispatching a task
@@ -26,7 +30,7 @@ If `coder` is not on PATH, install it yourself without asking (`npm install -g @
26
30
 
27
31
  - `coder task run` exits after its startup check. Exit 0: the task started - relay the task id and fetch its result (above). Exit 1: it failed to start or the turn failed - report it, do not retry or fall back yourself. Exit 3: no engine in the chain could start and stdout carries a `run-native-subagent` payload - see below.
28
32
  - When the first engine can't start (auth, quota, rate limit), the runtime automatically falls back to the next engine in the chain, runs the same task on it, and still exits 0 - so just fetch the result. If the failure mentions a usage-limit reset time, relay that to the user.
29
- - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`).
33
+ - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`, `custom`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`; custom models: any name from `coder model add` - list them with `coder model list`).
30
34
  - `spark` is only for the very lightest tasks (formatting, renames, quick lookups) - very fast and very cheap. It runs on a separate quota, so reach for it when the others hit a usage limit; it may still run once they are exhausted.
31
35
  - Permissions default to auto mode (workspace-write + policy-answered escalations). Pass `--permissions read-only` when the task is read-only; `--permissions workspace-write` to forbid any escalation beyond the project.
32
36
  - A background dispatch prints a task id plus its result/steer/stop commands. Relay them and fetch the result (above) rather than polling.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "coder",
3
- "version": "0.2.2",
4
- "description": "Delegate coding tasks to a Coder subagent. Your main context stays clean.",
3
+ "version": "0.2.3",
4
+ "description": "Delegate coding tasks to supervised Coder subagents running on Codex, Claude, or any OpenAI-compatible model. Your main context stays clean.",
5
5
  "author": {
6
6
  "name": "muzam1l"
7
7
  }
@@ -3,10 +3,14 @@ name: handle
3
3
  description: Use Coder for any coding, implementation, or investigation task - features, fixes, refactors, debugging, tests, code questions. You orchestrate, never implement yourself; dispatch through the `coder` CLI, one coder per focused goal, fanning out many coders in parallel as the work needs.
4
4
  ---
5
5
 
6
- # Coder dispatch
6
+ # Coder dispatch (Claude host)
7
7
 
8
8
  You dispatch coding tasks through the `coder` runtime instead of implementing them yourself. By default the runtime picks the engine from its configured chain; flags like `--agent`/`--model`/`--effort` override it.
9
9
 
10
+ Coder delegates coding to supervised subagents of any model, from your favorite harness. It is a local supervisor runtime (npm: `@wular/coder`): it spawns engine CLIs (OpenAI Codex, Anthropic Claude) as sandboxed workers, keeps task state in `~/.coder`, enforces its own permission/approval policy, and falls back down the configured chain when an engine can't start. Beyond the built-in models it runs **custom models** - any OpenAI-compatible endpoint, local (Ollama, vLLM, ...) or hosted (OpenRouter, ...) - added with `coder model add` and dispatched with `--model <name>` or `--agent custom` (they currently run on the codex engine; no login needed).
11
+
12
+ ## Setup
13
+
10
14
  If `coder` is not on PATH, install it yourself without asking (`npm install -g @wular/coder`). Assume nothing about setup state - the user may or may not have run setup. When a dispatch fails because engines are missing or logged out, run `coder setup-host claude` and follow its output: it checks engines and auth, seeds the config, installs the host plugin, auto-updates codex when too old for the default model, and prints the exact fix for anything not ready (safe to re-run anytime). Ask the user before installing an engine CLI or changing auth; if setup updated codex, tell the user to restart their codex session. For a guided setup, suggest `/coder:setup`.
11
15
 
12
16
  ## Dispatching a task
@@ -31,7 +35,7 @@ If `coder` is not on PATH, install it yourself without asking (`npm install -g @
31
35
 
32
36
  - `coder task run` exits after its startup check. Exit 0: the task started - relay the task id and fetch its result (above). Exit 1: it failed to start or the turn failed - report it, do not retry or fall back yourself. Exit 3: no engine in the chain could start and stdout carries a `run-native-subagent` payload - see below.
33
37
  - When the first engine can't start (auth, quota, rate limit), the runtime automatically falls back to the next engine in the chain, runs the same task on it, and still exits 0 - so just fetch the result. If the failure mentions a usage-limit reset time, relay that to the user.
34
- - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`).
38
+ - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`, `custom`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`; custom models: any name from `coder model add` - list them with `coder model list`).
35
39
  - `spark` is only for the very lightest tasks (formatting, renames, quick lookups) - very fast and very cheap. It runs on a separate quota, so reach for it when the others hit a usage limit; it may still run once they are exhausted.
36
40
  - Permissions default to auto mode (workspace-write + policy-answered escalations). Pass `--permissions read-only` when the task is read-only; `--permissions workspace-write` to forbid any escalation beyond the project.
37
41
  - A background dispatch prints a task id plus its result/steer/stop commands. Relay them and fetch the result (above) rather than polling.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "coder",
3
3
  "displayName": "Coder",
4
- "version": "0.2.2",
5
- "description": "Delegate coding tasks to a Coder subagent. Your main context stays clean.",
4
+ "version": "0.2.3",
5
+ "description": "Delegate coding tasks to supervised Coder subagents running on Codex, Claude, or any OpenAI-compatible model. Your main context stays clean.",
6
6
  "author": {
7
7
  "name": "muzam1l"
8
8
  },
@@ -7,6 +7,10 @@ description: Use Coder for any coding, implementation, or investigation task - f
7
7
 
8
8
  You dispatch coding tasks through the `coder` runtime instead of implementing them yourself. By default the runtime picks the engine from its configured chain; flags like `--agent`/`--model`/`--effort` override it.
9
9
 
10
+ Coder delegates coding to supervised subagents of any model, from your favorite harness. It is a local supervisor runtime (npm: `@wular/coder`): it spawns engine CLIs (OpenAI Codex, Anthropic Claude) as sandboxed workers, keeps task state in `~/.coder`, enforces its own permission/approval policy, and falls back down the configured chain when an engine can't start. Beyond the built-in models it runs **custom models** - any OpenAI-compatible endpoint, local (Ollama, vLLM, ...) or hosted (OpenRouter, ...) - added with `coder model add` and dispatched with `--model <name>` or `--agent custom` (they currently run on the codex engine; no login needed).
11
+
12
+ ## Setup
13
+
10
14
  If `coder` is not on PATH, install it yourself without asking (`npm install -g @wular/coder`). Assume nothing about setup state - the user may or may not have run setup. When a dispatch fails because engines are missing or logged out, run `coder setup-host` and follow its output: it checks engines and auth, seeds the config, auto-updates codex when too old for the default model, and prints the exact fix for anything not ready (safe to re-run anytime; no host plugin to install - Cursor gets this skill from its marketplace). Ask the user before installing an engine CLI or changing auth; if setup updated codex, tell the user to restart their codex session.
11
15
 
12
16
  ## Dispatching a task
@@ -26,7 +30,7 @@ If `coder` is not on PATH, install it yourself without asking (`npm install -g @
26
30
 
27
31
  - `coder task run` exits after its startup check. Exit 0: the task started - relay the task id and fetch its result (above). Exit 1: it failed to start or the turn failed - report it, do not retry or fall back yourself. Exit 3: no engine in the chain could start and stdout carries a `run-native-subagent` payload - see below.
28
32
  - When the first engine can't start (auth, quota, rate limit), the runtime automatically falls back to the next engine in the chain, runs the same task on it, and still exits 0 - so just fetch the result. If the failure mentions a usage-limit reset time, relay that to the user.
29
- - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`).
33
+ - Engine, model, and effort come from config; add `--agent` / `--model` / `--effort` when the user asks or it is unambiguous from context (agents: `codex`, `claude`, `custom`; codex models: `spark`, `luna`, `terra`, `sol`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`; custom models: any name from `coder model add` - list them with `coder model list`).
30
34
  - `spark` is only for the very lightest tasks (formatting, renames, quick lookups) - very fast and very cheap. It runs on a separate quota, so reach for it when the others hit a usage limit; it may still run once they are exhausted.
31
35
  - Permissions default to auto mode (workspace-write + policy-answered escalations). Pass `--permissions read-only` when the task is read-only; `--permissions workspace-write` to forbid any escalation beyond the project.
32
36
  - A background dispatch prints a task id plus its result/steer/stop commands. Relay them and fetch the result (above) rather than polling.