@wular/coder 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/cli.js +30 -27
- package/package.json +2 -2
- package/plugins/claude/commands/setup.md +11 -7
- package/plugins/codex/skills/coder/SKILL.md +1 -4
package/README.md
CHANGED
|
@@ -88,11 +88,11 @@ coder approve <job> <id> # answer an escalated permission (--deny)
|
|
|
88
88
|
|
|
89
89
|
Common flags:
|
|
90
90
|
|
|
91
|
-
| Flag
|
|
92
|
-
|
|
|
93
|
-
| `--wait` | run in the foreground and print the answer
|
|
94
|
-
| `--agent` | `codex`, `claude`
|
|
95
|
-
| `--model` | `5.5`, `spark`, `opus`, `sonnet`, `fable` or any raw model slug | from config
|
|
96
|
-
| `--effort` | `low`, `medium`, `high`
|
|
97
|
-
| `--permissions` | `read-only`, `workspace-write`, `auto`
|
|
98
|
-
| `--resume <job>` | continue that job's thread instead of starting fresh
|
|
91
|
+
| Flag | Values | Default |
|
|
92
|
+
| ------------------ | ------------------------------------------------------------------------- | ----------------- |
|
|
93
|
+
| `--wait` | run in the foreground and print the answer | background |
|
|
94
|
+
| `--agent` | `codex`, `claude` | first in`chain` |
|
|
95
|
+
| `--model` | `5.5`, `spark`, `opus`, `sonnet`, `fable` or any raw model slug | from config |
|
|
96
|
+
| `--effort` | `low`, `medium`, `high` | from config |
|
|
97
|
+
| `--permissions` | `read-only`, `workspace-write`, `auto` | `auto` |
|
|
98
|
+
| `--resume <job>` | continue that job's thread instead of starting fresh | fresh run |
|
package/dist/cli.js
CHANGED
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
`,"utf8"),K}function
|
|
4
|
-
`,"utf8")}function
|
|
5
|
-
`,"utf8")}function y0(
|
|
6
|
-
${Y.stdout}`.trim();if(!Y.error&&
|
|
7
|
-
`);while(
|
|
8
|
-
`)}}handleLine(
|
|
9
|
-
${
|
|
10
|
-
`,
|
|
11
|
-
`,
|
|
12
|
-
`)}function r($,W=72){let Z=String($??"").trim().replace(/\s+/g," ");if(!Z)return"";if(Z.length<=W)return Z;return`${Z.slice(0,W-3)}...`}function S0($){let W=r($,56);return W?`${b$}: ${W}`:b$}function E0($){return $?.params?.threadId??null}function T0($){if($?.params?.turnId)return $.params.turnId;if($?.params?.turn?.id)return $.params.turn.id;return null}function u0($){let W=new Set;for(let Z of $)for(let Q of Z.changes??[])if(Q.path)W.add(Q.path);return[...W]}function c$($){return String($??"").replace(/\s+/g," ").trim()}function I($){if(!$)return[];if(typeof $==="string"){let W=c$($);return W?[W]:[]}if(Array.isArray($))return $.flatMap((W)=>I(W));if(typeof $==="object"){if(typeof $.text==="string")return I($.text);if("summary"in $)return I($.summary);if("content"in $)return I($.content);if("parts"in $)return I($.parts)}return[]}function I0($,W){let Z=[];for(let Q of[...$,...W]){let V=c$(Q);if(!V||Z.includes(V))continue;Z.push(V)}return Z}function P($,W,Z=null,Q={}){if(!$||!W)return;$({message:W,phase:Z,...Q})}function j0($){switch($.type){case"commandExecution":return{message:`Running command: ${r($.command,96)}`,phase:"running"};case"fileChange":return{message:`Applying ${$.changes.length} file change(s).`,phase:"editing"};case"mcpToolCall":return{message:`Calling ${$.server}/${$.tool}.`,phase:"investigating"};case"dynamicToolCall":return{message:`Running tool: ${$.tool}.`,phase:"investigating"};case"webSearch":return{message:`Searching: ${r($.query,96)}`,phase:"investigating"};default:return null}}function h0($){switch($.type){case"commandExecution":return{message:`Command ${$.status==="completed"?"completed":$.status}: ${r($.command,96)} (exit ${$.exitCode??"?"})`,phase:"running"};case"fileChange":return{message:`File changes ${$.status}.`,phase:"editing"};case"mcpToolCall":return{message:`Tool ${$.server}/${$.tool} ${$.status}.`,phase:"investigating"};case"dynamicToolCall":return{message:`Tool ${$.tool} ${$.status}.`,phase:"investigating"};default:return null}}function w0($,W={}){let Z,Q,V=new Promise((Y,K)=>{Z=Y,Q=K});return{threadId:$,rootThreadId:$,threadIds:new Set([$]),threadTurnIds:new Map,turnId:null,bufferedNotifications:[],completion:V,resolveCompletion:Z,rejectCompletion:Q,finalTurn:null,completed:!1,finalAnswerSeen:!1,pendingCollaborations:new Set,activeSubagentTurns:new Set,completionTimer:null,lastAgentMessage:"",reasoningSummary:[],error:null,fileChanges:[],commandExecutions:[],itemIndex:new Map,onProgress:W.onProgress??null}}function U$($){if($.completionTimer)clearTimeout($.completionTimer),$.completionTimer=null}function M$($,W=null){if($.completed)return;if(U$($),$.completed=!0,W){if($.finalTurn=W,!$.turnId)$.turnId=W.id}else if(!$.finalTurn)$.finalTurn={id:$.turnId??"inferred-turn",status:"completed"};$.resolveCompletion($)}function q$($){if($.completed||$.finalTurn||!$.finalAnswerSeen)return;if($.pendingCollaborations.size>0||$.activeSubagentTurns.size>0)return;U$($),$.completionTimer=setTimeout(()=>{if($.completionTimer=null,$.completed||$.finalTurn||!$.finalAnswerSeen)return;if($.pendingCollaborations.size>0||$.activeSubagentTurns.size>0)return;M$($,null)},250),$.completionTimer.unref?.()}function g$($,W){let Z=E0(W);if(!Z||!$.threadIds.has(Z))return!1;let Q=$.threadTurnIds.get(Z)??null,V=T0(W);return Q===null||V===null||V===Q}function m$($,W,Z,Q=null){if(W.id)$.itemIndex.set(W.id,W);if(W.type==="collabAgentToolCall"){if(!Q||Q===$.threadId){if(Z==="started"||W.status==="inProgress")$.pendingCollaborations.add(W.id);else if(Z==="completed")$.pendingCollaborations.delete(W.id),q$($)}for(let V of W.receiverThreadIds??[])$.threadIds.add(V)}if(W.type==="agentMessage"){if(W.text&&(!Q||Q===$.threadId)){if($.lastAgentMessage=W.text,Z==="completed"&&W.phase==="final_answer")$.finalAnswerSeen=!0,q$($)}return}if(W.type==="reasoning"&&Z==="completed"){$.reasoningSummary=I0($.reasoningSummary,I(W.summary));return}if(W.type==="fileChange"&&Z==="completed"){$.fileChanges.push(W);return}if(W.type==="commandExecution"&&Z==="completed")$.commandExecutions.push(W)}function z$($,W){switch(W.method){case"thread/started":$.threadIds.add(W.params.thread.id);break;case"turn/started":if($.threadIds.add(W.params.threadId),$.threadTurnIds.set(W.params.threadId,W.params.turn.id),(W.params.threadId??null)!==$.threadId)$.activeSubagentTurns.add(W.params.threadId);P($.onProgress,`Turn started (${W.params.turn.id}).`,"starting",{threadId:W.params.threadId??null,turnId:W.params.turn.id??null});break;case"item/started":m$($,W.params.item,"started",W.params.threadId??null);{let Z=j0(W.params.item);P($.onProgress,Z?.message,Z?.phase??null)}break;case"item/completed":m$($,W.params.item,"completed",W.params.threadId??null);{let Z=h0(W.params.item);P($.onProgress,Z?.message,Z?.phase??null)}break;case"error":$.error=W.params.error,P($.onProgress,`Codex error: ${W.params.error.message}`,"failed");break;case"turn/completed":if((W.params.threadId??null)!==$.threadId){$.activeSubagentTurns.delete(W.params.threadId),q$($);break}P($.onProgress,`Turn ${W.params.turn.status}.`,"finalizing"),M$($,W.params.turn);break;default:break}}async function v0($,W,Z,Q={}){let V=w0(W,Q),Y=$.notificationHandler;if($.setNotificationHandler((K)=>{if(!V.turnId){V.bufferedNotifications.push(K);return}if(K.method==="thread/started"){z$(V,K);return}if(!g$(V,K)){Y?.(K);return}z$(V,K)}),Q.onApprovalRequest)$.setServerRequestHandler((K,G)=>Q.onApprovalRequest(K,G,V));try{let K=await Z();if(V.turnId=K.turn?.id??null,V.turnId)V.threadTurnIds.set(V.threadId,V.turnId);for(let G of V.bufferedNotifications)if(g$(V,G))z$(V,G);else Y?.(G);if(V.bufferedNotifications.length=0,K.turn?.status&&K.turn.status!=="inProgress")M$(V,K.turn);return await V.completion}finally{U$(V),$.setNotificationHandler(Y??null),$.setServerRequestHandler(null)}}async function b0($,W){let Z=null;try{Z=await u.connect($);let Q=await W(Z);return await Z.close(),Q}catch(Q){let V=Z?.transport==="broker"||Boolean(process.env[i]),Y=Z?.transport==="broker"&&Q?.rpcCode===I$||V&&(Q?.code==="ENOENT"||Q?.code==="ECONNREFUSED");if(Z)await Z.close().catch(()=>{}),Z=null;if(!Y)throw Q;let K=await u.connect($,{disableBroker:!0});try{return await W(K)}finally{await K.close()}}}function c($){let W=K$("codex",["--version"],{cwd:$});if(!W.available)return W;let Z=K$("codex",["app-server","--help"],{cwd:$});if(!Z.available)return{available:!1,detail:`${W.detail}; app-server runtime unavailable: ${Z.detail}`};return{available:!0,detail:`${W.detail}; app-server runtime available`}}async function l$($){let W=c($);if(!W.available)return{available:!1,loggedIn:!1,detail:W.detail};let Z=null;try{Z=await u.connect($,{reuseExistingBroker:!0});let Q=await Z.request("account/read",{refreshToken:!1}),V=Q?.account??null;if(V?.type==="chatgpt")return{available:!0,loggedIn:!0,detail:V.email?`ChatGPT login active for ${V.email}`:"ChatGPT login active"};if(V?.type==="apiKey")return{available:!0,loggedIn:!0,detail:"API key configured"};if(Q?.requiresOpenaiAuth===!1)return{available:!0,loggedIn:!0,detail:"Active provider does not require OpenAI authentication"};return{available:!0,loggedIn:!1,detail:"Not authenticated. Run `codex login`."}}catch(Q){return{available:!0,loggedIn:!1,detail:Q instanceof Error?Q.message:String(Q)}}finally{await Z?.close().catch(()=>{})}}async function p$($,{threadId:W,turnId:Z}){if(!W||!Z)return{interrupted:!1,detail:"missing threadId or turnId"};let Q=null;try{return Q=await u.connect($,{reuseExistingBroker:!0}),await Q.request("turn/interrupt",{threadId:W,turnId:Z}),{interrupted:!0,detail:`Interrupted ${Z} on ${W}.`}}catch(V){return{interrupted:!1,detail:V instanceof Error?V.message:String(V)}}finally{await Q?.close().catch(()=>{})}}async function n$($,W={}){let Z=c($);if(!Z.available)throw Error(`Codex CLI is not available: ${Z.detail}`);let Q=W.prompt?.trim();if(!Q)throw Error("A prompt is required.");return b0($,async(V)=>{let Y;if(W.resumeThreadId)P(W.onProgress,`Resuming thread ${W.resumeThreadId}.`,"starting"),Y=(await V.request("thread/resume",{threadId:W.resumeThreadId,cwd:$,model:W.model??null,approvalPolicy:W.approvalPolicy??"never",sandbox:W.sandbox??"read-only"})).thread.id;else{P(W.onProgress,"Starting Codex task thread.","starting"),Y=(await V.request("thread/start",{cwd:$,model:W.model??null,approvalPolicy:W.approvalPolicy??"never",sandbox:W.sandbox??"read-only",serviceName:P0,ephemeral:W.ephemeral??!1})).thread.id;try{await V.request("thread/name/set",{threadId:Y,name:S0(Q)})}catch(X){let H=String(X?.message??X??"");if(!H.includes("unknown variant")&&!H.includes("unknown method"))throw X}}P(W.onProgress,`Thread ready (${Y}).`,"starting",{threadId:Y});let K=await v0(V,Y,()=>V.request("turn/start",{threadId:Y,input:[{type:"text",text:Q,text_elements:[]}],model:W.model??null,effort:W.effort??null,outputSchema:W.outputSchema??null}),{onProgress:W.onProgress,onApprovalRequest:W.onApprovalRequest});return{status:K.finalTurn?.status==="completed"?0:1,threadId:Y,turnId:K.turnId,finalMessage:K.lastAgentMessage,reasoningSummary:K.reasoningSummary,turn:K.finalTurn,error:K.error,stderr:D0(V.stderr),fileChanges:K.fileChanges,touchedFiles:u0(K.fileChanges),commandExecutions:K.commandExecutions}})}import{spawn as c0,spawnSync as l0}from"node:child_process";import{randomUUID as p0}from"node:crypto";import a from"node:fs";import B$ from"node:path";var N$={chain:["codex","claude"],agents:{codex:{model:"gpt-5.5",effort:"medium",permissions:"auto"},claude:{model:"opus",permissions:"auto"}},approvals:{escalationTimeoutMs:120000,allowedNetworkHosts:[]}},g0={spark:"gpt-5.3-codex-spark","5.5":"gpt-5.5"},L$=new Set(["low","medium","high"]);var J$=new Set(["low","medium","high"]),l={"read-only":{sandbox:"read-only",approvalPolicy:"never",approvalMode:null},"workspace-write":{sandbox:"workspace-write",approvalPolicy:"never",approvalMode:null},auto:{sandbox:"workspace-write",approvalPolicy:"on-request",approvalMode:"auto"}},m0=["ls","cat","head","tail","wc","grep","rg","find","fd","tree","file","stat","du","df","which","pwd","env","git status","git log","git diff","git show","git branch","git blame","git remote"].map(($)=>`Bash(${$}:*)`),x$={"read-only":["--permission-mode","dontAsk","--disallowedTools","Edit","Write","NotebookEdit","--allowedTools",...m0],"workspace-write":["--permission-mode","acceptEdits"],auto:["--permission-mode","auto"]};function d$($){if(!a.existsSync($))return null;try{return JSON.parse(a.readFileSync($,"utf8"))}catch(W){throw Error(`Invalid JSON in ${$}: ${W.message}`)}}function O$($,W){if(!W||typeof W!=="object"||Array.isArray(W))return W??$;let Z={...$};for(let[Q,V]of Object.entries(W))if(V&&typeof V==="object"&&!Array.isArray(V)&&$?.[Q]&&typeof $[Q]==="object")Z[Q]=O$($[Q],V);else Z[Q]=V;return Z}function t(){return B$.join($$(),"config.json")}function o($){let W=w($),Z=N$;return Z=O$(Z,d$(t())),Z=O$(Z,d$(B$.join(W,"coder.config.json"))),Z}function i$($){if(!$)return null;return g0[$]??$}function r$($){let W=t();return a.mkdirSync(B$.dirname(W),{recursive:!0}),a.writeFileSync(W,`${JSON.stringify($,null,2)}
|
|
13
|
-
`,"utf8")
|
|
14
|
-
`,"utf8")}async function
|
|
15
|
-
`,"utf8"),Q?.({kind:"approval-escalated",approvalId:Y,summary
|
|
16
|
-
`),
|
|
17
|
-
`)}function
|
|
18
|
-
`)}}function
|
|
19
|
-
`)}}),
|
|
20
|
-
`,"utf8"),
|
|
21
|
-
`,"utf8"),Y}function
|
|
22
|
-
`);if(G.agent==="codex"&&
|
|
23
|
-
`),
|
|
24
|
-
`);
|
|
25
|
-
`),K.touchedFiles?.length)
|
|
26
|
-
`)}async function
|
|
27
|
-
|
|
28
|
-
`)
|
|
2
|
+
import E from"node:fs";import k from"node:path";import U from"node:process";import{spawn as H1,spawnSync as h}from"node:child_process";import{fileURLToPath as Q$}from"node:url";function f(Z,$={}){let W=new Set($.valueOptions??[]),Q=new Set($.booleanOptions??[]),V=$.aliasMap??{},Y={},K=[],G=!1;for(let H=0;H<Z.length;H+=1){let X=Z[H];if(G){K.push(X);continue}if(X==="--"){G=!0;continue}if(!X.startsWith("-")||X==="-"){K.push(X);continue}if(X.startsWith("--")){let[M,q]=X.slice(2).split("=",2),B=V[M]??M;if(Q.has(B)){Y[B]=q===void 0?!0:q!=="false";continue}if(W.has(B)){let T=q??Z[H+1];if(T===void 0)throw Error(`Missing value for --${M}`);if(Y[B]=T,q===void 0)H+=1;continue}K.push(X);continue}let z=X.slice(1),O=V[z]??z;if(Q.has(O)){Y[O]=!0;continue}if(W.has(O)){let M=Z[H+1];if(M===void 0)throw Error(`Missing value for -${z}`);Y[O]=M,H+=1;continue}K.push(X)}return{options:Y,positionals:K}}import{createHash as X0}from"node:crypto";import{execFileSync as z0}from"node:child_process";import S from"node:fs";import q0 from"node:os";import P from"node:path";var M0="CODER_HOME";function Y$(){return P.resolve(process.env[M0]||P.join(q0.homedir(),".coder"))}function w(Z){try{return z0("git",["rev-parse","--show-toplevel"],{cwd:Z,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return Z}}function e(Z){let $=w(Z),W=$;try{W=S.realpathSync.native($)}catch{W=$}let V=(P.basename($)||"workspace").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"workspace",Y=X0("sha256").update(W).digest("hex").slice(0,12);return P.join(Y$(),"state",`${V}-${Y}`)}function S$(Z){return P.join(e(Z),"jobs")}function A(Z,$){return P.join(S$(Z),$)}function E$(){let Z=Math.random().toString(36).slice(2,8);return`coder-${Date.now().toString(36)}-${Z}`}function y(Z,$,W){let Q=A(Z,$);S.mkdirSync(Q,{recursive:!0});let V=P.join(Q,"job.json"),K={...v(Z,$)??{id:$,createdAt:new Date().toISOString()},...W,updatedAt:new Date().toISOString()};return S.writeFileSync(V,`${JSON.stringify(K,null,2)}
|
|
3
|
+
`,"utf8"),K}function v(Z,$){let W=P.join(A(Z,$),"job.json");if(!S.existsSync(W))return null;try{return JSON.parse(S.readFileSync(W,"utf8"))}catch{return null}}function G$(Z){let $=S$(Z);if(!S.existsSync($))return[];return S.readdirSync($).map((W)=>v(Z,W)).filter(Boolean).sort((W,Q)=>String(Q.updatedAt??"").localeCompare(String(W.updatedAt??"")))}function K$(Z,$){let W=G$(Z);if(!$)return W[0]??null;let Q=W.find((Y)=>Y.id===$);if(Q)return Q;let V=W.filter((Y)=>Y.id.startsWith($));if(V.length===1)return V[0];if(V.length>1)throw Error(`Job reference "${$}" is ambiguous. Use a longer id.`);return null}function n(Z,$,W){let Q=A(Z,$);S.mkdirSync(Q,{recursive:!0}),S.appendFileSync(P.join(Q,"log.jsonl"),`${JSON.stringify({at:new Date().toISOString(),...W})}
|
|
4
|
+
`,"utf8")}function H$(Z,$,W=40){let Q=P.join(A(Z,$),"log.jsonl");if(!S.existsSync(Q))return[];return S.readFileSync(Q,"utf8").split(/\r?\n/).filter(Boolean).slice(-W).map((Y)=>{try{return JSON.parse(Y)}catch{return{message:Y}}})}import{spawnSync as I0}from"node:child_process";import S0 from"node:net";import r from"node:process";import{spawn as E0}from"node:child_process";import T0 from"node:readline";import T$ from"node:path";import U0 from"node:process";function O0(Z){return String(Z??"").replace(/[^A-Za-z0-9._-]/g,"-").replace(/^-+|-+$/g,"")}function I$(Z,$=U0.platform){if($==="win32")return`pipe:\\\\.\\pipe\\${O0(`${T$.win32.basename(Z)}-codex-app-server`)}`;return`unix:${T$.join(Z,"broker.sock")}`}function d(Z){if(typeof Z!=="string"||Z.length===0)throw Error("Missing broker endpoint.");if(Z.startsWith("pipe:")){let $=Z.slice(5);if(!$)throw Error("Broker pipe endpoint is missing its path.");return{kind:"pipe",path:$}}if(Z.startsWith("unix:")){let $=Z.slice(5);if(!$)throw Error("Broker Unix socket endpoint is missing its path.");return{kind:"unix",path:$}}throw Error(`Unsupported broker endpoint: ${Z}`)}import J from"node:fs";import B0 from"node:net";import N0 from"node:os";import b from"node:path";import X$ from"node:process";import{spawn as L0}from"node:child_process";import{fileURLToPath as J0}from"node:url";var x0="broker.json";function _0(Z="coder-"){return J.mkdtempSync(b.join(N0.tmpdir(),Z))}function k0(Z){let $=d(Z);return B0.createConnection({path:$.path})}async function u$(Z,$=2000){let W=Date.now();while(Date.now()-W<$){if(await new Promise((V)=>{let Y=k0(Z);Y.on("connect",()=>{Y.end(),V(!0)}),Y.on("error",()=>V(!1))}))return!0;await new Promise((V)=>setTimeout(V,50))}return!1}function R0({scriptPath:Z,cwd:$,endpoint:W,pidFile:Q,logFile:V,env:Y=X$.env}){let K=J.openSync(V,"a"),G=L0(X$.execPath,[Z,"serve","--endpoint",W,"--cwd",$,"--pid-file",Q],{cwd:$,env:Y,detached:!0,stdio:["ignore",K,K]});return G.unref(),J.closeSync(K),G}function f0(){let Z=[new URL("./lib/broker.js",import.meta.url),new URL("./broker.js",import.meta.url)];for(let $ of Z){let W=J0($);if(J.existsSync(W))return W}throw Error("Coder broker script not found next to the runtime. Rebuild with `bun run build`.")}function z$(Z){return b.join(e(Z),x0)}function q$(Z){let $=z$(Z);if(!J.existsSync($))return null;try{return JSON.parse(J.readFileSync($,"utf8"))}catch{return null}}function A0(Z,$){let W=e(Z);J.mkdirSync(W,{recursive:!0}),J.writeFileSync(z$(Z),`${JSON.stringify($,null,2)}
|
|
5
|
+
`,"utf8")}function y0(Z){let $=z$(Z);if(J.existsSync($))J.unlinkSync($)}async function C0(Z){if(!Z)return!1;try{return await u$(Z,150)}catch{return!1}}async function h$(Z,$={}){let W=q$(Z);if(W&&await C0(W.endpoint))return W;if(W)j$({endpoint:W.endpoint??null,pidFile:W.pidFile??null,logFile:W.logFile??null,sessionDir:W.sessionDir??null,pid:W.pid??null,killProcess:$.killProcess??null}),y0(Z);let Q=_0(),Y=($.createBrokerEndpoint??I$)(Q,$.platform),K=b.join(Q,"broker.pid"),G=b.join(Q,"broker.log"),H=$.scriptPath??f0(),X=R0({scriptPath:H,cwd:Z,endpoint:Y,pidFile:K,logFile:G,env:$.env??X$.env});if(!await u$(Y,$.timeoutMs??2000))return j$({endpoint:Y,pidFile:K,logFile:G,sessionDir:Q,pid:X.pid??null,killProcess:$.killProcess??null}),null;let O={endpoint:Y,pidFile:K,logFile:G,sessionDir:Q,pid:X.pid??null};return A0(Z,O),O}function j$({endpoint:Z=null,pidFile:$,logFile:W,sessionDir:Q=null,pid:V=null,killProcess:Y=null}){if(Number.isFinite(V)&&Y)try{Y(V)}catch{}if($&&J.existsSync($))J.unlinkSync($);if(W&&J.existsSync(W))J.unlinkSync(W);if(Z)try{let G=d(Z);if(G.kind==="unix"&&J.existsSync(G.path))J.unlinkSync(G.path)}catch{}let K=Q??($?b.dirname($):W?b.dirname(W):null);if(K&&J.existsSync(K))try{J.rmdirSync(K)}catch{}}import{spawnSync as D0}from"node:child_process";import i from"node:process";function w$(Z,$=[],W={}){let Q=D0(Z,$,{cwd:W.cwd,env:W.env,encoding:"utf8",input:W.input,maxBuffer:W.maxBuffer,stdio:W.stdio??"pipe",shell:i.platform==="win32"?i.env.SHELL||!0:!1,windowsHide:!0});return{command:Z,args:$,status:Q.status??0,signal:Q.signal??null,stdout:Q.stdout??"",stderr:Q.stderr??"",error:Q.error??null}}function M$(Z,$=["--version"],W={}){let Q=w$(Z,$,W);if(Q.error&&Q.error.code==="ENOENT")return{available:!1,detail:"not found"};if(Q.error)return{available:!1,detail:Q.error.message};if(Q.status!==0)return{available:!1,detail:Q.stderr.trim()||Q.stdout.trim()||`exit ${Q.status}`};return{available:!0,detail:Q.stdout.trim()||Q.stderr.trim()||"ok"}}function F0(Z){return/not found|no running instance|cannot find|does not exist|no such process/i.test(Z)}function v$(Z,$={}){if(!Number.isFinite(Z))return{attempted:!1,delivered:!1,method:null};let W=$.platform??i.platform,Q=$.runCommandImpl??w$,V=$.killImpl??i.kill.bind(i);if(W==="win32"){let Y=Q("taskkill",["/PID",String(Z),"/T","/F"],{cwd:$.cwd,env:$.env});if(!Y.error&&Y.status===0)return{attempted:!0,delivered:!0,method:"taskkill",result:Y};let K=`${Y.stderr}
|
|
6
|
+
${Y.stdout}`.trim();if(!Y.error&&F0(K))return{attempted:!0,delivered:!1,method:"taskkill",result:Y};if(Y.error?.code==="ENOENT")try{return V(Z),{attempted:!0,delivered:!0,method:"kill"}}catch(G){if(G?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"kill"};throw G}if(Y.error)throw Y.error;throw Error(P0(Y))}try{return V(-Z,"SIGTERM"),{attempted:!0,delivered:!0,method:"process-group"}}catch(Y){if(Y?.code!=="ESRCH")try{return V(Z,"SIGTERM"),{attempted:!0,delivered:!0,method:"process"}}catch(K){if(K?.code==="ESRCH")return{attempted:!0,delivered:!1,method:"process"};throw K}return{attempted:!0,delivered:!1,method:"process-group"}}}function P0(Z){let $=[`${Z.command} ${Z.args.join(" ")}`.trim()];if(Z.signal)$.push(`signal=${Z.signal}`);else $.push(`exit=${Z.status}`);let W=(Z.stderr||"").trim(),Q=(Z.stdout||"").trim();if(W)$.push(W);else if(Q)$.push(Q);return $.join(": ")}var $$="CODER_APP_SERVER_ENDPOINT",g$=-32001,m$={title:"Coder",name:"coder",version:"0.1.0"},c$={experimentalApi:!1,requestAttestation:!1,optOutNotificationMethods:["item/agentMessage/delta","item/reasoning/summaryTextDelta","item/reasoning/summaryPartAdded","item/reasoning/textDelta"]};function b$(Z,$,W){return W===void 0?{code:Z,message:$}:{code:Z,message:$,data:W}}function U$(Z,$){let W=Error(Z);if(W.data=$,$?.code!==void 0)W.rpcCode=$.code;return W}class O${cwd;options;pending;nextId;stderr;closed;exitError;notificationHandler;serverRequestHandler;lineBuffer;transport;exitPromise;exitResolved;resolveExit;handleServerRequest;constructor(Z,$={}){this.cwd=Z,this.options=$,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=(W)=>this.defaultHandleServerRequest(W),this.exitPromise=new Promise((W)=>{this.resolveExit=W})}setNotificationHandler(Z){this.notificationHandler=Z}setServerRequestHandler(Z){this.serverRequestHandler=Z}request(Z,$){if(this.closed)throw Error("codex app-server client is closed.");let W=this.nextId;return this.nextId+=1,new Promise((Q,V)=>{this.pending.set(W,{resolve:Q,reject:V,method:Z}),this.sendMessage({id:W,method:Z,params:$})})}notify(Z,$={}){if(this.closed)return;this.sendMessage({method:Z,params:$})}handleChunk(Z){this.lineBuffer+=Z;let $=this.lineBuffer.indexOf(`
|
|
7
|
+
`);while($!==-1){let W=this.lineBuffer.slice(0,$);this.lineBuffer=this.lineBuffer.slice($+1),this.handleLine(W),$=this.lineBuffer.indexOf(`
|
|
8
|
+
`)}}handleLine(Z){if(!Z.trim())return;let $;try{$=JSON.parse(Z)}catch(W){this.handleExit(U$(`Failed to parse codex app-server JSONL: ${W.message}`,{line:Z}));return}if($.id!==void 0&&$.method){this.handleServerRequest($);return}if($.id!==void 0){let W=this.pending.get($.id);if(!W)return;if(this.pending.delete($.id),$.error)W.reject(U$($.error.message??`codex app-server ${W.method} failed.`,$.error));else W.resolve($.result??{});return}if($.method&&this.notificationHandler)this.notificationHandler($)}defaultHandleServerRequest(Z){if(!this.serverRequestHandler){this.sendMessage({id:Z.id,error:b$(-32601,`Unsupported server request: ${Z.method}`)});return}Promise.resolve().then(()=>this.serverRequestHandler(Z.method,Z.params??{})).then(($)=>{this.sendMessage({id:Z.id,result:$??{}})}).catch(($)=>{this.sendMessage({id:Z.id,error:b$(-32000,$ instanceof Error?$.message:String($))})})}handleExit(Z){if(this.exitResolved)return;this.exitResolved=!0,this.exitError=Z??null;for(let $ of this.pending.values())$.reject(this.exitError??Error("codex app-server connection closed."));this.pending.clear(),this.resolveExit(void 0)}sendMessage(Z){throw Error("sendMessage must be implemented by subclasses.")}}class l$ extends O${proc;readline;constructor(Z,$={}){super(Z,$);this.transport="direct"}async initialize(){this.proc=E0("codex",["app-server"],{cwd:this.cwd,env:this.options.env??r.env,stdio:["pipe","pipe","pipe"],shell:r.platform==="win32"?r.env.SHELL||!0:!1,windowsHide:!0}),this.proc.stdout.setEncoding("utf8"),this.proc.stderr.setEncoding("utf8"),this.proc.stderr.on("data",(Z)=>{this.stderr+=Z}),this.proc.on("error",(Z)=>{this.handleExit(Z)}),this.proc.on("exit",(Z,$)=>{let W=this.stderr.trim(),Q=Z===0?null:U$(`codex app-server exited unexpectedly (${$?`signal ${$}`:`exit ${Z}`}).${W?`
|
|
9
|
+
${W}`:""}`);this.handleExit(Q)}),this.readline=T0.createInterface({input:this.proc.stdout}),this.readline.on("line",(Z)=>{this.handleLine(Z)}),await this.request("initialize",{clientInfo:this.options.clientInfo??m$,capabilities:this.options.capabilities??c$}),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(r.platform==="win32")try{v$(this.proc.pid)}catch{}else this.proc.kill("SIGTERM")},50).unref?.();await this.exitPromise}sendMessage(Z){let $=`${JSON.stringify(Z)}
|
|
10
|
+
`,W=this.proc?.stdin;if(!W)throw Error("codex app-server stdin is not available.");W.write($)}}class p$ extends O${endpoint;socket;constructor(Z,$={}){super(Z,$);this.transport="broker",this.endpoint=$.brokerEndpoint}async initialize(){await new Promise((Z,$)=>{let W=d(this.endpoint);this.socket=S0.createConnection({path:W.path}),this.socket.setEncoding("utf8"),this.socket.on("connect",Z),this.socket.on("data",(Q)=>{this.handleChunk(Q)}),this.socket.on("error",(Q)=>{if(!this.exitResolved)$(Q);this.handleExit(Q)}),this.socket.on("close",()=>{this.handleExit(this.exitError)})}),await this.request("initialize",{clientInfo:this.options.clientInfo??m$,capabilities:this.options.capabilities??c$}),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(Z){let $=`${JSON.stringify(Z)}
|
|
11
|
+
`,W=this.socket;if(!W)throw Error("codex app-server broker connection is not connected.");W.write($)}}class g{static async connect(Z,$={}){let W=null;if(!$.disableBroker){if(W=$.brokerEndpoint??$.env?.[$$]??r.env[$$]??null,!W&&$.reuseExistingBroker)W=q$(Z)?.endpoint??null;if(!W&&!$.reuseExistingBroker)W=(await h$(Z,{env:$.env}))?.endpoint??null}let Q=W?new p$(Z,{...$,brokerEndpoint:W}):new l$(Z,$);return await Q.initialize(),Q}}var j0="coder_runtime",n$="Coder Task";function u0(Z){return Z.split(/\r?\n/).map(($)=>$.trimEnd()).filter(($)=>$&&!$.startsWith("WARNING: proceeding, even though we could not update PATH:")).join(`
|
|
12
|
+
`)}function Z$(Z,$=72){let W=String(Z??"").trim().replace(/\s+/g," ");if(!W)return"";if(W.length<=$)return W;return`${W.slice(0,$-3)}...`}function h0(Z){let $=Z$(Z,56);return $?`${n$}: ${$}`:n$}function w0(Z){return Z?.params?.threadId??null}function v0(Z){if(Z?.params?.turnId)return Z.params.turnId;if(Z?.params?.turn?.id)return Z.params.turn.id;return null}function b0(Z){let $=new Set;for(let W of Z)for(let Q of W.changes??[])if(Q.path)$.add(Q.path);return[...$]}function r$(Z){return String(Z??"").replace(/\s+/g," ").trim()}function m(Z){if(!Z)return[];if(typeof Z==="string"){let $=r$(Z);return $?[$]:[]}if(Array.isArray(Z))return Z.flatMap(($)=>m($));if(typeof Z==="object"){if(typeof Z.text==="string")return m(Z.text);if("summary"in Z)return m(Z.summary);if("content"in Z)return m(Z.content);if("parts"in Z)return m(Z.parts)}return[]}function g0(Z,$){let W=[];for(let Q of[...Z,...$]){let V=r$(Q);if(!V||W.includes(V))continue;W.push(V)}return W}function I(Z,$,W=null,Q={}){if(!Z||!$)return;Z({message:$,phase:W,...Q})}function m0(Z){switch(Z.type){case"commandExecution":return{message:`Running command: ${Z$(Z.command,96)}`,phase:"running"};case"fileChange":return{message:`Applying ${Z.changes.length} file change(s).`,phase:"editing"};case"mcpToolCall":return{message:`Calling ${Z.server}/${Z.tool}.`,phase:"investigating"};case"dynamicToolCall":return{message:`Running tool: ${Z.tool}.`,phase:"investigating"};case"webSearch":return{message:`Searching: ${Z$(Z.query,96)}`,phase:"investigating"};default:return null}}function c0(Z){switch(Z.type){case"commandExecution":return{message:`Command ${Z.status==="completed"?"completed":Z.status}: ${Z$(Z.command,96)} (exit ${Z.exitCode??"?"})`,phase:"running"};case"fileChange":return{message:`File changes ${Z.status}.`,phase:"editing"};case"mcpToolCall":return{message:`Tool ${Z.server}/${Z.tool} ${Z.status}.`,phase:"investigating"};case"dynamicToolCall":return{message:`Tool ${Z.tool} ${Z.status}.`,phase:"investigating"};default:return null}}function l0(Z,$={}){let W,Q,V=new Promise((Y,K)=>{W=Y,Q=K});return{threadId:Z,rootThreadId:Z,threadIds:new Set([Z]),threadTurnIds:new Map,turnId:null,bufferedNotifications:[],completion:V,resolveCompletion:W,rejectCompletion:Q,finalTurn:null,completed:!1,finalAnswerSeen:!1,pendingCollaborations:new Set,activeSubagentTurns:new Set,completionTimer:null,lastAgentMessage:"",reasoningSummary:[],error:null,fileChanges:[],commandExecutions:[],itemIndex:new Map,onProgress:$.onProgress??null}}function L$(Z){if(Z.completionTimer)clearTimeout(Z.completionTimer),Z.completionTimer=null}function J$(Z,$=null){if(Z.completed)return;if(L$(Z),Z.completed=!0,$){if(Z.finalTurn=$,!Z.turnId)Z.turnId=$.id}else if(!Z.finalTurn)Z.finalTurn={id:Z.turnId??"inferred-turn",status:"completed"};Z.resolveCompletion(Z)}function N$(Z){if(Z.completed||Z.finalTurn||!Z.finalAnswerSeen)return;if(Z.pendingCollaborations.size>0||Z.activeSubagentTurns.size>0)return;L$(Z),Z.completionTimer=setTimeout(()=>{if(Z.completionTimer=null,Z.completed||Z.finalTurn||!Z.finalAnswerSeen)return;if(Z.pendingCollaborations.size>0||Z.activeSubagentTurns.size>0)return;J$(Z,null)},250),Z.completionTimer.unref?.()}function d$(Z,$){let W=w0($);if(!W||!Z.threadIds.has(W))return!1;let Q=Z.threadTurnIds.get(W)??null,V=v0($);return Q===null||V===null||V===Q}function i$(Z,$,W,Q=null){if($.id)Z.itemIndex.set($.id,$);if($.type==="collabAgentToolCall"){if(!Q||Q===Z.threadId){if(W==="started"||$.status==="inProgress")Z.pendingCollaborations.add($.id);else if(W==="completed")Z.pendingCollaborations.delete($.id),N$(Z)}for(let V of $.receiverThreadIds??[])Z.threadIds.add(V)}if($.type==="agentMessage"){if($.text&&(!Q||Q===Z.threadId)){if(Z.lastAgentMessage=$.text,W==="completed"&&$.phase==="final_answer")Z.finalAnswerSeen=!0,N$(Z)}return}if($.type==="reasoning"&&W==="completed"){Z.reasoningSummary=g0(Z.reasoningSummary,m($.summary));return}if($.type==="fileChange"&&W==="completed"){Z.fileChanges.push($);return}if($.type==="commandExecution"&&W==="completed")Z.commandExecutions.push($)}function B$(Z,$){switch($.method){case"thread/started":Z.threadIds.add($.params.thread.id);break;case"turn/started":if(Z.threadIds.add($.params.threadId),Z.threadTurnIds.set($.params.threadId,$.params.turn.id),($.params.threadId??null)!==Z.threadId)Z.activeSubagentTurns.add($.params.threadId);I(Z.onProgress,`Turn started (${$.params.turn.id}).`,"starting",{threadId:$.params.threadId??null,turnId:$.params.turn.id??null});break;case"item/started":i$(Z,$.params.item,"started",$.params.threadId??null);{let W=m0($.params.item);I(Z.onProgress,W?.message,W?.phase??null)}break;case"item/completed":i$(Z,$.params.item,"completed",$.params.threadId??null);{let W=c0($.params.item);I(Z.onProgress,W?.message,W?.phase??null)}break;case"error":Z.error=$.params.error,I(Z.onProgress,`Codex error: ${$.params.error.message}`,"failed");break;case"turn/completed":if(($.params.threadId??null)!==Z.threadId){Z.activeSubagentTurns.delete($.params.threadId),N$(Z);break}I(Z.onProgress,`Turn ${$.params.turn.status}.`,"finalizing"),J$(Z,$.params.turn);break;default:break}}async function p0(Z,$,W,Q={}){let V=l0($,Q),Y=Z.notificationHandler;if(Z.setNotificationHandler((K)=>{if(!V.turnId){V.bufferedNotifications.push(K);return}if(K.method==="thread/started"){B$(V,K);return}if(!d$(V,K)){Y?.(K);return}B$(V,K)}),Q.onApprovalRequest)Z.setServerRequestHandler((K,G)=>Q.onApprovalRequest(K,G,V));try{let K=await W();if(V.turnId=K.turn?.id??null,V.turnId)V.threadTurnIds.set(V.threadId,V.turnId);for(let G of V.bufferedNotifications)if(d$(V,G))B$(V,G);else Y?.(G);if(V.bufferedNotifications.length=0,K.turn?.status&&K.turn.status!=="inProgress")J$(V,K.turn);return await V.completion}finally{L$(V),Z.setNotificationHandler(Y??null),Z.setServerRequestHandler(null)}}async function n0(Z,$){let W=null;try{W=await g.connect(Z);let Q=await $(W);return await W.close(),Q}catch(Q){let V=W?.transport==="broker"||Boolean(process.env[$$]),Y=W?.transport==="broker"&&Q?.rpcCode===g$||V&&(Q?.code==="ENOENT"||Q?.code==="ECONNREFUSED");if(W)await W.close().catch(()=>{}),W=null;if(!Y)throw Q;let K=await g.connect(Z,{disableBroker:!0});try{return await $(K)}finally{await K.close()}}}function a(Z){let $=M$("codex",["--version"],{cwd:Z});if(!$.available)return $;let W=M$("codex",["app-server","--help"],{cwd:Z});if(!W.available)return{available:!1,detail:`${$.detail}; app-server runtime unavailable: ${W.detail}`};return{available:!0,detail:`${$.detail}; app-server runtime available`}}async function a$(Z){let $=a(Z);if(!$.available)return{available:!1,loggedIn:!1,detail:$.detail};let W=null;try{W=await g.connect(Z,{reuseExistingBroker:!0});let Q=await W.request("account/read",{refreshToken:!1}),V=Q?.account??null;if(V?.type==="chatgpt")return{available:!0,loggedIn:!0,detail:V.email?`ChatGPT login active for ${V.email}`:"ChatGPT login active"};if(V?.type==="apiKey")return{available:!0,loggedIn:!0,detail:"API key configured"};if(Q?.requiresOpenaiAuth===!1)return{available:!0,loggedIn:!0,detail:"Active provider does not require OpenAI authentication"};return{available:!0,loggedIn:!1,detail:"Not authenticated. Run `codex login`."}}catch(Q){let V=I0("codex",["login","status"],{encoding:"utf8"}),Y=`${V.stdout??""}${V.stderr??""}`.trim();if(V.status===0)return{available:!0,loggedIn:!0,detail:Y||"Logged in"};return{available:!0,loggedIn:!1,detail:Y||(Q instanceof Error?Q.message:String(Q))}}finally{await W?.close().catch(()=>{})}}async function t$(Z,{threadId:$,turnId:W}){if(!$||!W)return{interrupted:!1,detail:"missing threadId or turnId"};let Q=null;try{return Q=await g.connect(Z,{reuseExistingBroker:!0}),await Q.request("turn/interrupt",{threadId:$,turnId:W}),{interrupted:!0,detail:`Interrupted ${W} on ${$}.`}}catch(V){return{interrupted:!1,detail:V instanceof Error?V.message:String(V)}}finally{await Q?.close().catch(()=>{})}}async function o$(Z,$={}){let W=a(Z);if(!W.available)throw Error(`Codex CLI is not available: ${W.detail}`);let Q=$.prompt?.trim();if(!Q)throw Error("A prompt is required.");return n0(Z,async(V)=>{let Y;if($.resumeThreadId)I($.onProgress,`Resuming thread ${$.resumeThreadId}.`,"starting"),Y=(await V.request("thread/resume",{threadId:$.resumeThreadId,cwd:Z,model:$.model??null,approvalPolicy:$.approvalPolicy??"never",sandbox:$.sandbox??"read-only"})).thread.id;else{I($.onProgress,"Starting Codex task thread.","starting"),Y=(await V.request("thread/start",{cwd:Z,model:$.model??null,approvalPolicy:$.approvalPolicy??"never",sandbox:$.sandbox??"read-only",serviceName:j0,ephemeral:$.ephemeral??!1})).thread.id;try{await V.request("thread/name/set",{threadId:Y,name:h0(Q)})}catch(H){let X=String(H?.message??H??"");if(!X.includes("unknown variant")&&!X.includes("unknown method"))throw H}}I($.onProgress,`Thread ready (${Y}).`,"starting",{threadId:Y});let K=await p0(V,Y,()=>V.request("turn/start",{threadId:Y,input:[{type:"text",text:Q,text_elements:[]}],model:$.model??null,effort:$.effort??null,outputSchema:$.outputSchema??null}),{onProgress:$.onProgress,onApprovalRequest:$.onApprovalRequest});return{status:K.finalTurn?.status==="completed"?0:1,threadId:Y,turnId:K.turnId,finalMessage:K.lastAgentMessage,reasoningSummary:K.reasoningSummary,turn:K.finalTurn,error:K.error,stderr:u0(V.stderr),fileChanges:K.fileChanges,touchedFiles:b0(K.fileChanges),commandExecutions:K.commandExecutions}})}import{spawn as r0,spawnSync as a0}from"node:child_process";import{randomUUID as t0}from"node:crypto";import W$ from"node:fs";import _$ from"node:path";var k$={chain:["codex","claude"],agents:{codex:{model:"gpt-5.5",effort:"medium",permissions:"auto"},claude:{model:"opus",permissions:"auto"}},approvals:{escalationTimeoutMs:120000,allowedNetworkHosts:[]}},d0={spark:"gpt-5.3-codex-spark","5.5":"gpt-5.5"},R$=new Set(["low","medium","high"]);var f$=new Set(["low","medium","high"]),t={"read-only":{sandbox:"read-only",approvalPolicy:"never",approvalMode:null},"workspace-write":{sandbox:"workspace-write",approvalPolicy:"never",approvalMode:null},auto:{sandbox:"workspace-write",approvalPolicy:"on-request",approvalMode:"auto"}},i0=["ls","cat","head","tail","wc","grep","rg","find","fd","tree","file","stat","du","df","which","pwd","env","git status","git log","git diff","git show","git branch","git blame","git remote"].map((Z)=>`Bash(${Z}:*)`),A$={"read-only":["--permission-mode","dontAsk","--disallowedTools","Edit","Write","NotebookEdit","--allowedTools",...i0],"workspace-write":["--permission-mode","acceptEdits"],auto:["--permission-mode","auto"]};function s$(Z){if(!W$.existsSync(Z))return null;try{return JSON.parse(W$.readFileSync(Z,"utf8"))}catch($){throw Error(`Invalid JSON in ${Z}: ${$.message}`)}}function x$(Z,$){if(!$||typeof $!=="object"||Array.isArray($))return $??Z;let W={...Z};for(let[Q,V]of Object.entries($))if(V&&typeof V==="object"&&!Array.isArray(V)&&Z?.[Q]&&typeof Z[Q]==="object")W[Q]=x$(Z[Q],V);else W[Q]=V;return W}function o(){return _$.join(Y$(),"config.json")}function u(Z){let $=w(Z),W=k$;return W=x$(W,s$(o())),W=x$(W,s$(_$.join($,"coder.config.json"))),W}function e$(Z){if(!Z)return null;return d0[Z]??Z}function $0(Z){let $=o();return W$.mkdirSync(_$.dirname($),{recursive:!0}),W$.writeFileSync($,`${JSON.stringify(Z,null,2)}
|
|
13
|
+
`,"utf8"),$}function y$(){let Z=a0("claude",["--version"],{encoding:"utf8"});if(Z.error||Z.status!==0)return{available:!1,detail:"claude CLI not found on PATH (npm install -g @anthropic-ai/claude-code)"};return{available:!0,detail:String(Z.stdout||"").trim()}}async function Z0(Z,$){let W=$.resumeSessionId??t0(),Q=["-p",$.prompt,"--output-format","json"];if(Q.push($.resumeSessionId?"--resume":"--session-id",W),$.model)Q.push("--model",$.model);if($.effort)Q.push("--effort",$.effort);return Q.push(...A$[$.permissions??"auto"]??A$.auto),$.onProgress?.({message:`claude turn started (session ${W})`,threadId:W}),new Promise((V,Y)=>{let K=r0("claude",Q,{cwd:Z,stdio:["ignore","pipe","pipe"]}),G="",H="";K.stdout.on("data",(z)=>{G+=z}),K.stderr.on("data",(z)=>{H+=z});let X=()=>{K.kill("SIGTERM"),process.exit(143)};process.on("SIGTERM",X),K.on("error",(z)=>{process.removeListener("SIGTERM",X),Y(Error(`claude spawn failed: ${z.message}`))}),K.on("close",(z)=>{process.removeListener("SIGTERM",X);let O=null;try{O=JSON.parse(G)}catch{}let M=O?.result??G.trim(),q=z!==0||O?.is_error===!0;V({status:q?1:0,threadId:O?.session_id??W,turnId:null,finalMessage:M,error:q?{message:M||H.trim()||`claude exited ${z}`}:null})})})}import C from"node:fs";import D from"node:path";var o0="item/commandExecution/requestApproval",s0="item/fileChange/requestApproval",e0=new Set(["commit","checkout","switch","restore","stash","reset","rebase","merge","push","pull","cherry-pick","revert","clean","am","apply","tag","branch","worktree","filter-branch","filter-repo","gc","prune","reflog","remote","submodule","config"]),$1=[/\bsudo\b/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)\b.*\s(\/\*?|~\/?|\$HOME\/?)(\s|$)/,/\b(shutdown|reboot|halt|poweroff)\b/,/\bmkfs\b|\bdiskutil\s+erase/i,/\b(chmod|chown)\b.*-R.*\s\/(\s|$)/,/\bkill(all)?\s+-9\s+1\b/,/curl[^|;&]*\|\s*(ba|z|da)?sh\b/,/wget[^|;&]*\|\s*(ba|z|da)?sh\b/,/\blaunchctl\b|\bsystemctl\b/,/\bdefaults\s+write\b/,/>\s*\/dev\/(sd|disk)/],Z1=new Set(["ls","cat","head","tail","wc","grep","rg","ugrep","find","fd","diff","file","stat","du","df","which","whoami","pwd","echo","printf","env","date","uname","sw_vers","jq","sort","uniq","tr","cut","basename","dirname","realpath","readlink","xxd","shasum","sha256sum","md5","tree","ps"]),W1=new Set(["status","log","diff","show","blame","rev-parse","ls-files","ls-tree","cat-file","describe","shortlog","grep","branch","stash"]),Q1=new Map([["npm",new Set(["test","run","exec","ls","view","why","outdated","ping"])],["pnpm",new Set(["test","run","exec","ls","why","outdated"])],["yarn",new Set(["test","run","why","info"])],["bun",new Set(["test","run","x","pm"])],["npx",null],["bunx",null],["node",null],["python",null],["python3",null],["tsc",null],["eslint",null],["prettier",null],["vitest",null],["jest",null],["pytest",null],["cargo",new Set(["build","test","check","clippy","fmt","run","bench","doc","tree","metadata"])],["go",new Set(["build","test","vet","run","fmt","list","env","version"])],["make",null],["turbo",null]]);function V1(Z){let $=Z.match(/^\s*(?:ba|z|da)?sh\s+(?:-[a-zA-Z]+\s+)*(?:-c\s+)?(["'])([\s\S]*)\1\s*$/);return $?$[2]:Z}function Y1(Z){return Z.trim().split(/\s+/).filter(Boolean)}function G1(Z){let $=Z.find((W,Q)=>Q>0&&!W.startsWith("-"));if(!$)return{decision:"accept",reason:"bare git"};if($==="branch"&&Z.some((W)=>/^-(d|D|m|M|c|C|f|u)|^--(delete|move|copy|force|set-upstream)/.test(W)))return{decision:"decline",reason:"git branch write operation (git is read-only for Coder)"};if($==="stash"){let W=Z.find((Q,V)=>V>1&&!Q.startsWith("-"));if(W==="list"||W==="show")return{decision:"accept",reason:`git stash ${W} is read-only`};return{decision:"decline",reason:"git stash write operation (git is read-only for Coder)"}}if(W1.has($))return{decision:"accept",reason:`git ${$} is read-only`};if(e0.has($))return{decision:"decline",reason:`git ${$} is a write operation (git is read-only for Coder)`};return{decision:"escalate",reason:`unrecognized git subcommand: ${$}`}}function Q0(Z,$={}){let W=V1(String(Z??""));if(!W.trim())return{decision:"escalate",reason:"empty command"};for(let G of $1)if(G.test(W))return{decision:"decline",reason:`matches hard-deny pattern ${G}`};if(/\$\(|`|<\(/.test(W))return{decision:"escalate",reason:"contains command substitution"};let Q=W.split(/&&|\|\||;|\||\r?\n/).map((G)=>G.trim()).filter(Boolean);if(Q.length>1){let G={decision:"accept",reason:"all segments safe"};for(let H of Q){let X=Q0(H,$);if(X.decision==="decline")return X;if(X.decision==="escalate")G=X}return G}let V=Y1(W),Y=D.basename(V[0]??"");if(Y==="git")return G1(V);if($.networkHost){if(($.allowedNetworkHosts??[]).some((H)=>$.networkHost===H||$.networkHost.endsWith(`.${H}`)))return{decision:"accept",reason:`network host ${$.networkHost} is allowlisted`};return{decision:"escalate",reason:`network access to ${$.networkHost}`}}if(Z1.has(Y))return{decision:"accept",reason:`${Y} is on the safe-binaries list`};let K=Q1.get(Y);if(K!==void 0){if(K===null)return{decision:"accept",reason:`${Y} is a trusted runner`};let G=V.find((H,X)=>X>0&&!H.startsWith("-"));if(G&&K.has(G))return{decision:"accept",reason:`${Y} ${G} is a trusted runner command`};return{decision:"escalate",reason:`${Y} ${G??""} is not on the trusted subcommand list`}}return{decision:"escalate",reason:`unknown binary: ${Y}`}}function K1(Z,$){if(!Z.length)return{decision:"escalate",reason:"file change with no resolvable paths"};for(let W of Z){let Q=D.resolve($,W),V=D.relative($,Q);if(V.startsWith("..")||D.isAbsolute(V))return{decision:"escalate",reason:`path outside workspace: ${W}`};if(V===".git"||V.startsWith(`.git${D.sep}`))return{decision:"decline",reason:`direct .git modification: ${W}`}}return{decision:"accept",reason:"all paths inside workspace"}}function C$(Z){return D.join(Z,"approvals")}function D$(Z){let $=C$(Z);if(!C.existsSync($))return[];return C.readdirSync($).filter((W)=>W.endsWith(".request.json")).map((W)=>{let Q=W.replace(/\.request\.json$/,""),V=JSON.parse(C.readFileSync(D.join($,W),"utf8")),Y=D.join($,`${Q}.response.json`),K=C.existsSync(Y)?JSON.parse(C.readFileSync(Y,"utf8")):null;return{id:Q,...V,response:K}}).sort((W,Q)=>String(W.createdAt??"").localeCompare(String(Q.createdAt??"")))}function V0(Z,$,W){let Q=C$(Z),V=D.join(Q,`${$}.request.json`);if(!C.existsSync(V))throw Error(`No pending approval "${$}" for this job.`);C.writeFileSync(D.join(Q,`${$}.response.json`),`${JSON.stringify({decision:W,answeredAt:new Date().toISOString()},null,2)}
|
|
14
|
+
`,"utf8")}async function W0(Z,$,{timeoutMs:W,onEvent:Q}){let V=C$(Z);C.mkdirSync(V,{recursive:!0});let Y=`apr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`;C.writeFileSync(D.join(V,`${Y}.request.json`),`${JSON.stringify({...$,createdAt:new Date().toISOString()},null,2)}
|
|
15
|
+
`,"utf8"),Q?.({kind:"approval-escalated",approvalId:Y,summary:$.summary,message:`Approval needed (${Y}): ${$.summary}. Answer with: coder approve <job> ${Y} [--deny]`});let K=D.join(V,`${Y}.response.json`),G=Date.now()+W;while(Date.now()<G){if(C.existsSync(K))try{let X=JSON.parse(C.readFileSync(K,"utf8")).decision==="accept"?"accept":"decline";return Q?.({kind:"approval-answered",approvalId:Y,decision:X}),X}catch{}await new Promise((H)=>setTimeout(H,400))}return Q?.({kind:"approval-timeout",approvalId:Y,message:`Approval ${Y} timed out; declining.`}),"decline"}function Y0({workspaceRoot:Z,jobDir:$,mode:W="auto",escalationTimeoutMs:Q=120000,allowedNetworkHosts:V=[],onEvent:Y=null}){return async(K,G,H)=>{if(K===o0){let X=G.command??H?.itemIndex?.get(G.itemId)?.command??"",z=`run command: ${X||"(unknown command)"}${G.reason?` — ${G.reason}`:""}`;if(W==="deny")return Y?.({kind:"approval-decision",method:K,decision:"decline",reason:"deny mode",summary:z}),{decision:"decline"};let O=Q0(X,{networkHost:G.networkApprovalContext?.host??null,allowedNetworkHosts:V});if(Y?.({kind:"approval-decision",method:K,decision:O.decision,reason:O.reason,summary:z}),O.decision==="escalate")return{decision:await W0($,{method:K,summary:z,command:X,params:G},{timeoutMs:Q,onEvent:Y})};return{decision:O.decision}}if(K===s0){let z=(H?.itemIndex?.get(G.itemId)?.changes??[]).map((q)=>q.path).filter(Boolean),O=`apply file changes: ${z.join(", ")||"(unknown paths)"}${G.reason?` — ${G.reason}`:""}`;if(W==="deny")return Y?.({kind:"approval-decision",method:K,decision:"decline",reason:"deny mode",summary:O}),{decision:"decline"};let M=K1(z,Z);if(Y?.({kind:"approval-decision",method:K,decision:M.decision,reason:M.reason,summary:O}),M.decision==="escalate")return{decision:await W0($,{method:K,summary:O,paths:z,params:G},{timeoutMs:Q,onEvent:Y})};return{decision:M.decision}}throw Y?.({kind:"approval-unsupported",method:K}),Error(`Coder does not handle server request ${K}; treating as denied.`)}}var X1=Q$(import.meta.url),F$=/usage|quota|rate.?limit|429|401|unauthorized|not authenticated|login|insufficient|exhausted|not available|ENOENT/i;function R(Z,$=1){U.stderr.write(`${Z}
|
|
16
|
+
`),U.exit($)}function x(Z){U.stdout.write(`${JSON.stringify(Z,null,2)}
|
|
17
|
+
`)}function c(Z,$){let W=K$(Z,$);if(!W)R($?`No job found for "${$}".`:"No jobs found for this workspace.");return W}function G0(Z,$,{echo:W}){return(Q)=>{let V=typeof Q==="string"?{message:Q}:Q;if(n(Z,$,V),W&&V.message)U.stderr.write(`[coder] ${V.message}
|
|
18
|
+
`)}}function z1(Z,$){let W=Z.agent??$.chain[0]??"codex",Q=$.agents[W]??{},V=Z.model??Q.model??null,Y=Z.effort??Q.effort??null,K=Z.permissions??Q.permissions??"auto";if(!(K in t))R(`Invalid --permissions "${K}". Use one of: ${Object.keys(t).join(", ")}`);if(W==="codex"&&Y&&!R$.has(Y))R(`Invalid codex --effort "${Y}". Use one of: ${[...R$].join(", ")}`);if(W==="claude"&&Y&&!f$.has(Y))R(`Invalid claude --effort "${Y}". Use one of: ${[...f$].join(", ")}`);return{agent:W,model:V,effort:Y,permissions:K}}function s(Z,$,W,Q=null){let V=Z.agents.claude??{};return{agent:"claude",action:"spawn-claude-subagent",reason:W,model:V.model??"opus",permissions:Q??V.permissions??"auto",note:"Spawn a general-purpose subagent with this model and forward the task verbatim.",task:$}}async function q1(Z,$,{echo:W}){let Q=w(Z),V=A(Z,$.id),Y=u(Z),K=G0(Z,$.id,{echo:W}),G=t[$.permissions]??t.auto,H=G.approvalPolicy==="never"?void 0:Y0({workspaceRoot:Q,jobDir:V,mode:G.approvalMode,escalationTimeoutMs:Y.approvals.escalationTimeoutMs,allowedNetworkHosts:Y.approvals.allowedNetworkHosts,onEvent:(O)=>{if(n(Z,$.id,O),W&&O.message)U.stderr.write(`[coder] ${O.message}
|
|
19
|
+
`)}}),X=await o$(Z,{prompt:$.prompt,model:e$($.model),effort:$.effort,sandbox:G.sandbox,approvalPolicy:G.approvalPolicy,onApprovalRequest:H,resumeThreadId:$.resumeThreadId??null,onProgress:(O)=>{K(O);let M=typeof O==="object"?O.threadId:null,q=typeof O==="object"?O.turnId:null;if(M||q)y(Z,$.id,{status:"running",...M?{threadId:M}:{},...q?{turnId:q}:{}})}}),z=X.status===0?"completed":"failed";return y(Z,$.id,{status:z,threadId:X.threadId,turnId:X.turnId,completedAt:new Date().toISOString()}),E.writeFileSync(k.join(V,"result.json"),`${JSON.stringify(X,null,2)}
|
|
20
|
+
`,"utf8"),X}async function M1(Z,$,{echo:W}){let Q=A(Z,$.id),V=G0(Z,$.id,{echo:W}),Y=await Z0(Z,{prompt:$.prompt,model:$.model,effort:$.effort,permissions:$.permissions,resumeSessionId:$.resumeThreadId??null,onProgress:(K)=>{if(V(K),K.threadId)y(Z,$.id,{status:"running",threadId:K.threadId})}});return y(Z,$.id,{status:Y.status===0?"completed":"failed",threadId:Y.threadId,completedAt:new Date().toISOString()}),E.writeFileSync(k.join(Q,"result.json"),`${JSON.stringify(Y,null,2)}
|
|
21
|
+
`,"utf8"),Y}function K0(Z){return Z.agent==="claude"?M1:q1}async function H0(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["agent","model","effort","permissions","resume","cwd","host"],booleanOptions:["background","wait","json"]}),Q=$.wait?!1:!0,V=$.cwd?k.resolve($.cwd):U.cwd(),Y=W.join(" ").trim();if(!Y)R('Usage: coder task [options] "<task text>"');let K=u(V),G=z1($,K),H=$.host??"claude";if(G.agent==="claude"&&H==="claude")x(s(K,Y,"configured",G.permissions)),U.exit(3);if(G.agent==="codex"){let M=a(V);if(!M.available)x({error:`Codex unavailable: ${M.detail}`,fallback:s(K,Y,"codex-failed",G.permissions)}),U.exit(3)}else{let M=y$();if(!M.available)R(`Claude unavailable: ${M.detail}`)}let X=null;if($.resume)X=K$(V,$.resume)?.threadId??$.resume;let z=E$(),O=y(V,z,{status:"queued",kind:"task",agent:G.agent,host:H,prompt:Y,model:G.model,effort:G.effort,permissions:G.permissions,resumeThreadId:X,cwd:V,background:Q});if(Q){let M=A(V,z),q=E.openSync(k.join(M,"worker.log"),"a"),B=H1(U.execPath,[X1,"_worker",z,"--cwd",V],{cwd:V,detached:!0,stdio:["ignore",q,q]});B.unref(),E.closeSync(q),y(V,z,{pid:B.pid??null});let T=Date.now()+15000,L=O,F=null;while(Date.now()<(F??T)){if(L=v(V,z)??L,L.status==="failed"||L.status==="completed")break;if(L.threadId&&!F)F=Date.now()+5000;await new Promise((j)=>setTimeout(j,300))}if(L.status==="failed"){let j=H$(V,z,5).map((V$)=>V$.message??"").join(`
|
|
22
|
+
`);if(G.agent==="codex"&&F$.test(j))x({error:`Codex failed to start: ${j}`,fallback:s(K,Y,"codex-failed",G.permissions)}),U.exit(3);x({jobId:z,status:"failed",detail:j}),U.exit(1)}x({jobId:z,status:L.status,threadId:L.threadId??null,startupCheck:L.threadId?"passed":"pending",commands:{status:`coder status ${z}`,result:`coder result ${z}`,steer:`coder steer ${z} "<follow-up>"`,stop:`coder stop ${z}`}});return}y(V,z,{status:"running",pid:U.pid});try{let M=v(V,z),q=await K0(M)(V,M,{echo:!$.json}),B=q.error?.message??"";if(G.agent==="codex"&&q.status!==0&&F$.test(B))x({error:`Codex failed to start: ${B}`,fallback:s(K,Y,"codex-failed",G.permissions)}),U.exit(3);if($.json)x({jobId:z,status:q.status===0?"completed":"failed",threadId:q.threadId,finalMessage:q.finalMessage});else U.stdout.write(`${q.finalMessage||"(no final message)"}
|
|
23
|
+
`),U.stderr.write(`[coder] job=${z} thread=${q.threadId} status=${q.status===0?"completed":"failed"}
|
|
24
|
+
`);U.exit(q.status===0?0:1)}catch(M){let q=M instanceof Error?M.message:String(M);if(y(V,z,{status:"failed",error:q}),n(V,z,{kind:"error",message:q}),G.agent==="codex"&&F$.test(q))x({error:`Codex failed to start: ${q}`,fallback:s(K,Y,"codex-failed",G.permissions)}),U.exit(3);R(`${G.agent} run failed: ${q}`)}}async function U1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),V=W[0],Y=v(Q,V);if(!Y)R(`Worker: job ${V} not found.`);y(Q,V,{status:"running",pid:U.pid});try{await K0(Y)(Q,Y,{echo:!1})}catch(K){let G=K instanceof Error?K.message:String(K);y(Q,V,{status:"failed",error:G}),n(Q,V,{kind:"error",message:G}),U.exit(1)}}async function O1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"],booleanOptions:["json"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),V=c(Q,W[0]),Y=D$(A(Q,V.id)).filter((G)=>!G.response),K=H$(Q,V.id,6);x({jobId:V.id,status:V.status,agent:V.agent,threadId:V.threadId??null,turnId:V.turnId??null,createdAt:V.createdAt,updatedAt:V.updatedAt,pendingApprovals:Y.map((G)=>({id:G.id,summary:G.summary})),recentProgress:K.map((G)=>G.message??G.kind).filter(Boolean)})}async function B1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"],booleanOptions:["json"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),V=c(Q,W[0]),Y=k.join(A(Q,V.id),"result.json");if(!E.existsSync(Y))R(`Job ${V.id} is ${V.status}; no result yet. Check: coder status ${V.id}`);let K=JSON.parse(E.readFileSync(Y,"utf8"));if($.json){x(K);return}if(U.stdout.write(`${K.finalMessage||"(no final message)"}
|
|
25
|
+
`),K.touchedFiles?.length)U.stderr.write(`[coder] touched files: ${K.touchedFiles.join(", ")}
|
|
26
|
+
`)}async function N1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd","model","effort","permissions"],booleanOptions:["background","wait"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),[V,...Y]=W,K=Y.join(" ").trim();if(!V||!K)R('Usage: coder steer <job-id> "<follow-up instructions>" [--wait]');let G=c(Q,V);if(!G.threadId)R(`Job ${G.id} has no thread to steer yet (status: ${G.status}).`);if(G.status==="running")R(`Job ${G.id} is still running. Stop it first (coder stop ${G.id}) or wait, then steer.`);let H=[K,"--resume",G.id,"--cwd",Q,...G.agent?["--agent",G.agent]:[],...G.host&&G.host!=="claude"?["--host",G.host]:[],...$.model?["--model",$.model]:["--model",G.model].filter(()=>G.model),...$.effort?["--effort",$.effort]:G.effort?["--effort",G.effort]:[],...$.permissions?["--permissions",$.permissions]:G.permissions?["--permissions",G.permissions]:[],...$.wait?["--wait"]:[]];await H0(H)}async function L1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),V=c(Q,W[0]),Y=V.agent==="claude"?{detail:"claude worker terminated"}:await t$(Q,{threadId:V.threadId,turnId:V.turnId});if(V.pid&&V.status==="running")try{U.kill(V.pid,"SIGTERM")}catch{}y(Q,V.id,{status:"cancelled",completedAt:new Date().toISOString()}),x({jobId:V.id,status:"cancelled",interrupt:Y.detail})}async function J1(Z){let{options:$}=f(Z,{valueOptions:["cwd"]}),W=$.cwd?k.resolve($.cwd):U.cwd();x(G$(W).map((Q)=>({jobId:Q.id,status:Q.status,agent:Q.agent,threadId:Q.threadId??null,prompt:String(Q.prompt??"").slice(0,80),updatedAt:Q.updatedAt})))}async function x1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),V=c(Q,W[0]);x(D$(A(Q,V.id)).map((Y)=>({id:Y.id,summary:Y.summary,createdAt:Y.createdAt,answered:Y.response?.decision??null})))}async function _1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"],booleanOptions:["deny"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),[V,Y]=W;if(!V||!Y)R("Usage: coder approve <job-id> <approval-id> [--deny]");let K=c(Q,V);V0(A(Q,K.id),Y,$.deny?"decline":"accept"),x({jobId:K.id,approvalId:Y,decision:$.deny?"decline":"accept"})}async function k1(Z){let{options:$,positionals:W}=f(Z,{valueOptions:["cwd"],booleanOptions:["workspace"]}),Q=$.cwd?k.resolve($.cwd):U.cwd(),[V="list",Y,...K]=W,G=$.workspace?k.join(w(Q),"coder.config.json"):o(),H=(B,T)=>T.split(".").reduce((L,F)=>L==null?void 0:L[F],B);if(V==="list"){x(u(Q));return}if(V==="get"){if(!Y)R("Usage: coder config get <key> (e.g. chain, agents.codex.model)");let B=H(u(Q),Y);x(B===void 0?null:B);return}if(V!=="set"&&V!=="unset")R("Usage: coder config [get|set|unset] <key> [value] [--workspace]");if(!Y||V==="set"&&K.length===0)R(`Usage: coder config ${V} <key>${V==="set"?" <value>":""}`);let X=K.join(" "),z;try{z=JSON.parse(X)}catch{z=X.includes(",")?X.split(",").map((B)=>B.trim()).filter(Boolean):X}let O=E.existsSync(G)?JSON.parse(E.readFileSync(G,"utf8")):{},M=Y.split("."),q=O;for(let B of M.slice(0,-1)){if(typeof q[B]!=="object"||q[B]===null)q[B]={};q=q[B]}if(V==="set")q[M.at(-1)]=z;else delete q[M.at(-1)];E.mkdirSync(k.dirname(G),{recursive:!0}),E.writeFileSync(G,`${JSON.stringify(O,null,2)}
|
|
27
|
+
`,"utf8"),x({file:G,key:Y,...V==="set"?{value:z}:{unset:!0},effective:H(u(Q),Y)??null})}async function R1(Z){let{options:$}=f(Z,{valueOptions:["cwd"],booleanOptions:["codex","claude","json"]}),W=$.cwd?k.resolve($.cwd):U.cwd(),Q=a(W),V=Q.available?await a$(W):{loggedIn:!1,detail:Q.detail},Y=y$(),K=o();if(!E.existsSync(K))$0(k$);let G=null;if($.codex){let N=Q$(new URL("../plugins",import.meta.url));h("codex",["plugin","remove","Coder@wular-plugins"],{encoding:"utf8"}),h("codex",["plugin","marketplace","remove","wular-plugins"],{encoding:"utf8"});let _=h("codex",["plugin","marketplace","add","."],{cwd:N,encoding:"utf8"}),l=h("codex",["plugin","add","Coder@wular-plugins"],{encoding:"utf8"}),p=_.status===0&&l.status===0;G={marketplace:N,installed:p,note:p?"Plugin installed; restart any running codex session to load it.":`Automatic install failed (${(l.stderr||_.stderr||"codex not found").trim()}); run: codex plugin marketplace add "${N}" && codex plugin add Coder@wular-plugins`}}let H=null;if($.claude){let N=Q$(new URL("../plugins",import.meta.url));h("claude",["plugin","marketplace","remove","wular-plugins"],{encoding:"utf8"});let _=h("claude",["plugin","marketplace","add",N],{encoding:"utf8"}),l=h("claude",["plugin","install","Coder@wular-plugins"],{encoding:"utf8"}),p=_.status===0&&l.status===0;H={marketplace:N,installed:p,note:p?"Plugin installed; restart any running Claude Code session to load it.":`Automatic install failed (${(l.stderr||_.stderr||"claude not found").trim()}); run: claude plugin marketplace add "${N}" && claude plugin install Coder@wular-plugins`}}let X=u(W),z=Q.available&&V.loggedIn;if($.json){x({codex:{available:Q.available,detail:Q.detail,auth:V.detail,loggedIn:V.loggedIn},claude:{available:Y.available,detail:Y.detail},configFile:K,runtime:Q$(new URL("../bin/coder.mjs",import.meta.url)),...G?{codexPlugin:G}:{},...H?{claudePlugin:H}:{},config:X,ready:z});return}let O=U.stdout.isTTY&&!U.env.NO_COLOR,M=(N,_)=>O?`\x1B[${N}m${_}\x1B[0m`:_,q=(N)=>` ${M("32","✔")} ${N}`,B=(N)=>` ${M("31","✘")} ${N}`,T=(N)=>M("1",N),L=(N)=>M("38;5;245",N),F=[T("Coder setup"),""],j=Q.available?V.loggedIn?q(`codex ${L(`${Q.detail}; ${V.detail}`)}`):B(`codex not logged in ${L(`(${V.detail})`)} - run: codex login`):B("codex not installed - run: npm install -g @openai/codex"),V$=Y.available?q(`claude ${L(Y.detail)}`):B("claude not installed - run: npm install -g @anthropic-ai/claude-code");F.push(T("Engines"),j,V$,"");let P$=(N)=>{let _=X.agents?.[N]??{};return[_.model,_.effort,_.permissions].filter(Boolean).join("/")};F.push(T("Config"),` chain: ${(X.chain??[]).join(" -> ")} codex: ${P$("codex")} claude: ${P$("claude")}`,` ${L(K)} ${L("(coder config set <key> <value> to change)")}`,"");for(let[N,_]of[["codex plugin ",G],["claude plugin",H]])if(_)F.push(_.installed?q(`${N} ${L(_.note)}`):B(`${N} ${_.note}`),"");F.push(z?q(`ready - try: coder task --wait "explain this repo's layout"`):B("not ready - fix the engine issues above (tasks fall back to the claude engine meanwhile)")),U.stdout.write(`${F.join(`
|
|
28
|
+
`)}
|
|
29
|
+
`)}var f1={task:H0,_worker:U1,status:O1,result:B1,steer:N1,stop:L1,jobs:J1,approvals:x1,approve:_1,config:k1,setup:R1};async function A1(){let[Z,...$]=U.argv.slice(2),W=f1[Z];if(!W){let Q=U.stderr.isTTY&&!U.env.NO_COLOR,V=(H)=>Q?`\x1B[1m${H}\x1B[0m`:H,Y=(H)=>Q?`\x1B[36m${H}\x1B[0m`:H,K=(H)=>Q?`\x1B[38;5;245m${H}\x1B[0m`:H,G=(H,X)=>` ${Y(H.padEnd(34))}${K(X)}`;R([`${V("Coder")}`,"",V("Usage:")," coder <command> [flags]","",V("Commands:"),G('task "<text>" [--wait]',"run a coding task (background; --wait blocks)"),G("status [job]","job status, progress, pending approvals"),G("result [job]","final message of a finished job"),G('steer <job> "<follow-up>"',"continue a job's thread with new instructions"),G("stop <job>","interrupt a running job"),G("jobs","list jobs for this workspace"),G("approvals <job>","list escalated approvals"),G("approve <job> <id> [--deny]","answer an escalated permission"),G("config [get|set|unset] <key> [value]","read or write config (e.g. set chain claude,codex)"),G("setup [--claude|--codex]","check engines, write config, install the host plugin"),"",V("Task flags:")+K(" (task and steer)"),G("--agent <codex|claude>","engine (default: first in configured chain)"),G("--model <alias|slug>","spark, 5.5 | opus, sonnet, fable | any raw slug"),G("--effort <low|medium|high>","reasoning effort"),G("--permissions <mode>","read-only | workspace-write | auto (default: auto)"),G("--resume <job>","continue that job's thread instead of starting fresh"),"",G("--cwd <dir>","workspace directory, any command (default: current)")].join(`
|
|
30
|
+
`))}await W($)}A1().catch((Z)=>{U.stderr.write(`${Z instanceof Error?Z.message:String(Z)}
|
|
31
|
+
`),U.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wular/coder",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Delegating coding-agent runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"coder": "
|
|
7
|
+
"coder": "bin/coder.mjs"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "bun build src/cli.ts src/lib/broker.ts --outdir dist --root src --target node --format esm --minify",
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Set up the Coder runtime (install the CLI, verify
|
|
2
|
+
description: Set up the Coder runtime (install the CLI, verify engines, configure the chain)
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Set up the Coder runtime for this machine.
|
|
5
|
+
Set up the Coder runtime for this machine. Use AskUserQuestion for the decision points.
|
|
6
6
|
|
|
7
|
-
1.
|
|
8
|
-
2. Run `coder setup` and
|
|
9
|
-
3.
|
|
10
|
-
4. If Codex is
|
|
11
|
-
|
|
7
|
+
1. Runtime: `command -v coder`; if missing, install it (`npm install -g @wular/coder`).
|
|
8
|
+
2. Run `coder setup --json` and read it (codex/claude availability and auth).
|
|
9
|
+
3. Tell the user Coder uses Codex as the primary engine with Claude as fallback, and ask if that ordering suits them. If they prefer Claude first: `coder config set chain claude,codex`.
|
|
10
|
+
4. If Codex is kept first but is not ready:
|
|
11
|
+
- Not installed: ask if they want it installed; on yes run `npm install -g @openai/codex`.
|
|
12
|
+
- Not logged in: ask them to run `codex login` themselves (interactive), then re-run `coder setup` to confirm.
|
|
13
|
+
- If they decline Codex: `coder config set chain claude,codex` so tasks go straight to the Claude engine, and say Codex can be enabled later by reversing the chain.
|
|
14
|
+
5. Show the final config (`coder config`) and mention overrides live in `~/.coder/config.json` (machine) and `coder.config.json` (per repo).
|
|
15
|
+
6. Suggest trying it: "Use Coder to <some small task>".
|
|
12
16
|
|
|
13
17
|
$ARGUMENTS
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
name: coder
|
|
3
3
|
description: Use for any coding or implementation task - features, fixes, refactors, debugging, tests. Dispatches the task to the configured engine chain (Codex or Claude). Give it one focused, self-contained goal with all context - overview, file paths, constraints e.g. read-only, git rules.
|
|
4
4
|
---
|
|
5
|
-
|
|
6
5
|
# Coder dispatch (codex host)
|
|
7
6
|
|
|
8
7
|
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
8
|
|
|
10
|
-
If `coder` is not on PATH,
|
|
9
|
+
If `coder` is not on PATH, set it up yourself: `npm install -g @wular/coder`, then `coder setup --codex`. Only if that fails, show the user the error and those two commands. On first setup, mention the chain is Codex-first and Claude on fallback; if the user prefers Claude engines first, run `coder config set chain claude,codex` (the Claude engine needs the claude CLI: `npm install -g @anthropic-ai/claude-code`, then run `claude` once to log in).
|
|
11
10
|
|
|
12
11
|
## Dispatching a task
|
|
13
12
|
|
|
@@ -17,7 +16,6 @@ If `coder` is not on PATH, tell the user to set it up (`npm install -g @wular/co
|
|
|
17
16
|
```bash
|
|
18
17
|
coder task --host codex --wait "<task text>"
|
|
19
18
|
```
|
|
20
|
-
|
|
21
19
|
- Always pass `--host codex` so the runtime executes Claude itself instead of asking the host to spawn a subagent.
|
|
22
20
|
- Exit 0: relay the final message. Exit 1: the engine ran but the turn failed - report it, do not retry.
|
|
23
21
|
- Exit 3: Codex could not start (auth, quota, rate limit - mention this to the user, including any limit-reset time). Rerun once with the Claude engine and relay its result:
|
|
@@ -25,7 +23,6 @@ If `coder` is not on PATH, tell the user to set it up (`npm install -g @wular/co
|
|
|
25
23
|
```bash
|
|
26
24
|
coder task --host codex --agent claude --wait "<same task text, verbatim>"
|
|
27
25
|
```
|
|
28
|
-
|
|
29
26
|
- 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`, `5.5`; claude models: `opus`, `sonnet`, `fable`; efforts: `low|medium|high`).
|
|
30
27
|
- Permissions default to auto mode. Pass `--permissions read-only` when the task is read-only; `--permissions workspace-write` to forbid any escalation beyond the project.
|
|
31
28
|
- For long jobs the user may want to manage by id, drop `--wait`: the runtime detaches a worker and prints a job id plus status/result/steer commands. Relay that.
|