@wular/coder 0.3.2 → 0.3.4

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 CHANGED
@@ -114,15 +114,16 @@ coder run "<text>" # dispatch a task (--wait to block for th
114
114
  coder list # list recent tasks (running + just stopped)
115
115
  coder result [task-id] # status + final answer (--wait blocks until done)
116
116
  coder task steer <task-id> "<text>" # continue a task with new instructions
117
+ coder task ask <task-id> "<question>" # ask about a task without interrupting it
117
118
  coder task stop <task-id> # interrupt it
118
- coder task stream [task-id] # watch the live progress log
119
+ coder task watch [task-id] # watch the live progress log
119
120
  coder task approve <task-id> <appr-id> # answer an escalated permission (--deny)
120
121
 
121
122
  coder flow run <name|path> --wait # run a flow (--dry-run to preview prompts)
122
123
  coder flow list # recent flow runs
123
124
  coder flow discover # flows runnable here (workspace + global)
124
125
  coder flow result [run-id] # progress and result across the whole wave
125
- coder flow stream [run-id] # watch the wave live (replay + follow)
126
+ coder flow watch [run-id] # watch the wave live (replay + follow)
126
127
  coder flow stop [run-id] # stop a run and its tasks
127
128
  coder flow resume [run-id] # continue a crashed or edited run
128
129
 
