@wular/coder 0.1.26 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- var T$=Object.defineProperty;var Q1=($,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 d from"node:path";import x from"node:process";function o($,W={}){let q=new Set(W.valueOptions??[]),Z=new Set(W.booleanOptions??[]),G=W.aliasMap??{},Y={},Q=[],y=!1;for(let X=0;X<$.length;X+=1){let H=$[X];if(y){Q.push(H);continue}if(H==="--"){y=!0;continue}if(!H.startsWith("-")||H==="-"){Q.push(H);continue}if(H.startsWith("--")){let[V,_]=H.slice(2).split("=",2),P=G[V]??V;if(Z.has(P)){Y[P]=_===void 0?!0:_!=="false";continue}if(q.has(P)){let h=_??$[X+1];if(h===void 0)throw Error(`Missing value for --${V}`);if(Y[P]=h,_===void 0)X+=1;continue}throw Error(`Unknown option --${V} (use -- to pass literal text starting with -)`)}let N=H.slice(1),J=G[N]??N;if(Z.has(J)){Y[J]=!0;continue}if(q.has(J)){let V=$[X+1];if(V===void 0)throw Error(`Missing value for -${N}`);Y[J]=V,X+=1;continue}throw Error(`Unknown option -${N} (use -- to pass literal text starting with -)`)}return{options:Y,positionals:Q}}import r$ from"node:net";import k from"node:process";import{spawn as s$}from"node:child_process";import o$ from"node:readline";import e from"node:path";import x$ from"node:process";function A$($){return String($??"").replace(/[^A-Za-z0-9._-]/g,"-").replace(/^-+|-+$/g,"")}function $$($,W=x$.platform){if(W==="win32")return`pipe:\\\\.\\pipe\\${A$(`${e.win32.basename($)}-codex-app-server`)}`;return`unix:${e.join($,"broker.sock")}`}function f($){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 M from"node:fs";import F$ from"node:net";import v$ from"node:os";import E from"node:path";import p from"node:process";import{spawn as j$}from"node:child_process";import{fileURLToPath as w$}from"node:url";import{createHash as P$}from"node:crypto";import{execFileSync as Z$}from"node:child_process";import O from"node:fs";import f$ from"node:os";import L from"node:path";var _$=["completed","failed","cancelled"],U1=["queued","running"];var R$="CODER_HOME";function B$(){return L.resolve(process.env[R$]||L.join(f$.homedir(),".coder"))}var W$=new Map;function E$($){let W=W$.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 W$.set($,q),q}var q$=new Map;function v($){let W=q$.get($);if(W!==void 0)return W;let q=E$($),Z=q;try{Z=O.realpathSync.native(q)}catch{Z=q}let Y=(L.basename(q)||"workspace").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"workspace",Q=P$("sha256").update(Z).digest("hex").slice(0,12),y=L.join(B$(),"state",`${Y}-${Q}`);return q$.set($,y),y}function G$($){return L.join(v($),"jobs")}function R($,W){return L.join(G$($),W)}function x1(){let $=Math.random().toString(36).slice(2,8);return`coder-${Date.now().toString(36)}-${$}`}function C$($,W,q){let Z=R($,W);O.mkdirSync(Z,{recursive:!0});let G=L.join(Z,"job.json"),Q={...K$($,W)??{id:W,createdAt:new Date().toISOString(),status:"queued"},...q,updatedAt:new Date().toISOString()};return O.writeFileSync(G,`${JSON.stringify(Q,null,2)}
3
- `,"utf8"),Q}function K$($,W){let q=L.join(R($,W),"job.json");if(!O.existsSync(q))return null;try{return JSON.parse(O.readFileSync(q,"utf8"))}catch{return null}}function A1($,W){let q=R($,W);if(!O.existsSync(q))return!1;return O.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 S$($){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=S$($),Z=Date.parse(W.createdAt??"");if(q===null||!Number.isFinite(Z))return!0;return q<=Z+60000}var k$=60000;function h$($,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>k$}if(q)return C$($,W.id,{status:"failed",error:"worker exited without finishing",completedAt:new Date().toISOString()});return W}function D$($){let W=G$($);if(!O.existsSync(W))return[];return O.readdirSync(W).map((q)=>K$($,q)).filter((q)=>q!==null).map((q)=>h$($,q)).sort((q,Z)=>String(Z.updatedAt??"").localeCompare(String(q.updatedAt??"")))}function _1($,W){let q=D$($);if(!W)return q[0]??null;let Z=q.find((Y)=>Y.id===W);if(Z)return Z;let G=q.filter((Y)=>Y.id.startsWith(W));if(G.length===1)return G[0];if(G.length>1)throw Error(`Job reference "${W}" is ambiguous. Use a longer id.`);return null}function P1($,W){let q=R($,W);try{O.mkdirSync(q,{recursive:!0}),O.writeFileSync(L.join(q,"heartbeat"),"","utf8")}catch{}}function f1($,W){let q=R($,W.id),Z=Date.parse(W.updatedAt??"")||0;for(let G of["log.jsonl","heartbeat"])try{Z=Math.max(Z,O.statSync(L.join(q,G)).mtimeMs)}catch{}return Z?new Date(Z).toISOString():void 0}function R1($,W,q){let Z=R($,W);O.mkdirSync(Z,{recursive:!0}),O.appendFileSync(L.join(Z,"log.jsonl"),`${JSON.stringify({at:new Date().toISOString(),...q})}
4
- `,"utf8")}function B1($,W,q=40){let Z=L.join(R($,W),"log.jsonl");if(!O.existsSync(Z))return[];return O.readFileSync(Z,"utf8").split(/\r?\n/).filter(Boolean).slice(-q).map((Y)=>{try{return JSON.parse(Y)}catch{return{message:Y}}})}import g from"node:fs";import{fileURLToPath as m}from"node:url";var S1=m(import.meta.url);function Q$(){try{return JSON.parse(g.readFileSync(m(new URL("../package.json",import.meta.url)),"utf8")).version??"unknown"}catch{return"unknown"}}function I1($){try{return JSON.parse(g.readFileSync($,"utf8")).version??null}catch{return null}}function k1(){return m(new URL("..",import.meta.url))}var b$="broker.json";function g$($="coder-"){return M.mkdtempSync(E.join(v$.tmpdir(),$))}function m$($){let W=f($);return F$.createConnection({path:W.path})}async function z$($,W=2000){let q=Date.now();while(Date.now()-q<W){if(await new Promise((G)=>{let Y=m$($);Y.on("connect",()=>{Y.end(),G(!0)}),Y.on("error",()=>G(!1))}))return!0;await new Promise((G)=>setTimeout(G,50))}return!1}function p$({scriptPath:$,cwd:W,endpoint:q,pidFile:Z,logFile:G,env:Y=p.env}){let Q=M.openSync(G,"a"),y=j$(p.execPath,[$,"serve","--endpoint",q,"--cwd",W,"--pid-file",Z],{cwd:W,env:Y,detached:!0,stdio:["ignore",Q,Q]});return y.unref(),M.closeSync(Q),y}function n$(){let $=[new URL("./lib/broker.js",import.meta.url),new URL("./broker.js",import.meta.url)];for(let W of $){let q=w$(W);if(M.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(v($),b$)}function c($){let W=n($);if(!M.existsSync(W))return null;try{return JSON.parse(M.readFileSync(W,"utf8"))}catch{return null}}function c$($,W){let q=v($);M.mkdirSync(q,{recursive:!0}),M.writeFileSync(n($),`${JSON.stringify(W,null,2)}
5
- `,"utf8")}function l$($){let W=n($);if(M.existsSync(W))M.unlinkSync(W)}async function a$($){if(!$)return!1;try{return await z$($,150)}catch{return!1}}async function X$($,W={}){let q=W.scriptPath??n$(),Z=Q$(),G=c($),Y=G?.version===Z&&G?.scriptPath===q;if(G&&Y&&await a$(G.endpoint))return G;if(G)Y$({endpoint:G.endpoint??null,pidFile:G.pidFile??null,logFile:G.logFile??null,sessionDir:G.sessionDir??null,pid:G.pid??null,killProcess:W.killProcess??null}),l$($);let Q=g$(),X=(W.createBrokerEndpoint??$$)(Q,W.platform),H=E.join(Q,"broker.pid"),N=E.join(Q,"broker.log"),J=p$({scriptPath:q,cwd:$,endpoint:X,pidFile:H,logFile:N,env:W.env??p.env});if(!await z$(X,W.timeoutMs??2000))return Y$({endpoint:X,pidFile:H,logFile:N,sessionDir:Q,pid:J.pid??null,killProcess:W.killProcess??null}),null;let _={endpoint:X,pidFile:H,logFile:N,sessionDir:Q,pid:J.pid??null,version:Z,scriptPath:q};return c$($,_),_}function Y$({endpoint:$=null,pidFile:W,logFile:q,sessionDir:Z=null,pid:G=null,killProcess:Y=null}){if(Number.isFinite(G)&&Y)try{Y(G)}catch{}if(W&&M.existsSync(W))M.unlinkSync(W);if(q&&M.existsSync(q))M.unlinkSync(q);if($)try{let y=f($);if(y.kind==="unix"&&M.existsSync(y.path))M.unlinkSync(y.path)}catch{}let Q=Z??(W?E.dirname(W):q?E.dirname(q):null);if(Q&&M.existsSync(Q))try{M.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 y$($,W={}){if(!Number.isFinite($))return{attempted:!1,delivered:!1,method:null};let q=$,Z=W.platform??I.platform,G=W.runCommandImpl??j,Y=W.killImpl??I.kill.bind(I);if(Z==="win32"){let Q=G("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 y=`${Q.stderr}
6
- ${Q.stdout}`.trim();if(!Q.error&&t$(y))return{attempted:!0,delivered:!1,method:"taskkill",result:Q};if(Q.error?.code==="ENOENT")try{return Y(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 Y(-q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process-group"}}catch(Q){if(Q?.code!=="ESRCH")try{return Y(q,"SIGTERM"),{attempted:!0,delivered:!0,method:"process"}}catch(y){if(y?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"process"};throw y}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 H$="CODER_APP_SERVER_ENDPOINT",M$=-32001,e$="0.144.1",l;function $1(){if(l===void 0){let $=j("codex",["--version"]),W=/(\d+\.\d+\.\d+(?:-[\w.]+)?)/.exec(`${$.stdout} ${$.stderr}`);l=W?W[1]:e$}return l}function N$(){return{title:"Coder",name:"coder",version:$1()}}var O$={experimentalApi:!1,requestAttestation:!1,optOutNotificationMethods:["item/agentMessage/delta","item/reasoning/summaryTextDelta","item/reasoning/summaryPartAdded","item/reasoning/textDelta"]};function U$($,W,q){return q===void 0?{code:$,message:W}:{code:$,message:W,data:q}}function a($,W){let q=Error($);if(q.data=W,W?.code!==void 0)q.rpcCode=W.code;return q}class i{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,G)=>{this.pending.set(q,{resolve:Z,reject:G,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 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(`
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(a(`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(a(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:U$(-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:U$(-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 V$ extends i{proc;readline;constructor($,W={}){super($,W);this.transport="direct"}async initialize(){this.proc=s$("codex",["-c","sandbox_workspace_write.network_access=false","app-server","--disable","plugins"],{cwd:this.cwd,env:this.options.env??k.env,stdio:["pipe","pipe","pipe"],shell:k.platform==="win32"?k.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 G=this.stderr.trim(),Y=q===0?null:a(`codex app-server exited unexpectedly (${Z?`signal ${Z}`:`exit ${q}`}).${G?`
9
- ${G}`:""}`);this.handleExit(Y)}),this.readline=o$.createInterface({input:$}),this.readline.on("line",(q)=>{this.handleLine(q)}),await this.request("initialize",{clientInfo:this.options.clientInfo??N$(),capabilities:this.options.capabilities??O$}),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(k.platform==="win32")try{y$(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 i{endpoint;socket;constructor($,W={}){super($,W);this.transport="broker",this.endpoint=W.brokerEndpoint}async initialize(){await new Promise(($,W)=>{let q=f(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??N$(),capabilities:this.options.capabilities??O$}),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 t{static async connect($,W={}){let q=null;if(!W.disableBroker){if(q=W.brokerEndpoint??W.env?.[H$]??k.env[H$]??null,!q&&W.reuseExistingBroker)q=c($)?.endpoint??null;if(!q&&!W.reuseExistingBroker)q=(await X$($,{env:W.env}))?.endpoint??null}let Z=q?new L$($,{...W,brokerEndpoint:q}):new V$($,W);return await Z.initialize(),Z}}var q1=new Set(["turn/start","review/start","thread/compact/start"]);function J$($,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 A($,W){if($.destroyed)return;$.write(`${JSON.stringify(W)}
12
- `)}function Z1($){return $?.method==="turn/interrupt"}function G1($){if(!$)return;u.mkdirSync(d.dirname($),{recursive:!0}),u.writeFileSync($,`${x.pid}
13
- `,"utf8")}async function K1(){let[$,...W]=x.argv.slice(2);if($!=="serve")throw Error("Usage: node src/lib/broker.mjs serve --endpoint <value> [--cwd <path>] [--pid-file <path>]");let{options:q}=o(W,{valueOptions:["cwd","pid-file","endpoint"]});if(!q.endpoint)throw Error("Missing required --endpoint.");let Z=q.cwd?d.resolve(x.cwd(),q.cwd):x.cwd(),G=String(q.endpoint),Y=f(G),Q=q["pid-file"]?d.resolve(q["pid-file"]):null;G1(Q);let y=await t.connect(Z,{disableBroker:!0}),X=null,H=null,N=null,J=new Set,V=new Map;function _(K){for(let[U,B]of V)if(B===K)V.delete(U),y.sendMessage({id:U,error:C(-32000,"Broker client disconnected before answering the server request.")})}function P(K){if(_(K),X===K)X=null;if(H===K)H=null,N=null}function h(K){let U=X??H;if(!U)return;if(A(U,K),K.method==="turn/completed"&&H===U){let B=K.params?.threadId??null;if(!B||!N||N.has(B)){if(H=null,N=null,X===U)X=null}}}async function w(K){for(let U of J)U.end();if(await y.close().catch(()=>{}),await new Promise((U)=>K.close(U)),Y.kind==="unix"&&u.existsSync(Y.path))u.unlinkSync(Y.path);if(Q&&u.existsSync(Q))u.unlinkSync(Q)}y.setNotificationHandler(h),y.handleServerRequest=(K)=>{let U=H??X;if(!U||U.destroyed){y.sendMessage({id:K.id,error:C(-32601,`No broker client available to answer ${K.method}.`)});return}V.set(K.id,U),A(U,K)};let D=W1.createServer((K)=>{J.add(K),K.setEncoding("utf8");let U="";K.on("data",async(B)=>{U+=B;let F=U.indexOf(`
14
- `);while(F!==-1){let r=U.slice(0,F);if(U=U.slice(F+1),F=U.indexOf(`
15
- `),!r.trim())continue;let z;try{z=JSON.parse(r)}catch(T){A(K,{id:null,error:C(-32700,`Invalid JSON: ${T instanceof Error?T.message:String(T)}`)});continue}if(z.id!==void 0&&!z.method&&V.has(z.id)){V.delete(z.id),y.sendMessage(z);continue}if(z.id!==void 0&&z.method==="initialize"){A(K,{id:z.id,result:{userAgent:"coder-broker"}});continue}if(z.method==="initialized"&&z.id===void 0)continue;if(z.id!==void 0&&z.method==="broker/shutdown")A(K,{id:z.id,result:{}}),await w(D),x.exit(0);if(z.id===void 0||!z.method)continue;let s=Z1(z)&&H&&H!==K&&!X;if((X&&X!==K||H&&H!==K)&&!s){A(K,{id:z.id,error:C(M$,"Shared Codex broker is busy.")});continue}if(s){try{let T=await y.request(z.method,z.params??{});A(K,{id:z.id,result:T})}catch(T){let S=T;A(K,{id:z.id,error:C(S.rpcCode??-32000,S.message)})}continue}let b=q1.has(z.method);if(X=K,b)H=K,N=J$(z.method,z.params??{},null);try{let T=await y.request(z.method,z.params??{});if(A(K,{id:z.id,result:T}),b)N=J$(z.method,z.params??{},T);if(X===K)X=null}catch(T){let S=T;if(A(K,{id:z.id,error:C(S.rpcCode??-32000,S.message)}),X===K)X=null;if(H===K&&b)H=null,N=null}}}),K.on("close",()=>{J.delete(K),P(K)}),K.on("error",()=>{J.delete(K),P(K)})});x.on("SIGTERM",async()=>{await w(D),x.exit(0)}),x.on("SIGINT",async()=>{await w(D),x.exit(0)}),D.listen(Y.path)}K1().catch(($)=>{x.stderr.write(`${$ instanceof Error?$.message:String($)}
16
- `),x.exit(1)});
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($)}
16
+ `),L.exit(1)});
@@ -0,0 +1,45 @@
1
+ # Bring your own model
2
+
3
+ Point Coder at any OpenAI-compatible URL, like Ollama or llama.cpp on your laptop, a vLLM GPU box, OpenRouter, etc., and dispatch subagents to it like any built-in model. No login, no extra setup: permissions, steering, and fallback just work.
4
+
5
+ ## Connect a model
6
+
7
+ ```bash
8
+ # local Ollama model, no key
9
+ coder setup-model qwen --base-url http://localhost:11434/v1 --model qwen2.5-coder:32b
10
+
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
13
+ ```
14
+
15
+ `setup-model` saves the entry, probes the endpoint, and reports anything missing (unreachable URL, unset key env var, no codex). Flags:
16
+
17
+ | Flag | Meaning |
18
+ | --- | --- |
19
+ | `--base-url <url>` | OpenAI-compatible API base (e.g. `http://localhost:11434/v1`) |
20
+ | `--model <id>` | the provider's model id (e.g. `qwen2.5-coder:32b`) |
21
+ | `--env-key <VAR>` | env var holding the API key; omit for keyless local endpoints |
22
+ | `--remove <name>` | delete a configured model |
23
+ | `--workspace` | write to `<repo>/coder.config.json` instead of the user file |
24
+
25
+ ## Use it
26
+
27
+ Anywhere a model name goes:
28
+
29
+ ```bash
30
+ 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
33
+ ```
34
+
35
+ ## Config shape
36
+
37
+ `setup-model` writes the `models` section of the [config](../README.md#configuration):
38
+
39
+ ```json
40
+ {
41
+ "models": {
42
+ "qwen": { "baseUrl": "http://localhost:11434/v1", "model": "qwen2.5-coder:32b", "envKey": "MY_KEY" }
43
+ }
44
+ }
45
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wular/coder",
3
- "version": "0.1.26",
3
+ "version": "0.2.0",
4
4
  "description": "Delegating coding-agent runtime",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,7 +23,8 @@
23
23
  "plugins",
24
24
  ".claude-plugin",
25
25
  ".agents",
26
- "README.md"
26
+ "README.md",
27
+ "docs"
27
28
  ],
28
29
  "publishConfig": {
29
30
  "access": "public"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder",
3
- "version": "0.1.26",
3
+ "version": "0.2.0",
4
4
  "description": "Delegate coding tasks to a Coder subagent. Your main context stays clean.",
5
5
  "author": {
6
6
  "name": "muzam1l"
@@ -9,12 +9,12 @@ shell steps, keep commentary to a line or two, and only expand when something
9
9
  needs the user's decision. Use AskUserQuestion for the decision points.
10
10
 
11
11
  1. In one shell call, ensure the runtime then read its status:
12
- `command -v coder >/dev/null || npm install -g @wular/coder; coder host-setup --json`
12
+ `command -v coder >/dev/null || npm install -g @wular/coder; coder setup-host --json`
13
13
  (codex/claude availability and auth are in the JSON).
14
14
  2. Codex is the recommended primary engine; Claude (opus subagents in Claude Code) is the fallback. Choose the default from what is installed. Do NOT ask about chain ordering:
15
15
  - **Codex installed** (logged in, or logged out; installed still counts): keep the default `codex → claude` chain.
16
- - **Auto-update if stale**: the default codex model is a GPT-5.6 tier, which needs codex `>= 0.144`. Parse the version from the JSON's `codex.detail` (e.g. `codex-cli 0.143.0`); if it is below `0.144.0`, update it automatically without asking with `codex update` (codex's own updater - it detects the install method and refetches the binary; fall back to `npm install -g @openai/codex@latest` if that fails), then re-run `coder host-setup --json` to confirm.
17
- - If it is logged out, tell the user to run `codex login` themselves, then re-run `coder host-setup` to confirm.
16
+ - **Auto-update if stale**: the default codex model is a GPT-5.6 tier, which needs codex `>= 0.144`. Parse the version from the JSON's `codex.detail` (e.g. `codex-cli 0.143.0`); if it is below `0.144.0`, update it automatically without asking with `codex update` (codex's own updater - it detects the install method and refetches the binary; fall back to `npm install -g @openai/codex@latest` if that fails), then re-run `coder setup-host --json` to confirm.
17
+ - If it is logged out, tell the user to run `codex login` themselves, then re-run `coder setup-host` to confirm.
18
18
  - **Codex not installed**: run `coder config set chain claude,codex` so tasks run on Claude opus subagents immediately, tell the user that is the default for now, then ask (AskUserQuestion) whether to install Codex since it is the recommended primary. On yes: `npm install -g @openai/codex`, have them run `codex login`, then `coder config set chain codex,claude`.
19
19
  3. Show the final config (`coder config`) and mention overrides live in `~/.coder/config.json` (machine) and `coder.config.json` (per repo).
20
20
  4. Suggest trying it: "Use Coder to <some small task>".
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder",
3
- "version": "0.1.26",
3
+ "version": "0.2.0",
4
4
  "interface": {
5
5
  "displayName": "Coder (plugin)"
6
6
  },
@@ -7,7 +7,7 @@ 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; `--agent`/`--model`/`--effort` override it. You never spawn agents yourself in this host.
9
9
 
10
- If `coder` is not on PATH, install it yourself without asking: `npm install -g @wular/coder`, then `coder host-setup --codex`. Only if that fails, show the user the error and those two commands. The configured chain (`coder config`) decides which engine runs first and which is the fallback; set it with `coder config set chain <first>,<second>`. Each engine needs its own CLI; the claude engine needs the claude CLI installed - if it is not, ask the user before installing it (on yes: `npm install -g @anthropic-ai/claude-code`, then have them run `claude` once to log in).
10
+ If `coder` is not on PATH, install it yourself without asking: `npm install -g @wular/coder`, then `coder setup-host codex`. Only if that fails, show the user the error and those two commands. The configured chain (`coder config`) decides which engine runs first and which is the fallback; set it with `coder config set chain <first>,<second>`. Each engine needs its own CLI; the claude engine needs the claude CLI installed - if it is not, ask the user before installing it (on yes: `npm install -g @anthropic-ai/claude-code`, then have them run `claude` once to log in).
11
11
 
12
12
  When you run setup, also check codex is new enough for the default GPT-5.6 model, which needs codex `>= 0.144` (`codex --version`). If it is older, update it automatically without asking with `codex update` (codex's own updater; fall back to `npm install -g @openai/codex@latest` if it fails), then tell the user to restart their codex session so the update takes effect.
13
13
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "coder",
3
3
  "displayName": "Coder",
4
- "version": "0.1.26",
4
+ "version": "0.2.0",
5
5
  "description": "Delegate coding tasks to a Coder subagent. Your main context stays clean.",
6
6
  "author": {
7
7
  "name": "muzam1l"
@@ -21,7 +21,7 @@ Plugs into Claude Code or Codex to enable the harness with Coder instances.
21
21
 
22
22
  ## Get started
23
23
 
24
- Coder runs your tasks on an **engine CLI** - it needs at least one of the [codex CLI](https://github.com/openai/codex) (`npm install -g @openai/codex`, then `codex login`) or the [Claude Code CLI](https://github.com/anthropics/claude-code) (`npm install -g @anthropic-ai/claude-code`, then `claude auth login`) installed and logged in. `coder host-setup` reports which are ready; if none is, install one of them to run tasks.
24
+ Coder runs your tasks on an **engine CLI** - it needs at least one of the [codex CLI](https://github.com/openai/codex) (`npm install -g @openai/codex`, then `codex login`) or the [Claude Code CLI](https://github.com/anthropics/claude-code) (`npm install -g @anthropic-ai/claude-code`, then `claude auth login`) installed and logged in. `coder setup-host` reports which are ready; if none is, install one of them to run tasks.
25
25
 
26
26
  Follow the install host specific guides below, then you can ask like:
27
27
 
@@ -55,7 +55,7 @@ Or from the shell:
55
55
 
56
56
  ```
57
57
  npm install -g @wular/coder
58
- coder host-setup --claude
58
+ coder setup-host claude
59
59
  ```
60
60
 
61
61
  ### Codex
@@ -69,7 +69,7 @@ Or from the npm directly:
69
69
 
70
70
  ```
71
71
  npm install -g @wular/coder
72
- coder host-setup --codex
72
+ coder setup-host codex
73
73
  ```
74
74
 
75
75
  Note: Codex 'Approve for me' just disables invoking CLI agents, so just use 'Ask for approval'/'Full Access' when using Codex/ChatGPT app as host.
@@ -7,7 +7,7 @@ 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; `--agent`/`--model`/`--effort` override it. You never spawn agents yourself; the runtime spawns and supervises them.
9
9
 
10
- If `coder` is not on PATH, install it yourself without asking: `npm install -g @wular/coder`, then run `coder host-setup` to seed the config and check engine readiness (no host plugin is installed - Cursor gets this skill from the marketplace). Only if that fails, show the user the error and those commands. Coder needs at least one engine CLI installed and logged in: codex (`npm install -g @openai/codex`, then `codex login`) and/or claude (`npm install -g @anthropic-ai/claude-code`, then run `claude` once to log in) - ask the user before installing an engine CLI. The configured chain (`coder config`) decides which engine runs first and which is the fallback; set it with `coder config set chain <first>,<second>`.
10
+ If `coder` is not on PATH, install it yourself without asking: `npm install -g @wular/coder`, then run `coder setup-host` to seed the config and check engine readiness (no host plugin is installed - Cursor gets this skill from the marketplace). Only if that fails, show the user the error and those commands. Coder needs at least one engine CLI installed and logged in: codex (`npm install -g @openai/codex`, then `codex login`) and/or claude (`npm install -g @anthropic-ai/claude-code`, then run `claude` once to log in) - ask the user before installing an engine CLI. The configured chain (`coder config`) decides which engine runs first and which is the fallback; set it with `coder config set chain <first>,<second>`.
11
11
 
12
12
  When you run setup, also check codex is new enough for the default GPT-5.6 model, which needs codex `>= 0.144` (`codex --version`). If it is older, update it automatically without asking with `codex update` (codex's own updater; fall back to `npm install -g @openai/codex@latest` if it fails), then tell the user to restart their codex session so the update takes effect.
13
13