@agimon-ai/workflow-mcp 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const e=require(`./stdio-Bt5DIqt_.cjs`);let t=require(`node:child_process`),n=require(`node:fs/promises`),r=require(`node:path`),i=require(`node:fs`),a=require(`@agimon-ai/foundation-process-registry`),o=require(`node:readline`),s=require(`commander`),c=require(`node:module`);var l=`0.2.6`;const u=`WORKFLOW_STATUS_FILE`,ee={readStdin:oe,readStatusFile:se,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
3
- `,`utf8`)},workflowStatusFile:process.env[u]};async function te(e=ee){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=d(n);if(!r?.conversationId)return;let i=await e.readStatusFile(t);if(!(i===null||i.trim()===`YES`)){if(!r.fullyIdle){e.writeStdout?.(ne(`In-progress work is still running. Continue the execution loop until background tasks finish.`));return}ie(r.error)||r.terminationReason!==`model_stop`||await e.writeStatusFile(t)}}function d(e){try{let t=JSON.parse(e);return ae(t)?{conversationId:typeof t.conversationId==`string`?t.conversationId:void 0,transcriptPath:re(t.transcriptPath),terminationReason:typeof t.terminationReason==`string`?t.terminationReason:void 0,error:typeof t.error==`string`?t.error:void 0,fullyIdle:t.fullyIdle===!0}:null}catch{return null}}function ne(e){return`${JSON.stringify({decision:`continue`,reason:e})}\n`}function re(e){return typeof e==`string`&&e.trim().length>0?e:null}function ie(e){return typeof e==`string`&&e.trim().length>0}function ae(e){return typeof e==`object`&&!!e}async function oe(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function se(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}const ce=new s.Command(`antigravity-stop-hook`).description(`Antigravity stop hook: reads Stop hook JSON on stdin and marks ${u} when the execution is fully idle`).action(async()=>{await te()});var f=class extends Error{constructor(e,t,n={},r){super(e,r),this.code=t,this.context=n,this.name=`WorkflowCommandError`}};const p=`check-codex-quota`;function le(t={}){let n=t.createService??(()=>new e.i),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(p).description(`Check whether Codex quota is currently blocking new work`).action(async()=>{try{let e=await n().getQuotaStatus();if(a(`${JSON.stringify({blockingLimit:e?.blockingLimit??null,planType:e?.planType??null},null,2)}\n`),e?.blockingLimit){let t=new f(`Codex quota is blocking work at ${e.blockingLimit.limitId}/${e.blockingLimit.window}.`,`CODEX_QUOTA_BLOCKED`,{command:p,limitId:e.blockingLimit.limitId,limitName:e.blockingLimit.limitName,window:e.blockingLimit.window});i(`${t.message} [${t.code}]`,t),r(2);return}r(0)}catch(e){let t=e instanceof f?e:new f(`Error checking Codex quota.`,`CHECK_CODEX_QUOTA_COMMAND_FAILED`,{command:p},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const m=le(),h=`WORKFLOW_STATUS_FILE`,g=`session_meta`,ue=[`sub_agent`,`subagent`],de=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),fe=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),pe={readStdin:y,readStatusFile:b,readTranscriptHead:x,readTranscriptState:S,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
4
- `,`utf8`)},workflowStatusFile:process.env[h]},me={readStdin:y,readStatusFile:b,writeSessionBinding:async(e,t)=>{await(0,n.writeFile)(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[h]};async function he(e=me){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=ye(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function ge(e=pe){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=be(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`)return;let i=xe(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=_(r.transcript_path);if(!a)return;let o=await ve(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||Se(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(!r.hasTaskRegistry&&r.stop_hook_active){await e.writeStatusFile(t);return}if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(_e(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function _e(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function ve(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===x?S(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function ye(e){try{let t=JSON.parse(e);return v(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function be(e){try{let t=JSON.parse(e);if(!v(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:_(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function _(e){return typeof e==`string`&&e.trim().length>0?e:null}function xe(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function Se(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):v(e)?ue.some(t=>t in e):!1}function v(e){return typeof e==`object`&&!!e}async function y(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function b(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}async function x(e){return(await S(e)).sessionMeta}async function S(e){let t=(0,i.createReadStream)(e,{encoding:`utf8`}),n=(0,o.createInterface)({input:t,crlfDelay:1/0}),r=new Set,a=new Map,s=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=Ce(t);n&&(s||=we(n),Te(n,r),Ee(n,a))}}finally{n.close(),t.destroy()}return{sessionMeta:s,hasPendingWork:r.size>0||Array.from(a.values()).some(T)}}function Ce(e){try{let t=JSON.parse(e);return v(t)?t:null}catch{return null}}function we(e){return e.type===g?e.payload??null:e.item?.type===g?e.item.payload??null:null}function Te(e,t){let n=E(e,[`payload`,`item`])??E(e,[`item`,`payload`,`item`]);if(!n)return;let r=D(n.id),i=D(n.type);!r||!i||!fe.has(i)||(T(n.status)?t.add(r):t.delete(r))}function Ee(e,t){let n=E(e,[`payload`])??E(e,[`item`,`payload`]);if(!n||!D(n.type)?.startsWith(`collab_`))return;C(t,D(n.new_thread_id),n.status),C(t,D(n.receiver_thread_id),n.status);let r=E(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))C(t,e,n)}function C(e,t,n){let r=w(n);!t||!r||e.set(t,r)}function w(e){if(typeof e==`string`)return e;if(!v(e))return null;let[t]=Object.keys(e);return t??null}function T(e){let t=typeof e==`string`?e:w(e);return t!==null&&de.has(t)}function E(e,t){let n=e;for(let e of t){if(!v(n))return null;n=n[e]}return v(n)?n:null}function D(e){return typeof e==`string`&&e.length>0?e:void 0}const De=new s.Command(`claude-session-start-hook`).description(`Claude Code SessionStart hook: binds ${h} to the root Claude session id`).action(async()=>{await he()}),Oe=new s.Command(`claude-stop-hook`).description(`Claude Code stop hook: reads Stop hook JSON on stdin and marks ${h} when the root session is complete`).action(async()=>{await ge()}),O=`WORKFLOW_STATUS_FILE`,k=`session_meta`,ke=[`sub_agent`,`subagent`],Ae=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),je=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),Me={readStdin:M,readStatusFile:N,readTranscriptHead:P,readTranscriptState:F,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
5
- `,`utf8`)},workflowStatusFile:process.env[O]},Ne={readStdin:M,readStatusFile:N,writeSessionBinding:async(e,t)=>{await(0,n.writeFile)(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[O]};async function Pe(e=Ne){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Re(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function Fe(e=Me){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=ze(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`||r.stop_hook_active&&!r.hasTaskRegistry)return;let i=Be(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=A(r.transcript_path);if(!a)return;let o=await Le(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||Ve(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(Ie(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function Ie(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function Le(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===P?F(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function Re(e){try{let t=JSON.parse(e);return j(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function ze(e){try{let t=JSON.parse(e);if(!j(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:A(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function A(e){return typeof e==`string`&&e.trim().length>0?e:null}function Be(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function Ve(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):j(e)?ke.some(t=>t in e):!1}function j(e){return typeof e==`object`&&!!e}async function M(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function N(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}async function P(e){return(await F(e)).sessionMeta}async function F(e){let t=(0,i.createReadStream)(e,{encoding:`utf8`}),n=(0,o.createInterface)({input:t,crlfDelay:1/0}),r=new Set,a=new Map,s=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=He(t);n&&(s||=Ue(n),We(n,r),Ge(n,a))}}finally{n.close(),t.destroy()}return{sessionMeta:s,hasPendingWork:r.size>0||Array.from(a.values()).some(R)}}function He(e){try{let t=JSON.parse(e);return j(t)?t:null}catch{return null}}function Ue(e){return e.type===k?e.payload??null:e.item?.type===k?e.item.payload??null:null}function We(e,t){let n=z(e,[`payload`,`item`])??z(e,[`item`,`payload`,`item`]);if(!n)return;let r=B(n.id),i=B(n.type);!r||!i||!je.has(i)||(R(n.status)?t.add(r):t.delete(r))}function Ge(e,t){let n=z(e,[`payload`])??z(e,[`item`,`payload`]);if(!n||!B(n.type)?.startsWith(`collab_`))return;I(t,B(n.new_thread_id),n.status),I(t,B(n.receiver_thread_id),n.status);let r=z(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))I(t,e,n)}function I(e,t,n){let r=L(n);!t||!r||e.set(t,r)}function L(e){if(typeof e==`string`)return e;if(!j(e))return null;let[t]=Object.keys(e);return t??null}function R(e){let t=typeof e==`string`?e:L(e);return t!==null&&Ae.has(t)}function z(e,t){let n=e;for(let e of t){if(!j(n))return null;n=n[e]}return j(n)?n:null}function B(e){return typeof e==`string`&&e.length>0?e:void 0}const Ke=new s.Command(`codex-session-start-hook`).description(`Codex session-start hook: binds ${O} to the first workflow Codex session id`).action(async()=>{await Pe()}),qe=new s.Command(`codex-stop-hook`).description(`Codex stop hook: reads stop-hook JSON on stdin and marks ${O} when the root session ends`).action(async()=>{await Fe()}),V=`list-crons`;function Je(t={}){let n=t.createService??(()=>new e.o),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(V).description(`List cron jobs scheduled via workflow-mcp`).action(async()=>{try{let e=await n().list();a(`${JSON.stringify(e,null,2)}\n`),r(0)}catch(e){let t=new f(`Error listing cron jobs.`,`LIST_CRONS_COMMAND_FAILED`,{command:V},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const Ye=Je(),H=`list-workflow-statuses`;function U(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new s.InvalidArgumentError(`Expected a positive integer.`);return t}function Xe(t={}){let n=t.createRegistry??(()=>new e.a),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(H).description(`List tracked workflow runs and their current stages`).option(`--page <number>`,`Page number to return`,U,1).option(`--page-size <number>`,`Number of workflow runs per page`,U,20).option(`-w, --workspace <name>`,`Filter workflow runs by workspace`,`all`).action(async e=>{try{let t=n(),i=e.workspace===`all`?void 0:e.workspace,o=await t.listRunsPage({page:e.page,pageSize:e.pageSize,workspace:i});a(`${JSON.stringify(o,null,2)}\n`),r(0)}catch(t){let n=new f(`Error listing workflow statuses.`,`LIST_WORKFLOW_STATUSES_FAILED`,{command:H,workspace:e.workspace??`all`},{cause:t});i(`${n.message} [${n.code}]`,n),r(1)}})}const Ze=Xe(),Qe=()=>{try{return(0,c.createRequire)(require(`url`).pathToFileURL(__filename).href)(`@agimon-ai/foundation-process-registry`)}catch{return null}};function W(e,t){for(let n of e){if(n==null||typeof n!=`object`&&typeof n!=`function`)continue;let e=n;for(let n of t){let t=e[n];if(typeof t==`function`)return t}}return null}function $e(e){let t=[e];if(e&&typeof e==`object`){let n=e.default;if(n&&(t.push(n),typeof n==`function`))try{t.push(new n)}catch{}}return t}async function et(e){let t=Qe();if(!t)return async()=>{};let n=$e(t),r=W(n,[`registerProcess`,`register`,`registerProcessInstance`]),i=W(n,[`unregisterProcess`,`unregister`,`releaseProcess`]);if(!r)return async()=>{};try{await Promise.resolve(r({name:e,pid:process.pid,command:process.argv.join(` `)}))}catch{return async()=>{}}return i?async()=>{await Promise.resolve(i({name:e,pid:process.pid}))}:async()=>{}}async function tt(e,t){await e.start();let n=async n=>{console.error(`\\nReceived ${n}, shutting down gracefully...`);let r=0;try{await e.stop()}catch(e){console.error(`Error during shutdown:`,e),r=1}try{await t()}catch(e){console.error(`Error during resource cleanup:`,e),r=1}process.exit(r)};process.on(`SIGINT`,()=>{n(`SIGINT`)}),process.on(`SIGTERM`,()=>{n(`SIGTERM`)})}async function nt(e){try{await e()}catch{}}const rt=new s.Command(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--service-name <name>`,`Service name for registry tracking`,`workflow-mcp`).action(async t=>{let n=await et(t.serviceName);try{let r=t.type.toLowerCase();r===`stdio`?await tt(new e.t(e.n()),n):(console.error(`Unknown transport type: ${r}. Use: stdio`),process.exit(1))}catch(e){await nt(n),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),G=`run-workflow`,K=`RUN_WORKFLOW_COMMAND_FAILED`,q=`WORKFLOW_MCP_BACKGROUND_CHILD`,J=`workflow-mcp-background-run`;function Y(e){if(!e||e.length===0)return;let t={};for(let n of e){let[e,...r]=n.split(`=`);t[e]=r.join(`=`)}return Object.keys(t).length>0?t:void 0}function X(e){if(e.runner&&e.cliAgent&&e.runner!==e.cliAgent)throw new f(`Conflicting runner selectors.`,K,{cliAgent:e.cliAgent,command:G,runner:e.runner});return e.runner??e.cliAgent}function it(e,n){let r=process.argv[1];if(!r)throw new f(`Unable to determine the workflow-mcp CLI entry point for background execution.`,`RUN_WORKFLOW_BACKGROUND_LAUNCH_FAILED`,{command:G,workflow:e,workspace:n.workspace});let i=[r,`run-workflow`,e];n.job&&i.push(`--job`,n.job);for(let e of n.input??[])i.push(`--input`,e);for(let e of n.env??[])i.push(`--env`,e);n.secretFile&&i.push(`--secret-file`,n.secretFile),n.dryRun&&i.push(`--dry-run`),n.continueOnError&&i.push(`--continue-on-error`),n.keepWorktree&&i.push(`--keep-worktree`);let a=X(n);a&&i.push(`--runner`,a),n.prompt&&i.push(`--prompt`,n.prompt),n.name&&i.push(`--name`,n.name),n.workspace&&i.push(`--workspace`,n.workspace);let o=(0,t.spawn)(process.execPath,i,{detached:!0,env:{...process.env,[q]:`1`},stdio:`ignore`});return o.unref(),o.pid}async function at(e,t){if(process.env[q]!==`1`)return async()=>{};let n=new a.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH),i=(0,r.resolve)(process.cwd()),o=process.env.NODE_ENV??`development`;return(await n.registerProcess({repositoryPath:i,serviceName:J,serviceType:`tool`,environment:o,pid:process.pid,command:process.argv.join(` `),args:process.argv.slice(2),metadata:{workflow:e,workspace:t.workspace,job:t.job,name:t.name,runner:t.runner??t.cliAgent},force:!0})).success?async()=>{let e=await n.releaseProcess({repositoryPath:i,serviceName:J,serviceType:`tool`,environment:o,pid:process.pid,kill:!1,releasePort:!1,force:!0});if(!e.success&&!e.error?.includes(`No matching process entry`))throw Error(e.error??`Failed to release workflow background process`)}:async()=>{}}function ot(t={}){let n=t.createService??(()=>new e.r),r=t.exit??(e=>process.exit(e)),i=t.launchBackgroundRun??it,a=t.registerBackgroundChild??at,o=t.logError??((e,t)=>console.error(e,t)),c=t.logInfo??(e=>process.stdout.write(`${e}\n`));return new s.Command(G).description(`Run a GitHub Actions workflow file locally on macOS`).argument(`<workflow>`,`Path to the workflow YAML file`).option(`-j, --job <name>`,`Run only this job (and its dependencies)`).option(`-i, --input <key=value...>`,`Set workflow_dispatch input (repeatable)`).option(`-e, --env <key=value...>`,`Set extra environment variable (repeatable)`).option(`--secret-file <path>`,`Load secrets from a dotenv-style file`).option(`--dry-run`,`Print steps without executing`).option(`--continue-on-error`,`Continue past step failures`).option(`--runner <runner>`,`Preferred runner key for step command maps`).option(`--cli-agent <agent>`,`Deprecated alias for --runner`).option(`-p, --prompt <text>`,`User prompt for user_prompt trigger workflows`).option(`-n, --name <name>`,`Name for the workflow run context directory`).option(`-w, --workspace <name>`,`Workspace for workflow registry storage`).option(`--keep-worktree`,`Keep worktree on completion (skip merge and cleanup for retry)`).option(`--skip-launch`,`Skip launch-command delegation (used by inner invocations)`).option(`-b, --background`,`Run the workflow in a detached background process`).action(async(e,t)=>{try{if(t.background){let n=i(e,t);c(`Started workflow in background${n?` (PID: ${n})`:``}`),r(0);return}let o=await a(e,t),s=n();try{let n=X(t),i=await s.run({cliAgent:t.cliAgent,runner:n,workflowPath:e,job:t.job,inputs:Y(t.input),env:Y(t.env),secretFile:t.secretFile,dryRun:t.dryRun,continueOnError:t.continueOnError,keepWorktree:t.keepWorktree,prompt:t.prompt,name:t.name,workspace:t.workspace,skipLaunch:t.skipLaunch});await o(),r(i.exitCode)}catch(e){throw await o(),e}}catch(n){let i=n instanceof f?n:new f(`Error executing run-workflow.`,K,{background:!!t.background,command:G,workflow:e,workspace:t.workspace},{cause:n});o(`${i.message} [${i.code}]`,i),r(1)}})}const Z=ot(),Q=`schedule-cron`;function st(t={}){let n=t.createService??(()=>new e.o),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(`${e}\n`));return new s.Command(Q).description(`Schedule a headless Claude Code or Codex CLI run via system crontab`).argument(`<name>`,`Unique name for this cron job`).option(`-d, --cwd <path>`,`Working directory for the CLI run`,process.cwd()).option(`-c, --cli <cli>`,`CLI to use: claude or codex`,e.s).option(`-p, --prompt <text>`,`Prompt to pass to the CLI`).option(`-f, --prompt-file <path>`,`Path to a file whose content is used as the prompt (read at cron execution time)`).option(`-s, --schedule <cron>`,`Cron expression (e.g., "*/10 * * * *")`).option(`-i, --interval-minutes <minutes>`,`Run every N minutes (alternative to --schedule)`).action(async(t,o)=>{try{let i=e.c.parse({name:t,cwd:o.cwd??process.cwd(),cli:o.cli??`claude`,prompt:o.prompt,promptFile:o.promptFile,schedule:o.schedule,intervalMinutes:o.intervalMinutes?Number.parseInt(o.intervalMinutes,10):void 0}),s=await n().schedule(i);a(`Scheduled cron job "${s.name}" with schedule: ${s.schedule}`),a(`CLI: ${s.cli} | CWD: ${s.cwd}`),s.prompt&&a(`Prompt: ${s.prompt}`),r(0)}catch(e){let n=e instanceof f?e:new f(`Error scheduling cron job.`,`SCHEDULE_CRON_COMMAND_FAILED`,{command:Q,name:t},{cause:e});i(`${n.message} [${n.code}]`,n),r(1)}})}const ct=st(),$=`stop-workflow`;function lt(t={}){let n=t.createRegistry??(()=>new e.a),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command($).description(`Request a running workflow to stop gracefully`).argument(`<run-key>`,`Running workflow run key`).option(`-w, --workspace <name>`,`Workspace containing the running workflow`,`default`).option(`-r, --reason <text>`,`Optional stop reason to record`).action(async(e,t)=>{try{let i=n(),o=await i.requestStop(t.workspace,e,t.reason);a(`${JSON.stringify({reason:o.reason,requestedAt:o.requestedAt,runKey:e,workspace:i.resolveWorkspace(t.workspace)},null,2)}\n`),r(0)}catch(n){let a=new f(`Error requesting workflow stop.`,`STOP_WORKFLOW_FAILED`,{command:$,runKey:e,workspace:t.workspace},{cause:n});i(`${a.message} [${a.code}]`,a),r(1)}})}const ut=lt();async function dt(){let e=new s.Command;e.name(`workflow-mcp`).description(`MCP server for running GitHub Actions workflows locally`).version(l),e.addCommand(Ye),e.addCommand(Ze),e.addCommand(m),e.addCommand(ce),e.addCommand(De),e.addCommand(Oe),e.addCommand(Ke),e.addCommand(qe),e.addCommand(rt),e.addCommand(Z),e.addCommand(ct),e.addCommand(ut),await e.parseAsync(process.argv)}dt().catch(e=>{console.error(`[CLI_STARTUP_ERROR] workflow-mcp startup failed:`,e),process.exit(1)});
2
+ const e=require(`./stdio-Bt5DIqt_.cjs`);let t=require(`node:child_process`),n=require(`node:fs/promises`),r=require(`node:path`),i=require(`node:fs`),a=require(`@agimon-ai/foundation-process-registry`),o=require(`node:readline`),s=require(`commander`),c=require(`node:module`);var l=`0.2.7`;const u=`WORKFLOW_STATUS_FILE`,ee={readStdin:ae,readStatusFile:oe,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
3
+ `,`utf8`)},workflowStatusFile:process.env[u]};async function te(e=ee){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=d(n);if(!r?.conversationId)return;let i=await e.readStatusFile(t);if(!(i===null||i.trim()===`YES`)){if(!r.fullyIdle){e.writeStdout?.(ne(`In-progress work is still running. Continue the execution loop until background tasks finish.`));return}f(r.error)||r.terminationReason!==`model_stop`||await e.writeStatusFile(t)}}function d(e){try{let t=JSON.parse(e);return ie(t)?{conversationId:typeof t.conversationId==`string`?t.conversationId:void 0,transcriptPath:re(t.transcriptPath),terminationReason:typeof t.terminationReason==`string`?t.terminationReason:void 0,error:typeof t.error==`string`?t.error:void 0,fullyIdle:t.fullyIdle===!0}:null}catch{return null}}function ne(e){return`${JSON.stringify({decision:`continue`,reason:e})}\n`}function re(e){return typeof e==`string`&&e.trim().length>0?e:null}function f(e){return typeof e==`string`&&e.trim().length>0}function ie(e){return typeof e==`object`&&!!e}async function ae(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function oe(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}const se=new s.Command(`antigravity-stop-hook`).description(`Antigravity stop hook: reads Stop hook JSON on stdin and marks ${u} when the execution is fully idle`).action(async()=>{await te()});var p=class extends Error{constructor(e,t,n={},r){super(e,r),this.code=t,this.context=n,this.name=`WorkflowCommandError`}};const m=`check-codex-quota`;function ce(t={}){let n=t.createService??(()=>new e.i),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(m).description(`Check whether Codex quota is currently blocking new work`).action(async()=>{try{let e=await n().getQuotaStatus();if(a(`${JSON.stringify({blockingLimit:e?.blockingLimit??null,planType:e?.planType??null},null,2)}\n`),e?.blockingLimit){let t=new p(`Codex quota is blocking work at ${e.blockingLimit.limitId}/${e.blockingLimit.window}.`,`CODEX_QUOTA_BLOCKED`,{command:m,limitId:e.blockingLimit.limitId,limitName:e.blockingLimit.limitName,window:e.blockingLimit.window});i(`${t.message} [${t.code}]`,t),r(2);return}r(0)}catch(e){let t=e instanceof p?e:new p(`Error checking Codex quota.`,`CHECK_CODEX_QUOTA_COMMAND_FAILED`,{command:m},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const le=ce(),h=`WORKFLOW_STATUS_FILE`,ue={readStdin:_,readStatusFile:v,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
4
+ `,`utf8`)},workflowStatusFile:process.env[h]},de={readStdin:_,readStatusFile:v,writeSessionBinding:async(e,t)=>{await(0,n.writeFile)(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[h]};async function fe(e=de){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=he(n);if(!r?.session_id||r.hook_event_name&&r.hook_event_name!==`SessionStart`)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function pe(e=ue){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=ge(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`)return;let i=_e(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=r.background_tasks.length>0,o=r.session_crons.length>0;if(a){e.writeStdout?.(me(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}o||await e.writeStatusFile(t)}function me(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}function he(e){try{let t=JSON.parse(e);return g(t)?{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function ge(e){try{let t=JSON.parse(e);if(!g(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:[],r=Array.isArray(t.session_crons)?t.session_crons:[];return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r}}catch{return null}}function _e(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function g(e){return typeof e==`object`&&!!e}async function _(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function v(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}const ve=new s.Command(`claude-session-start-hook`).description(`Claude Code SessionStart hook: binds ${h} to the root Claude session id`).action(async()=>{await fe()}),ye=new s.Command(`claude-stop-hook`).description(`Claude Code stop hook: reads Stop hook JSON on stdin and marks ${h} when the root session is complete`).action(async()=>{await pe()}),y=`WORKFLOW_STATUS_FILE`,b=`session_meta`,be=[`sub_agent`,`subagent`],xe=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),Se=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),x={readStdin:N,readStatusFile:P,readTranscriptHead:F,readTranscriptState:I,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await(0,n.writeFile)(e,`YES
5
+ `,`utf8`)},workflowStatusFile:process.env[y]},S={readStdin:N,readStatusFile:P,writeSessionBinding:async(e,t)=>{await(0,n.writeFile)(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[y]};async function C(e=S){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=D(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function w(e=x){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=O(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`||r.stop_hook_active&&!r.hasTaskRegistry)return;let i=A(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=k(r.transcript_path);if(!a)return;let o=await E(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||j(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(T(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function T(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function E(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===F?I(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function D(e){try{let t=JSON.parse(e);return M(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function O(e){try{let t=JSON.parse(e);if(!M(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:k(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function k(e){return typeof e==`string`&&e.trim().length>0?e:null}function A(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function j(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):M(e)?be.some(t=>t in e):!1}function M(e){return typeof e==`object`&&!!e}async function N(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function P(e){try{return await(0,n.readFile)(e,`utf8`)}catch{return null}}async function F(e){return(await I(e)).sessionMeta}async function I(e){let t=(0,i.createReadStream)(e,{encoding:`utf8`}),n=(0,o.createInterface)({input:t,crlfDelay:1/0}),r=new Set,a=new Map,s=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=Ce(t);n&&(s||=we(n),Te(n,r),Ee(n,a))}}finally{n.close(),t.destroy()}return{sessionMeta:s,hasPendingWork:r.size>0||Array.from(a.values()).some(z)}}function Ce(e){try{let t=JSON.parse(e);return M(t)?t:null}catch{return null}}function we(e){return e.type===b?e.payload??null:e.item?.type===b?e.item.payload??null:null}function Te(e,t){let n=B(e,[`payload`,`item`])??B(e,[`item`,`payload`,`item`]);if(!n)return;let r=V(n.id),i=V(n.type);!r||!i||!Se.has(i)||(z(n.status)?t.add(r):t.delete(r))}function Ee(e,t){let n=B(e,[`payload`])??B(e,[`item`,`payload`]);if(!n||!V(n.type)?.startsWith(`collab_`))return;L(t,V(n.new_thread_id),n.status),L(t,V(n.receiver_thread_id),n.status);let r=B(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))L(t,e,n)}function L(e,t,n){let r=R(n);!t||!r||e.set(t,r)}function R(e){if(typeof e==`string`)return e;if(!M(e))return null;let[t]=Object.keys(e);return t??null}function z(e){let t=typeof e==`string`?e:R(e);return t!==null&&xe.has(t)}function B(e,t){let n=e;for(let e of t){if(!M(n))return null;n=n[e]}return M(n)?n:null}function V(e){return typeof e==`string`&&e.length>0?e:void 0}const De=new s.Command(`codex-session-start-hook`).description(`Codex session-start hook: binds ${y} to the first workflow Codex session id`).action(async()=>{await C()}),Oe=new s.Command(`codex-stop-hook`).description(`Codex stop hook: reads stop-hook JSON on stdin and marks ${y} when the root session ends`).action(async()=>{await w()}),H=`list-crons`;function ke(t={}){let n=t.createService??(()=>new e.o),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(H).description(`List cron jobs scheduled via workflow-mcp`).action(async()=>{try{let e=await n().list();a(`${JSON.stringify(e,null,2)}\n`),r(0)}catch(e){let t=new p(`Error listing cron jobs.`,`LIST_CRONS_COMMAND_FAILED`,{command:H},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const Ae=ke(),U=`list-workflow-statuses`;function W(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new s.InvalidArgumentError(`Expected a positive integer.`);return t}function je(t={}){let n=t.createRegistry??(()=>new e.a),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command(U).description(`List tracked workflow runs and their current stages`).option(`--page <number>`,`Page number to return`,W,1).option(`--page-size <number>`,`Number of workflow runs per page`,W,20).option(`-w, --workspace <name>`,`Filter workflow runs by workspace`,`all`).action(async e=>{try{let t=n(),i=e.workspace===`all`?void 0:e.workspace,o=await t.listRunsPage({page:e.page,pageSize:e.pageSize,workspace:i});a(`${JSON.stringify(o,null,2)}\n`),r(0)}catch(t){let n=new p(`Error listing workflow statuses.`,`LIST_WORKFLOW_STATUSES_FAILED`,{command:U,workspace:e.workspace??`all`},{cause:t});i(`${n.message} [${n.code}]`,n),r(1)}})}const Me=je(),Ne=()=>{try{return(0,c.createRequire)(require(`url`).pathToFileURL(__filename).href)(`@agimon-ai/foundation-process-registry`)}catch{return null}};function G(e,t){for(let n of e){if(n==null||typeof n!=`object`&&typeof n!=`function`)continue;let e=n;for(let n of t){let t=e[n];if(typeof t==`function`)return t}}return null}function Pe(e){let t=[e];if(e&&typeof e==`object`){let n=e.default;if(n&&(t.push(n),typeof n==`function`))try{t.push(new n)}catch{}}return t}async function Fe(e){let t=Ne();if(!t)return async()=>{};let n=Pe(t),r=G(n,[`registerProcess`,`register`,`registerProcessInstance`]),i=G(n,[`unregisterProcess`,`unregister`,`releaseProcess`]);if(!r)return async()=>{};try{await Promise.resolve(r({name:e,pid:process.pid,command:process.argv.join(` `)}))}catch{return async()=>{}}return i?async()=>{await Promise.resolve(i({name:e,pid:process.pid}))}:async()=>{}}async function Ie(e,t){await e.start();let n=async n=>{console.error(`\\nReceived ${n}, shutting down gracefully...`);let r=0;try{await e.stop()}catch(e){console.error(`Error during shutdown:`,e),r=1}try{await t()}catch(e){console.error(`Error during resource cleanup:`,e),r=1}process.exit(r)};process.on(`SIGINT`,()=>{n(`SIGINT`)}),process.on(`SIGTERM`,()=>{n(`SIGTERM`)})}async function Le(e){try{await e()}catch{}}const Re=new s.Command(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--service-name <name>`,`Service name for registry tracking`,`workflow-mcp`).action(async t=>{let n=await Fe(t.serviceName);try{let r=t.type.toLowerCase();r===`stdio`?await Ie(new e.t(e.n()),n):(console.error(`Unknown transport type: ${r}. Use: stdio`),process.exit(1))}catch(e){await Le(n),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),K=`run-workflow`,q=`RUN_WORKFLOW_COMMAND_FAILED`,J=`WORKFLOW_MCP_BACKGROUND_CHILD`,Y=`workflow-mcp-background-run`;function X(e){if(!e||e.length===0)return;let t={};for(let n of e){let[e,...r]=n.split(`=`);t[e]=r.join(`=`)}return Object.keys(t).length>0?t:void 0}function Z(e){if(e.runner&&e.cliAgent&&e.runner!==e.cliAgent)throw new p(`Conflicting runner selectors.`,q,{cliAgent:e.cliAgent,command:K,runner:e.runner});return e.runner??e.cliAgent}function ze(e,n){let r=process.argv[1];if(!r)throw new p(`Unable to determine the workflow-mcp CLI entry point for background execution.`,`RUN_WORKFLOW_BACKGROUND_LAUNCH_FAILED`,{command:K,workflow:e,workspace:n.workspace});let i=[r,`run-workflow`,e];n.job&&i.push(`--job`,n.job);for(let e of n.input??[])i.push(`--input`,e);for(let e of n.env??[])i.push(`--env`,e);n.secretFile&&i.push(`--secret-file`,n.secretFile),n.dryRun&&i.push(`--dry-run`),n.continueOnError&&i.push(`--continue-on-error`),n.keepWorktree&&i.push(`--keep-worktree`);let a=Z(n);a&&i.push(`--runner`,a),n.prompt&&i.push(`--prompt`,n.prompt),n.name&&i.push(`--name`,n.name),n.workspace&&i.push(`--workspace`,n.workspace);let o=(0,t.spawn)(process.execPath,i,{detached:!0,env:{...process.env,[J]:`1`},stdio:`ignore`});return o.unref(),o.pid}async function Be(e,t){if(process.env[J]!==`1`)return async()=>{};let n=new a.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH),i=(0,r.resolve)(process.cwd()),o=process.env.NODE_ENV??`development`;return(await n.registerProcess({repositoryPath:i,serviceName:Y,serviceType:`tool`,environment:o,pid:process.pid,command:process.argv.join(` `),args:process.argv.slice(2),metadata:{workflow:e,workspace:t.workspace,job:t.job,name:t.name,runner:t.runner??t.cliAgent},force:!0})).success?async()=>{let e=await n.releaseProcess({repositoryPath:i,serviceName:Y,serviceType:`tool`,environment:o,pid:process.pid,kill:!1,releasePort:!1,force:!0});if(!e.success&&!e.error?.includes(`No matching process entry`))throw Error(e.error??`Failed to release workflow background process`)}:async()=>{}}function Ve(t={}){let n=t.createService??(()=>new e.r),r=t.exit??(e=>process.exit(e)),i=t.launchBackgroundRun??ze,a=t.registerBackgroundChild??Be,o=t.logError??((e,t)=>console.error(e,t)),c=t.logInfo??(e=>process.stdout.write(`${e}\n`));return new s.Command(K).description(`Run a GitHub Actions workflow file locally on macOS`).argument(`<workflow>`,`Path to the workflow YAML file`).option(`-j, --job <name>`,`Run only this job (and its dependencies)`).option(`-i, --input <key=value...>`,`Set workflow_dispatch input (repeatable)`).option(`-e, --env <key=value...>`,`Set extra environment variable (repeatable)`).option(`--secret-file <path>`,`Load secrets from a dotenv-style file`).option(`--dry-run`,`Print steps without executing`).option(`--continue-on-error`,`Continue past step failures`).option(`--runner <runner>`,`Preferred runner key for step command maps`).option(`--cli-agent <agent>`,`Deprecated alias for --runner`).option(`-p, --prompt <text>`,`User prompt for user_prompt trigger workflows`).option(`-n, --name <name>`,`Name for the workflow run context directory`).option(`-w, --workspace <name>`,`Workspace for workflow registry storage`).option(`--keep-worktree`,`Keep worktree on completion (skip merge and cleanup for retry)`).option(`--skip-launch`,`Skip launch-command delegation (used by inner invocations)`).option(`-b, --background`,`Run the workflow in a detached background process`).action(async(e,t)=>{try{if(t.background){let n=i(e,t);c(`Started workflow in background${n?` (PID: ${n})`:``}`),r(0);return}let o=await a(e,t),s=n();try{let n=Z(t),i=await s.run({cliAgent:t.cliAgent,runner:n,workflowPath:e,job:t.job,inputs:X(t.input),env:X(t.env),secretFile:t.secretFile,dryRun:t.dryRun,continueOnError:t.continueOnError,keepWorktree:t.keepWorktree,prompt:t.prompt,name:t.name,workspace:t.workspace,skipLaunch:t.skipLaunch});await o(),r(i.exitCode)}catch(e){throw await o(),e}}catch(n){let i=n instanceof p?n:new p(`Error executing run-workflow.`,q,{background:!!t.background,command:K,workflow:e,workspace:t.workspace},{cause:n});o(`${i.message} [${i.code}]`,i),r(1)}})}const He=Ve(),Q=`schedule-cron`;function Ue(t={}){let n=t.createService??(()=>new e.o),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(`${e}\n`));return new s.Command(Q).description(`Schedule a headless Claude Code or Codex CLI run via system crontab`).argument(`<name>`,`Unique name for this cron job`).option(`-d, --cwd <path>`,`Working directory for the CLI run`,process.cwd()).option(`-c, --cli <cli>`,`CLI to use: claude or codex`,e.s).option(`-p, --prompt <text>`,`Prompt to pass to the CLI`).option(`-f, --prompt-file <path>`,`Path to a file whose content is used as the prompt (read at cron execution time)`).option(`-s, --schedule <cron>`,`Cron expression (e.g., "*/10 * * * *")`).option(`-i, --interval-minutes <minutes>`,`Run every N minutes (alternative to --schedule)`).action(async(t,o)=>{try{let i=e.c.parse({name:t,cwd:o.cwd??process.cwd(),cli:o.cli??`claude`,prompt:o.prompt,promptFile:o.promptFile,schedule:o.schedule,intervalMinutes:o.intervalMinutes?Number.parseInt(o.intervalMinutes,10):void 0}),s=await n().schedule(i);a(`Scheduled cron job "${s.name}" with schedule: ${s.schedule}`),a(`CLI: ${s.cli} | CWD: ${s.cwd}`),s.prompt&&a(`Prompt: ${s.prompt}`),r(0)}catch(e){let n=e instanceof p?e:new p(`Error scheduling cron job.`,`SCHEDULE_CRON_COMMAND_FAILED`,{command:Q,name:t},{cause:e});i(`${n.message} [${n.code}]`,n),r(1)}})}const We=Ue(),$=`stop-workflow`;function Ge(t={}){let n=t.createRegistry??(()=>new e.a),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new s.Command($).description(`Request a running workflow to stop gracefully`).argument(`<run-key>`,`Running workflow run key`).option(`-w, --workspace <name>`,`Workspace containing the running workflow`,`default`).option(`-r, --reason <text>`,`Optional stop reason to record`).action(async(e,t)=>{try{let i=n(),o=await i.requestStop(t.workspace,e,t.reason);a(`${JSON.stringify({reason:o.reason,requestedAt:o.requestedAt,runKey:e,workspace:i.resolveWorkspace(t.workspace)},null,2)}\n`),r(0)}catch(n){let a=new p(`Error requesting workflow stop.`,`STOP_WORKFLOW_FAILED`,{command:$,runKey:e,workspace:t.workspace},{cause:n});i(`${a.message} [${a.code}]`,a),r(1)}})}const Ke=Ge();async function qe(){let e=new s.Command;e.name(`workflow-mcp`).description(`MCP server for running GitHub Actions workflows locally`).version(l),e.addCommand(Ae),e.addCommand(Me),e.addCommand(le),e.addCommand(se),e.addCommand(ve),e.addCommand(ye),e.addCommand(De),e.addCommand(Oe),e.addCommand(Re),e.addCommand(He),e.addCommand(We),e.addCommand(Ke),await e.parseAsync(process.argv)}qe().catch(e=>{console.error(`[CLI_STARTUP_ERROR] workflow-mcp startup failed:`,e),process.exit(1)});
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./stdio-CHIzO6hv.mjs";import{createRequire as c}from"node:module";import{spawn as l}from"node:child_process";import{readFile as u,writeFile as d}from"node:fs/promises";import{resolve as ee}from"node:path";import{createReadStream as f}from"node:fs";import{ProcessRegistryService as te}from"@agimon-ai/foundation-process-registry";import{createInterface as ne}from"node:readline";import{Command as p,InvalidArgumentError as re}from"commander";var ie=`0.2.6`;const m=`WORKFLOW_STATUS_FILE`,ae={readStdin:fe,readStatusFile:pe,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
3
- `,`utf8`)},workflowStatusFile:process.env[m]};async function oe(e=ae){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=se(n);if(!r?.conversationId)return;let i=await e.readStatusFile(t);if(!(i===null||i.trim()===`YES`)){if(!r.fullyIdle){e.writeStdout?.(ce(`In-progress work is still running. Continue the execution loop until background tasks finish.`));return}ue(r.error)||r.terminationReason!==`model_stop`||await e.writeStatusFile(t)}}function se(e){try{let t=JSON.parse(e);return de(t)?{conversationId:typeof t.conversationId==`string`?t.conversationId:void 0,transcriptPath:le(t.transcriptPath),terminationReason:typeof t.terminationReason==`string`?t.terminationReason:void 0,error:typeof t.error==`string`?t.error:void 0,fullyIdle:t.fullyIdle===!0}:null}catch{return null}}function ce(e){return`${JSON.stringify({decision:`continue`,reason:e})}\n`}function le(e){return typeof e==`string`&&e.trim().length>0?e:null}function ue(e){return typeof e==`string`&&e.trim().length>0}function de(e){return typeof e==`object`&&!!e}async function fe(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function pe(e){try{return await u(e,`utf8`)}catch{return null}}const me=new p(`antigravity-stop-hook`).description(`Antigravity stop hook: reads Stop hook JSON on stdin and marks ${m} when the execution is fully idle`).action(async()=>{await oe()});var h=class extends Error{constructor(e,t,n={},r){super(e,r),this.code=t,this.context=n,this.name=`WorkflowCommandError`}};const g=`check-codex-quota`;function he(e={}){let t=e.createService??(()=>new n),r=e.exit??(e=>process.exit(e)),i=e.logError??((e,t)=>console.error(e,t)),a=e.writeStdout??(e=>process.stdout.write(e));return new p(g).description(`Check whether Codex quota is currently blocking new work`).action(async()=>{try{let e=await t().getQuotaStatus();if(a(`${JSON.stringify({blockingLimit:e?.blockingLimit??null,planType:e?.planType??null},null,2)}\n`),e?.blockingLimit){let t=new h(`Codex quota is blocking work at ${e.blockingLimit.limitId}/${e.blockingLimit.window}.`,`CODEX_QUOTA_BLOCKED`,{command:g,limitId:e.blockingLimit.limitId,limitName:e.blockingLimit.limitName,window:e.blockingLimit.window});i(`${t.message} [${t.code}]`,t),r(2);return}r(0)}catch(e){let t=e instanceof h?e:new h(`Error checking Codex quota.`,`CHECK_CODEX_QUOTA_COMMAND_FAILED`,{command:g},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const ge=he(),_=`WORKFLOW_STATUS_FILE`,v=`session_meta`,_e=[`sub_agent`,`subagent`],ve=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),ye=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),be={readStdin:x,readStatusFile:S,readTranscriptHead:C,readTranscriptState:w,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
4
- `,`utf8`)},workflowStatusFile:process.env[_]},xe={readStdin:x,readStatusFile:S,writeSessionBinding:async(e,t)=>{await d(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[_]};async function Se(e=xe){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Ee(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function Ce(e=be){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=De(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`)return;let i=Oe(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=y(r.transcript_path);if(!a)return;let o=await Te(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||ke(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(!r.hasTaskRegistry&&r.stop_hook_active){await e.writeStatusFile(t);return}if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(we(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function we(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function Te(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===C?w(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function Ee(e){try{let t=JSON.parse(e);return b(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function De(e){try{let t=JSON.parse(e);if(!b(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:y(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function y(e){return typeof e==`string`&&e.trim().length>0?e:null}function Oe(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function ke(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):b(e)?_e.some(t=>t in e):!1}function b(e){return typeof e==`object`&&!!e}async function x(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function S(e){try{return await u(e,`utf8`)}catch{return null}}async function C(e){return(await w(e)).sessionMeta}async function w(e){let t=f(e,{encoding:`utf8`}),n=ne({input:t,crlfDelay:1/0}),r=new Set,i=new Map,a=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=Ae(t);n&&(a||=je(n),Me(n,r),Ne(n,i))}}finally{n.close(),t.destroy()}return{sessionMeta:a,hasPendingWork:r.size>0||Array.from(i.values()).some(D)}}function Ae(e){try{let t=JSON.parse(e);return b(t)?t:null}catch{return null}}function je(e){return e.type===v?e.payload??null:e.item?.type===v?e.item.payload??null:null}function Me(e,t){let n=O(e,[`payload`,`item`])??O(e,[`item`,`payload`,`item`]);if(!n)return;let r=k(n.id),i=k(n.type);!r||!i||!ye.has(i)||(D(n.status)?t.add(r):t.delete(r))}function Ne(e,t){let n=O(e,[`payload`])??O(e,[`item`,`payload`]);if(!n||!k(n.type)?.startsWith(`collab_`))return;T(t,k(n.new_thread_id),n.status),T(t,k(n.receiver_thread_id),n.status);let r=O(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))T(t,e,n)}function T(e,t,n){let r=E(n);!t||!r||e.set(t,r)}function E(e){if(typeof e==`string`)return e;if(!b(e))return null;let[t]=Object.keys(e);return t??null}function D(e){let t=typeof e==`string`?e:E(e);return t!==null&&ve.has(t)}function O(e,t){let n=e;for(let e of t){if(!b(n))return null;n=n[e]}return b(n)?n:null}function k(e){return typeof e==`string`&&e.length>0?e:void 0}const Pe=new p(`claude-session-start-hook`).description(`Claude Code SessionStart hook: binds ${_} to the root Claude session id`).action(async()=>{await Se()}),Fe=new p(`claude-stop-hook`).description(`Claude Code stop hook: reads Stop hook JSON on stdin and marks ${_} when the root session is complete`).action(async()=>{await Ce()}),A=`WORKFLOW_STATUS_FILE`,j=`session_meta`,Ie=[`sub_agent`,`subagent`],Le=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),Re=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),ze={readStdin:P,readStatusFile:F,readTranscriptHead:I,readTranscriptState:L,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
5
- `,`utf8`)},workflowStatusFile:process.env[A]},Be={readStdin:P,readStatusFile:F,writeSessionBinding:async(e,t)=>{await d(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[A]};async function Ve(e=Be){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Ge(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function He(e=ze){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Ke(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`||r.stop_hook_active&&!r.hasTaskRegistry)return;let i=qe(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=M(r.transcript_path);if(!a)return;let o=await We(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||Je(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(Ue(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function Ue(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function We(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===I?L(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function Ge(e){try{let t=JSON.parse(e);return N(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function Ke(e){try{let t=JSON.parse(e);if(!N(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:M(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function M(e){return typeof e==`string`&&e.trim().length>0?e:null}function qe(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function Je(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):N(e)?Ie.some(t=>t in e):!1}function N(e){return typeof e==`object`&&!!e}async function P(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function F(e){try{return await u(e,`utf8`)}catch{return null}}async function I(e){return(await L(e)).sessionMeta}async function L(e){let t=f(e,{encoding:`utf8`}),n=ne({input:t,crlfDelay:1/0}),r=new Set,i=new Map,a=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=Ye(t);n&&(a||=Xe(n),Ze(n,r),Qe(n,i))}}finally{n.close(),t.destroy()}return{sessionMeta:a,hasPendingWork:r.size>0||Array.from(i.values()).some(B)}}function Ye(e){try{let t=JSON.parse(e);return N(t)?t:null}catch{return null}}function Xe(e){return e.type===j?e.payload??null:e.item?.type===j?e.item.payload??null:null}function Ze(e,t){let n=V(e,[`payload`,`item`])??V(e,[`item`,`payload`,`item`]);if(!n)return;let r=H(n.id),i=H(n.type);!r||!i||!Re.has(i)||(B(n.status)?t.add(r):t.delete(r))}function Qe(e,t){let n=V(e,[`payload`])??V(e,[`item`,`payload`]);if(!n||!H(n.type)?.startsWith(`collab_`))return;R(t,H(n.new_thread_id),n.status),R(t,H(n.receiver_thread_id),n.status);let r=V(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))R(t,e,n)}function R(e,t,n){let r=z(n);!t||!r||e.set(t,r)}function z(e){if(typeof e==`string`)return e;if(!N(e))return null;let[t]=Object.keys(e);return t??null}function B(e){let t=typeof e==`string`?e:z(e);return t!==null&&Le.has(t)}function V(e,t){let n=e;for(let e of t){if(!N(n))return null;n=n[e]}return N(n)?n:null}function H(e){return typeof e==`string`&&e.length>0?e:void 0}const $e=new p(`codex-session-start-hook`).description(`Codex session-start hook: binds ${A} to the first workflow Codex session id`).action(async()=>{await Ve()}),et=new p(`codex-stop-hook`).description(`Codex stop hook: reads stop-hook JSON on stdin and marks ${A} when the root session ends`).action(async()=>{await He()}),U=`list-crons`;function tt(e={}){let t=e.createService??(()=>new i),n=e.exit??(e=>process.exit(e)),r=e.logError??((e,t)=>console.error(e,t)),a=e.writeStdout??(e=>process.stdout.write(e));return new p(U).description(`List cron jobs scheduled via workflow-mcp`).action(async()=>{try{let e=await t().list();a(`${JSON.stringify(e,null,2)}\n`),n(0)}catch(e){let t=new h(`Error listing cron jobs.`,`LIST_CRONS_COMMAND_FAILED`,{command:U},{cause:e});r(`${t.message} [${t.code}]`,t),n(1)}})}const nt=tt(),W=`list-workflow-statuses`;function G(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new re(`Expected a positive integer.`);return t}function rt(t={}){let n=t.createRegistry??(()=>new e),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new p(W).description(`List tracked workflow runs and their current stages`).option(`--page <number>`,`Page number to return`,G,1).option(`--page-size <number>`,`Number of workflow runs per page`,G,20).option(`-w, --workspace <name>`,`Filter workflow runs by workspace`,`all`).action(async e=>{try{let t=n(),i=e.workspace===`all`?void 0:e.workspace,o=await t.listRunsPage({page:e.page,pageSize:e.pageSize,workspace:i});a(`${JSON.stringify(o,null,2)}\n`),r(0)}catch(t){let n=new h(`Error listing workflow statuses.`,`LIST_WORKFLOW_STATUSES_FAILED`,{command:W,workspace:e.workspace??`all`},{cause:t});i(`${n.message} [${n.code}]`,n),r(1)}})}const it=rt(),at=()=>{try{return c(import.meta.url)(`@agimon-ai/foundation-process-registry`)}catch{return null}};function K(e,t){for(let n of e){if(n==null||typeof n!=`object`&&typeof n!=`function`)continue;let e=n;for(let n of t){let t=e[n];if(typeof t==`function`)return t}}return null}function ot(e){let t=[e];if(e&&typeof e==`object`){let n=e.default;if(n&&(t.push(n),typeof n==`function`))try{t.push(new n)}catch{}}return t}async function st(e){let t=at();if(!t)return async()=>{};let n=ot(t),r=K(n,[`registerProcess`,`register`,`registerProcessInstance`]),i=K(n,[`unregisterProcess`,`unregister`,`releaseProcess`]);if(!r)return async()=>{};try{await Promise.resolve(r({name:e,pid:process.pid,command:process.argv.join(` `)}))}catch{return async()=>{}}return i?async()=>{await Promise.resolve(i({name:e,pid:process.pid}))}:async()=>{}}async function ct(e,t){await e.start();let n=async n=>{console.error(`\\nReceived ${n}, shutting down gracefully...`);let r=0;try{await e.stop()}catch(e){console.error(`Error during shutdown:`,e),r=1}try{await t()}catch(e){console.error(`Error during resource cleanup:`,e),r=1}process.exit(r)};process.on(`SIGINT`,()=>{n(`SIGINT`)}),process.on(`SIGTERM`,()=>{n(`SIGTERM`)})}async function lt(e){try{await e()}catch{}}const ut=new p(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--service-name <name>`,`Service name for registry tracking`,`workflow-mcp`).action(async e=>{let t=await st(e.serviceName);try{let n=e.type.toLowerCase();n===`stdio`?await ct(new s(r()),t):(console.error(`Unknown transport type: ${n}. Use: stdio`),process.exit(1))}catch(e){await lt(t),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),q=`run-workflow`,J=`RUN_WORKFLOW_COMMAND_FAILED`,Y=`WORKFLOW_MCP_BACKGROUND_CHILD`,X=`workflow-mcp-background-run`;function Z(e){if(!e||e.length===0)return;let t={};for(let n of e){let[e,...r]=n.split(`=`);t[e]=r.join(`=`)}return Object.keys(t).length>0?t:void 0}function Q(e){if(e.runner&&e.cliAgent&&e.runner!==e.cliAgent)throw new h(`Conflicting runner selectors.`,J,{cliAgent:e.cliAgent,command:q,runner:e.runner});return e.runner??e.cliAgent}function dt(e,t){let n=process.argv[1];if(!n)throw new h(`Unable to determine the workflow-mcp CLI entry point for background execution.`,`RUN_WORKFLOW_BACKGROUND_LAUNCH_FAILED`,{command:q,workflow:e,workspace:t.workspace});let r=[n,`run-workflow`,e];t.job&&r.push(`--job`,t.job);for(let e of t.input??[])r.push(`--input`,e);for(let e of t.env??[])r.push(`--env`,e);t.secretFile&&r.push(`--secret-file`,t.secretFile),t.dryRun&&r.push(`--dry-run`),t.continueOnError&&r.push(`--continue-on-error`),t.keepWorktree&&r.push(`--keep-worktree`);let i=Q(t);i&&r.push(`--runner`,i),t.prompt&&r.push(`--prompt`,t.prompt),t.name&&r.push(`--name`,t.name),t.workspace&&r.push(`--workspace`,t.workspace);let a=l(process.execPath,r,{detached:!0,env:{...process.env,[Y]:`1`},stdio:`ignore`});return a.unref(),a.pid}async function ft(e,t){if(process.env[Y]!==`1`)return async()=>{};let n=new te(process.env.PROCESS_REGISTRY_PATH),r=ee(process.cwd()),i=process.env.NODE_ENV??`development`;return(await n.registerProcess({repositoryPath:r,serviceName:X,serviceType:`tool`,environment:i,pid:process.pid,command:process.argv.join(` `),args:process.argv.slice(2),metadata:{workflow:e,workspace:t.workspace,job:t.job,name:t.name,runner:t.runner??t.cliAgent},force:!0})).success?async()=>{let e=await n.releaseProcess({repositoryPath:r,serviceName:X,serviceType:`tool`,environment:i,pid:process.pid,kill:!1,releasePort:!1,force:!0});if(!e.success&&!e.error?.includes(`No matching process entry`))throw Error(e.error??`Failed to release workflow background process`)}:async()=>{}}function pt(e={}){let t=e.createService??(()=>new a),n=e.exit??(e=>process.exit(e)),r=e.launchBackgroundRun??dt,i=e.registerBackgroundChild??ft,o=e.logError??((e,t)=>console.error(e,t)),s=e.logInfo??(e=>process.stdout.write(`${e}\n`));return new p(q).description(`Run a GitHub Actions workflow file locally on macOS`).argument(`<workflow>`,`Path to the workflow YAML file`).option(`-j, --job <name>`,`Run only this job (and its dependencies)`).option(`-i, --input <key=value...>`,`Set workflow_dispatch input (repeatable)`).option(`-e, --env <key=value...>`,`Set extra environment variable (repeatable)`).option(`--secret-file <path>`,`Load secrets from a dotenv-style file`).option(`--dry-run`,`Print steps without executing`).option(`--continue-on-error`,`Continue past step failures`).option(`--runner <runner>`,`Preferred runner key for step command maps`).option(`--cli-agent <agent>`,`Deprecated alias for --runner`).option(`-p, --prompt <text>`,`User prompt for user_prompt trigger workflows`).option(`-n, --name <name>`,`Name for the workflow run context directory`).option(`-w, --workspace <name>`,`Workspace for workflow registry storage`).option(`--keep-worktree`,`Keep worktree on completion (skip merge and cleanup for retry)`).option(`--skip-launch`,`Skip launch-command delegation (used by inner invocations)`).option(`-b, --background`,`Run the workflow in a detached background process`).action(async(e,a)=>{try{if(a.background){let t=r(e,a);s(`Started workflow in background${t?` (PID: ${t})`:``}`),n(0);return}let o=await i(e,a),c=t();try{let t=Q(a),r=await c.run({cliAgent:a.cliAgent,runner:t,workflowPath:e,job:a.job,inputs:Z(a.input),env:Z(a.env),secretFile:a.secretFile,dryRun:a.dryRun,continueOnError:a.continueOnError,keepWorktree:a.keepWorktree,prompt:a.prompt,name:a.name,workspace:a.workspace,skipLaunch:a.skipLaunch});await o(),n(r.exitCode)}catch(e){throw await o(),e}}catch(t){let r=t instanceof h?t:new h(`Error executing run-workflow.`,J,{background:!!a.background,command:q,workflow:e,workspace:a.workspace},{cause:t});o(`${r.message} [${r.code}]`,r),n(1)}})}const mt=pt(),$=`schedule-cron`;function ht(e={}){let n=e.createService??(()=>new i),r=e.exit??(e=>process.exit(e)),a=e.logError??((e,t)=>console.error(e,t)),s=e.writeStdout??(e=>process.stdout.write(`${e}\n`));return new p($).description(`Schedule a headless Claude Code or Codex CLI run via system crontab`).argument(`<name>`,`Unique name for this cron job`).option(`-d, --cwd <path>`,`Working directory for the CLI run`,process.cwd()).option(`-c, --cli <cli>`,`CLI to use: claude or codex`,o).option(`-p, --prompt <text>`,`Prompt to pass to the CLI`).option(`-f, --prompt-file <path>`,`Path to a file whose content is used as the prompt (read at cron execution time)`).option(`-s, --schedule <cron>`,`Cron expression (e.g., "*/10 * * * *")`).option(`-i, --interval-minutes <minutes>`,`Run every N minutes (alternative to --schedule)`).action(async(e,i)=>{try{let a=t.parse({name:e,cwd:i.cwd??process.cwd(),cli:i.cli??`claude`,prompt:i.prompt,promptFile:i.promptFile,schedule:i.schedule,intervalMinutes:i.intervalMinutes?Number.parseInt(i.intervalMinutes,10):void 0}),o=await n().schedule(a);s(`Scheduled cron job "${o.name}" with schedule: ${o.schedule}`),s(`CLI: ${o.cli} | CWD: ${o.cwd}`),o.prompt&&s(`Prompt: ${o.prompt}`),r(0)}catch(t){let n=t instanceof h?t:new h(`Error scheduling cron job.`,`SCHEDULE_CRON_COMMAND_FAILED`,{command:$,name:e},{cause:t});a(`${n.message} [${n.code}]`,n),r(1)}})}const gt=ht(),_t=`stop-workflow`;function vt(t={}){let n=t.createRegistry??(()=>new e),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new p(_t).description(`Request a running workflow to stop gracefully`).argument(`<run-key>`,`Running workflow run key`).option(`-w, --workspace <name>`,`Workspace containing the running workflow`,`default`).option(`-r, --reason <text>`,`Optional stop reason to record`).action(async(e,t)=>{try{let i=n(),o=await i.requestStop(t.workspace,e,t.reason);a(`${JSON.stringify({reason:o.reason,requestedAt:o.requestedAt,runKey:e,workspace:i.resolveWorkspace(t.workspace)},null,2)}\n`),r(0)}catch(n){let a=new h(`Error requesting workflow stop.`,`STOP_WORKFLOW_FAILED`,{command:_t,runKey:e,workspace:t.workspace},{cause:n});i(`${a.message} [${a.code}]`,a),r(1)}})}const yt=vt();async function bt(){let e=new p;e.name(`workflow-mcp`).description(`MCP server for running GitHub Actions workflows locally`).version(ie),e.addCommand(nt),e.addCommand(it),e.addCommand(ge),e.addCommand(me),e.addCommand(Pe),e.addCommand(Fe),e.addCommand($e),e.addCommand(et),e.addCommand(ut),e.addCommand(mt),e.addCommand(gt),e.addCommand(yt),await e.parseAsync(process.argv)}bt().catch(e=>{console.error(`[CLI_STARTUP_ERROR] workflow-mcp startup failed:`,e),process.exit(1)});export{};
2
+ import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./stdio-CHIzO6hv.mjs";import{createRequire as c}from"node:module";import{spawn as l}from"node:child_process";import{readFile as u,writeFile as d}from"node:fs/promises";import{resolve as ee}from"node:path";import{createReadStream as te}from"node:fs";import{ProcessRegistryService as ne}from"@agimon-ai/foundation-process-registry";import{createInterface as f}from"node:readline";import{Command as p,InvalidArgumentError as re}from"commander";var ie=`0.2.7`;const m=`WORKFLOW_STATUS_FILE`,ae={readStdin:fe,readStatusFile:h,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
3
+ `,`utf8`)},workflowStatusFile:process.env[m]};async function oe(e=ae){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=se(n);if(!r?.conversationId)return;let i=await e.readStatusFile(t);if(!(i===null||i.trim()===`YES`)){if(!r.fullyIdle){e.writeStdout?.(ce(`In-progress work is still running. Continue the execution loop until background tasks finish.`));return}ue(r.error)||r.terminationReason!==`model_stop`||await e.writeStatusFile(t)}}function se(e){try{let t=JSON.parse(e);return de(t)?{conversationId:typeof t.conversationId==`string`?t.conversationId:void 0,transcriptPath:le(t.transcriptPath),terminationReason:typeof t.terminationReason==`string`?t.terminationReason:void 0,error:typeof t.error==`string`?t.error:void 0,fullyIdle:t.fullyIdle===!0}:null}catch{return null}}function ce(e){return`${JSON.stringify({decision:`continue`,reason:e})}\n`}function le(e){return typeof e==`string`&&e.trim().length>0?e:null}function ue(e){return typeof e==`string`&&e.trim().length>0}function de(e){return typeof e==`object`&&!!e}async function fe(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function h(e){try{return await u(e,`utf8`)}catch{return null}}const pe=new p(`antigravity-stop-hook`).description(`Antigravity stop hook: reads Stop hook JSON on stdin and marks ${m} when the execution is fully idle`).action(async()=>{await oe()});var g=class extends Error{constructor(e,t,n={},r){super(e,r),this.code=t,this.context=n,this.name=`WorkflowCommandError`}};const _=`check-codex-quota`;function me(e={}){let t=e.createService??(()=>new n),r=e.exit??(e=>process.exit(e)),i=e.logError??((e,t)=>console.error(e,t)),a=e.writeStdout??(e=>process.stdout.write(e));return new p(_).description(`Check whether Codex quota is currently blocking new work`).action(async()=>{try{let e=await t().getQuotaStatus();if(a(`${JSON.stringify({blockingLimit:e?.blockingLimit??null,planType:e?.planType??null},null,2)}\n`),e?.blockingLimit){let t=new g(`Codex quota is blocking work at ${e.blockingLimit.limitId}/${e.blockingLimit.window}.`,`CODEX_QUOTA_BLOCKED`,{command:_,limitId:e.blockingLimit.limitId,limitName:e.blockingLimit.limitName,window:e.blockingLimit.window});i(`${t.message} [${t.code}]`,t),r(2);return}r(0)}catch(e){let t=e instanceof g?e:new g(`Error checking Codex quota.`,`CHECK_CODEX_QUOTA_COMMAND_FAILED`,{command:_},{cause:e});i(`${t.message} [${t.code}]`,t),r(1)}})}const he=me(),v=`WORKFLOW_STATUS_FILE`,ge={readStdin:b,readStatusFile:x,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
4
+ `,`utf8`)},workflowStatusFile:process.env[v]},_e={readStdin:b,readStatusFile:x,writeSessionBinding:async(e,t)=>{await d(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[v]};async function ve(e=_e){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=xe(n);if(!r?.session_id||r.hook_event_name&&r.hook_event_name!==`SessionStart`)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function ye(e=ge){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Se(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`)return;let i=Ce(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=r.background_tasks.length>0,o=r.session_crons.length>0;if(a){e.writeStdout?.(be(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}o||await e.writeStatusFile(t)}function be(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}function xe(e){try{let t=JSON.parse(e);return y(t)?{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function Se(e){try{let t=JSON.parse(e);if(!y(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:[],r=Array.isArray(t.session_crons)?t.session_crons:[];return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r}}catch{return null}}function Ce(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function y(e){return typeof e==`object`&&!!e}async function b(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function x(e){try{return await u(e,`utf8`)}catch{return null}}const we=new p(`claude-session-start-hook`).description(`Claude Code SessionStart hook: binds ${v} to the root Claude session id`).action(async()=>{await ve()}),S=new p(`claude-stop-hook`).description(`Claude Code stop hook: reads Stop hook JSON on stdin and marks ${v} when the root session is complete`).action(async()=>{await ye()}),C=`WORKFLOW_STATUS_FILE`,w=`session_meta`,T=[`sub_agent`,`subagent`],E=new Set([`in_progress`,`inProgress`,`running`,`pending_init`,`pendingInit`]),D=new Set([`collabAgentToolCall`,`commandExecution`,`dynamicToolCall`,`imageGeneration`,`local_shell_call`,`mcpToolCall`]),O={readStdin:M,readStatusFile:N,readTranscriptHead:P,readTranscriptState:F,writeStdout:e=>{process.stdout.write(e)},writeStatusFile:async e=>{await d(e,`YES
5
+ `,`utf8`)},workflowStatusFile:process.env[C]},k={readStdin:M,readStatusFile:N,writeSessionBinding:async(e,t)=>{await d(e,`${JSON.stringify({sessionId:t})}\n`,`utf8`)},workflowStatusFile:process.env[C]};async function Te(e=k){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=ke(n);if(!r?.session_id)return;let i=await e.readStatusFile(t);i===null||i.trim().length>0||await e.writeSessionBinding(t,r.session_id)}async function Ee(e=O){let t=e.workflowStatusFile;if(!t)return;let n=await e.readStdin();if(n.trim().length===0)return;let r=Ae(n);if(!r||r.hook_event_name&&r.hook_event_name!==`Stop`||r.stop_hook_active&&!r.hasTaskRegistry)return;let i=je(await e.readStatusFile(t));if(!r.session_id||r.session_id!==i)return;let a=A(r.transcript_path);if(!a)return;let o=await Oe(e,a),s=o.sessionMeta;if(!s||r.session_id&&s.id&&r.session_id!==s.id||Me(s.source))return;let c=r.hasTaskRegistry&&(r.background_tasks?.length??0)>0,l=r.hasTaskRegistry&&(r.session_crons?.length??0)>0;if(c||!r.hasTaskRegistry&&o.hasPendingWork){e.writeStdout?.(De(`In-progress work is still running. Wait for spawned agents and running tool calls to finish before ending the turn.`));return}l||await e.writeStatusFile(t)}function De(e){return`${JSON.stringify({decision:`block`,reason:e,suppressOutput:!0})}\n`}async function Oe(e,t){return e.readTranscriptState?e.readTranscriptState(t):e.readTranscriptHead===P?F(t):{sessionMeta:await e.readTranscriptHead(t),hasPendingWork:!1}}function ke(e){try{let t=JSON.parse(e);return j(t)?{session_id:typeof t.session_id==`string`?t.session_id:void 0}:null}catch{return null}}function Ae(e){try{let t=JSON.parse(e);if(!j(t))return null;let n=Array.isArray(t.background_tasks)?t.background_tasks:void 0,r=Array.isArray(t.session_crons)?t.session_crons:void 0;return{hook_event_name:typeof t.hook_event_name==`string`?t.hook_event_name:void 0,session_id:typeof t.session_id==`string`?t.session_id:void 0,transcript_path:A(t.transcript_path),stop_hook_active:t.stop_hook_active===!0,background_tasks:n,session_crons:r,hasTaskRegistry:n!==void 0||r!==void 0}}catch{return null}}function A(e){return typeof e==`string`&&e.trim().length>0?e:null}function je(e){if(!e)return null;let t=e.trim();if(!t||t===`YES`)return null;try{let e=JSON.parse(t);return typeof e.sessionId==`string`&&e.sessionId.length>0?e.sessionId:null}catch{return null}}function Me(e){return typeof e==`string`?e.startsWith(`subagent_`)||e.startsWith(`internal_`):j(e)?T.some(t=>t in e):!1}function j(e){return typeof e==`object`&&!!e}async function M(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(e).toString(`utf8`)}async function N(e){try{return await u(e,`utf8`)}catch{return null}}async function P(e){return(await F(e)).sessionMeta}async function F(e){let t=te(e,{encoding:`utf8`}),n=f({input:t,crlfDelay:1/0}),r=new Set,i=new Map,a=null;try{for await(let e of n){let t=e.trim();if(t.length===0)continue;let n=Ne(t);n&&(a||=Pe(n),Fe(n,r),Ie(n,i))}}finally{n.close(),t.destroy()}return{sessionMeta:a,hasPendingWork:r.size>0||Array.from(i.values()).some(R)}}function Ne(e){try{let t=JSON.parse(e);return j(t)?t:null}catch{return null}}function Pe(e){return e.type===w?e.payload??null:e.item?.type===w?e.item.payload??null:null}function Fe(e,t){let n=z(e,[`payload`,`item`])??z(e,[`item`,`payload`,`item`]);if(!n)return;let r=B(n.id),i=B(n.type);!r||!i||!D.has(i)||(R(n.status)?t.add(r):t.delete(r))}function Ie(e,t){let n=z(e,[`payload`])??z(e,[`item`,`payload`]);if(!n||!B(n.type)?.startsWith(`collab_`))return;I(t,B(n.new_thread_id),n.status),I(t,B(n.receiver_thread_id),n.status);let r=z(n,[`statuses`]);if(r)for(let[e,n]of Object.entries(r))I(t,e,n)}function I(e,t,n){let r=L(n);!t||!r||e.set(t,r)}function L(e){if(typeof e==`string`)return e;if(!j(e))return null;let[t]=Object.keys(e);return t??null}function R(e){let t=typeof e==`string`?e:L(e);return t!==null&&E.has(t)}function z(e,t){let n=e;for(let e of t){if(!j(n))return null;n=n[e]}return j(n)?n:null}function B(e){return typeof e==`string`&&e.length>0?e:void 0}const Le=new p(`codex-session-start-hook`).description(`Codex session-start hook: binds ${C} to the first workflow Codex session id`).action(async()=>{await Te()}),Re=new p(`codex-stop-hook`).description(`Codex stop hook: reads stop-hook JSON on stdin and marks ${C} when the root session ends`).action(async()=>{await Ee()}),V=`list-crons`;function H(e={}){let t=e.createService??(()=>new i),n=e.exit??(e=>process.exit(e)),r=e.logError??((e,t)=>console.error(e,t)),a=e.writeStdout??(e=>process.stdout.write(e));return new p(V).description(`List cron jobs scheduled via workflow-mcp`).action(async()=>{try{let e=await t().list();a(`${JSON.stringify(e,null,2)}\n`),n(0)}catch(e){let t=new g(`Error listing cron jobs.`,`LIST_CRONS_COMMAND_FAILED`,{command:V},{cause:e});r(`${t.message} [${t.code}]`,t),n(1)}})}const ze=H(),U=`list-workflow-statuses`;function W(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw new re(`Expected a positive integer.`);return t}function Be(t={}){let n=t.createRegistry??(()=>new e),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new p(U).description(`List tracked workflow runs and their current stages`).option(`--page <number>`,`Page number to return`,W,1).option(`--page-size <number>`,`Number of workflow runs per page`,W,20).option(`-w, --workspace <name>`,`Filter workflow runs by workspace`,`all`).action(async e=>{try{let t=n(),i=e.workspace===`all`?void 0:e.workspace,o=await t.listRunsPage({page:e.page,pageSize:e.pageSize,workspace:i});a(`${JSON.stringify(o,null,2)}\n`),r(0)}catch(t){let n=new g(`Error listing workflow statuses.`,`LIST_WORKFLOW_STATUSES_FAILED`,{command:U,workspace:e.workspace??`all`},{cause:t});i(`${n.message} [${n.code}]`,n),r(1)}})}const Ve=Be(),He=()=>{try{return c(import.meta.url)(`@agimon-ai/foundation-process-registry`)}catch{return null}};function G(e,t){for(let n of e){if(n==null||typeof n!=`object`&&typeof n!=`function`)continue;let e=n;for(let n of t){let t=e[n];if(typeof t==`function`)return t}}return null}function Ue(e){let t=[e];if(e&&typeof e==`object`){let n=e.default;if(n&&(t.push(n),typeof n==`function`))try{t.push(new n)}catch{}}return t}async function We(e){let t=He();if(!t)return async()=>{};let n=Ue(t),r=G(n,[`registerProcess`,`register`,`registerProcessInstance`]),i=G(n,[`unregisterProcess`,`unregister`,`releaseProcess`]);if(!r)return async()=>{};try{await Promise.resolve(r({name:e,pid:process.pid,command:process.argv.join(` `)}))}catch{return async()=>{}}return i?async()=>{await Promise.resolve(i({name:e,pid:process.pid}))}:async()=>{}}async function Ge(e,t){await e.start();let n=async n=>{console.error(`\\nReceived ${n}, shutting down gracefully...`);let r=0;try{await e.stop()}catch(e){console.error(`Error during shutdown:`,e),r=1}try{await t()}catch(e){console.error(`Error during resource cleanup:`,e),r=1}process.exit(r)};process.on(`SIGINT`,()=>{n(`SIGINT`)}),process.on(`SIGTERM`,()=>{n(`SIGTERM`)})}async function Ke(e){try{await e()}catch{}}const qe=new p(`mcp-serve`).description(`Start MCP server with specified transport`).option(`-t, --type <type>`,`Transport type: stdio`,`stdio`).option(`--service-name <name>`,`Service name for registry tracking`,`workflow-mcp`).action(async e=>{let t=await We(e.serviceName);try{let n=e.type.toLowerCase();n===`stdio`?await Ge(new s(r()),t):(console.error(`Unknown transport type: ${n}. Use: stdio`),process.exit(1))}catch(e){await Ke(t),console.error(`Failed to start MCP server:`,e),process.exit(1)}}),K=`run-workflow`,q=`RUN_WORKFLOW_COMMAND_FAILED`,J=`WORKFLOW_MCP_BACKGROUND_CHILD`,Y=`workflow-mcp-background-run`;function X(e){if(!e||e.length===0)return;let t={};for(let n of e){let[e,...r]=n.split(`=`);t[e]=r.join(`=`)}return Object.keys(t).length>0?t:void 0}function Z(e){if(e.runner&&e.cliAgent&&e.runner!==e.cliAgent)throw new g(`Conflicting runner selectors.`,q,{cliAgent:e.cliAgent,command:K,runner:e.runner});return e.runner??e.cliAgent}function Je(e,t){let n=process.argv[1];if(!n)throw new g(`Unable to determine the workflow-mcp CLI entry point for background execution.`,`RUN_WORKFLOW_BACKGROUND_LAUNCH_FAILED`,{command:K,workflow:e,workspace:t.workspace});let r=[n,`run-workflow`,e];t.job&&r.push(`--job`,t.job);for(let e of t.input??[])r.push(`--input`,e);for(let e of t.env??[])r.push(`--env`,e);t.secretFile&&r.push(`--secret-file`,t.secretFile),t.dryRun&&r.push(`--dry-run`),t.continueOnError&&r.push(`--continue-on-error`),t.keepWorktree&&r.push(`--keep-worktree`);let i=Z(t);i&&r.push(`--runner`,i),t.prompt&&r.push(`--prompt`,t.prompt),t.name&&r.push(`--name`,t.name),t.workspace&&r.push(`--workspace`,t.workspace);let a=l(process.execPath,r,{detached:!0,env:{...process.env,[J]:`1`},stdio:`ignore`});return a.unref(),a.pid}async function Ye(e,t){if(process.env[J]!==`1`)return async()=>{};let n=new ne(process.env.PROCESS_REGISTRY_PATH),r=ee(process.cwd()),i=process.env.NODE_ENV??`development`;return(await n.registerProcess({repositoryPath:r,serviceName:Y,serviceType:`tool`,environment:i,pid:process.pid,command:process.argv.join(` `),args:process.argv.slice(2),metadata:{workflow:e,workspace:t.workspace,job:t.job,name:t.name,runner:t.runner??t.cliAgent},force:!0})).success?async()=>{let e=await n.releaseProcess({repositoryPath:r,serviceName:Y,serviceType:`tool`,environment:i,pid:process.pid,kill:!1,releasePort:!1,force:!0});if(!e.success&&!e.error?.includes(`No matching process entry`))throw Error(e.error??`Failed to release workflow background process`)}:async()=>{}}function Xe(e={}){let t=e.createService??(()=>new a),n=e.exit??(e=>process.exit(e)),r=e.launchBackgroundRun??Je,i=e.registerBackgroundChild??Ye,o=e.logError??((e,t)=>console.error(e,t)),s=e.logInfo??(e=>process.stdout.write(`${e}\n`));return new p(K).description(`Run a GitHub Actions workflow file locally on macOS`).argument(`<workflow>`,`Path to the workflow YAML file`).option(`-j, --job <name>`,`Run only this job (and its dependencies)`).option(`-i, --input <key=value...>`,`Set workflow_dispatch input (repeatable)`).option(`-e, --env <key=value...>`,`Set extra environment variable (repeatable)`).option(`--secret-file <path>`,`Load secrets from a dotenv-style file`).option(`--dry-run`,`Print steps without executing`).option(`--continue-on-error`,`Continue past step failures`).option(`--runner <runner>`,`Preferred runner key for step command maps`).option(`--cli-agent <agent>`,`Deprecated alias for --runner`).option(`-p, --prompt <text>`,`User prompt for user_prompt trigger workflows`).option(`-n, --name <name>`,`Name for the workflow run context directory`).option(`-w, --workspace <name>`,`Workspace for workflow registry storage`).option(`--keep-worktree`,`Keep worktree on completion (skip merge and cleanup for retry)`).option(`--skip-launch`,`Skip launch-command delegation (used by inner invocations)`).option(`-b, --background`,`Run the workflow in a detached background process`).action(async(e,a)=>{try{if(a.background){let t=r(e,a);s(`Started workflow in background${t?` (PID: ${t})`:``}`),n(0);return}let o=await i(e,a),c=t();try{let t=Z(a),r=await c.run({cliAgent:a.cliAgent,runner:t,workflowPath:e,job:a.job,inputs:X(a.input),env:X(a.env),secretFile:a.secretFile,dryRun:a.dryRun,continueOnError:a.continueOnError,keepWorktree:a.keepWorktree,prompt:a.prompt,name:a.name,workspace:a.workspace,skipLaunch:a.skipLaunch});await o(),n(r.exitCode)}catch(e){throw await o(),e}}catch(t){let r=t instanceof g?t:new g(`Error executing run-workflow.`,q,{background:!!a.background,command:K,workflow:e,workspace:a.workspace},{cause:t});o(`${r.message} [${r.code}]`,r),n(1)}})}const Ze=Xe(),Q=`schedule-cron`;function Qe(e={}){let n=e.createService??(()=>new i),r=e.exit??(e=>process.exit(e)),a=e.logError??((e,t)=>console.error(e,t)),s=e.writeStdout??(e=>process.stdout.write(`${e}\n`));return new p(Q).description(`Schedule a headless Claude Code or Codex CLI run via system crontab`).argument(`<name>`,`Unique name for this cron job`).option(`-d, --cwd <path>`,`Working directory for the CLI run`,process.cwd()).option(`-c, --cli <cli>`,`CLI to use: claude or codex`,o).option(`-p, --prompt <text>`,`Prompt to pass to the CLI`).option(`-f, --prompt-file <path>`,`Path to a file whose content is used as the prompt (read at cron execution time)`).option(`-s, --schedule <cron>`,`Cron expression (e.g., "*/10 * * * *")`).option(`-i, --interval-minutes <minutes>`,`Run every N minutes (alternative to --schedule)`).action(async(e,i)=>{try{let a=t.parse({name:e,cwd:i.cwd??process.cwd(),cli:i.cli??`claude`,prompt:i.prompt,promptFile:i.promptFile,schedule:i.schedule,intervalMinutes:i.intervalMinutes?Number.parseInt(i.intervalMinutes,10):void 0}),o=await n().schedule(a);s(`Scheduled cron job "${o.name}" with schedule: ${o.schedule}`),s(`CLI: ${o.cli} | CWD: ${o.cwd}`),o.prompt&&s(`Prompt: ${o.prompt}`),r(0)}catch(t){let n=t instanceof g?t:new g(`Error scheduling cron job.`,`SCHEDULE_CRON_COMMAND_FAILED`,{command:Q,name:e},{cause:t});a(`${n.message} [${n.code}]`,n),r(1)}})}const $e=Qe(),$=`stop-workflow`;function et(t={}){let n=t.createRegistry??(()=>new e),r=t.exit??(e=>process.exit(e)),i=t.logError??((e,t)=>console.error(e,t)),a=t.writeStdout??(e=>process.stdout.write(e));return new p($).description(`Request a running workflow to stop gracefully`).argument(`<run-key>`,`Running workflow run key`).option(`-w, --workspace <name>`,`Workspace containing the running workflow`,`default`).option(`-r, --reason <text>`,`Optional stop reason to record`).action(async(e,t)=>{try{let i=n(),o=await i.requestStop(t.workspace,e,t.reason);a(`${JSON.stringify({reason:o.reason,requestedAt:o.requestedAt,runKey:e,workspace:i.resolveWorkspace(t.workspace)},null,2)}\n`),r(0)}catch(n){let a=new g(`Error requesting workflow stop.`,`STOP_WORKFLOW_FAILED`,{command:$,runKey:e,workspace:t.workspace},{cause:n});i(`${a.message} [${a.code}]`,a),r(1)}})}const tt=et();async function nt(){let e=new p;e.name(`workflow-mcp`).description(`MCP server for running GitHub Actions workflows locally`).version(ie),e.addCommand(ze),e.addCommand(Ve),e.addCommand(he),e.addCommand(pe),e.addCommand(we),e.addCommand(S),e.addCommand(Le),e.addCommand(Re),e.addCommand(qe),e.addCommand(Ze),e.addCommand($e),e.addCommand(tt),await e.parseAsync(process.argv)}nt().catch(e=>{console.error(`[CLI_STARTUP_ERROR] workflow-mcp startup failed:`,e),process.exit(1)});export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/workflow-mcp",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "MCP server for running GitHub Actions workflows locally",
5
5
  "keywords": [
6
6
  "mcp",
@@ -36,10 +36,10 @@
36
36
  "commander": "14.0.3",
37
37
  "js-yaml": "4.1.1",
38
38
  "zod": "4.4.1",
39
- "@agimon-ai/foundation-process-registry": "0.9.5",
40
- "@agimon-ai/foundation-validator": "0.6.5",
41
- "@agimon-ai/log-sink-mcp": "0.9.5",
42
- "@agimon-ai/foundation-port-registry": "0.9.5"
39
+ "@agimon-ai/foundation-process-registry": "0.9.6",
40
+ "@agimon-ai/foundation-port-registry": "0.9.6",
41
+ "@agimon-ai/foundation-validator": "0.6.6",
42
+ "@agimon-ai/log-sink-mcp": "0.9.6"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/js-yaml": "4.0.9",