@@ -0,0 +1,3 @@
1
+ import e from"node:process";import t from"node:fs";import n from"node:path";import{execFileSync as r,spawn as i,spawnSync as a}from"node:child_process";import o from"node:os";import{fileURLToPath as s}from"node:url";import*as c from"zod/mini";import l from"node:net";import u from"node:readline";function d(e){try{let t=i(`codex`,[`archive`,e],{detached:!0,stdio:`ignore`});t.on(`error`,()=>{}),t.unref()}catch{}}function f(e){let r=n.join(process.env.CODEX_HOME||n.join(o.homedir(),`.codex`),`archived_sessions`);try{return t.readdirSync(r).some(t=>t.endsWith(`-${e}.jsonl`))}catch{return!1}}function p(e){return new Promise(t=>{try{let n=i(`codex`,[`unarchive`,e],{stdio:`ignore`});n.on(`error`,()=>t(!1)),n.on(`close`,e=>t(e===0))}catch{t(!1)}})}function ee(e){return a(`codex`,[`delete`,`--force`,e],{encoding:`utf8`}).status===0}const m=[`completed`,`failed`,`cancelled`],te=[`queued`,`running`],ne=/^[a-z0-9][a-z0-9_-]*$/i;function h(e){return ne.test(e)}function g(e,t){if(!h(e))throw Error(`Invalid ${t} "${e}".`)}function _(){return n.resolve(process.env.CODER_HOME||n.join(o.homedir(),`.coder`))}const v=new Map;function re(e){let t=v.get(e);if(t!==void 0)return t;let n;try{n=r(`git`,[`rev-parse`,`--show-toplevel`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{n=e}return v.set(e,n),n}const y=`global`;function b(e){return n.join(_(),`state`,y)}let x=null;function S(){if(x)return x;let e=n.join(_(),`state`),r=[];try{r=t.readdirSync(e,{withFileTypes:!0})}catch{}return x=r.filter(e=>e.isDirectory()&&e.name!==y).map(t=>n.join(e,t.name)),x}function C(e){return n.join(b(e),`jobs`)}const ie=6e5;function w(e){return n.join(b(e),`archive`)}function T(e,r){g(r,`task id`);let i=n.join(C(e),r);if(t.existsSync(n.join(i,`job.json`)))return i;let a=n.join(w(e),r);if(t.existsSync(n.join(a,`job.json`)))return a;for(let e of S()){let i=n.join(e,`jobs`,r);if(t.existsSync(n.join(i,`job.json`)))return i}return i}function E(e,t){return t.archived?t:O(e,t.id,{archived:!0,archivedAt:new Date().toISOString()})}function D(e,r){let i=E(e,r);r.engine===`codex`&&r.threadId&&d(r.threadId);let a=T(e,r.id),o=n.join(w(e),r.id);if(a!==o)try{t.mkdirSync(w(e),{recursive:!0}),t.renameSync(a,o)}catch{}return i}function ae(){let e=Math.random().toString(36).slice(2,8);return`task-${Date.now().toString(36)}-${e}`}function O(e,r,i){let a=T(e,r);t.mkdirSync(a,{recursive:!0});let o=n.join(a,`job.json`),s={...A(e,r)??{id:r,createdAt:new Date().toISOString(),status:`queued`},...i,updatedAt:new Date().toISOString()};return t.writeFileSync(o,`${JSON.stringify(s,null,2)}\n`,`utf8`),s}function k(e){return!e.engine&&(e.agent===`codex`||e.agent===`claude`)&&(e.engine=e.agent),e}function A(e,r){if(!h(r))return null;let i=n.join(T(e,r),`job.json`);if(!t.existsSync(i))return null;try{return k(JSON.parse(t.readFileSync(i,`utf8`)))}catch{return null}}function oe(e,n){let r=T(e,n);return t.existsSync(r)?(t.rmSync(r,{recursive:!0,force:!0}),!0):!1}function se(e){if(!e)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}const j=new Map;function M(e){let t=j.get(e);if(t&&Date.now()-t.at<5e3)return t.value;let n=ce(e);return j.set(e,{at:Date.now(),value:n}),n}function ce(e){try{let t=r(`ps`,[`-o`,`lstart=`,`-p`,String(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`],env:{...process.env,TZ:Intl.DateTimeFormat().resolvedOptions().timeZone}}).trim(),n=t?Date.parse(t):NaN;return Number.isFinite(n)?n:null}catch{return null}}function le(e,t){if(!se(e))return!1;let n=M(e),r=Date.parse(t.resumedAt??t.createdAt??``);return n===null||!Number.isFinite(r)||n<=r+6e4}function N(e,t){if(t.status!==`running`&&t.status!==`queued`)return t;let n;if(t.pid)n=!le(t.pid,t);else{let e=Date.parse(t.updatedAt??t.createdAt??``);n=Number.isFinite(e)&&Date.now()-e>6e4}return n?O(e,t.id,{status:`failed`,error:`worker exited without finishing`,completedAt:new Date().toISOString()}):t}function P(e,r){let i=[];for(let a of e){let e=[];try{e=t.readdirSync(a)}catch{continue}for(let o of e){if(r.has(o))continue;let e=n.join(a,o,`job.json`);try{let n=k(JSON.parse(t.readFileSync(e,`utf8`)));r.add(o),i.push(n)}catch{}}}return i}const F=(e,t)=>String(t.updatedAt??``).localeCompare(String(e.updatedAt??``));function ue(e){let t=[C(e),...S().map(e=>n.join(e,`jobs`))],r=[];for(let n of P(t,new Set))n.archived?D(e,n):r.push(N(e,n));return r.sort(F)}function I(e,t){let r=t?.migrate??!0,i=new Set,a=P([w(e)],i),o=[C(e),...S().map(e=>n.join(e,`jobs`))];for(let t of P(o,i))t.archived&&a.push(r?D(e,t):t);return a.sort(F)}function de(e,t){let n=[...ue(e),...I(e)].sort(F);if(!t)return n[0]??null;let r=n.find(e=>e.id===t);if(r)return r;let i=n.filter(e=>e.id.startsWith(t));if(i.length===1)return i[0];if(i.length>1)throw Error(`Job reference "${t}" is ambiguous. Use a longer id.`);return null}function fe(e,r){let i=T(e,r);try{t.mkdirSync(i,{recursive:!0}),t.writeFileSync(n.join(i,`heartbeat`),``,`utf8`)}catch{}}function pe(e,r){let i=T(e,r.id),a=Date.parse(r.updatedAt??``)||0;for(let e of[`log.jsonl`,`heartbeat`])try{a=Math.max(a,t.statSync(n.join(i,e)).mtimeMs)}catch{}return a?new Date(a).toISOString():void 0}async function me(e,t,n=400){let r=t;for(;!m.includes(r.status);)await new Promise(e=>setTimeout(e,n)),r=N(e,A(e,r.id)??r);return r}const L=`steer-queue.jsonl`;function he(e,r,i){let a=T(e,r);t.mkdirSync(a,{recursive:!0}),t.appendFileSync(n.join(a,L),`${JSON.stringify({at:new Date().toISOString(),text:i})}\n`,`utf8`)}function ge(e,r){let i=T(e,r),a=n.join(i,L),o=n.join(i,`steer-claim-${process.pid}-${Date.now()}.tmp`);try{t.renameSync(a,o)}catch{return[]}try{return t.readFileSync(o,`utf8`).split(/\r?\n/).filter(Boolean).map(e=>{try{return String(JSON.parse(e).text??``)}catch{return``}}).filter(Boolean)}finally{try{t.unlinkSync(o)}catch{}}}function _e(e,r,i){let a=T(e,r);t.mkdirSync(a,{recursive:!0}),t.appendFileSync(n.join(a,`log.jsonl`),`${JSON.stringify({at:new Date().toISOString(),...i})}\n`,`utf8`)}function ve(e,r){let i=n.join(T(e,r),`results.jsonl`);return t.existsSync(i)?t.readFileSync(i,`utf8`).split(/\r?\n/).filter(Boolean).flatMap(e=>{try{return[JSON.parse(e)]}catch{return[]}}):[]}function ye(e,r,i=40){let a=n.join(T(e,r),`log.jsonl`);return t.existsSync(a)?t.readFileSync(a,`utf8`).split(/\r?\n/).filter(Boolean).slice(-i).map(e=>{try{return JSON.parse(e)}catch{return{message:e}}}):[]}function be(){let e=n.dirname(s(import.meta.url));for(let r=0;r<10;r++){let r=n.join(e,`package.json`);try{if(JSON.parse(t.readFileSync(r,`utf8`)).name===`@wular/coder`)return e}catch{}let i=n.dirname(e);if(i===e)break;e=i}return n.resolve(n.dirname(s(import.meta.url)),`..`)}const R=be(),xe=t.existsSync(n.join(R,`dist/cli.js`))?n.join(R,`dist/cli.js`):n.join(R,`src/cli.ts`);function z(){try{return JSON.parse(t.readFileSync(n.join(R,`package.json`),`utf8`)).version??`unknown`}catch{return`unknown`}}function Se(e){try{return JSON.parse(t.readFileSync(e,`utf8`)).version??null}catch{return null}}function Ce(){return R}const B=c.optional(c.boolean()),V=c.optional(c.string()),we={cwd:V,json:B},Te=c.optional(c.union([c.literal(`all`),c.coerce.number().check(c.int(),c.positive())],{error:`expected a positive integer or "all"`})),Ee=c.optional(c.union([c.literal(`all`),c.coerce.number().check(c.int(),c.nonnegative())],{error:`expected a number or "all"`}));function H(e){let t=e.def;for(;t;){if(t.type===`boolean`)return!0;let e=t.innerType??t.in;t=e?e.def:void 0}return!1}function De(e,t){let n=t.shape,r={},i=[],a=!1,o=(e,t,i,a)=>{let o=n[t],s=a?`-`:`--`;if(!o)throw Error(`Unknown option ${s}${e} (use -- to pass literal text starting with -)`);if(H(o))return r[t]=i===void 0||i!==`false`,0;if(i===void 0)throw Error(`Missing value for ${s}${e}`);return r[t]=i,1};for(let t=0;t<e.length;t+=1){let r=e[t];if(a){i.push(r);continue}if(r===`--`){a=!0;continue}if(!r.startsWith(`-`)||r===`-`){i.push(r);continue}if(r.startsWith(`--`)){let[i,a]=r.slice(2).split(`=`,2);a===void 0&&n[i]&&!H(n[i])?t+=o(i,i,e[t+1],!1):o(i,i,a,!1);continue}let s=r.slice(1);n[s]&&!H(n[s])?t+=o(s,s,e[t+1],!0):o(s,s,void 0,!0)}let s=t.safeParse(r);if(!s.success){let e=s.error.issues[0],t=String(e.path[0]??``),n=r[t];throw Error(n===void 0?`Missing required --${t}.`:`Invalid --${t} value ${JSON.stringify(n)}: ${e.message}`)}return{options:s.data,positionals:i}}function Oe(e){return String(e??``).replace(/[^A-Za-z0-9._-]/g,`-`).replace(/^-+|-+$/g,``)}function ke(t,r=e.platform){return r===`win32`?`pipe:\\\\.\\pipe\\${Oe(`${n.win32.basename(t)}-codex-app-server`)}`:`unix:${n.join(t,`broker.sock`)}`}function U(e){if(typeof e!=`string`||e.length===0)throw Error(`Missing broker endpoint.`);if(e.startsWith(`pipe:`)){let t=e.slice(5);if(!t)throw Error(`Broker pipe endpoint is missing its path.`);return{kind:`pipe`,path:t}}if(e.startsWith(`unix:`)){let t=e.slice(5);if(!t)throw Error(`Broker Unix socket endpoint is missing its path.`);return{kind:`unix`,path:t}}throw Error(`Unsupported broker endpoint: ${e}`)}function Ae(e=`coder-`){return t.mkdtempSync(n.join(o.tmpdir(),e))}function je(e){let t=U(e);return l.createConnection({path:t.path})}async function W(e,t=2e3){let n=Date.now();for(;Date.now()-n<t;){if(await new Promise(t=>{let n=je(e);n.on(`connect`,()=>{n.end(),t(!0)}),n.on(`error`,()=>t(!1))}))return!0;await new Promise(e=>setTimeout(e,50))}return!1}function Me({scriptPath:n,cwd:r,endpoint:a,pidFile:o,logFile:s,env:c=e.env}){let l=t.openSync(s,`a`),u=i(e.execPath,[n,`serve`,`--endpoint`,a,`--cwd`,r,`--pid-file`,o],{cwd:r,env:c,detached:!0,stdio:[`ignore`,l,l]});return u.unref(),t.closeSync(l),u}function Ne(){let e=[new URL(`./lib/broker.js`,import.meta.url),new URL(`./broker.js`,import.meta.url)];for(let n of e){let e=s(n);if(t.existsSync(e))return e}throw Error("Coder broker script not found next to the runtime. Rebuild with `bun run build`.")}function G(e){return n.join(b(e),`broker.json`)}function K(e){let n=G(e);if(!t.existsSync(n))return null;try{return JSON.parse(t.readFileSync(n,`utf8`))}catch{return null}}function Pe(e,n){let r=b(e);t.mkdirSync(r,{recursive:!0}),t.writeFileSync(G(e),`${JSON.stringify(n,null,2)}\n`,`utf8`)}function Fe(e){let n=G(e);t.existsSync(n)&&t.unlinkSync(n)}async function Ie(e){if(!e)return!1;try{return await W(e,150)}catch{return!1}}async function Le(t,r={}){let i=r.scriptPath??Ne(),a=z(),o=K(t),s=o?.version===a&&o?.scriptPath===i;if(o&&s&&await Ie(o.endpoint))return o;o&&(q({endpoint:o.endpoint??null,pidFile:o.pidFile??null,logFile:o.logFile??null,sessionDir:o.sessionDir??null,pid:o.pid??null,killProcess:r.killProcess??null}),Fe(t));let c=Ae(),l=(r.createBrokerEndpoint??ke)(c,r.platform),u=n.join(c,`broker.pid`),d=n.join(c,`broker.log`),f=Me({scriptPath:i,cwd:t,endpoint:l,pidFile:u,logFile:d,env:r.env??e.env});if(!await W(l,r.timeoutMs??2e3))return q({endpoint:l,pidFile:u,logFile:d,sessionDir:c,pid:f.pid??null,killProcess:r.killProcess??null}),null;let p={endpoint:l,pidFile:u,logFile:d,sessionDir:c,pid:f.pid??null,version:a,scriptPath:i};return Pe(t,p),p}function q({endpoint:e=null,pidFile:r,logFile:i,sessionDir:a=null,pid:o=null,killProcess:s=null}){if(Number.isFinite(o)&&s)try{s(o)}catch{}if(r&&t.existsSync(r)&&t.unlinkSync(r),i&&t.existsSync(i)&&t.unlinkSync(i),e)try{let n=U(e);n.kind===`unix`&&t.existsSync(n.path)&&t.unlinkSync(n.path)}catch{}let c=a??(r?n.dirname(r):i?n.dirname(i):null);if(c&&t.existsSync(c))try{t.rmdirSync(c)}catch{}}function J(t,n=[],r={}){let i=a(t,n,{cwd:r.cwd,env:r.env,encoding:`utf8`,input:r.input,maxBuffer:r.maxBuffer,stdio:r.stdio??`pipe`,shell:e.platform===`win32`?e.env.SHELL||!0:!1,windowsHide:!0});return{command:t,args:n,status:i.status??0,signal:i.signal??null,stdout:i.stdout??``,stderr:i.stderr??``,error:i.error??null}}function Re(e,t=[`--version`],n={}){let r=J(e,t,n);return r.error&&r.error.code===`ENOENT`?{available:!1,detail:`not found`}:r.error?{available:!1,detail:r.error.message}:r.status===0?{available:!0,detail:r.stdout.trim()||r.stderr.trim()||`ok`}:{available:!1,detail:r.stderr.trim()||r.stdout.trim()||`exit ${r.status}`}}function ze(e){return/not found|no running instance|cannot find|does not exist|no such process/i.test(e)}function Be(t,n={}){if(!Number.isFinite(t))return{attempted:!1,delivered:!1,method:null};let r=t,i=n.platform??e.platform,a=n.runCommandImpl??J,o=n.killImpl??e.kill.bind(e);if(i===`win32`){let e=a(`taskkill`,[`/PID`,String(r),`/T`,`/F`],{cwd:n.cwd,env:n.env});if(!e.error&&e.status===0)return{attempted:!0,delivered:!0,method:`taskkill`,result:e};let t=`${e.stderr}\n${e.stdout}`.trim();if(!e.error&&ze(t))return{attempted:!0,delivered:!1,method:`taskkill`,result:e};if(e.error?.code===`ENOENT`)try{return o(r),{attempted:!0,delivered:!0,method:`kill`}}catch(e){if(e?.code===`ESRCH`)return{attempted:!0,delivered:!1,method:`kill`};throw e}throw e.error?e.error:Error(Ve(e))}try{return o(-r,`SIGTERM`),{attempted:!0,delivered:!0,method:`process-group`}}catch(e){if(e?.code!==`ESRCH`)try{return o(r,`SIGTERM`),{attempted:!0,delivered:!0,method:`process`}}catch(e){if(e?.code===`ESRCH`)return{attempted:!0,delivered:!1,method:`process`};throw e}return{attempted:!0,delivered:!1,method:`process-group`}}}function Ve(e){let t=[`${e.command} ${e.args.join(` `)}`.trim()];e.signal?t.push(`signal=${e.signal}`):t.push(`exit=${e.status}`);let n=(e.stderr||``).trim(),r=(e.stdout||``).trim();return n?t.push(n):r&&t.push(r),t.join(`: `)}const He=`CODER_APP_SERVER_ENDPOINT`,Ue=-32001;let Y;function We(){if(Y===void 0){let e=J(`codex`,[`--version`]),t=/(\d+\.\d+\.\d+(?:-[\w.]+)?)/.exec(`${e.stdout} ${e.stderr}`);Y=t?t[1]:`0.144.1`}return Y}function X(){return{title:`Coder`,name:`coder`,version:We()}}const Z={experimentalApi:!1,requestAttestation:!1,optOutNotificationMethods:[`item/agentMessage/delta`,`item/reasoning/summaryTextDelta`,`item/reasoning/summaryPartAdded`,`item/reasoning/textDelta`]};function Q(e,t,n){return n===void 0?{code:e,message:t}:{code:e,message:t,data:n}}function $(e,t){let n=Error(e);return n.data=t,t?.code!==void 0&&(n.rpcCode=t.code),n}var Ge=class{cwd;options;pending;nextId;stderr;closed;exitError;notificationHandler;serverRequestHandler;lineBuffer;transport;exitPromise;exitResolved;resolveExit;handleServerRequest;constructor(e,t={}){this.cwd=e,this.options=t,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=e=>this.defaultHandleServerRequest(e),this.exitPromise=new Promise(e=>{this.resolveExit=e})}setNotificationHandler(e){this.notificationHandler=e}setServerRequestHandler(e){this.serverRequestHandler=e}request(e,t){if(this.closed)throw Error(`codex app-server client is closed.`);let n=this.nextId;return this.nextId+=1,new Promise((r,i)=>{this.pending.set(n,{resolve:r,reject:i,method:e}),this.sendMessage({id:n,method:e,params:t})})}notify(e,t={}){this.closed||this.sendMessage({method:e,params:t})}handleChunk(e){this.lineBuffer+=e;let t=this.lineBuffer.indexOf(`
2
+ `);for(;t!==-1;){let e=this.lineBuffer.slice(0,t);this.lineBuffer=this.lineBuffer.slice(t+1),this.handleLine(e),t=this.lineBuffer.indexOf(`
3
+ `)}}handleLine(e){if(!e.trim())return;let t;try{t=JSON.parse(e)}catch(t){this.handleExit($(`Failed to parse codex app-server JSONL: ${t instanceof Error?t.message:String(t)}`,{line:e}));return}if(t.id!==void 0&&t.method){this.handleServerRequest(t);return}if(t.id!==void 0){let e=this.pending.get(t.id);if(!e)return;this.pending.delete(t.id),t.error?e.reject($(t.error.message??`codex app-server ${e.method} failed.`,t.error)):e.resolve(t.result??{});return}t.method&&this.notificationHandler&&this.notificationHandler(t)}defaultHandleServerRequest(e){let t=this.serverRequestHandler;if(!t){this.sendMessage({id:e.id,error:Q(-32601,`Unsupported server request: ${e.method}`)});return}Promise.resolve().then(()=>t(e.method,e.params??{})).then(t=>{this.sendMessage({id:e.id,result:t??{}})}).catch(t=>{this.sendMessage({id:e.id,error:Q(-32e3,t instanceof Error?t.message:String(t))})})}handleExit(e){if(!this.exitResolved){this.exitResolved=!0,this.exitError=e??null;for(let e of this.pending.values())e.reject(this.exitError??Error(`codex app-server connection closed.`));this.pending.clear(),this.resolveExit(void 0)}}sendMessage(e){throw Error(`sendMessage must be implemented by subclasses.`)}},Ke=class extends Ge{proc;readline;constructor(e,t={}){super(e,t),this.transport=`direct`}async initialize(){this.proc=i(`codex`,[`-c`,`sandbox_workspace_write.network_access=false`,`app-server`,`--disable`,`plugins`],{cwd:this.cwd,env:this.options.env??e.env,stdio:[`pipe`,`pipe`,`pipe`],shell:e.platform===`win32`?e.env.SHELL||!0:!1,windowsHide:!0});let t=this.proc.stdout,n=this.proc.stderr;if(!t||!n)throw Error(`codex app-server did not expose stdio streams.`);t.setEncoding(`utf8`),n.setEncoding(`utf8`),n.on(`data`,e=>{this.stderr+=e}),this.proc.on(`error`,e=>{this.handleExit(e)}),this.proc.on(`exit`,(e,t)=>{let n=this.stderr.trim(),r=e===0?null:$(`codex app-server exited unexpectedly (${t?`signal ${t}`:`exit ${e}`}).${n?`\n${n}`:``}`);this.handleExit(r)}),this.readline=u.createInterface({input:t}),this.readline.on(`line`,e=>{this.handleLine(e)}),await this.request(`initialize`,{clientInfo:this.options.clientInfo??X(),capabilities:this.options.capabilities??Z}),this.notify(`initialized`,{})}async close(){if(this.closed){await this.exitPromise;return}this.closed=!0,this.readline&&this.readline.close(),this.proc&&!this.proc.killed&&(this.proc.stdin?.end(),setTimeout(()=>{if(this.proc&&!this.proc.killed&&this.proc.exitCode===null)if(e.platform===`win32`)try{Be(this.proc.pid)}catch{}else this.proc.kill(`SIGTERM`)},50).unref?.()),await this.exitPromise}sendMessage(e){let t=`${JSON.stringify(e)}\n`,n=this.proc?.stdin;if(!n)throw Error(`codex app-server stdin is not available.`);n.write(t)}},qe=class extends Ge{endpoint;socket;constructor(e,t={}){super(e,t),this.transport=`broker`,this.endpoint=t.brokerEndpoint}async initialize(){await new Promise((e,t)=>{let n=U(this.endpoint);this.socket=l.createConnection({path:n.path}),this.socket.setEncoding(`utf8`),this.socket.on(`connect`,e),this.socket.on(`data`,e=>{this.handleChunk(e)}),this.socket.on(`error`,e=>{this.exitResolved||t(e),this.handleExit(e)}),this.socket.on(`close`,()=>{this.handleExit(this.exitError)})}),await this.request(`initialize`,{clientInfo:this.options.clientInfo??X(),capabilities:this.options.capabilities??Z}),this.notify(`initialized`,{})}async close(){if(this.closed){await this.exitPromise;return}this.closed=!0,this.socket&&this.socket.end(),await this.exitPromise}sendMessage(e){let t=`${JSON.stringify(e)}\n`,n=this.socket;if(!n)throw Error(`codex app-server broker connection is not connected.`);n.write(t)}},Je=class{static async connect(t,n={}){let r=null;n.disableBroker||(r=n.brokerEndpoint??n.env?.CODER_APP_SERVER_ENDPOINT??e.env.CODER_APP_SERVER_ENDPOINT??null,!r&&n.reuseExistingBroker&&(r=K(t)?.endpoint??null),!r&&!n.reuseExistingBroker&&(r=(await Le(t,{env:n.env}))?.endpoint??null));let i=r?new qe(t,{...n,brokerEndpoint:r}):new Ke(t,n);return await i.initialize(),i}};export{M as A,O as B,de as C,I as D,pe as E,_ as F,p as G,m as H,T as I,re as L,ye as M,ve as N,ue as O,N as P,fe as R,he as S,h as T,ee as U,te as V,f as W,_e as _,U as a,ge as b,Te as c,Ee as d,xe as f,ie as g,Ce as h,Re as i,A as j,E as k,De as l,z as m,He as n,we as o,Se as p,Je as r,B as s,Ue as t,V as u,D as v,ae as w,oe as x,g as y,me as z};
package/dist/cli.d.ts CHANGED
@@ -1 +1 @@
1
- export {};
1
+ export {}
package/dist/cli.js CHANGED
@@ -1,66 +1,80 @@
1
1
  #!/usr/bin/env node
2
- import{B as e,E as t,F as n,M as r,V as i,c as a,d as o,f as s,l as c,m as l,o as u,s as d,u as f}from"./app-server-Dwd7IcQH.js";import{$t as p,A as m,Bt as h,D as g,Ft as _,Gt as ee,Ht as v,It as y,Jt as b,Kt as x,Lt as te,M as S,Nt as ne,O as C,Ot as w,Qt as T,R as re,Rt as E,S as D,T as O,Ut as ie,Vt as ae,Xt as oe,Yt as k,Zt as A,_ as se,a as ce,b as le,d as ue,en as de,g as j,h as fe,j as pe,jt as me,kt as he,l as M,n as ge,nn as _e,p as ve,qt as N,r as ye,rn as be,s as xe,t as Se,tn as Ce,u as we,v as P,vt as Te,w as Ee,x as De,xt as Oe,y as ke,yt as Ae,zt as je}from"./runtime-DRtQOCSz.js";import{D as Me,E as Ne,S as Pe,a as Fe,h as Ie,p as F,r as Le,t as Re,v as ze,w as I,x as Be}from"./upgrade-BNwIk8zT.js";import L from"node:process";import R from"node:fs";import z from"node:path";import{spawn as Ve,spawnSync as He}from"node:child_process";import Ue from"node:os";import*as B from"zod/mini";const We=[[`--wait`,`run in the foreground and block until the answer is ready`],[`--agent <codex|claude|custom>`,`engine to use; custom runs your configured custom models (default: first in the chain)`],[`--model <alias|slug>`,`mini/luna/terra/sol (codex) · haiku/sonnet/opus/fable (claude) · a custom model (coder model list)`],[`--effort <low|medium|high>`,`reasoning effort`],[`--permissions <mode>`,`read-only · workspace-write · auto (default: auto)`],[`--resume <task-id>`,`continue that task's thread instead of a fresh run`],[`--json`,`machine-readable JSON output`]],V=[`--cwd <dir>`,`workspace directory (default: current)`],H=[`--json`,`JSON output`],Ge=[{sub:`run`,usage:`run "<text>"`,blurb:`run a task (background; --wait blocks)`,alias:`run`},{sub:`list`,usage:`list`,blurb:`list recent tasks (running + just stopped)`,alias:`list`},{sub:`result`,usage:`result [task-id]`,blurb:`status + final answer (--wait blocks)`,alias:`result`},{sub:`stream`,usage:`stream [task-id]`,blurb:`watch a task live (progress log)`,alias:`stream`},{sub:`steer`,usage:`steer <task-id> "<follow-up>"`,blurb:`continue a task's thread`},{sub:`stop`,usage:`stop <task-id>`,blurb:`interrupt a running task`},{sub:`archive`,usage:`archive <task-id>`,blurb:`archive a session (or --all-stopped)`},{sub:`delete`,usage:`delete <task-id>`,blurb:`delete a session (or --all-archived)`},{sub:`approvals`,usage:`approvals <task-id>`,blurb:`list escalated approvals`},{sub:`approve`,usage:`approve <task-id> <id>`,blurb:`answer an escalated permission`}],U={"task run":{list:[`task run "<text>"`,`run a coding task (background; --wait blocks)`],usage:`coder task run "<task text>"`,summary:`Dispatch a coding task to the configured engine. Backgrounds by default and
2
+ import{B as e,E as t,H as n,I as r,L as i,M as a,N as o,O as s,R as c,V as l,_ as u,b as d,c as f,d as p,f as m,j as h,l as g,m as _,o as v,s as y,u as b}from"./app-server-bHl6RBZ2.js";import{$t as x,A as ee,B as S,Bt as C,Ct as te,D as w,Et as ne,F as re,Ft as T,Gt as E,Ht as D,I as O,Kt as ie,L as ae,Lt as k,M as A,Mt as oe,N as se,Nt as ce,O as le,Qt as j,R as ue,S as de,St as fe,T as pe,Tt as me,Ut as he,Vt as ge,Wt as M,Xt as _e,Y as ve,Yt as ye,Zt as N,_ as be,_t as xe,a as Se,an as Ce,at as we,b as Te,bt as Ee,d as De,dt as Oe,en as ke,g as P,h as Ae,in as je,j as Me,kt as Ne,l as Pe,lt as Fe,n as Ie,nn as Le,on as Re,ot as ze,p as Be,qt as Ve,r as He,rn as F,s as Ue,sn as We,t as Ge,tn as I,tt as L,u as Ke,ut as qe,v as R,w as Je,wt as Ye,x as Xe,xt as Ze,y as Qe,yt as $e,zt as z}from"./runtime-DVrs6VXX.js";import{C as et,E as B,O as tt,a as nt,h as rt,k as it,p as at,r as ot,t as st,v as ct,w as lt,x as ut}from"./upgrade-Dgk4Gl4g.js";import V from"node:process";import H from"node:fs";import U from"node:path";import{spawn as dt,spawnSync as ft}from"node:child_process";import pt from"node:os";import*as W from"zod/mini";import mt from"node:readline";const ht=[[`--wait`,`run in the foreground and block until the answer is ready`],[`--agent <codex|claude|custom>`,`engine to use; custom runs your configured custom models (default: first in the chain)`],[`--model <alias|slug>`,`mini/luna/terra/sol (codex) · haiku/sonnet/opus/fable (claude) · a custom model (coder model list)`],[`--effort <low|medium|high>`,`reasoning effort`],[`--permissions <mode>`,`read-only · workspace-write · auto (default: auto)`],[`--resume <task-id>`,`continue that task's thread instead of a fresh run`],[`--json`,`machine-readable JSON output`]],G=[`--cwd <dir>`,`workspace directory (default: current)`],K=[`--json`,`JSON output`],gt=[{sub:`run`,usage:`run "<text>"`,blurb:`run a task (background; --wait blocks)`,alias:`run`},{sub:`list`,usage:`list`,blurb:`list recent tasks (running + just stopped)`,alias:`list`},{sub:`result`,usage:`result [task-id]`,blurb:`status + final answer (--wait blocks)`,alias:`result`},{sub:`watch`,usage:`watch [task-id]`,blurb:`watch a task live (progress log)`,alias:`watch`},{sub:`steer`,usage:`steer <task-id> "<follow-up>"`,blurb:`continue a task's thread`},{sub:`ask`,usage:`ask <task-id> "<question>"`,blurb:`ask about a task without interrupting it`},{sub:`stop`,usage:`stop <task-id>`,blurb:`interrupt a running task`},{sub:`archive`,usage:`archive <task-id>`,blurb:`archive a session (or --all-stopped)`},{sub:`delete`,usage:`delete <task-id>`,blurb:`delete a session (or --all-archived)`},{sub:`approvals`,usage:`approvals [task-id]`,blurb:`pending approvals (all tasks, or one)`},{sub:`approve`,usage:`approve <id>`,blurb:`answer an escalated permission`}],q={"task run":{list:[`task run "<text>"`,`run a coding task (background; --wait blocks)`],usage:`coder task run "<task text>"`,summary:`Dispatch a coding task to the configured engine. Backgrounds by default and
3
3
  prints a task id; --wait runs in the foreground and prints the answer.
4
- Shortcut: \`coder run "<text>"\`.`,flags:[[`--name <name>`,`label the task (shown in list/result)`],[`--system <text>`,`standing instructions prepended to the task (kept out of prompt previews)`],...We,V],examples:[[`coder run "add a /health endpoint"`,`dispatch in the background, print a task id`],[`coder run --wait "fix the failing test"`,`block until done, print the answer`],[`coder task run --model mini --system "tests live in test/, don't touch anything outside of it" "rename foo to bar"`,`pick an engine via its model alias; --system adds standing instructions`]],seeAlso:`task result · task steer · task stop · task stream`},"task list":{list:[`task list [--running|--stopped|--archived]`,`list recent tasks (running + just stopped)`],usage:`coder task list [--running] [--stopped] [--archived [--limit N]]`,summary:`List recent tasks across all workspaces, most recent first: running tasks plus
4
+ Shortcut: \`coder run "<text>"\`.`,flags:[[`--name <name>`,`label the task (shown in list/result)`],[`--system <text>`,`standing instructions prepended to the task (kept out of prompt previews)`],...ht,G],examples:[[`coder run "add a /health endpoint"`,`dispatch in the background, print a task id`],[`coder result <task-id> --wait`,`then block until it finishes and print the answer`],[`coder run --wait "fix the failing test"`,`or block on the run itself`],[`coder task run --model mini --system "tests live in test/, don't touch anything outside of it" "rename foo to bar"`,`pick an engine via its model alias; --system adds standing instructions`]],seeAlso:`task result · task steer · task stop · task watch`},"task list":{list:[`task list [--running|--stopped|--archived]`,`list recent tasks (running + just stopped)`],usage:`coder task list [--running] [--stopped] [--archived [--limit N]]`,summary:`List recent tasks across all workspaces, most recent first: running tasks plus
5
5
  ones stopped within the last 10 minutes. Older stopped tasks auto-archive and
6
- move to --archived. Shortcut: \`coder list\`.`,flags:[[`--running`,`show only running tasks`],[`--stopped`,`show only recently stopped tasks (not yet archived)`],[`--archived`,`show only archived tasks (auto-archived or via task archive)`],[`--limit <n|all>`,`show at most n tasks (default all)`],[`--dir <dir>`,`only tasks launched in that workspace`],H],seeAlso:`task result · task archive · task delete`},"task result":{list:[`task result [task-id]`,`status + final answer of a task`],usage:`coder task result [task-id]`,summary:`Show a task's status and its final answer (result pending while it runs), plus
6
+ move to --archived. Shortcut: \`coder list\`.`,flags:[[`--running`,`show only running tasks`],[`--stopped`,`show only recently stopped tasks (not yet archived)`],[`--archived`,`show only archived tasks (auto-archived or via task archive)`],[`--limit <n|all>`,`show at most n tasks (default all)`],[`--dir <dir>`,`only tasks launched in that workspace`],K],seeAlso:`task result · task archive · task delete`},"task result":{list:[`task result [task-id]`,`status + final answer of a task`],usage:`coder task result [task-id]`,summary:`Show a task's status and its final answer (result pending while it runs), plus
7
7
  any pending approvals. --wait blocks until it finishes, then prints. --tail <n>
8
8
  includes the last n progress-log steps (--tail all for the whole transcript).
9
- Defaults to the most recent task. Shortcut: \`coder result\`.`,flags:[[`--wait`,`block until the task finishes, then print`],[`--tail <n|all>`,`include the last n progress-log steps (default: 0, final result only)`],H,V],seeAlso:`task list · task steer · task stream`},"task stream":{list:[`task stream [task-id]`,`watch a task live (progress log)`],usage:`coder task stream [task-id]`,summary:`Watch a running task's progress log live (for you/debugging), then print its
9
+ Defaults to the most recent task. Shortcut: \`coder result\`.`,flags:[[`--wait`,`block until the task finishes, then print`],[`--turns`,`every turn's answer (a steered task accretes turns)`],[`--tail <n|all>`,`include the last n progress-log steps (default: 0, final result only)`],K,G],examples:[[`coder result <task-id> --wait`,`block until the task finishes, print the answer`],[`coder result <task-id> --turns`,`every turn's answer for a steered task`]],seeAlso:`task list · task steer · task watch`},"task watch":{list:[`task watch [task-id]`,`watch a task live (progress log)`],usage:`coder task watch [task-id]`,summary:`Watch a running task's progress log live (for you/debugging), then print its
10
10
  final answer. Replays the last line first so the current step is visible;
11
11
  --tail <n> replays the last n lines (--tail all for the whole transcript).
12
12
  Blocks until it finishes; exits 0 on success, 1 otherwise. For the answer
13
- alone, prefer \`coder result\`.`,flags:[[`--tail <n|all>`,`replay the last n log lines first (default: 1)`],[`--trim <n|none>`,`cap each step at n chars, text and JSON alike (default: 128)`],[`--json`,`emit each log entry as a JSON line, then the result`],V],examples:[[`coder stream`,`follow the most recent task to completion`]],seeAlso:`task result · task run`},"task steer":{list:[`task steer <task-id> "<follow-up>"`,`continue a task's thread`],usage:`coder task steer <task-id> "<follow-up instructions>" [--wait]`,summary:`Continue a finished task's thread with new instructions. Reuses the task's
14
- engine, model, and permissions unless you override them.`,flags:[[`--wait`,`run in the foreground and block until the answer is ready`],[`--model <alias|slug>`,`override the task's model for this follow-up`],[`--effort <low|medium|high>`,`override the task's reasoning effort`],[`--permissions <mode>`,`read-only · workspace-write · auto`],V],examples:[[`coder task steer task-abc "now add tests"`,`continue that task with a follow-up`]],seeAlso:`task run · task stop`},"task stop":{list:[`task stop <task-id>`,`interrupt a running task`],usage:`coder task stop <task-id>`,summary:`Interrupt a running task and mark it cancelled.`,flags:[H,V],seeAlso:`task result · task steer`},"task archive":{list:[`task archive <task-id> | --all-stopped`,`hide a task (or all stopped) from the list`],usage:`coder task archive <task-id> | coder task archive --all-stopped`,summary:`Archive a task session so it drops out of the default list (see it again with
13
+ alone, prefer \`coder result\`. Alias: stream.`,flags:[[`--tail <n|all>`,`replay the last n log lines first (default: 1)`],[`--trim <n|none>`,`cap each step at n chars, text and JSON alike (default: 128)`],[`--json`,`emit each log entry as a JSON line, then the result`],G],examples:[[`coder watch`,`follow the most recent task to completion`]],seeAlso:`task result · task run`},"task ask":{list:[`task ask <task-id> "<question>"`,`ask about a task without interrupting it`],usage:`coder task ask <task-id> "<question>"`,summary:`Answer a question ABOUT a task without touching it: a read-only sidecar reads
14
+ the task's progress log, result, and workspace and answers; the task never
15
+ sees the question and its thread is not steered. Works whether the task is
16
+ running or stopped. To change what the task does, use \`coder task steer\`.`,flags:[[`--model <alias|slug>`,`sidecar model (default: the task's own)`],[`--effort <low|medium|high>`,`sidecar reasoning effort`],K,G],examples:[[`coder task ask task-abc "what approach did you take and why?"`,`probe a decision without derailing the task`]],seeAlso:`task steer · task result · task watch`},"task steer":{list:[`task steer <task-id> "<follow-up>"`,`continue a task's thread`],usage:`coder task steer <task-id> "<follow-up instructions>" [--wait]`,summary:`Continue a task's thread with new instructions: injected into the live turn
17
+ (codex), queued for after it (claude), or — for a stopped task — resumed on the
18
+ same task id. Reuses the task's engine, model, and permissions unless overridden.`,flags:[[`--wait`,`run in the foreground and block until the answer is ready`],[`--model <alias|slug>`,`override the task's model for this follow-up`],[`--effort <low|medium|high>`,`override the task's reasoning effort`],[`--permissions <mode>`,`read-only · workspace-write · auto`],G],examples:[[`coder task steer task-abc "now add tests"`,`continue that task with a follow-up`]],seeAlso:`task run · task stop`},"task stop":{list:[`task stop <task-id>`,`interrupt a running task`],usage:`coder task stop <task-id>`,summary:`Interrupt a running task and mark it cancelled.`,flags:[K,G],seeAlso:`task result · task steer`},"task archive":{list:[`task archive <task-id> | --all-stopped`,`hide a task (or all stopped) from the list`],usage:`coder task archive <task-id> | coder task archive --all-stopped`,summary:`Archive a task session so it drops out of the default list (see it again with
15
19
  \`coder task list --archived [--limit N]\`). Pass --all-stopped to archive every
16
- finished task.`,flags:[[`--all-stopped`,`archive every stopped (finished) task`],H,V],seeAlso:`task list · task delete`},"task delete":{list:[`task delete <task-id> | --all-archived`,`delete a task session (or all archived)`],usage:`coder task delete <task-id> | coder task delete --all-archived`,summary:`Delete a task's session from disk. This is permanent. Pass --all-archived to
17
- delete every archived task at once. A running task must be stopped first.`,flags:[[`--all-archived`,`delete every archived task`],H,V],seeAlso:`task archive · task stop`},"task approvals":{list:[`task approvals <task-id>`,`list escalated approvals`],usage:`coder task approvals <task-id>`,summary:`List permission escalations a task has raised, and how each was answered.`,flags:[H,V],seeAlso:`task approve`},"task approve":{list:[`task approve <task-id> <id> [--deny]`,`answer an escalated permission`],usage:`coder task approve <task-id> <approval-id> [--deny]`,summary:`Answer an escalated permission request. Accepts by default; --deny rejects it.`,flags:[[`--deny`,`reject the request instead of accepting`],H,V],seeAlso:`task approvals · task result`},"flow run":{list:[`flow run <name|path> [--args | key=value...]`,`run a flow (orchestrate a wave of tasks)`],usage:`coder flow run <name|path> [--args '<json>' | key=value...] [--wait] [--concurrency N] [--max-tasks N] [--json] [--dry-run]`,summary:`Run a flow: a TypeScript file that orchestrates many coder tasks with gates,
20
+ finished task.`,flags:[[`--all-stopped`,`archive every stopped (finished) task`],K,G],seeAlso:`task list · task delete`},"task delete":{list:[`task delete <task-id> | --all-archived`,`delete a task session (or all archived)`],usage:`coder task delete <task-id> | coder task delete --all-archived`,summary:`Delete a task's session from disk. This is permanent. Pass --all-archived to
21
+ delete every archived task at once. A running task must be stopped first.`,flags:[[`--all-archived`,`delete every archived task`],K,G],seeAlso:`task archive · task stop`},"task approvals":{list:[`task approvals [task-id]`,`pending approvals (all tasks, or one)`],usage:`coder task approvals [task-id]`,summary:"Without a task id: pending approvals across all tasks. With one: that task's\npermission escalations and how each was answered. Shortcut: `coder approvals`.",flags:[K,G],seeAlso:`task approve`},"task approve":{list:[`task approve <id> [--deny]`,`answer an escalated permission`],usage:`coder task approve [task-id] <approval-id> [--deny]`,summary:"Answer an escalated permission request. Accepts by default; --deny rejects it.\nApproval ids are unique, so the task id is optional. Shortcut: `coder approve`.",flags:[[`--deny`,`reject the request instead of accepting`],K,G],seeAlso:`task approvals · task result`},"flow run":{list:[`flow run <name|path> [--args | key=value...]`,`run a flow (orchestrate a wave of tasks)`],usage:`coder flow run <name|path> [--args '<json>' | key=value...] [--wait] [--concurrency N] [--max-tasks N] [--json] [--dry-run]`,summary:`Run a flow: a TypeScript file that orchestrates many coder tasks with gates,
18
22
  journaling, and resume. Prints the run id and orchestrates in the background;
19
23
  --wait follows the run in the foreground with live progress (Ctrl-C detaches;
20
- it keeps running), and \`coder flow stream\` shows the same lines any time.
21
- Stop a run with \`coder flow stop\`.`,flags:[[`--wait`,`follow the run in the foreground (Ctrl-C detaches; it keeps running)`],[`--args <json>`,`the flow's input as a JSON value (or pass bare key=value pairs)`],[`--concurrency <n>`,`tasks running at once (default: CPU count)`],[`--max-tasks <n>`,`total tasks the run may dispatch (default: CPU count x 10)`],[`--dry-run`,`print every resolved prompt and gate command without dispatching`],H,V],examples:[[`coder flow run audit-routes --wait`,`run a discovered flow`],[`coder flow run ./scratch/one-off.ts --wait`,`run a flow by path`],[`coder flow run verify --args '{"clusters":["a","b"]}' --wait`,`pass structured input`]],seeAlso:`flow list · flow discover · flow result · flow resume`},"flow list":{list:[`flow list`,`recent flow runs (running + just stopped)`],usage:`coder flow list [--archived] [--limit N] [--json]`,summary:`List recent flow runs, most recent first: running runs plus ones that ended
22
- within the last 10 minutes. Older runs auto-archive and move to --archived.`,flags:[[`--archived`,`show archived runs (auto-archived or via flow archive)`],[`--limit <n|all>`,`show at most n runs (default all)`],H,V],seeAlso:`flow run · flow result · flow resume`},"flow discover":{list:[`flow discover`,`list flows runnable here (workspace + global)`],usage:`coder flow discover [--json]`,summary:`List every flow discoverable from the current directory: workspace flows in
23
- .coder/flows/ (walking up to the repo root) and global flows in ~/.coder/flows/.`,flags:[H,V],seeAlso:`flow run · flow result`},"flow result":{list:[`flow result [run-id]`,`progress and result of a flow run`],usage:`coder flow result [run-id] [--tail <n|all>] [--json]`,summary:`Show a flow run's status and result, with its tasks, gates, and token ledger.
24
+ it keeps running), and \`coder flow watch\` shows the same lines any time.
25
+ Stop a run with \`coder flow stop\`.`,flags:[[`--wait`,`follow the run in the foreground (Ctrl-C detaches; it keeps running)`],[`--args <json>`,`the flow's input as a JSON value (or pass bare key=value pairs)`],[`--concurrency <n>`,`tasks running at once (default: CPU count)`],[`--max-tasks <n>`,`total tasks the run may dispatch (default: CPU count x 10)`],[`--dry-run`,`print every resolved prompt and gate command without dispatching`],K,G],examples:[[`coder flow run audit-routes --wait`,`run a discovered flow`],[`coder flow run ./scratch/one-off.ts --wait`,`run a flow by path`],[`coder flow run verify --args '{"clusters":["a","b"]}' --wait`,`pass structured input`]],seeAlso:`flow list · flow discover · flow result · flow resume`},"flow list":{list:[`flow list`,`recent flow runs (running + just stopped)`],usage:`coder flow list [--archived] [--limit N] [--json]`,summary:`List recent flow runs, most recent first: running runs plus ones that ended
26
+ within the last 10 minutes. Older runs auto-archive and move to --archived.`,flags:[[`--archived`,`show archived runs (auto-archived or via flow archive)`],[`--limit <n|all>`,`show at most n runs (default all)`],K,G],seeAlso:`flow run · flow result · flow resume`},"flow discover":{list:[`flow discover`,`list flows runnable here (workspace + global)`],usage:`coder flow discover [--json]`,summary:`List every flow discoverable from the current directory: workspace flows in
27
+ .coder/flows/ (walking up to the repo root) and global flows in ~/.coder/flows/.`,flags:[K,G],seeAlso:`flow run · flow result`},"flow result":{list:[`flow result [run-id]`,`progress and result of a flow run`],usage:`coder flow result [run-id] [--tail <n|all>] [--json]`,summary:`Show a flow run's status and result, with its tasks, gates, and token ledger.
24
28
  --tail <n> caps the step rows (0 for the result alone). Defaults to the most
25
- recent run. To watch a run live, prefer \`coder flow stream\`.`,flags:[[`--tail <n|all>`,`show the last n step rows (default: all; 0 hides them)`],H,V],examples:[[`coder flow result --tail 0`,`the most recent run's result, no step rows`]],seeAlso:`flow run · flow stream · flow resume`},"flow stream":{list:[`flow stream [run-id]`,`watch a flow run live (replay + follow)`],usage:`coder flow stream [run-id] [--tail <n|all>] [--json]`,summary:`Watch a flow run live: replay its progress lines from the start, then keep
29
+ recent run. To watch a run live, prefer \`coder flow watch\`.`,flags:[[`--tail <n|all>`,`show the last n step rows (default: all; 0 hides them)`],K,G],examples:[[`coder flow result --tail 0`,`the most recent run's result, no step rows`]],seeAlso:`flow run · flow watch · flow resume`},"flow watch":{list:[`flow watch [run-id]`,`watch a flow run live (replay + follow)`],usage:`coder flow watch [run-id] [--tail <n|all>] [--json]`,summary:`Watch a flow run live: replay its progress lines from the start, then keep
26
30
  following while it runs (Ctrl-C detaches; it keeps running). Blocks until it
27
31
  finishes; exits 0 on success, 1 otherwise. Defaults to the most recent run.
28
- For the result alone, prefer \`coder flow result\`.`,flags:[[`--tail <n|all>`,`replay only the last n events first (default: all)`],[`--json`,`emit each event as a JSON line, then the result`],V],examples:[[`coder flow stream`,`follow the most recent run to completion`]],seeAlso:`flow result · flow run`},"flow stop":{list:[`flow stop [run-id]`,`stop a run and its still-running tasks`],usage:`coder flow stop [run-id] [--keep-tasks] [--json]`,summary:`Stop a running flow: signal the orchestrator so it stops dispatching, stamp the
32
+ For the result alone, prefer \`coder flow result\`. Alias: stream.`,flags:[[`--tail <n|all>`,`replay only the last n events first (default: all)`],[`--json`,`emit each event as a JSON line, then the result`],G],examples:[[`coder flow watch`,`follow the most recent run to completion`]],seeAlso:`flow result · flow run`},"flow stop":{list:[`flow stop [run-id]`,`stop a run and its still-running tasks`],usage:`coder flow stop [run-id] [--keep-tasks] [--json]`,summary:`Stop a running flow: signal the orchestrator so it stops dispatching, stamp the
29
33
  run stopped, and stop its still-running tasks. Defaults to the most recent run;
30
34
  the journal stays ready for \`coder flow resume\`.`,flags:[[`--keep-tasks`,`leave the run's still-running tasks running`],[`--json`,`print { runId, status, stoppedTasks, keptTasks }`]],seeAlso:`flow resume · flow result`},"flow resume":{list:[`flow resume [run-id]`,`continue a stopped or edited run`],usage:`coder flow resume [run-id] [--wait] [--json] [--dry-run]`,summary:`Re-run a flow from its journal: finished steps replay instantly, the first
31
35
  changed or new step onward runs live. Defaults to the most recent run.
32
- Accepts the same flags as flow run.`,flags:[[`--wait`,`follow the run in the foreground (Ctrl-C detaches; it keeps running)`],[`--concurrency <n>`,`tasks running at once`],[`--max-tasks <n>`,`total tasks the run may dispatch`],H,V],examples:[[`coder flow resume`,`continue the most recent run`]],seeAlso:`flow run · flow result`},"flow archive":{list:[`flow archive <run-id> | --all-stopped`,`hide a run (or all stopped) from the list`],usage:`coder flow archive <run-id> | coder flow archive --all-stopped`,summary:`Archive a flow run so it drops out of the default list (see it again with
36
+ Accepts the same flags as flow run.`,flags:[[`--wait`,`follow the run in the foreground (Ctrl-C detaches; it keeps running)`],[`--concurrency <n>`,`tasks running at once`],[`--max-tasks <n>`,`total tasks the run may dispatch`],K,G],examples:[[`coder flow resume`,`continue the most recent run`]],seeAlso:`flow run · flow result`},"flow archive":{list:[`flow archive <run-id> | --all-stopped`,`hide a run (or all stopped) from the list`],usage:`coder flow archive <run-id> | coder flow archive --all-stopped`,summary:`Archive a flow run so it drops out of the default list (see it again with
33
37
  \`coder flow list --archived [--limit N]\`). Pass --all-stopped to archive every
34
- finished run. A running run must be stopped first.`,flags:[[`--all-stopped`,`archive every stopped (finished) run`],H],seeAlso:`flow list · flow delete`},"flow delete":{list:[`flow delete <run-id> | --all-archived`,`delete a run's record (or all archived)`],usage:`coder flow delete <run-id> | coder flow delete --all-archived`,summary:`Delete a flow run's record from disk (its journal, events, and logs). This is
38
+ finished run. A running run must be stopped first.`,flags:[[`--all-stopped`,`archive every stopped (finished) run`],K],seeAlso:`flow list · flow delete`},"flow delete":{list:[`flow delete <run-id> | --all-archived`,`delete a run's record (or all archived)`],usage:`coder flow delete <run-id> | coder flow delete --all-archived`,summary:`Delete a flow run's record from disk (its journal, events, and logs). This is
35
39
  permanent; the run's tasks are ordinary tasks and are not touched. Pass
36
40
  --all-archived to delete every archived run at once. A running run must be
37
- stopped first.`,flags:[[`--all-archived`,`delete every archived run`],H],seeAlso:`flow archive · flow stop`},config:{list:[`config [get|set|unset] <key> [value]`,`read or write config`],usage:`coder config [get|set|unset] <key> [value] [--workspace]`,summary:`Read or write configuration. No args prints the effective config; get/set/unset
38
- target a dotted key (e.g. agents.codex.model). Writes go to ~/.coder/config.json.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H,V],examples:[[`coder config`,`print the effective config`],[`coder config set chain codex,claude`,`set the engine fallback chain`],[`coder config get agents.codex.model`,`read one value`]]},"setup-host":{list:[`setup-host [claude|codex|agents]`,`set up the host: check engines, write config, install plugin`],usage:`coder setup-host [claude] [codex] [agents] [--json]`,summary:`Set up coder in your host: check engines and auth, seed the config, and
41
+ stopped first.`,flags:[[`--all-archived`,`delete every archived run`],K],seeAlso:`flow archive · flow stop`},config:{list:[`config [get|set|unset] <key> [value]`,`read or write config`],usage:`coder config [get|set|unset] <key> [value] [--workspace]`,summary:`Read or write configuration. No args prints the effective config; get/set/unset
42
+ target a dotted key (e.g. agents.codex.model). Writes go to ~/.coder/config.json.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K,G],examples:[[`coder config`,`print the effective config`],[`coder config set chain codex,claude`,`set the engine fallback chain`],[`coder config get agents.codex.model`,`read one value`]]},"setup-host":{list:[`setup-host [claude|codex|agents]`,`set up the host: check engines, write config, install plugin`],usage:`coder setup-host [claude] [codex] [agents] [--json]`,summary:`Set up coder in your host: check engines and auth, seed the config, and
39
43
  install the host plugin/skill for the named host(s). Claude Code gets its
40
44
  marketplace plugin; "agents" installs a skill into ~/.agents/skills for
41
45
  every host that reads the Agent Skills standard dir (Codex, Pi, OpenCode,
42
- ...). "codex" is an alias for agents. With no host, checks and seeds.`,flags:[[`--json`,`machine-readable output`]],examples:[[`coder setup-host claude`,`install the Claude Code plugin`],[`coder setup-host agents`,`install the skill into ~/.agents/skills (Codex, Pi, OpenCode, ...)`]]},"model list":{list:[`model list`,`list built-ins, custom models, and aliases`],usage:`coder model list [--json]`,summary:"List built-in aliases, configured custom models, and user aliases. Only custom\nmodels are probed. Also the default when `coder model` is run bare.",flags:[H,V],seeAlso:`model add · model remove`},"model add":{list:[`model add <name> --base-url <url> --model <id>`,`connect a local or third-party model (OpenAI-compatible)`],usage:`coder model add <name> --base-url <url> --model <id> [--env-key VAR]`,summary:`Connect a custom model behind an OpenAI-compatible endpoint (Ollama, LM Studio,
46
+ ...). "codex" is an alias for agents. With no host, checks and seeds.`,flags:[[`--json`,`machine-readable output`]],examples:[[`coder setup-host claude`,`install the Claude Code plugin`],[`coder setup-host agents`,`install the skill into ~/.agents/skills (Codex, Pi, OpenCode, ...)`]]},"model list":{list:[`model list`,`list built-ins, custom models, and aliases`],usage:`coder model list [--json]`,summary:"List built-in aliases, configured custom models, and user aliases. Only custom\nmodels are probed. Also the default when `coder model` is run bare.",flags:[K,G],seeAlso:`model add · model remove`},"model add":{list:[`model add <name> --base-url <url> --model <id>`,`connect a local or third-party model (OpenAI-compatible)`],usage:`coder model add <name> --base-url <url> --model <id> [--env-key VAR]`,summary:`Connect a custom model behind an OpenAI-compatible endpoint (Ollama, LM Studio,
43
47
  vLLM, OpenRouter, ...). It currently runs on the codex engine pointed at your
44
48
  URL and is usable anywhere a model is: --model <name>, --agent custom, or as an
45
- agent default in config. Alias: \`coder model setup\`.`,flags:[[`--base-url <url>`,`OpenAI-compatible API base (e.g. http://localhost:11434/v1)`],[`--model <id>`,`the provider's model id (e.g. qwen2.5-coder:32b)`],[`--env-key <VAR>`,`env var holding the API key (omit for keyless local endpoints)`],[`--workspace`,`write to <repo>/coder.config.json instead of the user file`],H],examples:[[`coder model add qwen --base-url http://localhost:11434/v1 --model qwen2.5-coder:32b`,`local Ollama model, no key`],[`coder model add kimi --base-url https://openrouter.ai/api/v1 --model moonshotai/kimi-k2 --env-key OPENROUTER_API_KEY`,`third-party provider via OpenRouter`],[`coder run --model qwen "explain this repo"`,`dispatch a task on it`]],seeAlso:`model list · model update · setup-host · config`},"model update":{list:[`model update <name> [--base-url|--model|--env-key]`,`change a custom model in place`],usage:`coder model update <name> [--base-url <url>] [--model <id>] [--env-key VAR]`,summary:`Update a configured custom model. Only the flags you pass change; the endpoint
46
- is re-probed and the wire protocol re-detected.`,flags:[[`--base-url <url>`,`new API base`],[`--model <id>`,`new provider model id`],[`--env-key <VAR>`,`new API-key env var`],[`--workspace`,`write to <repo>/coder.config.json instead of the user file`],H],seeAlso:`model list · model remove`},"model remove":{list:[`model remove <name>`,`delete a custom model`],usage:`coder model remove <name>`,summary:`Remove a configured custom model.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H],seeAlso:`model list · model add`},"model disable":{list:[`model disable <name>`,`turn off a model (built-in, custom, or alias)`],usage:`coder model disable <name> [--workspace]`,summary:`Disable a model - built-in, custom, or alias. Requests for it fail until re-enabled.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H],seeAlso:`model enable · model list`},"model enable":{list:[`model enable <name>`,`re-enable a disabled model`],usage:`coder model enable <name> [--workspace]`,summary:`Re-enable a disabled model.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H],seeAlso:`model disable · model list`},"model alias":{list:[`model alias <name> <spec>`,`add or replace a user alias`],usage:`coder model alias <name> <spec> [--workspace]`,summary:`Save an alias for an agent spec, e.g. fast -> codex:mini. An alias may reuse a
47
- built-in name to override it.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H],seeAlso:`model unalias · model list`},"model unalias":{list:[`model unalias <name>`,`remove a user alias`],usage:`coder model unalias <name> [--workspace]`,summary:`Remove a user-defined alias.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],H],seeAlso:`model alias · model list`},docs:{list:[`docs [topic]`,`print bundled documentation (for agents to read)`],usage:`coder docs [topic] [--json]`,summary:`Print bundled documentation. With no topic, list the available topics; with a
49
+ agent default in config. Alias: \`coder model setup\`.`,flags:[[`--base-url <url>`,`OpenAI-compatible API base (e.g. http://localhost:11434/v1)`],[`--model <id>`,`the provider's model id (e.g. qwen2.5-coder:32b)`],[`--env-key <VAR>`,`env var holding the API key (omit for keyless local endpoints)`],[`--workspace`,`write to <repo>/coder.config.json instead of the user file`],K],examples:[[`coder model add qwen --base-url http://localhost:11434/v1 --model qwen2.5-coder:32b`,`local Ollama model, no key`],[`coder model add kimi --base-url https://openrouter.ai/api/v1 --model moonshotai/kimi-k2 --env-key OPENROUTER_API_KEY`,`third-party provider via OpenRouter`],[`coder run --model qwen "explain this repo"`,`dispatch a task on it`]],seeAlso:`model list · model update · setup-host · config`},"model update":{list:[`model update <name> [--base-url|--model|--env-key]`,`change a custom model in place`],usage:`coder model update <name> [--base-url <url>] [--model <id>] [--env-key VAR]`,summary:`Update a configured custom model. Only the flags you pass change; the endpoint
50
+ is re-probed and the wire protocol re-detected.`,flags:[[`--base-url <url>`,`new API base`],[`--model <id>`,`new provider model id`],[`--env-key <VAR>`,`new API-key env var`],[`--workspace`,`write to <repo>/coder.config.json instead of the user file`],K],seeAlso:`model list · model remove`},"model remove":{list:[`model remove <name>`,`delete a custom model`],usage:`coder model remove <name>`,summary:`Remove a configured custom model.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K],seeAlso:`model list · model add`},"model disable":{list:[`model disable <name>`,`turn off a model (built-in, custom, or alias)`],usage:`coder model disable <name> [--workspace]`,summary:`Disable a model - built-in, custom, or alias. Requests for it fail until re-enabled.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K],seeAlso:`model enable · model list`},"model enable":{list:[`model enable <name>`,`re-enable a disabled model`],usage:`coder model enable <name> [--workspace]`,summary:`Re-enable a disabled model.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K],seeAlso:`model disable · model list`},"model alias":{list:[`model alias <name> <spec>`,`add or replace a user alias`],usage:`coder model alias <name> <spec> [--workspace]`,summary:`Save an alias for an agent spec, e.g. fast -> codex:mini. An alias may reuse a
51
+ built-in name to override it.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K],seeAlso:`model unalias · model list`},"model unalias":{list:[`model unalias <name>`,`remove a user alias`],usage:`coder model unalias <name> [--workspace]`,summary:`Remove a user-defined alias.`,flags:[[`--workspace`,`target <repo>/coder.config.json instead of the user file`],K],seeAlso:`model alias · model list`},docs:{list:[`docs [topic]`,`print bundled documentation (for agents to read)`],usage:`coder docs [topic] [--json]`,summary:`Print bundled documentation. With no topic, list the available topics; with a
48
52
  topic, print that doc's raw markdown to stdout (unstyled, for an agent to
49
- consume).`,flags:[[`--json`,`list topics as JSON (bare listing only)`]],examples:[[`coder docs`,`list the available topics`],[`coder docs flows`,`print the Flows doc`]]},upgrade:{list:[`upgrade [--cli-only|--plugins-only]`,`update the CLI and host plugins (alias: update)`],usage:`coder upgrade [--cli-only] [--plugins-only] [--codex] [--claude] [--pm <mgr>]`,summary:`Update the coder CLI through whichever package manager installed it, then refresh
50
- the host plugins to match. Alias: update.`,flags:[[`--cli-only`,`update just the CLI`],[`--plugins-only`,`refresh just the host plugins`],[`--codex`,`limit the refresh to the Agent Skills copy (Codex, Pi, ...)`],[`--claude`,`limit the refresh to the Claude Code plugin`],[`--pm <npm|pnpm|yarn|bun>`,`force a package manager instead of auto-detecting`]]}},W={run:`task run`,list:`task list`,stream:`task stream`,watch:`task stream`,result:`task result`,steer:`task steer`,stop:`task stop`,archive:`task archive`,delete:`task delete`,approvals:`task approvals`,approve:`task approve`,setup:`setup-host`,"host-setup":`setup-host`,update:`upgrade`},Ke=[{usage:`list`,blurb:`list built-ins, custom models, and aliases`},{usage:`add <name> --base-url <url> --model <id> [--env-key VAR]`,blurb:`connect a model (alias: setup)`},{usage:`update <name> [--base-url|--model|--env-key]`,blurb:`change a model in place`},{usage:`remove <name>`,blurb:`delete a custom model`},{usage:`disable <name>`,blurb:`turn off a model (built-in, custom, or alias)`},{usage:`enable <name>`,blurb:`re-enable a disabled model`},{usage:`alias <name> <spec>`,blurb:`name a spec, e.g. fast codex:mini`},{usage:`unalias <name>`,blurb:`remove an alias`}],qe=[{usage:`run <name|path> [--wait] [--args ...]`,blurb:`run a flow in the background (--wait to follow it live)`},{usage:`list`,blurb:`recent flow runs (running + just stopped)`},{usage:`discover`,blurb:`list flows runnable here (workspace + global)`},{usage:`result [run-id]`,blurb:`progress and result of a run`},{usage:`stream [run-id]`,blurb:`watch a run live (replay + follow)`},{usage:`stop [run-id]`,blurb:`stop a run and its still-running tasks`},{usage:`resume [run-id]`,blurb:`continue a stopped or edited run`},{usage:`archive <run-id> | --all-stopped`,blurb:`hide a run (or all stopped) from the list`},{usage:`delete <run-id> | --all-archived`,blurb:`delete a run's record (or all archived)`}];function G(){let e=N,t=qe.map(t=>` ${e.cyan(t.usage.padEnd(44))}${e.dim(t.blurb)}`);return`${[e.bold(`Usage:`),` coder flow <subcommand>`,``,`Orchestrate many coder tasks with a plain TypeScript file: dispatch, gates,`,`concurrency, journaling, and resume. Flows live in .coder/flows/ (workspace)`,"or ~/.coder/flows/ (global). See `coder docs flows`.",``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder flow <subcommand> --help' for details on any subcommand.`)].join(`
51
- `)}\n`}function Je(){let e=N,t=Ke.map(t=>` ${e.cyan(t.usage.padEnd(60))}${e.dim(t.blurb)}`);return`${[e.bold(`Usage:`),` coder model <subcommand>`,``,"Manage the models coder can dispatch to. `add` connects any OpenAI-compatible",`endpoint (Ollama, vLLM, OpenRouter, ...) as the custom agent, alongside the`,"built-in codex/claude models. Name your own shortcuts with `alias`",`(e.g. fast -> codex:mini); disable/enable turns any model off and on.`,``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder model <subcommand> --help' for details on any subcommand.`)].join(`
52
- `)}\n`}function Ye(e,t){return e.map(([e,n])=>` ${t.cyan(e.padEnd(30))}${t.dim(n)}`)}function K(e){let t=U[e];if(!t)return null;let n=N,r=[n.bold(`Usage:`),` ${t.usage}`];if(t.summary&&r.push(``,t.summary),t.flags?.length&&r.push(``,n.bold(`Flags:`),...Ye(t.flags,n)),t.examples?.length){r.push(``,n.bold(`Examples:`));for(let[e,i]of t.examples)r.push(` ${n.cyan(e)}`,` ${n.dim(i)}`)}return t.seeAlso&&r.push(``,n.dim(`Related: ${t.seeAlso}`)),`${r.join(`
53
- `)}\n`}function q(){let e=N,t=Ge.map(t=>{let n=t.alias?e.dim(` (coder ${t.alias})`):``;return` ${e.cyan(t.usage.padEnd(30))}${e.dim(t.blurb)}${n}`});return`${[e.bold(`Usage:`),` coder task <subcommand>`,``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder task <subcommand> --help' for details on any subcommand.`)].join(`
54
- `)}\n`}function J(){let e=N,t=([t,n])=>` ${e.cyan(t.padEnd(41))}${e.dim(n)}`,n=Ge.filter(e=>e.alias).map(e=>t([e.usage.replace(/^\S+/,e.alias),e.blurb]));return`${[`${e.bold(`Coder`)} ${e.dim(`v${l()}`)}`,`Delegate a coding task to the best available engine and steer it while it runs.`,``,e.bold(`Get started:`),` ${e.cyan(`coder setup-host claude`)} ${e.dim(`# or agents (Codex, Pi, ...); installs the host plugin/skill`)}`,` ${e.cyan(`coder run "explain this repo's layout"`)}`,``,e.bold(`Usage:`),` coder <command>`,``,e.bold(`Commands:`),...n,` ${e.cyan(`task <cmd>`.padEnd(41))}${e.dim(`more task commands (steer, stop, approve, ...): `)}${e.light(`coder task --help`)}`,` ${e.cyan(`flow <cmd>`.padEnd(41))}${e.dim(`orchestrate a wave of tasks: `)}${e.light(`coder flow --help`)}`,t(U.config.list),t([`model <list|add|alias|disable>`,`manage models: built-ins, aliases, custom endpoints`]),t(U.docs.list),t(U.upgrade.list),``,e.bold(`Global:`),t([`-h, --help`,`show help (top-level, or for a command)`]),t([`-v, --version`,`print the coder version`]),t([`--json`,`JSON output instead of human-readable text`]),t(V)].join(`
55
- `)}\n`}function Y(e){let t=e.indexOf(`--`),n=t===-1?e:e.slice(0,t);return n.includes(`-h`)||n.includes(`--help`)}const X=`CODER_FLOW_ATTACH`;function Xe(e){let t={};for(let n of e){let e=n.indexOf(`=`);e===-1&&y(`Invalid argument "${n}": expected key=value.`,{hint:`Help: coder flow run --help`});let r=n.slice(0,e),i=n.slice(e+1);try{t[r]=JSON.parse(i)}catch{t[r]=i}}return t}function Ze(e,t){if(e!==void 0)try{return JSON.parse(e)}catch(e){y(`Invalid --args JSON: ${e instanceof Error?e.message:String(e)}`)}return t.length?Xe(t):{}}function Qe(){try{return He(`bun`,[`--version`],{stdio:`ignore`}).status===0}catch{return!1}}function $e(e){if(!e.endsWith(`.ts`)||L.versions.bun||L.features.typescript)return;Qe()||y(`This flow is a TypeScript file (${e}) and this Node cannot run TypeScript.`,{hint:[`Upgrade to Node 23.6+ or install bun: https://bun.sh`,`Or write the flow as .mjs / .js`]});let t=He(`bun`,[s,...L.argv.slice(2)],{stdio:`inherit`});L.exit(t.status??1)}function et(e){L.once(`SIGINT`,()=>{(async()=>{let{runId:t}=e,n=R.existsSync(z.join(P(t),Se));if(L.stderr.write(`\n[flow] stopping run ${t} — no new tasks will dispatch.\n`),n){let t=e.runningIds();t.length&&L.stderr.write(`[flow] left running: ${t.join(`, `)}\n`)}else{let n=await le(t,e.runningIds());n.length&&L.stderr.write(`[flow] stopped tasks: ${n.join(`, `)}\n`)}L.stderr.write(`[flow] resume with: coder flow resume ${t}\n`),e.requestStop(),L.exit(130)})()})}const tt=[`⣾`,`⣽`,`⣻`,`⢿`,`⡿`,`⣟`,`⣯`,`⣷`];function Z(e,t=!1){let n=N;return t?_(`[${rt(e)}]`,10):e===`completed`?n.bold(n.green(`✔`)):e===`failed`||e===`cancelled`||e===`stopped`?n.bold(n.red(`✘`)):e===`running`?n.bold(n.cyan(`●`)):n.dim(`○`)}function nt(){return _(`[start]`,10)}function rt(e){return e===`completed`?`done`:e===`cancelled`?`failed`:e}function it(e,t){return e??t.replace(/\s+/g,` `).trim().slice(0,60)}function Q(e,t,n,r,i,a){let o=N,s=_(t??n,32);return[`${e} ${a?o.bold(s):s}`,o.dim(_(n,24)),o.light(_(i??``,20)),r?o.light(`${v(r.total)} tok`):``].join(` `).trimEnd()}function at(e){let t=z.join(P(e),`events.jsonl`);return R.existsSync(t)?R.readFileSync(t,`utf8`).split(`
56
- `).filter(Boolean).flatMap(e=>{try{return[JSON.parse(e)]}catch{return[]}}):[]}function ot(e,t=!1){let n=N;return`${Z(e.ok?`completed`:`failed`,t)} ${n.dim(`gate`)} ${n.light(e.cmd)}${e.ok?``:n.dim(` · exit ${e.code}`)}`}function st(e,t,n){let r=N,i=n!==void 0&&n>=1e3?r.dim(` · ${E(n)}`):``;return`${t} ${r.dim(`gate`)} ${r.light(e)}${i}`}function ct(e,t=!1){return N.dim(`${`│ `.repeat(e)}${t?`└─`:`├─`}`)}function lt(e){return N.dim(`${`│ `.repeat(e)}│ `)}function ut(e){return`${` `.repeat(e.depth)}${e.log?`${_(`[log]`,10)} `:``}${e.body}`}function dt(e,t,n=!1){return n?ut(e):`${e.log?lt(e.depth):ct(e.depth,t)} ${e.body}`}function ft(e){return N.dim(`${`│ `.repeat(Math.max(0,e))}│`)}function pt(e,t=!1){let n=N;if(t)return e.map(ut);let r=(t,n)=>{for(let r=t+1;r<e.length;r+=1){let t=e[r].depth;if(t<n)return!1;if(t===n)return!0}return!1};return e.map((e,t)=>{let i=``;for(let n=0;n<e.depth;n+=1)i+=r(t,n)?`│ `:` `;return i+=e.log?`│ `:r(t,e.depth)?`├─`:`└─`,`${n.dim(i)} ${e.body}`})}var mt=class{stream;names=new Map;active=new Map;activeGates=new Map;pending;previews=new Map;frame=0;hasCommitted=!1;timer;tty;region;constructor(e=L.stdout){this.stream=e,this.tty=!!e.isTTY,this.region=new me(e)}emit(e){let t=N;switch(e.kind){case`task-start`:{let t={name:it(e.name,e.prompt),agent:e.agent,depth:e.depth??0};if(this.names.set(e.taskId,t),!this.tty){this.final(t.depth,Q(nt(),t.name,e.taskId,null,t.agent));return}this.active.set(e.taskId,t),this.spin(!0),this.repaint();return}case`task-end`:{this.active.delete(e.taskId),this.previews.delete(e.taskId),this.idle();let t=this.names.get(e.taskId);this.final(t?.depth??0,Q(Z(e.status,!this.tty),t?.name??null,e.taskId,e.tokens,t?.agent));return}case`gate-start`:{let t={cmd:e.cmd,depth:e.depth??0,startedAt:Date.now()};if(!this.tty){this.final(t.depth,st(t.cmd,nt()));return}this.activeGates.set(e.gateId,t),this.spin(!0),this.repaint();return}case`gate`:e.gateId&&this.activeGates.delete(e.gateId),this.idle(),this.final(e.depth??0,ot(e,!this.tty));return;case`log`:for(let n of e.message.split(`
57
- `))this.final(e.depth??0,t.light(n),!0);return;case`flow-start`:this.final(e.depth-1,t.bold(`flow ${e.name}`));return;case`replay`:this.final(0,t.dim(`replayed ${e.count} steps from journal`),!0)}}done(){this.spin(!1),this.flush(0),this.tty&&this.repaint(),this.region.done()}flush(e){this.pending&&=(this.region.commit(`${dt(this.pending,e<this.pending.depth,!this.tty)}\n`),this.hasCommitted=!0,void 0)}final(e,t,n=!1){if(!this.tty){this.region.commit(`${ut({depth:e,body:t,log:n})}\n`),this.hasCommitted=!0;return}this.flush(e),this.pending={depth:e,body:t,log:n},this.tty&&this.repaint()}repaint(){let e=[],t=[];if(this.pending){let n=dt(this.pending,!1);e.push(n),t.push(n)}let n=this.timer?N.bold(N.cyan(tt[this.frame%tt.length])):Z(`running`);for(let[r,i]of this.active){let a=`${ct(i.depth??0)} ${Q(n,i.name,r,null,i.agent,!0)}`;(e.length||this.hasCommitted)&&e.push(ft(i.depth??0)),e.push(a),t.push(a);let o=this.previews.get(r);o&&e.push(`${lt(i.depth??0)} ${N.dim(o)}`)}for(let r of this.activeGates.values()){let i=`${ct(r.depth)} ${st(r.cmd,n,Date.now()-r.startedAt)}`;(e.length||this.hasCommitted)&&e.push(ft(r.depth)),e.push(i),t.push(i)}let r=(_e(this.stream)??1/0)-1,i=e.length<=r?e:t;if(i.length>r){let e=Math.max(0,r-1);i=[N.dim(`… +${i.length-e} more running`),...i.slice(-e)]}this.region.set(i)}refreshPreviews(){for(let e of this.active.keys())try{let t=r(L.cwd(),e,1)[0]?.message?.replace(/\s+/g,` `).trim();if(!t)continue;let n=(Ce(this.stream)??120)-8;this.previews.set(e,t.length>n?`${t.slice(0,n-1)}…`:t)}catch{}}idle(){!this.active.size&&!this.activeGates.size&&this.spin(!1)}spin(e){e&&!this.timer?this.timer=setInterval(()=>{this.frame++,this.frame%4==0&&this.refreshPreviews(),this.repaint()},120).unref():!e&&this.timer&&(clearInterval(this.timer),this.timer=void 0)}};function ht(e){if(e.json)return{};let t=new mt,n=e=>t.emit(e);return{onTaskStart:e=>n({kind:`task-start`,...e}),onTaskEnd:e=>n({kind:`task-end`,...e}),onGateStart:e=>n({kind:`gate-start`,...e}),onGate:e=>n({kind:`gate`,...e}),onLog:(e,t)=>n({kind:`log`,message:e,depth:t}),onFlowStart:e=>n({kind:`flow-start`,...e}),onReplay:e=>n({kind:`replay`,count:e})}}function gt(e){let t=z.join(P(e),`events.jsonl`),n=e=>{try{R.appendFileSync(t,`${JSON.stringify(e)}\n`,`utf8`)}catch{}};return{onStart:e=>et(e),onTaskStart:e=>n({kind:`task-start`,...e}),onTaskEnd:e=>n({kind:`task-end`,...e}),onGateStart:e=>n({kind:`gate-start`,...e}),onGate:e=>n({kind:`gate`,...e}),onLog:(e,t)=>n({kind:`log`,message:e,depth:t}),onFlowStart:e=>n({kind:`flow-start`,...e}),onReplay:e=>n({kind:`replay`,count:e})}}async function _t(e,t){try{await se(e,t,gt(e)),L.exit(0)}catch(t){ve(e,t instanceof Error?t.message:String(t)),L.exit(1)}}function vt(e,t){let n=P(e.runId);R.writeFileSync(z.join(n,`events.jsonl`),``,`utf8`);let r=R.openSync(z.join(n,`flow.log`),`a`),i=Ve(L.execPath,[s,...L.argv.slice(2)],{detached:!0,stdio:[`ignore`,r,r],env:{...L.env,[X]:e.runId}});return i.unref(),R.closeSync(r),t.wait?i.pid:t.json?(k({runId:e.runId,status:`running`}),i.pid):(L.stdout.write(`${N.dim(`[flow]`)} run ${N.cyan(e.runId)} started in the background (running).\n`),L.stdout.write(`\n${h([`Result: coder flow result ${e.runId}`,`Runs: coder flow list`],N)}\n`),i.pid)}async function yt(e,t,n){let r=!!(t.stream&&t.json);!t.json&&(j(e)?.status??`running`)===`running`&&L.stderr.write(`${N.dim(`[flow]`)} run ${N.cyan(e)} started (running); waiting for it to finish — Ctrl-C to detach (it keeps running).\n\n`);let i=t.json?()=>{}:x(),a=()=>{i(),r||(L.stderr.write(`\n${N.dim(`[flow] detached — run still going.`)}\n`),L.stderr.write(`\n${h([`Result: coder flow result ${e}`,`Stop it: coder flow stop ${e}`],N)}\n`)),L.exit(130)};L.on(`SIGINT`,a);let o=new mt;for await(let i of D(e,n,{tail:t.tail}))r?L.stdout.write(`${JSON.stringify(i)}\n`):t.json||o.emit(i);o.done(),i(),L.off(`SIGINT`,a);let s=j(e);s||y(`[flow] run ${e} vanished while following.`,{hint:`Recent runs: coder flow list`}),r&&(L.stdout.write(`${JSON.stringify(Ot(s))}\n`),L.exit(s.status===`completed`?0:1)),s.status===`completed`&&(St({runId:e,name:s.name,status:`completed`,result:s.result,tokens:s.ledger,taskCount:s.taskCount},t.json),L.exit(0)),s.status===`stopped`&&(t.json?k({runId:e,name:s.name,status:`stopped`,taskCount:s.taskCount}):L.stdout.write(`\n${N.dim(`[flow] run ${e} stopped — resume: coder flow resume ${e}`)}\n`),L.exit(1)),L.stdout.write(`\n${N.red(`error:`)} ${s.error??`unknown error`}\n`),L.stdout.write(`\n${h([`Resume: coder flow resume ${e}`],N)}\n`),L.exit(1)}const bt={cwd:f,json:d,args:f,wait:d,concurrency:f,"max-tasks":f,"dry-run":d},$=e=>e?Number(e):void 0;async function xt(e,t,n){let r=L.env[X];if(r&&(delete L.env[X],await _t(r,t)),e[`dry-run`])return!1;let i=n(),a=vt(i,e);return e.wait&&await yt(i.runId,e,a),!0}function St(e,t){if(t){k(e);return}let n=!L.stdout.isTTY,r=n?``:`${N.dim(`└─`)} `;L.stdout.write(`${r}${Z(`completed`,n)} run ${N.cyan(e.runId)} completed ${N.dim(`(${e.taskCount} tasks)`)}\n`),L.stdout.write(`\n${ae(e.result)}\n`),Tt(e.tokens)}function Ct(e,t,n){if(e instanceof S&&e.code===`flow-failed`){let r=n?`
58
- [flow] dry-run ended early: a downstream step depends on real task output (stub it or run for real).`:``;y(`[flow] ${t} ${e.runId} failed: ${e.message}${r}`,{hint:`Resume${t===`resume`?` again`:``}: coder flow resume ${e.runId}`})}throw e}async function wt(e){let{options:t,positionals:n}=c(e,B.object(bt)),[r,...i]=n;r||y(`Missing flow name or path.`,{hint:[`Usage: coder flow run <name|path>`,`List: coder flow discover`]});let a=p(t);$e(pe(r,a).path);let o={args:Ze(t.args,i),cwd:a,dryRun:t[`dry-run`],concurrency:$(t.concurrency),maxTasks:$(t[`max-tasks`])};if(!await xt(t,o,()=>fe(r,o)))try{St(await ke(r,o,ht(t)),t.json)}catch(e){Ct(e,`run`,o.dryRun)}}function Tt(e){let t=Object.keys(e);if(t.length){L.stdout.write(`\n${N.bold(`Tokens:`)}\n`);for(let n of t)L.stdout.write(` ${N.dim(ie(e[n],n))}\n`)}}async function Et(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,archived:d,limit:a}));A(n,0,`flow list`);let r=t.limit===`all`?void 0:t.limit,{runs:i,clipped:o}=ye({archived:t.archived,limit:r});if(t.json){k(i);return}if(!i.length){L.stdout.write(t.archived?`No archived flow runs.
53
+ consume). \`coder docs skill\` prints the host skill so an agent can load it
54
+ once per session (--claude for the Claude Code flavor).`,flags:[[`--claude`,`with the skill topic: print the Claude Code flavor`],[`--json`,`list topics as JSON (bare listing only)`]],examples:[[`coder docs`,`list the available topics`],[`coder docs flows`,`print the Flows doc`]]},upgrade:{list:[`upgrade [--cli-only|--plugins-only]`,`update the CLI and host plugins (alias: update)`],usage:`coder upgrade [--cli-only] [--plugins-only] [--codex] [--claude] [--pm <mgr>]`,summary:`Update the coder CLI through whichever package manager installed it, then refresh
55
+ the host plugins to match. Alias: update.`,flags:[[`--cli-only`,`update just the CLI`],[`--plugins-only`,`refresh just the host plugins`],[`--codex`,`limit the refresh to the Agent Skills copy (Codex, Pi, ...)`],[`--claude`,`limit the refresh to the Claude Code plugin`],[`--pm <npm|pnpm|yarn|bun>`,`force a package manager instead of auto-detecting`]]}},_t={run:`task run`,list:`task list`,watch:`task watch`,stream:`task watch`,result:`task result`,steer:`task steer`,ask:`task ask`,stop:`task stop`,archive:`task archive`,delete:`task delete`,approvals:`task approvals`,approve:`task approve`,setup:`setup-host`,"host-setup":`setup-host`,update:`upgrade`},vt=[{usage:`list`,blurb:`list built-ins, custom models, and aliases`},{usage:`add <name> --base-url <url> --model <id> [--env-key VAR]`,blurb:`connect a model (alias: setup)`},{usage:`update <name> [--base-url|--model|--env-key]`,blurb:`change a model in place`},{usage:`remove <name>`,blurb:`delete a custom model`},{usage:`disable <name>`,blurb:`turn off a model (built-in, custom, or alias)`},{usage:`enable <name>`,blurb:`re-enable a disabled model`},{usage:`alias <name> <spec>`,blurb:`name a spec, e.g. fast codex:mini`},{usage:`unalias <name>`,blurb:`remove an alias`}],yt=[{usage:`run <name|path> [--wait] [--args ...]`,blurb:`run a flow in the background (--wait to follow it live)`},{usage:`list`,blurb:`recent flow runs (running + just stopped)`},{usage:`discover`,blurb:`list flows runnable here (workspace + global)`},{usage:`result [run-id]`,blurb:`progress and result of a run`},{usage:`watch [run-id]`,blurb:`watch a run live (replay + follow)`},{usage:`stop [run-id]`,blurb:`stop a run and its still-running tasks`},{usage:`resume [run-id]`,blurb:`continue a stopped or edited run`},{usage:`archive <run-id> | --all-stopped`,blurb:`hide a run (or all stopped) from the list`},{usage:`delete <run-id> | --all-archived`,blurb:`delete a run's record (or all archived)`}];function J(){let e=N,t=yt.map(t=>` ${e.cyan(t.usage.padEnd(44))}${e.dim(t.blurb)}`);return`${[e.bold(`Usage:`),` coder flow <subcommand>`,``,`Orchestrate many coder tasks with a plain TypeScript file: dispatch, gates,`,`concurrency, journaling, and resume. Flows live in .coder/flows/ (workspace)`,"or ~/.coder/flows/ (global). See `coder docs flows`.",``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder flow <subcommand> --help' for details on any subcommand.`)].join(`
56
+ `)}\n`}function bt(){let e=N,t=vt.map(t=>` ${e.cyan(t.usage.padEnd(60))}${e.dim(t.blurb)}`);return`${[e.bold(`Usage:`),` coder model <subcommand>`,``,"Manage the models coder can dispatch to. `add` connects any OpenAI-compatible",`endpoint (Ollama, vLLM, OpenRouter, ...) as the custom agent, alongside the`,"built-in codex/claude models. Name your own shortcuts with `alias`",`(e.g. fast -> codex:mini); disable/enable turns any model off and on.`,``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder model <subcommand> --help' for details on any subcommand.`)].join(`
57
+ `)}\n`}function xt(e,t){return e.map(([e,n])=>` ${t.cyan(e.padEnd(30))}${t.dim(n)}`)}function Y(e){let t=q[e];if(!t)return null;let n=N,r=[n.bold(`Usage:`),` ${t.usage}`];if(t.summary&&r.push(``,t.summary),t.flags?.length&&r.push(``,n.bold(`Flags:`),...xt(t.flags,n)),t.examples?.length){r.push(``,n.bold(`Examples:`));for(let[e,i]of t.examples)r.push(` ${n.cyan(e)}`,` ${n.dim(i)}`)}return t.seeAlso&&r.push(``,n.dim(`Related: ${t.seeAlso}`)),`${r.join(`
58
+ `)}\n`}function X(){let e=N,t=gt.map(t=>{let n=t.alias?e.dim(` (coder ${t.alias})`):``;return` ${e.cyan(t.usage.padEnd(30))}${e.dim(t.blurb)}${n}`});return`${[e.bold(`Usage:`),` coder task <subcommand>`,``,e.bold(`Subcommands:`),...t,``,e.dim(`Run 'coder task <subcommand> --help' for details on any subcommand.`)].join(`
59
+ `)}\n`}function St(){let e=N,t=([t,n])=>` ${e.cyan(t.padEnd(41))}${e.dim(n)}`,n=gt.filter(e=>e.alias).map(e=>t([e.usage.replace(/^\S+/,e.alias),e.blurb]));return`${[`${e.bold(`Coder`)} ${e.dim(`v${_()}`)}`,`Delegate a coding task to the best available engine and steer it while it runs.`,``,e.bold(`Get started:`),` ${e.cyan(`coder setup-host claude`)} ${e.dim(`# or agents (Codex, Pi, ...); installs the host plugin/skill`)}`,` ${e.cyan(`coder run "explain this repo's layout"`)}`,``,e.dim("Agents: load the skill once with `coder docs skill [--claude]`."),``,e.bold(`Usage:`),` coder <command>`,``,e.bold(`Commands:`),...n,` ${e.cyan(`task <cmd>`.padEnd(41))}${e.dim(`more task commands (steer, stop, approve, ...): `)}${e.light(`coder task --help`)}`,` ${e.cyan(`flow <cmd>`.padEnd(41))}${e.dim(`orchestrate a wave of tasks: `)}${e.light(`coder flow --help`)}`,t(q.config.list),t([`model <list|add|alias|disable>`,`manage models: built-ins, aliases, custom endpoints`]),t(q.docs.list),t(q.upgrade.list),``,e.bold(`Global:`),t([`-h, --help`,`show help (top-level, or for a command)`]),t([`-v, --version`,`print the coder version`]),t([`--json`,`JSON output instead of human-readable text`]),t(G)].join(`
60
+ `)}\n`}function Z(e){let t=e.indexOf(`--`),n=t===-1?e:e.slice(0,t);return n.includes(`-h`)||n.includes(`--help`)}const Ct=`CODER_FLOW_ATTACH`;function wt(e){let t={};for(let n of e){let e=n.indexOf(`=`);e===-1&&C(`Invalid argument "${n}": expected key=value.`,{hint:`Help: coder flow run --help`});let r=n.slice(0,e),i=n.slice(e+1);try{t[r]=JSON.parse(i)}catch{t[r]=i}}return t}function Tt(e,t){if(e!==void 0)try{return JSON.parse(e)}catch(e){C(`Invalid --args JSON: ${e instanceof Error?e.message:String(e)}`)}return t.length?wt(t):{}}function Et(){try{return ft(`bun`,[`--version`],{stdio:`ignore`}).status===0}catch{return!1}}function Dt(e){if(!e.endsWith(`.ts`)||V.versions.bun||V.features.typescript)return;Et()||C(`This flow is a TypeScript file (${e}) and this Node cannot run TypeScript.`,{hint:[`Upgrade to Node 23.6+ or install bun: https://bun.sh`,`Or write the flow as .mjs / .js`]});let t=ft(`bun`,[m,...V.argv.slice(2)],{stdio:`inherit`});V.exit(t.status??1)}function Ot(e){V.once(`SIGINT`,()=>{(async()=>{let{runId:t}=e,n=H.existsSync(U.join(R(t),Ge));if(V.stderr.write(`\n[flow] stopping run ${t} — no new tasks will dispatch.\n`),n){let t=e.runningIds();t.length&&V.stderr.write(`[flow] left running: ${t.join(`, `)}\n`)}else{let n=await Te(t,e.runningIds());n.length&&V.stderr.write(`[flow] stopped tasks: ${n.join(`, `)}\n`)}V.stderr.write(`[flow] resume with: coder flow resume ${t}\n`),e.requestStop(),V.exit(130)})()})}const kt=[`⣾`,`⣽`,`⣻`,`⢿`,`⡿`,`⣟`,`⣯`,`⣷`];function Q(e,t=!1){let n=N;return t?z(`[${jt(e)}]`,10):e===`completed`?n.bold(n.green(`✔`)):e===`failed`||e===`cancelled`||e===`stopped`?n.bold(n.red(`✘`)):e===`running`?n.bold(n.cyan(`●`)):n.dim(`○`)}function At(){return z(`[start]`,10)}function jt(e){return e===`completed`?`done`:e===`cancelled`?`failed`:e}function Mt(e,t){return e??t.replace(/\s+/g,` `).trim().slice(0,60)}function $(e,t,n,r,i,a){let o=N,s=z(t??n,32);return[`${e} ${a?o.bold(s):s}`,o.dim(z(n,24)),o.light(z(i??``,20)),r?o.light(`${ie(r.total)} tok`):``].join(` `).trimEnd()}function Nt(e){let t=U.join(R(e),`events.jsonl`);return H.existsSync(t)?H.readFileSync(t,`utf8`).split(`
61
+ `).filter(Boolean).flatMap(e=>{try{return[JSON.parse(e)]}catch{return[]}}):[]}function Pt(e,t=!1){let n=N;return`${Q(e.ok?`completed`:`failed`,t)} ${n.dim(`gate`)} ${n.light(e.cmd)}${e.ok?``:n.dim(` · exit ${e.code}`)}`}function Ft(e,t,n){let r=N,i=n!==void 0&&n>=1e3?r.dim(` · ${D(n)}`):``;return`${t} ${r.dim(`gate`)} ${r.light(e)}${i}`}function It(e,t=!1){return N.dim(`${`│ `.repeat(e)}${t?`└─`:`├─`}`)}function Lt(e){return N.dim(`${`│ `.repeat(e)}│ `)}function Rt(e){return`${` `.repeat(e.depth)}${e.log?`${z(`[log]`,10)} `:``}${e.body}`}function zt(e,t,n=!1){return n?Rt(e):`${e.log?Lt(e.depth):It(e.depth,t)} ${e.body}`}function Bt(e){return N.dim(`${`│ `.repeat(Math.max(0,e))}│`)}function Vt(e,t=!1){let n=N;if(t)return e.map(Rt);let r=(t,n)=>{for(let r=t+1;r<e.length;r+=1){let t=e[r].depth;if(t<n)return!1;if(t===n)return!0}return!1};return e.map((e,t)=>{let i=``;for(let n=0;n<e.depth;n+=1)i+=r(t,n)?`│ `:` `;return i+=e.log?`│ `:r(t,e.depth)?`├─`:`└─`,`${n.dim(i)} ${e.body}`})}var Ht=class{stream;names=new Map;active=new Map;activeGates=new Map;pending;previews=new Map;frame=0;hasCommitted=!1;timer;tty;region;constructor(e=V.stdout){this.stream=e,this.tty=!!e.isTTY,this.region=new T(e)}emit(e){let t=N;switch(e.kind){case`task-start`:{let t={name:Mt(e.name,e.prompt),agent:e.agent,depth:e.depth??0};if(this.names.set(e.taskId,t),!this.tty){this.final(t.depth,$(At(),t.name,e.taskId,null,t.agent));return}this.active.set(e.taskId,t),this.spin(!0),this.repaint();return}case`task-end`:{this.active.delete(e.taskId),this.previews.delete(e.taskId),this.idle();let t=this.names.get(e.taskId);this.final(t?.depth??0,$(Q(e.status,!this.tty),t?.name??null,e.taskId,e.tokens,t?.agent));return}case`gate-start`:{let t={cmd:e.cmd,depth:e.depth??0,startedAt:Date.now()};if(!this.tty){this.final(t.depth,Ft(t.cmd,At()));return}this.activeGates.set(e.gateId,t),this.spin(!0),this.repaint();return}case`gate`:e.gateId&&this.activeGates.delete(e.gateId),this.idle(),this.final(e.depth??0,Pt(e,!this.tty));return;case`log`:for(let n of e.message.split(`
62
+ `))this.final(e.depth??0,t.light(n),!0);return;case`flow-start`:this.final(e.depth-1,t.bold(`flow ${e.name}`));return;case`replay`:this.final(0,t.dim(`replayed ${e.count} steps from journal`),!0)}}done(){this.spin(!1),this.flush(0),this.tty&&this.repaint(),this.region.done()}flush(e){this.pending&&=(this.region.commit(`${zt(this.pending,e<this.pending.depth,!this.tty)}\n`),this.hasCommitted=!0,void 0)}final(e,t,n=!1){if(!this.tty){this.region.commit(`${Rt({depth:e,body:t,log:n})}\n`),this.hasCommitted=!0;return}this.flush(e),this.pending={depth:e,body:t,log:n},this.tty&&this.repaint()}repaint(){let e=[],t=[];if(this.pending){let n=zt(this.pending,!1);e.push(n),t.push(n)}let n=this.timer?N.bold(N.cyan(kt[this.frame%kt.length])):Q(`running`);for(let[r,i]of this.active){let a=`${It(i.depth??0)} ${$(n,i.name,r,null,i.agent,!0)}`;(e.length||this.hasCommitted)&&e.push(Bt(i.depth??0)),e.push(a),t.push(a);let o=this.previews.get(r);o&&e.push(`${Lt(i.depth??0)} ${N.dim(o)}`)}for(let r of this.activeGates.values()){let i=`${It(r.depth)} ${Ft(r.cmd,n,Date.now()-r.startedAt)}`;(e.length||this.hasCommitted)&&e.push(Bt(r.depth)),e.push(i),t.push(i)}let r=(Re(this.stream)??1/0)-1,i=e.length<=r?e:t;if(i.length>r){let e=Math.max(0,r-1);i=[N.dim(`… +${i.length-e} more running`),...i.slice(-e)]}this.region.set(i)}refreshPreviews(){for(let e of this.active.keys())try{let t=a(V.cwd(),e,1)[0]?.message?.replace(/\s+/g,` `).trim();if(!t)continue;let n=(Ce(this.stream)??120)-8;this.previews.set(e,t.length>n?`${t.slice(0,n-1)}…`:t)}catch{}}idle(){!this.active.size&&!this.activeGates.size&&this.spin(!1)}spin(e){e&&!this.timer?this.timer=setInterval(()=>{this.frame++,this.frame%4==0&&this.refreshPreviews(),this.repaint()},120).unref():!e&&this.timer&&(clearInterval(this.timer),this.timer=void 0)}};function Ut(e){if(e.json)return{};let t=new Ht,n=e=>t.emit(e);return{onTaskStart:e=>n({kind:`task-start`,...e}),onTaskEnd:e=>n({kind:`task-end`,...e}),onGateStart:e=>n({kind:`gate-start`,...e}),onGate:e=>n({kind:`gate`,...e}),onLog:(e,t)=>n({kind:`log`,message:e,depth:t}),onFlowStart:e=>n({kind:`flow-start`,...e}),onReplay:e=>n({kind:`replay`,count:e})}}function Wt(e){let t=U.join(R(e),`events.jsonl`),n=e=>{try{H.appendFileSync(t,`${JSON.stringify(e)}\n`,`utf8`)}catch{}};return{onStart:e=>Ot(e),onTaskStart:e=>n({kind:`task-start`,...e}),onTaskEnd:e=>n({kind:`task-end`,...e}),onGateStart:e=>n({kind:`gate-start`,...e}),onGate:e=>n({kind:`gate`,...e}),onLog:(e,t)=>n({kind:`log`,message:e,depth:t}),onFlowStart:e=>n({kind:`flow-start`,...e}),onReplay:e=>n({kind:`replay`,count:e})}}async function Gt(e,t){try{await be(e,t,Wt(e)),V.exit(0)}catch(t){Be(e,t instanceof Error?t.message:String(t)),V.exit(1)}}function Kt(e,t){let n=R(e.runId);H.writeFileSync(U.join(n,`events.jsonl`),``,`utf8`);let r=H.openSync(U.join(n,`flow.log`),`a`),i=dt(V.execPath,[m,...V.argv.slice(2)],{detached:!0,stdio:[`ignore`,r,r],env:{...V.env,[Ct]:e.runId}});return i.unref(),H.closeSync(r),t.wait?i.pid:t.json?(x({runId:e.runId,status:`running`}),i.pid):(V.stdout.write(`${N.dim(`[flow]`)} run ${N.cyan(e.runId)} started in the background (running).\n`),V.stdout.write(`\n${M([`Result: coder flow result ${e.runId}`,`Runs: coder flow list`],N)}\n`),i.pid)}async function qt(e,t,n){let r=!!(t.stream&&t.json);!t.json&&(P(e)?.status??`running`)===`running`&&V.stderr.write(`${N.dim(`[flow]`)} run ${N.cyan(e)} started (running); waiting for it to finish — Ctrl-C to detach (it keeps running).\n\n`);let i=t.json?()=>{}:_e(),a=()=>{i(),r||(V.stderr.write(`\n${N.dim(`[flow] detached — run still going.`)}\n`),V.stderr.write(`\n${M([`Result: coder flow result ${e}`,`Stop it: coder flow stop ${e}`],N)}\n`)),V.exit(130)};V.on(`SIGINT`,a);let o=new Ht;for await(let i of de(e,n,{tail:t.tail}))r?V.stdout.write(`${JSON.stringify(i)}\n`):t.json||o.emit(i);o.done(),i(),V.off(`SIGINT`,a);let s=P(e);s||C(`[flow] run ${e} vanished while following.`,{hint:`Recent runs: coder flow list`}),r&&(V.stdout.write(`${JSON.stringify(rn(s))}\n`),V.exit(s.status===`completed`?0:1)),s.status===`completed`&&(Zt({runId:e,name:s.name,status:`completed`,result:s.result,tokens:s.ledger,taskCount:s.taskCount},t.json),V.exit(0)),s.status===`stopped`&&(t.json?x({runId:e,name:s.name,status:`stopped`,taskCount:s.taskCount}):V.stdout.write(`\n${N.dim(`[flow] run ${e} stopped — resume: coder flow resume ${e}`)}\n`),V.exit(1)),V.stdout.write(`\n${N.red(`error:`)} ${s.error??`unknown error`}\n`),V.stdout.write(`\n${M([`Resume: coder flow resume ${e}`],N)}\n`),V.exit(1)}const Jt={cwd:b,json:y,args:b,wait:y,concurrency:b,"max-tasks":b,"dry-run":y},Yt=e=>e?Number(e):void 0;async function Xt(e,t,n){let r=V.env[Ct];if(r&&(delete V.env[Ct],await Gt(r,t)),e[`dry-run`])return!1;let i=n(),a=Kt(i,e);return e.wait&&await qt(i.runId,e,a),!0}function Zt(e,t){if(t){x(e);return}let n=!V.stdout.isTTY,r=n?``:`${N.dim(`└─`)} `;V.stdout.write(`${r}${Q(`completed`,n)} run ${N.cyan(e.runId)} completed ${N.dim(`(${e.taskCount} tasks)`)}\n`),V.stdout.write(`\n${E(e.result)}\n`),en(e.tokens)}function Qt(e,t,n){if(e instanceof A&&e.code===`flow-failed`){let r=n?`
63
+ [flow] dry-run ended early: a downstream step depends on real task output (stub it or run for real).`:``;C(`[flow] ${t} ${e.runId} failed: ${e.message}${r}`,{hint:`Resume${t===`resume`?` again`:``}: coder flow resume ${e.runId}`})}throw e}async function $t(e){let{options:t,positionals:n}=g(e,W.object(Jt)),[r,...i]=n;r||C(`Missing flow name or path.`,{hint:[`Usage: coder flow run <name|path>`,`List: coder flow discover`]});let a=F(t);Dt(Me(r,a).path);let o={args:Tt(t.args,i),cwd:a,dryRun:t[`dry-run`],concurrency:Yt(t.concurrency),maxTasks:Yt(t[`max-tasks`])};if(!await Xt(t,o,()=>Ae(r,o)))try{Zt(await Qe(r,o,Ut(t)),t.json)}catch(e){Qt(e,`run`,o.dryRun)}}function en(e){let t=Object.keys(e);if(t.length){V.stdout.write(`\n${N.bold(`Tokens:`)}\n`);for(let n of t)V.stdout.write(` ${N.dim(Ve(e[n],n))}\n`)}}async function tn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,archived:y,limit:f}));I(n,0,`flow list`);let r=t.limit===`all`?void 0:t.limit,{runs:i,clipped:a}=He({archived:t.archived,limit:r});if(t.json){x(i);return}if(!i.length){V.stdout.write(t.archived?`No archived flow runs.
59
64
  `:`No recent flow runs.
60
- `),L.stdout.write(`\n${h([`Run one: coder flow run <name>`,`Runnable flows: coder flow discover`],N)}\n`);return}let s=N;L.stdout.write(s.bold(s.light(`${`run-id`.padEnd(24)} ${`name`.padEnd(20)} ${`status`.padEnd(10)} ${`tasks`.padEnd(9)} ${`tokens`.padEnd(10)} age\n`)));for(let e of i){let t=Object.values(e.ledger).reduce((e,t)=>e+t.total,0);L.stdout.write(`${s.cyan(_(e.runId,24))} ${_(e.name,20)} ${b(e.status,10)} ${s.light(_(`${e.taskCount} tasks`,9))} ${s.light(_(t?`${v(t)} tok`:`-`,10))} ${s.light(E(ne(e.startedAt)))}\n`)}o&&L.stdout.write(s.dim(`\n... ${o} more not shown (--limit ${r})\n`)),L.stdout.write(`\n${h([`Result: coder flow result <run-id>`,`Tasks: coder list`,`Runnable flows: coder flow discover`],s)}\n`)}async function Dt(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d}));A(n,0,`flow discover`);let r=p(t),i=m(r);if(t.json){k(i);return}if(!i.length){L.stdout.write(`No flows found in .coder/flows/ (workspace) or ~/.coder/flows/ (global).
61
- `),L.stdout.write(`\n${h([`Authoring guide: coder docs flows`],N)}\n`);return}let a=N;L.stdout.write(a.bold(a.light(`${`name`.padEnd(24)} ${`scope`.padEnd(10)} path\n`)));for(let e of i){let t=e.scope===`workspace`?z.relative(r,e.path)||e.path:e.path.replace(Ue.homedir(),`~`);L.stdout.write(`${a.cyan(e.name.padEnd(24))} ${a.light(e.scope.padEnd(10))} ${a.light(t)}\n`)}L.stdout.write(`\n${h([`Run one: coder flow run <name>`,`Recent runs: coder flow list`],a)}\n`)}function Ot(e){let t=Ee(`${P(e.runId)}/journal.jsonl`);return{...e,journal:t.map(e=>({kind:e.kind,taskId:e.taskId,tokens:e.tokens}))}}function kt(e,t,n=`all`){if(t){k(Ot(e));return}let r=N,a=!L.stdout.isTTY;L.stdout.write(`${r.bold(`Flow`)} ${r.cyan(e.name)} ${r.dim(`(${e.runId})`)} — ${r.bold(b(e.status))}\n`);let o=xe(e.runId),s=o.filter(e=>i.includes(e.status)).length,c=e.status===`running`?`${s}/${o.length} tasks`:`${e.taskCount} tasks`;if(L.stdout.write(`${r.dim(`started ${e.startedAt}${e.endedAt?` · ended ${e.endedAt}`:``} · ${c}`)}\n`),n!==0){let t=at(e.runId),i=new Map,s=new Map,c=new Map,l=[];for(let e of t)if(e.kind===`task-start`){let t={name:it(e.name,e.prompt),agent:e.agent,depth:e.depth??0};i.set(e.taskId,t),s.set(e.taskId,t)}else if(e.kind===`task-end`){s.delete(e.taskId);let t=i.get(e.taskId);l.push({depth:t?.depth??0,body:Q(Z(e.status,a),t?.name??null,e.taskId,e.tokens,t?.agent)})}else if(e.kind===`gate-start`)c.set(e.gateId,{cmd:e.cmd,depth:e.depth??0});else if(e.kind===`gate`)e.gateId&&c.delete(e.gateId),l.push({depth:e.depth??0,body:ot(e,a)});else if(e.kind===`log`)for(let t of e.message.split(`
62
- `))l.push({depth:e.depth??0,body:r.light(t),log:!0});else e.kind===`flow-start`&&l.push({depth:e.depth-1,body:r.bold(`flow ${e.name}`)});for(let[e,t]of s)l.push({depth:t.depth??0,body:Q(Z(`running`,a),t.name,e,null,t.agent)+(a?``:` ${r.light(`running`)}`)});for(let e of c.values())l.push({depth:e.depth,body:st(e.cmd,Z(`running`,a))+(a?``:` ${r.light(`running`)}`)});if(!l.length)for(let t of n===`all`?o:xe(e.runId,n))l.push({depth:0,body:Q(Z(t.status,a),t.name,t.taskId??`-`,t.tokens)});let u=pt(l,a),d=n===`all`?u:u.slice(-n);d.length&&L.stdout.write(`\n${d.join(`
63
- `)}\n`)}e.endedAt&&e.result!==void 0&&L.stdout.write(`\n${r.bold(`Result:`)}\n${ae(e.result)}\n`),e.error&&L.stdout.write(`\n${r.red(`error:`)} ${e.error}\n`),Tt(e.ledger);let l=e.status===`running`?[`Follow live: coder flow stream ${e.runId}`,`Stop it: coder flow stop ${e.runId}`]:e.status===`stopped`||e.status===`failed`?[`Resume: coder flow resume ${e.runId}`]:[];l.length&&L.stdout.write(`\n${h(l,r)}\n`)}async function At(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,tail:o})),r=n[0]?j(n[0]):M();if(!r){if(t.json){k(null);return}y(n[0]?`No flow run "${n[0]}".`:`No flow runs yet.`,{hint:`Run one: coder flow run <name>`})}kt(r,!!t.json,t.tail)}async function jt(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,tail:o})),r=n[0]?j(n[0]):M();r||y(n[0]?`No flow run "${n[0]}".`:`No flow runs yet.`,{hint:`Run one: coder flow run <name>`}),await yt(r.runId,{json:t.json,stream:!0,tail:t.tail})}async function Mt(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,"keep-tasks":d}));A(n,1,`flow stop`);try{let e=await De(n[0],{keepTasks:t[`keep-tasks`]});if(t.json){k(e);return}let r=N;e.status===`failed`?L.stdout.write(`${r.dim(`[flow]`)} run ${r.cyan(e.runId)} orchestrator died — marked ${b(`failed`)}.\n`):L.stdout.write(`${r.dim(`[flow]`)} run ${r.cyan(e.runId)} ${b(e.status)}.\n`),e.stoppedTasks.length&&L.stdout.write(`${r.dim(`[flow]`)} stopped tasks: ${e.stoppedTasks.join(`, `)}\n`),e.keptTasks.length&&L.stdout.write(`${r.dim(`[flow]`)} left running: ${e.keptTasks.join(`, `)}\n`),L.stdout.write(`\n${h([`Resume: coder flow resume ${e.runId}`],r)}\n`)}catch(e){throw e instanceof S&&e.code===`flow-failed`&&y(e.message,e.hint?{hint:e.hint}:{}),e}}async function Nt(e){let{options:t,positionals:n}=c(e,B.object(bt)),r=n[0]?j(n[0]):M();r||y(n[0]?`No flow run "${n[0]}".`:`No flow runs to resume.`,{hint:`Run one: coder flow run <name>`}),$e(r.script);let i={cwd:p(t),dryRun:t[`dry-run`],concurrency:$(t.concurrency),maxTasks:$(t[`max-tasks`]),...t.args===void 0?{}:{args:Ze(t.args,[])}};if(!await xt(t,i,()=>fe(``,i,r.runId)))try{St(await se(r.runId,i,ht(t)),t.json)}catch(e){Ct(e,`resume`,i.dryRun)}}function Pt(e){let t=j(e);return t||y(`No flow run "${e}".`,{hint:`Recent runs: coder flow list`}),(t.status===`running`||t.status===`queued`)&&y(`Run ${t.runId} is still running.`,{hint:`Stop it first: coder flow stop ${t.runId}`}),t}async function Ft(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,"all-stopped":d}));if(A(n,1,`flow archive`),t[`all-stopped`]){let e=ue().filter(e=>e.status!==`running`&&e.status!==`queued`);for(let t of e)ge(t);let n=e.map(e=>e.runId);if(t.json){k({archived:n,count:n.length});return}L.stdout.write(n.length?`Archived ${n.length} stopped run${n.length===1?``:`s`}.\n`:`${N.dim(`No stopped runs to archive.`)}\n`);return}let r=n[0];r||y(`Missing run id.`,{hint:[`Archive one: coder flow archive <run-id>`,`Archive all stopped: coder flow archive --all-stopped`]});let i=Pt(r);if(ge(i),t.json){k({runId:i.runId,archived:!0});return}L.stdout.write(`Archived run ${N.cyan(i.runId)}.\n`)}async function It(e){let{options:t,positionals:n}=c(e,B.object({cwd:f,json:d,"all-archived":d}));if(A(n,1,`flow delete`),t[`all-archived`]){let e=we().filter(e=>ce(e.runId)).map(e=>e.runId);if(t.json){k({deleted:e,count:e.length});return}L.stdout.write(e.length?`Deleted ${e.length} archived run${e.length===1?``:`s`}.\n`:`${N.dim(`No archived runs to delete.`)}\n`);return}let r=n[0];r||y(`Missing run id.`,{hint:[`Delete one: coder flow delete <run-id>`,`Delete all archived: coder flow delete --all-archived`]});let i=Pt(r);if(ce(i.runId),t.json){k({runId:i.runId,deleted:!0});return}L.stdout.write(`Deleted run ${N.cyan(i.runId)}.\n`)}const Lt={run:wt,list:Et,discover:Dt,result:At,stream:jt,stop:Mt,resume:Nt,archive:Ft,delete:It};async function Rt(e){let[t,...n]=e;if(t===void 0||t===`help`||t===`-h`||t===`--help`){L.stdout.write(G());return}let r=Lt[t];if(r||(L.stdout.write(G()),L.stdout.write(`
64
- `),y(`Unknown flow subcommand "${t}".`,{hint:`Run a flow: coder flow run <name>`})),Y(n)){L.stdout.write(K(`flow ${t}`)??G());return}await r(n)}async function zt(i){let{options:a,positionals:s}=c(i,B.object({...u,tail:o,wait:d}));A(s,1,`task result`);let l=p(a),f=T(l,s[0]);if(a.wait){e.includes(f.status)&&L.stderr.write(`${N.dim(`[coder] waiting for task ${f.id} to finish...`)}\n`);let t=await Te(l,f);f=t.job,t.reason===`approval`&&de(f.id,t.approval,a.json)}let{steps:m,result:g}=re(l,f.id,{tail:a.tail}),_=Oe(n(l,f.id)).filter(e=>!e.response),v=e.includes(f.status),y=v?r(l,f.id,1)[0]:void 0,x=v?t(l,f):f.updatedAt,S=ne(x),C=v&&_.length===0&&S>6e5,w=()=>{a.wait&&L.exit(f.status===`completed`?0:1)};if(a.json)return k({taskId:f.id,name:f.name??null,prompt:f.prompt??null,system:f.system??null,status:f.status,agent:f.agent,model:f.model??null,effort:f.effort??null,permissions:f.permissions??null,cwd:f.cwd??null,...v?{idleMs:S,lastActivityAt:x??null,stalled:C}:{},pendingApprovals:_.map(e=>({id:e.id,summary:e.summary})),...m.length?{steps:m}:{},result:g}),w();let D=N,O=[`${D.dim(`task`)} ${D.cyan(f.id)}`,...f.name?[`${D.dim(`name`)} ${f.name}`]:[],`${D.dim(`status`)} ${b(f.status)}`,`${D.dim(`agent`)} ${je(f)}`,...ee(f,D),...g?.tokens?[`${D.dim(`tokens`)} ${ie(g.tokens,g.model??f.model)}`]:[]];if(f.prompt&&O.push(``,...oe(f.prompt,D)),_.length){O.push(``,D.dim(`pending approvals:`));for(let e of _)O.push(` ${D.cyan(e.id)} ${e.summary}`)}if(m.length){O.push(``,D.dim(`steps:`));for(let e of m){let t=e.message??e.kind;t&&O.push(` ${D.dim(be(t))}`)}}if(v&&y){let e=y.message??y.kind??``;O.push(`${D.dim(`last`)} ${D.dim(`${be(e)} (${E(S)} ago)`)}`)}if(O.push(``),g?O.push(te({...g,error:g.error??void 0},f.error,`(no final message)`,D)):v?O.push(D.dim(C?`Result pending, but no progress for ${E(S)} — the task may be stalled.`:`Result pending — task is still running.`)):O.push(D.dim(`(no result)`)),v&&!a.wait){let e=[`Wait for it: coder task result ${f.id} --wait`,`Follow live: coder task stream ${f.id}`];C&&e.push(`Check the transcript: coder task result ${f.id} --tail all`),O.push(``,h(e,D))}return L.stdout.write(`${O.join(`
65
- `)}\n`),g?.touchedFiles?.length&&L.stderr.write(`[coder] touched files: ${g.touchedFiles.join(`, `)}\n`),w()}async function Bt(e){let{options:t,positionals:r}=c(e,B.object(u));A(r,1,`task approvals`);let i=p(t),a=T(i,r[0]),o=Oe(n(i,a.id)).map(e=>({id:e.id,summary:e.summary,createdAt:e.createdAt,answered:e.response?.decision??null}));if(t.json){k(o);return}if(!o.length){L.stdout.write(`${N.dim(`No approvals for task ${a.id}.`)}\n`);return}let s=N;for(let e of o){let t=e.answered??`pending`;L.stdout.write(`${s.cyan(e.id)} ${t.padEnd(8)} ${s.dim(e.summary)}\n`)}}async function Vt(e){let{options:t,positionals:r}=c(e,B.object({...u,deny:d}));A(r,2,`task approve`);let i=p(t),[a,o]=r;(!a||!o)&&y(`Missing task id or approval id.`,{hint:[`List them: coder task approvals <task-id>`,`Usage: coder task approve <task-id> <id> [--deny]`]});let s=T(i,a),l=t.deny?`decline`:`accept`;if(Ae(n(i,s.id),o,l),t.json){k({taskId:s.id,approvalId:o,decision:l});return}L.stdout.write(`${t.deny?`Denied`:`Approved`} ${N.cyan(o)} on task ${N.cyan(s.id)}.\n`)}L.stdout.on(`error`,e=>{throw e.code===`EPIPE`&&L.exit(0),e});const Ht={run:Ne,list:Be,stream:I,result:zt,steer:Pe,stop:O,archive:g,delete:ze,approvals:Bt,approve:Vt};async function Ut(e){let[t,...n]=e;if(t===void 0||t===`help`||t===`-h`||t===`--help`){L.stdout.write(q());return}let r=Ht[t];if(r||(L.stdout.write(q()),y(`Unknown task subcommand "${t}".`,{hint:`Run a task: coder run "<text>"`})),Y(n)){L.stdout.write(K(`task ${t}`)??q());return}await r(n)}const Wt={task:Ut,flow:Rt,run:Ne,list:Be,stream:I,result:zt,steer:Pe,stop:O,archive:g,delete:ze,approvals:Bt,approve:Vt,watch:I,config:Ie,"setup-host":F,"host-setup":F,setup:F,model:Fe,docs:Le,upgrade:Re,update:Re,_worker:Me,_refreshUpdate:async()=>he(l()),_archiveSweep:C};async function Gt(){let[e,...t]=L.argv.slice(2);if(e===`--version`||e===`-v`){L.stdout.write(`${l()}\n`);return}if(e===void 0||e===`help`||e===`--help`||e===`-h`){if(t[0]===`task`&&t[1]===void 0){L.stdout.write(q());return}if(t[0]===`model`&&t[1]===void 0){L.stdout.write(Je());return}if(t[0]===`flow`&&t[1]===void 0){L.stdout.write(G());return}let e=t.map(e=>(e===`task`||e===`model`||e===`flow`)&&t[1]?`${e} ${t[1]}`:W[e]??e).find(e=>U[e]);L.stdout.write(e&&K(e)||J());return}e!==`_worker`&&e!==`_refreshUpdate`&&e!==`_archiveSweep`&&w(l(),s);let n=Wt[e];if(n||(L.stdout.write(J()),L.stdout.write(`
66
- `),y(`Unknown command "${e}".`,{hint:`See all commands: coder --help`})),e===`model`&&Y(t)){let e=t.find(e=>!e.startsWith(`-`));L.stdout.write(e&&K(`model ${e}`)||Je());return}if(e!==`task`&&e!==`flow`&&Y(t)){let t=W[e]??e;L.stdout.write(K(t)??J());return}try{await n(t)}catch(t){let n=t instanceof Error?t.message:String(t);throw/^(Unknown option|Missing value)/.test(n)&&U[W[e]??e]&&y(n,{hint:`Help: coder ${e} --help`}),t}}Gt().catch(e=>{L.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),L.exit(1)});export{};
65
+ `),V.stdout.write(`\n${M([`Run one: coder flow run <name>`,`Runnable flows: coder flow discover`],N)}\n`);return}let o=N,s=(e,t,n)=>Math.min(t,Math.max(e,...n.map(e=>e.length))),c={id:s(6,28,i.map(e=>e.runId)),name:s(4,30,i.map(e=>e.name))};V.stdout.write(o.bold(o.light(`${`run-id`.padEnd(c.id)} ${`name`.padEnd(c.name)} ${`status`.padEnd(10)} ${`tasks`.padEnd(9)} ${`tokens`.padEnd(10)} age\n`)));for(let e of i){let t=Object.values(e.ledger).reduce((e,t)=>e+t.total,0);V.stdout.write(`${o.cyan(z(e.runId,c.id))} ${z(e.name,c.name)} ${j(e.status,10)} ${o.light(z(`${e.taskCount} tasks`,9))} ${o.light(z(t?`${ie(t)} tok`:`-`,10))} ${o.light(D(k(e.startedAt)))}\n`)}a&&V.stdout.write(o.dim(`\n... ${a} more not shown (--limit ${r})\n`)),V.stdout.write(`\n${M([`Result: coder flow result <run-id>`,`Tasks: coder list`,`Runnable flows: coder flow discover`],o)}\n`)}async function nn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y}));I(n,0,`flow discover`);let r=F(t),i=ee(r);if(t.json){x(i);return}if(!i.length){V.stdout.write(`No flows found in .coder/flows/ (workspace) or ~/.coder/flows/ (global).
66
+ `),V.stdout.write(`\n${M([`Authoring guide: coder docs flows`],N)}\n`);return}let a=N;V.stdout.write(a.bold(a.light(`${`name`.padEnd(24)} ${`scope`.padEnd(10)} path\n`)));for(let e of i){let t=e.scope===`workspace`?U.relative(r,e.path)||e.path:e.path.replace(pt.homedir(),`~`);V.stdout.write(`${a.cyan(e.name.padEnd(24))} ${a.light(e.scope.padEnd(10))} ${a.light(t)}\n`)}V.stdout.write(`\n${M([`Run one: coder flow run <name>`,`Recent runs: coder flow list`],a)}\n`)}function rn(e){let t=Je(`${R(e.runId)}/journal.jsonl`);return{...e,journal:t.map(e=>({kind:e.kind,taskId:e.taskId,tokens:e.tokens}))}}function an(e,t,r=`all`){if(t){x(rn(e));return}let i=N,a=!V.stdout.isTTY;V.stdout.write(`${i.bold(`Flow`)} ${i.cyan(e.name)} ${i.dim(`(${e.runId})`)} — ${i.bold(j(e.status))}\n`);let o=Ue(e.runId),s=o.filter(e=>n.includes(e.status)).length,c=e.status===`running`?`${s}/${o.length} tasks`:`${e.taskCount} tasks`;if(V.stdout.write(`${i.dim(`started ${e.startedAt}${e.endedAt?` · ended ${e.endedAt}`:``} · ${c}`)}\n`),r!==0){let t=Nt(e.runId),n=new Map,s=new Map,c=new Map,l=[];for(let e of t)if(e.kind===`task-start`){let t={name:Mt(e.name,e.prompt),agent:e.agent,depth:e.depth??0};n.set(e.taskId,t),s.set(e.taskId,t)}else if(e.kind===`task-end`){s.delete(e.taskId);let t=n.get(e.taskId);l.push({depth:t?.depth??0,body:$(Q(e.status,a),t?.name??null,e.taskId,e.tokens,t?.agent)})}else if(e.kind===`gate-start`)c.set(e.gateId,{cmd:e.cmd,depth:e.depth??0});else if(e.kind===`gate`)e.gateId&&c.delete(e.gateId),l.push({depth:e.depth??0,body:Pt(e,a)});else if(e.kind===`log`)for(let t of e.message.split(`
67
+ `))l.push({depth:e.depth??0,body:i.light(t),log:!0});else e.kind===`flow-start`&&l.push({depth:e.depth-1,body:i.bold(`flow ${e.name}`)});for(let[e,t]of s)l.push({depth:t.depth??0,body:$(Q(`running`,a),t.name,e,null,t.agent)+(a?``:` ${i.light(`running`)}`)});for(let e of c.values())l.push({depth:e.depth,body:Ft(e.cmd,Q(`running`,a))+(a?``:` ${i.light(`running`)}`)});if(!l.length)for(let t of r===`all`?o:Ue(e.runId,r))l.push({depth:0,body:$(Q(t.status,a),t.name,t.taskId??`-`,t.tokens)});let u=Vt(l,a),d=r===`all`?u:u.slice(-r);d.length&&V.stdout.write(`\n${d.join(`
68
+ `)}\n`)}e.endedAt&&e.result!==void 0&&V.stdout.write(`\n${i.bold(`Result:`)}\n${E(e.result)}\n`),e.error&&V.stdout.write(`\n${i.red(`error:`)} ${e.error}\n`),en(e.ledger);let l=e.status===`running`?[`Follow live: coder flow watch ${e.runId}`,`Stop it: coder flow stop ${e.runId}`]:e.status===`stopped`||e.status===`failed`?[`Resume: coder flow resume ${e.runId}`]:[];l.length&&V.stdout.write(`\n${M(l,i)}\n`)}async function on(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,tail:p})),r=n[0]?P(n[0]):Pe();if(!r){if(t.json){x(null);return}C(n[0]?`No flow run "${n[0]}".`:`No flow runs yet.`,{hint:`Run one: coder flow run <name>`})}an(r,!!t.json,t.tail)}async function sn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,tail:p})),r=n[0]?P(n[0]):Pe();r||C(n[0]?`No flow run "${n[0]}".`:`No flow runs yet.`,{hint:`Run one: coder flow run <name>`}),await qt(r.runId,{json:t.json,stream:!0,tail:t.tail})}async function cn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,"keep-tasks":y}));I(n,1,`flow stop`);try{let e=await Xe(n[0],{keepTasks:t[`keep-tasks`]});if(t.json){x(e);return}let r=N;e.status===`failed`?V.stdout.write(`${r.dim(`[flow]`)} run ${r.cyan(e.runId)} orchestrator died — marked ${j(`failed`)}.\n`):V.stdout.write(`${r.dim(`[flow]`)} run ${r.cyan(e.runId)} ${j(e.status)}.\n`),e.stoppedTasks.length&&V.stdout.write(`${r.dim(`[flow]`)} stopped tasks: ${e.stoppedTasks.join(`, `)}\n`),e.keptTasks.length&&V.stdout.write(`${r.dim(`[flow]`)} left running: ${e.keptTasks.join(`, `)}\n`),V.stdout.write(`\n${M([`Resume: coder flow resume ${e.runId}`],r)}\n`)}catch(e){throw e instanceof A&&e.code===`flow-failed`&&C(e.message,e.hint?{hint:e.hint}:{}),e}}async function ln(e){let{options:t,positionals:n}=g(e,W.object(Jt)),r=n[0]?P(n[0]):Pe();r||C(n[0]?`No flow run "${n[0]}".`:`No flow runs to resume.`,{hint:`Run one: coder flow run <name>`}),Dt(r.script);let i={cwd:F(t),dryRun:t[`dry-run`],concurrency:Yt(t.concurrency),maxTasks:Yt(t[`max-tasks`]),...t.args===void 0?{}:{args:Tt(t.args,[])}};if(!await Xt(t,i,()=>Ae(``,i,r.runId)))try{Zt(await be(r.runId,i,Ut(t)),t.json)}catch(e){Qt(e,`resume`,i.dryRun)}}function un(e){let t=P(e);return t||C(`No flow run "${e}".`,{hint:`Recent runs: coder flow list`}),(t.status===`running`||t.status===`queued`)&&C(`Run ${t.runId} is still running.`,{hint:`Stop it first: coder flow stop ${t.runId}`}),t}async function dn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,"all-stopped":y}));if(I(n,1,`flow archive`),t[`all-stopped`]){let e=De().filter(e=>e.status!==`running`&&e.status!==`queued`);for(let t of e)Ie(t);let n=e.map(e=>e.runId);if(t.json){x({archived:n,count:n.length});return}V.stdout.write(n.length?`Archived ${n.length} stopped run${n.length===1?``:`s`}.\n`:`${N.dim(`No stopped runs to archive.`)}\n`);return}let r=n[0];r||C(`Missing run id.`,{hint:[`Archive one: coder flow archive <run-id>`,`Archive all stopped: coder flow archive --all-stopped`]});let i=un(r);if(Ie(i),t.json){x({runId:i.runId,archived:!0});return}V.stdout.write(`Archived run ${N.cyan(i.runId)}.\n`)}async function fn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b,json:y,"all-archived":y}));if(I(n,1,`flow delete`),t[`all-archived`]){let e=Ke().filter(e=>Se(e.runId)).map(e=>e.runId);if(t.json){x({deleted:e,count:e.length});return}V.stdout.write(e.length?`Deleted ${e.length} archived run${e.length===1?``:`s`}.\n`:`${N.dim(`No archived runs to delete.`)}\n`);return}let r=n[0];r||C(`Missing run id.`,{hint:[`Delete one: coder flow delete <run-id>`,`Delete all archived: coder flow delete --all-archived`]});let i=un(r);if(Se(i.runId),t.json){x({runId:i.runId,deleted:!0});return}V.stdout.write(`Deleted run ${N.cyan(i.runId)}.\n`)}const pn={run:$t,list:tn,discover:nn,result:on,watch:sn,stream:sn,stop:cn,resume:ln,archive:dn,delete:fn};async function mn(e){let[t,...n]=e;if(t===void 0||t===`help`||t===`-h`||t===`--help`){V.stdout.write(J());return}let r=pn[t];if(r||(V.stdout.write(J()),V.stdout.write(`
69
+ `),C(`Unknown flow subcommand "${t}".`,{hint:`Run a flow: coder flow run <name>`})),Z(n)){let e=t===`stream`?`watch`:t;V.stdout.write(Y(`flow ${e}`)??J());return}await r(n)}function hn(e){return e.resumeThreadId?e.currentPrompt??e.prompt??``:`<system>
70
+ You are running inside a coder task: do the work yourself, directly.
71
+ Do not load the coder skill (recursive), and never dispatch through the \`coder\` CLI - nested dispatch is disabled.
72
+ When finished, provide a concise implementation result summary.
73
+ Your turn is one-shot: background processes will not re-invoke you after it ends, so verify synchronously before finishing.${e.system?`\n-------\n${e.system}`:``}
74
+ </system>
75
+
76
+ ${e.prompt??``}`}function gn(e,t){let n=0;return()=>{Date.now()-n>=1e4&&(n=Date.now(),c(e,t))}}function _n(e,t,{echo:n}){return r=>{let i=typeof r==`string`?{message:r}:r;u(e,t,i),n&&i.message&&V.stderr.write(`[coder] ${i.message}\n`)}}async function vn(t,n,{echo:a}){let o=i(t),s=r(t,n.id),c=ze(t),l=_n(t,n.id,{echo:a}),d=L[n.permissions??`auto`]??L.auto,f=d.approvalPolicy===`never`?void 0:Ze({workspaceRoot:o,jobDir:s,mode:d.approvalMode,escalationTimeoutMs:c.approvals.escalationTimeoutMs,allowedNetworkHosts:c.approvals.allowedNetworkHosts,onEvent:e=>{u(t,n.id,e),a&&e.message&&V.stderr.write(`[coder] ${e.message}\n`)}}),p=n.model?c.models?.[n.model]:void 0,m=p&&we(p)?p:void 0;if(m&&!m.wireApi&&n.model){let e=await tt(m);e&&(m={...m,...e},c.models[n.model]=m,Fe(t,n.model,e),u(t,n.id,{kind:`info`,message:`detected wire api for ${n.model}: ${e.wireApi} @ ${m.baseUrl}`}))}if(m?.envKey&&!V.env[m.envKey])throw Error(`Missing environment variable: \`${m.envKey}\`.`);let h=m?await it(m,m.wireApi??`chat`):null,g=Oe(c,n.model,h??void 0);try{let r=await xe(t,{prompt:hn(n),model:g?.model??qe(n.model),modelProvider:g?.modelProvider??null,configOverrides:g?.configOverrides??null,effort:n.effort,sandbox:d.sandbox,approvalPolicy:d.approvalPolicy,onApprovalRequest:f,onHeartbeat:gn(t,n.id),resumeThreadId:n.resumeThreadId??null,onProgress:r=>{l(r);let i=typeof r==`object`?r.threadId:null,a=typeof r==`object`?r.turnId:null;(i||a)&&e(t,n.id,{status:`running`,...i?{threadId:i}:{},...a?{turnId:a}:{}})}});return e(t,n.id,{status:r.status===0?`completed`:`failed`,threadId:r.threadId,turnId:r.turnId,completedAt:new Date().toISOString()}),bn(t,n,s,r),r}finally{await h?.close()}}async function yn(t,n,{echo:i}){let a=r(t,n.id),o=_n(t,n.id,{echo:i}),s=L[n.permissions??`auto`]??L.auto,c=await ve(t,{prompt:hn(n),model:n.model,effort:n.effort,permissions:n.permissions,approvalJobId:s.approvalMode===`auto`?n.id:null,resumeSessionId:n.resumeThreadId??null,onHeartbeat:gn(t,n.id),onProgress:r=>{o(r),r.threadId&&e(t,n.id,{status:`running`,threadId:r.threadId})}});return e(t,n.id,{status:c.status===0?`completed`:`failed`,threadId:c.threadId,completedAt:new Date().toISOString()}),bn(t,n,a,c),c}function bn(e,t,n,r){Ne(U.join(n,`result.json`),r);let i={at:new Date().toISOString(),prompt:t.currentPrompt??t.prompt??null,...r};H.appendFileSync(U.join(n,`results.jsonl`),`${JSON.stringify(i)}\n`,`utf8`)}function xn(e){return e.engine===`claude`?yn:vn}async function Sn(t,n){for(let r=0;r<2;){let i=h(t,n);if(!i||i.status===`failed`||i.status===`cancelled`)return;let a=d(t,n);if(a.length===0){r+=1,await new Promise(e=>setTimeout(e,300));continue}r=0;for(let r of a){let a=e(t,n,{status:`running`,currentPrompt:r,resumeThreadId:i.threadId??null});u(t,n,{message:`Running steered follow-up.`});try{await xn(a)(t,a,{echo:!1})}catch(r){let i=r instanceof Error?r.message:String(r);e(t,n,{status:`failed`,error:i}),u(t,n,{kind:`error`,message:i});return}}}}function Cn(e,t){if(e instanceof A)switch(e.code){case`chain-exhausted`:x(e.payload),V.exit(3);case`read-only-unavailable`:wn(e.message,t);break;case`startup-failed`:t.json&&(x({taskId:e.taskId,status:`failed`,detail:e.message}),V.exit(1)),C(`Task ${e.taskId} failed to start.${e.message?`\n${e.message}`:``}`,{hint:`See: coder task result ${e.taskId}`});break;default:C(e.message,e.hint?{hint:e.hint}:{})}throw e}function wn(e,t){let n=`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.`;t.json?x({error:n,code:`read-only-unavailable`,detail:e}):V.stderr.write(`[coder] ${n}\n`),V.exit(1)}async function Tn(e){V.env.CODER_WORKER&&C(`Nested dispatch refused: this shell is already inside a coder task. Do the work yourself, directly in this session - ignore any skill or instruction telling you to orchestrate via the coder CLI.`);let{options:t,positionals:n}=g(e,W.object({...v,agent:b,model:b,effort:b,permissions:b,resume:b,host:b,name:b,system:b,background:y,wait:y,"simulate-approval":y})),r=F(t),i=n.join(` `).trim();i||C(`Missing task text.`,{hint:[`Usage: coder run "<task text>"`,`Help: coder task run --help`]});let a={prompt:i,cwd:r,agent:t.agent,model:t.model,effort:t.effort,permissions:t.permissions,name:t.name,system:t.system,resume:t.resume,wait:t.wait,simulateApproval:t[`simulate-approval`],onFallback:({agent:e,detail:t,next:n})=>V.stderr.write(`[coder] ${e} failed to start (${t}); falling back to ${n}.\n`),onInstallNote:e=>V.stderr.write(`[coder] ${e}\n`)},o;try{o=await O(a)}catch(e){Cn(e,t)}if(t.wait)for(;;){let e=o.taskId,n=o.job,s=[` result: coder task result ${e}`,` steer: coder task steer ${e} "<follow-up>"`].join(`
77
+ `);t.json||(V.stderr.write(`${N.dim(`[coder]`)} task ${N.cyan(e)} started (${n.status}); waiting for it to finish — Ctrl-C to detach (it keeps running).\n`),V.stderr.write(`${N.dim(s)}\n`));let c=()=>{V.stderr.write(`\n${N.dim(`[coder] detached — task still running: coder task result ${e}`)}\n`),V.exit(130)};V.on(`SIGINT`,c);let l;try{l=await S(r,e)}catch(n){throw V.off(`SIGINT`,c),n instanceof A&&n.code===`approval-pending`&&je(e,n.approval,t.json),n}V.off(`SIGINT`,c);let u=l.job,d=l.result,f=d?.error?.message??``;if(u.status===`failed`&&ae(u.permissions??`auto`,f)&&wn(f,t),u.status===`failed`&&se.test(f)){let e=ze(r).chain,n=e[e.indexOf(o.agent)+1];n||(x(re(o.agent,f,u.permissions??`auto`,t.system,i)),V.exit(3)),V.stderr.write(`[coder] ${o.agent} failed to start (${f}); falling back to ${n}.\n`);try{o=await O({...a,agent:n,model:void 0,effort:void 0,name:void 0,resume:void 0,simulateApproval:void 0})}catch(e){Cn(e,t)}continue}if(t.json)x({taskId:e,status:u.status,finalMessage:d?.finalMessage,...f?{error:f}:{},tokens:d?.tokens??null,model:d?.model??u.model??null});else{V.stdout.write(`\n${d?.finalMessage||(f?`${N.red(`error:`)} ${f}`:`(no final message)`)}\n\n`);let t=d?.tokens?` tokens=${Ve(d.tokens,d.model??u.model)}`:``;V.stderr.write(`${N.dim(`[coder] task=${e} status=${u.status}${t}`)}\n`)}V.exit(u.status===`completed`?0:1)}let s=o.taskId,c=o.job,l=[` result: coder task result ${s}`,` steer: coder task steer ${s} "<follow-up>"`].join(`
78
+ `);if(t.json){x({taskId:s,status:c.status,startupCheck:o.startupCheck,commands:{result:`coder task result ${s}`,steer:`coder task steer ${s} "<follow-up>"`,stop:`coder task stop ${s}`,watch:`coder task watch ${s}`}});return}V.stdout.write(`${N.dim(`[coder]`)} task ${N.cyan(s)} started in the background (${c.status}).\n`),V.stdout.write(`${N.dim(l)}\n`)}async function En(t){let{options:n,positionals:i}=g(t,W.object({cwd:b})),a=F(n),o=i[0],s=h(a,o);s||C(`Worker: task ${o} not found.`),e(a,o,{status:`running`,pid:V.pid});try{if(s.simulateApproval){let t=await ne(r(a,o),{onEvent:e=>u(a,o,e)});if(u(a,o,{message:`simulated approval: ${t}`}),t===`decline`){e(a,o,{status:`cancelled`,completedAt:new Date().toISOString(),error:`simulated approval denied`});return}}await xn(s)(a,s,{echo:!1}),await Sn(a,o)}catch(t){let n=t instanceof Error?t.message:String(t);e(a,o,{status:`failed`,error:n}),u(a,o,{kind:`error`,message:n}),V.exit(1)}}async function Dn(e){let{options:n,positionals:i}=g(e,W.object({...v,tail:p,wait:y,turns:y}));I(i,1,`task result`);let s=F(n),c=Le(s,i[0]);if(n.wait){l.includes(c.status)&&V.stderr.write(`${N.dim(`[coder] waiting for task ${c.id} to finish...`)}\n`);let e=await $e(s,c);c=e.job,e.reason===`approval`&&je(c.id,e.approval,n.json)}let{steps:u,result:d}=ue(s,c.id,{tail:n.tail}),f=o(s,c.id),m=me(r(s,c.id)).filter(e=>!e.response),h=l.includes(c.status),_=h&&m.length?`waiting-approval`:c.status,b=h?a(s,c.id,1)[0]:void 0,ee=h?t(s,c):c.updatedAt,S=k(ee),C=h&&m.length===0&&S>6e5,te=()=>{n.wait&&V.exit(c.status===`completed`?0:1)};if(n.json)return x({taskId:c.id,name:c.name??null,prompt:c.prompt??null,system:c.system??null,status:_,agent:c.agent,model:c.model??null,effort:c.effort??null,permissions:c.permissions??null,cwd:c.cwd??null,createdAt:c.createdAt??null,completedAt:c.completedAt??null,...h?{idleMs:S,lastActivityAt:ee??null,stalled:C}:{},pendingApprovals:m.map(e=>({id:e.id,summary:e.summary})),...u.length?{steps:u}:{},turnCount:f.length,...n.turns?{turns:f}:{},result:d}),te();let w=N,ne=c.createdAt?k(c.createdAt):null,re=!h&&c.completedAt?k(c.completedAt):null,T=c.createdAt&&c.completedAt?Date.parse(c.completedAt)-Date.parse(c.createdAt):null,E=h?ne===null?``:`started ${D(ne)} ago`:[re===null?``:`finished ${D(re)} ago`,T!==null&&T>=0?`took ${D(T)}`:``].filter(Boolean).join(` · `),O=[`${w.dim(`task`)} ${w.cyan(c.id)}`,...c.name?[`${w.dim(`name`)} ${c.name}`]:[],`${w.dim(`status`)} ${j(_)}${E?` ${w.dim(`(${E})`)}`:``}`,`${w.dim(`agent`)} ${he(c)}`,...ye(c,w),...d?.tokens?[`${w.dim(`tokens`)} ${Ve(d.tokens,d.model??c.model)}`]:[]];if(c.prompt&&O.push(``,...ke(c.prompt,w)),m.length){O.push(``,w.dim(`pending approvals:`));for(let e of m)O.push(` ${w.cyan(e.id)} ${e.summary}`),O.push(` ${w.bold(`coder approve ${c.id} ${e.id}`)} ${w.dim(`(--deny to reject)`)}`)}if(u.length){O.push(``,w.dim(`steps:`));for(let e of u){let t=e.message??e.kind;t&&O.push(` ${w.dim(We(t))}`)}}if(O.push(``),n.turns&&f.length?f.forEach((e,t)=>{t&&O.push(``),O.push(w.dim(`— turn ${t+1} of ${f.length}: ${We(String(e.prompt??``))}`)),O.push(String(e.finalMessage||w.dim(`(no final message)`)))}):d?(O.push(ge({...d,error:d.error??void 0},c.error,`(no final message)`,w)),f.length>1&&O.push(w.dim(`(turn ${f.length} of ${f.length} — all answers: coder task result ${c.id} --turns)`))):h?O.push(w.dim(C?`Result pending, but no progress for ${D(S)} — the task may be stalled.${b?` Last: ${We(b.message??b.kind??``)}`:``}`:`Result pending — task is still running.`)):O.push(w.dim(`(no result)`)),h&&!n.wait){let e=[`Wait for it: coder task result ${c.id} --wait`,`Follow live: coder task watch ${c.id}`];C&&e.push(`Check the transcript: coder task result ${c.id} --tail all`),O.push(``,M(e,w))}return V.stdout.write(`${O.join(`
79
+ `)}\n`),d?.touchedFiles?.length&&V.stderr.write(`[coder] touched files: ${d.touchedFiles.join(`, `)}\n`),te()}function On(e){return s(e).filter(e=>l.includes(e.status)).flatMap(t=>me(r(e,t.id)).filter(e=>!e.response).map(e=>({taskId:t.id,id:e.id,summary:String(e.summary??``),createdAt:e.createdAt?String(e.createdAt):void 0})))}async function kn(e){let{options:t,positionals:n}=g(e,W.object(v));I(n,1,`task approvals`);let i=F(t),a=N;if(n[0]){let e=Le(i,n[0]),o=me(r(i,e.id)).map(e=>({id:e.id,summary:e.summary,createdAt:e.createdAt,answered:e.response?.decision??null}));if(t.json){x(o);return}if(!o.length){V.stdout.write(`${a.dim(`No approvals for task ${e.id}.`)}\n`);return}for(let e of o){let t=e.answered??`pending`;V.stdout.write(`${a.cyan(e.id)} ${t.padEnd(8)} ${a.dim(String(e.summary??``))}\n`)}let s=o.filter(e=>!e.answered);s.length&&V.stdout.write(`\n${M([`Answer: coder approve ${s[0].id} [--deny]`],a)}\n`);return}let o=On(i);if(t.json){x(o);return}if(!o.length){V.stdout.write(`${a.dim(`No pending approvals.`)}\n`);return}let s={id:Math.max(11,...o.map(e=>e.id.length)),task:Math.max(7,...o.map(e=>e.taskId.length))};V.stdout.write(a.bold(a.light(`${`approval-id`.padEnd(s.id)} ${`task-id`.padEnd(s.task)} age summary\n`)));for(let e of o){let t=e.createdAt?D(k(e.createdAt)):`-`;V.stdout.write(`${a.cyan(e.id.padEnd(s.id))} ${a.cyan(e.taskId.padEnd(s.task))} ${t.padEnd(5)} ${a.light(e.summary)}\n`)}V.stdout.write(`\n${M([`Answer: coder approve ${o[0].id} [--deny]`],a)}\n`)}async function An(e){let{options:t,positionals:n}=g(e,W.object({...v,deny:y}));I(n,2,`task approve`);let i=F(t),[a,o]=n;a&&!o&&a.startsWith(`apr-`)&&(o=a,a=On(i).find(e=>e.id===o)?.taskId,a||C(`No pending approval "${o}".`,{hint:`List them: coder approvals`})),(!a||!o)&&C(`Missing approval id.`,{hint:[`List them: coder approvals`,`Usage: coder approve [task-id] <approval-id> [--deny]`]});let s=Le(i,a),c=t.deny?`decline`:`accept`;if(Ee(r(i,s.id),o,c),t.json){x({taskId:s.id,approvalId:o,decision:c});return}V.stdout.write(`${t.deny?`Denied`:`Approved`} ${N.cyan(o)} on task ${N.cyan(s.id)}.\n`)}const jn=new Set([`Write`,`Edit`,`MultiEdit`,`NotebookEdit`]);async function Mn(e,t,n){let a=String(n.tool_name??``),o=n.input??n.tool_input??{},s=i(e),c=r(e,t),l=ze(e),d=n=>u(e,t,n),f,p;if(a===`Bash`){let e=String(o.command??``);p=`run command: ${e||`(unknown command)`}`,f=fe(e,{allowedNetworkHosts:l.approvals.allowedNetworkHosts})}else if(jn.has(a)){let e=String(o.file_path??o.notebook_path??``);p=`${a}: ${e||`(unknown path)`}`,f=te(e?[e]:[],s)}else p=`${a||`(unknown tool)`}: ${JSON.stringify(o).slice(0,200)}`,f={decision:`escalate`,reason:`tool needs approval: ${a}`};d({kind:`approval-decision`,method:a,decision:f.decision,reason:f.reason,summary:p});let m=f.decision;return m===`escalate`&&(m=await Ye(c,{method:`claude/${a}`,summary:p,params:{tool_name:a,input:o}},{timeoutMs:l.approvals.escalationTimeoutMs,onEvent:d})),m===`accept`?{behavior:`allow`,updatedInput:o}:{behavior:`deny`,message:`Denied by coder policy: ${f.reason}`}}const Nn={approval_prompt:{description:`Coder approval policy for claude permission prompts.`,inputSchema:{type:`object`,additionalProperties:!0},handler:Mn}};async function Pn(e){let{options:t,positionals:n}=g(e,W.object({cwd:b})),r=F(t),i=n[0],a=e=>V.stdout.write(`${JSON.stringify(e)}\n`),o=mt.createInterface({input:V.stdin,terminal:!1});for await(let e of o){if(!e.trim())continue;let t;try{t=JSON.parse(e)}catch{continue}let{id:n,method:o,params:s}=t;if(o===`initialize`)a({jsonrpc:`2.0`,id:n,result:{protocolVersion:s?.protocolVersion??`2024-11-05`,capabilities:{tools:{}},serverInfo:{name:`coder`,version:_()}}});else if(o===`tools/list`)a({jsonrpc:`2.0`,id:n,result:{tools:Object.entries(Nn).map(([e,t])=>({name:e,description:t.description,inputSchema:t.inputSchema}))}});else if(o===`tools/call`){let e=Nn[String(s?.name??``)],t;try{if(!e)throw Error(`unknown tool: ${s?.name}`);t=await e.handler(r,i,s?.arguments??{})}catch(e){t={behavior:`deny`,message:`coder mcp tool failed: ${e instanceof Error?e.message:String(e)}`}}a({jsonrpc:`2.0`,id:n,result:{content:[{type:`text`,text:JSON.stringify(t)}]}})}else n!==void 0&&a({jsonrpc:`2.0`,id:n,result:{}})}}V.stdout.on(`error`,e=>{throw e.code===`EPIPE`&&V.exit(0),e});const Fn={run:Tn,list:ut,watch:B,stream:B,result:Dn,steer:lt,ask:et,stop:pe,archive:w,delete:ct,approvals:kn,approve:An};async function In(e){let[t,...n]=e;if(t===void 0||t===`help`||t===`-h`||t===`--help`){V.stdout.write(X());return}let r=Fn[t];if(r||(V.stdout.write(X()),C(`Unknown task subcommand "${t}".`,{hint:`Run a task: coder run "<text>"`})),Z(n)){let e=t===`stream`?`watch`:t;V.stdout.write(Y(`task ${e}`)??X());return}await r(n)}const Ln={task:In,flow:mn,run:Tn,list:ut,watch:B,result:Dn,stream:B,steer:lt,ask:et,stop:pe,archive:w,delete:ct,approvals:kn,approve:An,config:rt,"setup-host":at,"host-setup":at,setup:at,model:nt,docs:ot,upgrade:st,update:st,_worker:En,_mcp:Pn,_refreshUpdate:async()=>ce(_()),_archiveSweep:le};async function Rn(){let[e,...t]=V.argv.slice(2);if(e===`--version`||e===`-v`){V.stdout.write(`${_()}\n`);return}if(e===void 0||e===`help`||e===`--help`||e===`-h`){if(t[0]===`task`&&t[1]===void 0){V.stdout.write(X());return}if(t[0]===`model`&&t[1]===void 0){V.stdout.write(bt());return}if(t[0]===`flow`&&t[1]===void 0){V.stdout.write(J());return}let e=t.map(e=>(e===`task`||e===`model`||e===`flow`)&&t[1]?`${e} ${t[1]}`:_t[e]??e).find(e=>q[e]);V.stdout.write(e&&Y(e)||St());return}e!==`_worker`&&e!==`_mcp`&&e!==`_refreshUpdate`&&e!==`_archiveSweep`&&oe(_(),m);let n=Ln[e];if(n||(V.stdout.write(St()),V.stdout.write(`
80
+ `),C(`Unknown command "${e}".`,{hint:`See all commands: coder --help`})),e===`model`&&Z(t)){let e=t.find(e=>!e.startsWith(`-`));V.stdout.write(e&&Y(`model ${e}`)||bt());return}if(e!==`task`&&e!==`flow`&&Z(t)){let t=_t[e]??e;V.stdout.write(Y(t)??St());return}try{await n(t)}catch(t){let n=t instanceof Error?t.message:String(t);if(/^(Unknown option|Missing value)/.test(n)){let t=_t[e]??e;q[t]&&C(n,{hint:`Help: coder ${e} --help`})}throw t}}Rn().catch(e=>{V.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),V.exit(1)});export{};
@@ -1,31 +1,2 @@
1
- import {
2
- _ as FlowStep,
3
- b as GateResult,
4
- d as log,
5
- f as pipeline,
6
- h as FlowEvent,
7
- l as flow,
8
- n as flowSdk,
9
- p as task,
10
- r as CoderError,
11
- t as args,
12
- u as gate,
13
- v as FlowTaskOptions,
14
- y as FlowTaskResult,
15
- } from '../index-CUy_WPvw.js';
16
- export {
17
- CoderError,
18
- type FlowEvent,
19
- type FlowStep,
20
- type FlowTaskOptions,
21
- type FlowTaskResult,
22
- type GateResult,
23
- args,
24
- flowSdk as default,
25
- flowSdk,
26
- flow,
27
- gate,
28
- log,
29
- pipeline,
30
- task,
31
- };
1
+ import { _ as FlowStep, b as GateResult, d as log, f as pipeline, h as FlowEvent, l as flow, n as flowSdk, p as task, r as CoderError, t as args, u as gate, v as FlowTaskOptions, y as FlowTaskResult } from "../index-CTrgzW3M.js";
2
+ export { CoderError, type FlowEvent, type FlowStep, type FlowTaskOptions, type FlowTaskResult, type GateResult, args, flowSdk as default, flowSdk, flow, gate, log, pipeline, task };
@@ -1 +1 @@
1
- import{A as e,C as t,M as n,S as r,_ as i,a,c as o,d as s,f as c,g as l,i as u,m as d,n as f,o as p,r as m,s as h,x as g,y as _}from"../runtime-DRtQOCSz.js";const v=new Proxy({},{get(e,t){return u()?.[t]},has(e,t){let n=u();return n!=null&&t in Object(n)},ownKeys(){let e=u();return e?Reflect.ownKeys(Object(e)):[]},getOwnPropertyDescriptor(e,t){let n=u();if(n!=null&&t in Object(n))return{enumerable:!0,configurable:!0,value:n[t]}}});function y(e){let t=l(e);if(!t)throw new n(`flow-failed`,`No flow run "${e}".`,{hint:`Recent runs: coder flow list`});if(t.status===`running`||t.status===`queued`)throw new n(`flow-failed`,`Run ${t.runId} is still running.`,{runId:t.runId,hint:`Stop it first: coder flow stop ${t.runId}`});return t}const b={run(e,t={}){return _(e,t)},list(e={}){return m(e).runs},discover(t){return e(t??process.cwd())},result(e,t={}){let n=e?l(e):s()[0]??null;return n?{...n,steps:h(n.runId,t.tail)}:null},stream(e,t={}){let n=e??s()[0]?.runId;if(!n)throw Error(`No flow runs to stream.`);return r(n,void 0,{tail:t.tail})},stop(e,t={}){return g(e,t)},resume(e,t={}){let n=e??s()[0]?.runId;if(!n)throw Error(`No flow runs to resume.`);return i(n,t)},archive(e){return f(y(e)),{runId:e,archived:!0}},delete(e){return y(e),{runId:e,deleted:a(e)}}};export{n as CoderError,v as args,b as default,b as flowSdk,p as flow,o as gate,c as log,d as pipeline,t as task};
1
+ import{A as e,C as t,M as n,S as r,_ as i,a,c as o,d as s,f as c,g as l,i as u,m as d,n as f,o as p,r as m,s as h,x as g,y as _}from"../runtime-DVrs6VXX.js";const v=new Proxy({},{get(e,t){return u()?.[t]},has(e,t){let n=u();return n!=null&&t in Object(n)},ownKeys(){let e=u();return e?Reflect.ownKeys(Object(e)):[]},getOwnPropertyDescriptor(e,t){let n=u();if(n!=null&&t in Object(n))return{enumerable:!0,configurable:!0,value:n[t]}}});function y(e){let t=l(e);if(!t)throw new n(`flow-failed`,`No flow run "${e}".`,{hint:`Recent runs: coder flow list`});if(t.status===`running`||t.status===`queued`)throw new n(`flow-failed`,`Run ${t.runId} is still running.`,{runId:t.runId,hint:`Stop it first: coder flow stop ${t.runId}`});return t}const b={run(e,t={}){return _(e,t)},list(e={}){return m(e).runs},discover(t){return e(t??process.cwd())},result(e,t={}){let n=e?l(e):s()[0]??null;return n?{...n,steps:h(n.runId,t.tail)}:null},stream(e,t={}){let n=e??s()[0]?.runId;if(!n)throw Error(`No flow runs to stream.`);return r(n,void 0,{tail:t.tail})},stop(e,t={}){return g(e,t)},resume(e,t={}){let n=e??s()[0]?.runId;if(!n)throw Error(`No flow runs to resume.`);return i(n,t)},archive(e){return f(y(e)),{runId:e,archived:!0}},delete(e){return y(e),{runId:e,deleted:a(e)}}};export{n as CoderError,v as args,b as default,b as flowSdk,p as flow,o as gate,c as log,d as pipeline,t as task};