@wular/coder 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -86,7 +86,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
86
86
|
`)}}function Vb(r,i){let v=r.agent;if(!v&&r.model){if(r.model in J6)v="claude";else if(r.model in $$)v="codex"}if(v=v??i.chain[0]??"codex",v!=="codex"&&v!=="claude"){let g=v in $$||v in J6?` "${v}" is a model; use --model ${v}.`:"";M(`Invalid --agent "${v}". Use codex or claude.${g}`)}let u=i.agents[v]??{},n=r.model??u.model??null,$=r.effort??u.effort??null,t=r.permissions??u.permissions??"auto";if(!(t in jn))M(`Invalid --permissions "${t}". Use one of: ${Object.keys(jn).join(", ")}`);if(v==="codex"&&$&&!S6.has($))M(`Invalid codex --effort "${$}". Use one of: ${[...S6].join(", ")}`);if(v==="claude"&&$&&!P6.has($))M(`Invalid claude --effort "${$}". Use one of: ${[...P6].join(", ")}`);return{agent:v,model:n,effort:$,permissions:t}}function SU(r,i,v,u=null){let n=r.agents.claude??{};return{agent:"claude",action:"spawn-claude-subagent",reason:v,model:n.model??"opus",permissions:u??n.permissions??"auto",note:"Spawn a general-purpose subagent with this model and forward the task verbatim.",task:i}}async function Xb(r,i,{echo:v}){let u=fr(r),n=ir(r,i.id),$=mr(r),t=PU(r,i.id,{echo:v}),g=jn[i.permissions]??jn.auto,I=g.approvalPolicy==="never"?void 0:bU({workspaceRoot:u,jobDir:n,mode:g.approvalMode,escalationTimeoutMs:$.approvals.escalationTimeoutMs,allowedNetworkHosts:$.approvals.allowedNetworkHosts,onEvent:(_)=>{if(Yn(r,i.id,_),v&&_.message)W.stderr.write(`[coder] ${_.message}
|
|
87
87
|
`)}}),o=await rI(r,{prompt:i.prompt,model:IU(i.model),effort:i.effort,sandbox:g.sandbox,approvalPolicy:g.approvalPolicy,onApprovalRequest:I,resumeThreadId:i.resumeThreadId??null,onProgress:(_)=>{t(_);let b=typeof _==="object"?_.threadId:null,k=typeof _==="object"?_.turnId:null;if(b||k)ur(r,i.id,{status:"running",...b?{threadId:b}:{},...k?{turnId:k}:{}})}}),l=o.status===0?"completed":"failed";return ur(r,i.id,{status:l,threadId:o.threadId,turnId:o.turnId,completedAt:new Date().toISOString()}),C.writeFileSync(x.join(n,"result.json"),`${JSON.stringify(o,null,2)}
|
|
88
88
|
`,"utf8"),o}async function jb(r,i,{echo:v}){let u=ir(r,i.id),n=PU(r,i.id,{echo:v}),$=await UU(r,{prompt:i.prompt,model:i.model,effort:i.effort,permissions:i.permissions,resumeSessionId:i.resumeThreadId??null,onProgress:(t)=>{if(n(t),t.threadId)ur(r,i.id,{status:"running",threadId:t.threadId})}});return ur(r,i.id,{status:$.status===0?"completed":"failed",threadId:$.threadId,completedAt:new Date().toISOString()}),C.writeFileSync(x.join(u,"result.json"),`${JSON.stringify($,null,2)}
|
|
89
|
-
`,"utf8"),$}function WU(r){return r.agent==="claude"?jb:Xb}async function Y6(r){let{options:i,positionals:v}=nr(r,{valueOptions:["agent","model","effort","permissions","resume","cwd","host"],booleanOptions:["background","wait","json"]}),u=i.wait?!1:!0,n=i.cwd?x.resolve(i.cwd):W.cwd(),$=v.join(" ").trim();if(!$)M('Usage: coder task [options] "<task text>"');let t=mr(n),g=Vb(i,t),I=i.host??(W.env.CLAUDECODE?"claude":"codex");if(I!=="claude"&&I!=="codex")M(`Invalid --host "${I}". Use claude or codex.`);if(g.agent==="claude"&&I==="claude")f(SU(t,$,"configured",g.permissions)),W.exit(
|
|
89
|
+
`,"utf8"),$}function WU(r){return r.agent==="claude"?jb:Xb}async function Y6(r){let{options:i,positionals:v}=nr(r,{valueOptions:["agent","model","effort","permissions","resume","cwd","host"],booleanOptions:["background","wait","json"]}),u=i.wait?!1:!0,n=i.cwd?x.resolve(i.cwd):W.cwd(),$=v.join(" ").trim();if(!$)M('Usage: coder task [options] "<task text>"');let t=mr(n),g=Vb(i,t),I=i.host??(W.env.CLAUDECODE?"claude":"codex");if(I!=="claude"&&I!=="codex")M(`Invalid --host "${I}". Use claude or codex.`);if(g.agent==="claude"&&I==="claude")f(SU(t,$,"configured",g.permissions)),W.exit(0);let o=async(N,S)=>{let G=t.chain[t.chain.indexOf(N)+1];if(!G)M(`${N} failed to start: ${S}`);if(G==="claude"&&I==="claude")f({error:`${N} failed to start: ${S}`,fallback:SU(t,$,"codex-failed",g.permissions)}),W.exit(3);W.stderr.write(`[coder] ${N} failed to start (${S}); falling back to ${G}.
|
|
90
90
|
`),await Y6([$,"--agent",G,"--host",I,"--cwd",n,...i.wait?["--wait"]:[],...i.json?["--json"]:[],...i.permissions?["--permissions",i.permissions]:[]]),W.exit(0)},l=(N)=>{let S="read-only unavailable on this host: the OS sandbox failed to start (Linux/WSL2 needs bubblewrap + socat). Re-dispatch with --permissions auto (or workspace-write) if writes are acceptable, or install the sandbox deps.";if(i.json)f({error:S,code:"read-only-unavailable",detail:N});else W.stderr.write(`[coder] ${S}
|
|
91
91
|
`);W.exit(1)},_=(N)=>g.permissions==="read-only"&&tU.test(N??"");{let N=g.agent==="codex"?dr(n):u$();if(!N.available)await o(g.agent,N.detail)}let b=null;if(i.resume)b=o$(n,i.resume)?.threadId??i.resume;let k=H6(),P=ur(n,k,{status:"queued",kind:"task",agent:g.agent,host:I,prompt:$,model:g.model,effort:g.effort,permissions:g.permissions,resumeThreadId:b,cwd:n,background:u});if(u){let N=ir(n,k),S=C.openSync(x.join(N,"worker.log"),"a"),G=Gb(W.execPath,[K6,"_worker",k,"--cwd",n],{cwd:n,detached:!0,stdio:["ignore",S,S]});G.unref(),C.closeSync(S),ur(n,k,{pid:G.pid??null});let F=Date.now()+15000,q=P,j=null;while(Date.now()<(j??F)){if(q=Cr(n,k)??q,q.status==="failed"||q.status==="completed")break;if(q.threadId&&!j)j=Date.now()+5000;await new Promise((K)=>setTimeout(K,300))}if(q.status==="failed"){let K=x.join(ir(n,k),"result.json"),Nr=C.existsSync(K)?JSON.parse(C.readFileSync(K,"utf8")).error?.message??"":"",E=I$(n,k,5).map((XU)=>XU.message??"").join(`
|
|
92
92
|
`),T=Nr||E;if(_(T))l(T);if(j6.test(T))await o(g.agent,T);f({jobId:k,status:"failed",detail:T}),W.exit(1)}f({jobId:k,status:q.status,threadId:q.threadId??null,startupCheck:q.threadId?"passed":"pending",commands:{status:`coder status ${k}`,result:`coder result ${k}`,steer:`coder steer ${k} "<follow-up>"`,stop:`coder stop ${k}`}});return}ur(n,k,{status:"running",pid:W.pid});try{let N=Cr(n,k),S=await WU(N)(n,N,{echo:!i.json}),G=S.error?.message??"";if(S.status!==0&&_(G))l(G);if(S.status!==0&&j6.test(G))await o(g.agent,G);if(i.json)f({jobId:k,status:S.status===0?"completed":"failed",threadId:S.threadId,finalMessage:S.finalMessage});else W.stdout.write(`${S.finalMessage||"(no final message)"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wular/coder",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Delegating coding-agent runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"version-bump:patch": "node scripts/bump.mjs patch",
|
|
14
14
|
"version-bump:minor": "node scripts/bump.mjs minor",
|
|
15
15
|
"version-bump:major": "node scripts/bump.mjs major",
|
|
16
|
-
"prepublishOnly": "bun run build && bun run typecheck"
|
|
16
|
+
"prepublishOnly": "bun run build && bun run typecheck",
|
|
17
|
+
"npm-publish": "npm publish --access public --tag latest --registry=https://registry.npmjs.org --//registry.npmjs.org/:_authToken=\"$NPM_TOKEN\""
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"bin",
|
|
@@ -18,14 +18,16 @@ If `coder` is not on PATH, install it yourself without asking (`npm install -g @
|
|
|
18
18
|
coder task --wait "<task text>" # Bash run_in_background: true
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
- The harness re-invokes you when the command exits. Exit 0: relay the final message. Exit 1: the engine ran but the turn failed - report it, do not retry or fall back yourself.
|
|
21
|
+
- The harness re-invokes you when the command exits. Exit 0: usually relay the final message, BUT if stdout is a `spawn-claude-subagent` payload (Claude is the configured engine), this is a clean delegation - spawn the subagent as below, do not treat it as a result. Exit 1: the engine ran but the turn failed - report it, do not retry or fall back yourself. Exit 3: Codex failed and handed off to Claude (see below).
|
|
22
22
|
- 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`).
|
|
23
23
|
- Permissions default to auto mode (workspace-write + policy-answered escalations). Pass `--permissions read-only` when the task is read-only; `--permissions workspace-write` to forbid any escalation beyond the project.
|
|
24
24
|
- For long jobs the user may want to manage by id, drop `--wait`: the runtime detaches a worker, does its own startup check, and prints a job id plus status/result/steer commands. Relay that and do not poll.
|
|
25
25
|
|
|
26
|
-
## Claude engine (
|
|
26
|
+
## Claude engine (spawn-claude-subagent payload)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
The runtime prints a `spawn-claude-subagent` payload instead of running Codex when Claude should handle the task. Its `reason` field says why, and the exit code follows from it:
|
|
29
|
+
- `configured` (Claude is the selected engine): a planned delegation, so the runtime **exits 0** - present it as delegation, not an error.
|
|
30
|
+
- `codex-failed` (Codex missing, auth, quota, rate limit): the runtime **exits 3** and wraps the payload under a `fallback` key alongside an `error` string - mention the failure to the user, including any limit-reset time, then spawn the subagent.
|
|
29
31
|
|
|
30
32
|
Spawn one `general-purpose` subagent via the Agent tool, passing the payload's `model` as the Agent tool's model parameter. Its prompt is the original task text verbatim, prefixed with: "NEVER run git write operations (commit, checkout, stash, reset, push, etc.); leave changes uncommitted." Append the same for the payload's `permissions` if not the default `auto`: `read-only` means investigate and report without modifying anything; `workspace-write` means never touch anything outside the workspace.
|
|
31
33
|
|