@synergenius/flow-weaver 0.33.0 → 0.33.1

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.
@@ -5987,7 +5987,7 @@ var VERSION;
5987
5987
  var init_generated_version = __esm({
5988
5988
  "src/generated-version.ts"() {
5989
5989
  "use strict";
5990
- VERSION = "0.33.0";
5990
+ VERSION = "0.33.1";
5991
5991
  }
5992
5992
  });
5993
5993
 
@@ -84248,6 +84248,169 @@ var init_tools_debug = __esm({
84248
84248
  }
84249
84249
  });
84250
84250
 
84251
+ // src/mcp/run-registry.ts
84252
+ function storePendingRun(run) {
84253
+ pendingRuns.set(run.runId, run);
84254
+ }
84255
+ function getPendingRun(runId) {
84256
+ return pendingRuns.get(runId);
84257
+ }
84258
+ function removePendingRun(runId) {
84259
+ pendingRuns.delete(runId);
84260
+ }
84261
+ var pendingRuns;
84262
+ var init_run_registry = __esm({
84263
+ "src/mcp/run-registry.ts"() {
84264
+ "use strict";
84265
+ pendingRuns = /* @__PURE__ */ new Map();
84266
+ }
84267
+ });
84268
+
84269
+ // src/mcp/tools-workflow-run.ts
84270
+ function makeToolResult2(data) {
84271
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
84272
+ }
84273
+ function makeErrorResult2(code, message) {
84274
+ return {
84275
+ content: [{ type: "text", text: JSON.stringify({ error: code, message }) }],
84276
+ isError: true
84277
+ };
84278
+ }
84279
+ function generateRunId() {
84280
+ return `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
84281
+ }
84282
+ async function raceAgentPause(executionPromise, agentChannel) {
84283
+ try {
84284
+ const outcome = await Promise.race([
84285
+ executionPromise.then((r) => ({
84286
+ type: "completed",
84287
+ result: r?.result ?? r
84288
+ })),
84289
+ agentChannel.onPause().then((request) => ({
84290
+ type: "waiting_for_agent",
84291
+ request
84292
+ }))
84293
+ ]);
84294
+ return outcome;
84295
+ } catch (err) {
84296
+ return {
84297
+ type: "error",
84298
+ message: err instanceof Error ? err.message : String(err)
84299
+ };
84300
+ }
84301
+ }
84302
+ async function runWorkflowWithAgent(filePath, params, workflowName) {
84303
+ const agentChannel = new AgentChannel();
84304
+ const runId = generateRunId();
84305
+ const executionPromise = executeWorkflowFromFile(
84306
+ filePath,
84307
+ params,
84308
+ {
84309
+ workflowName,
84310
+ agentChannel,
84311
+ includeTrace: true
84312
+ }
84313
+ );
84314
+ const outcome = await raceAgentPause(executionPromise, agentChannel);
84315
+ if (outcome.type === "completed") {
84316
+ return { status: "completed", result: outcome.result };
84317
+ }
84318
+ if (outcome.type === "waiting_for_agent") {
84319
+ storePendingRun({
84320
+ runId,
84321
+ filePath,
84322
+ workflowName,
84323
+ executionPromise,
84324
+ agentChannel,
84325
+ request: outcome.request,
84326
+ createdAt: Date.now(),
84327
+ tmpFiles: []
84328
+ });
84329
+ return { status: "waiting_for_agent", runId, agentRequest: outcome.request, agentChannel };
84330
+ }
84331
+ return { status: "error", message: outcome.message };
84332
+ }
84333
+ async function resumeWorkflow(runId, agentResult) {
84334
+ const pendingRun = getPendingRun(runId);
84335
+ if (!pendingRun) {
84336
+ return { status: "error", message: `No pending run found with ID "${runId}".` };
84337
+ }
84338
+ pendingRun.agentChannel.resume(agentResult);
84339
+ const outcome = await raceAgentPause(pendingRun.executionPromise, pendingRun.agentChannel);
84340
+ if (outcome.type === "completed") {
84341
+ removePendingRun(runId);
84342
+ return { status: "completed", result: outcome.result };
84343
+ }
84344
+ if (outcome.type === "waiting_for_agent") {
84345
+ pendingRun.request = outcome.request;
84346
+ return { status: "waiting_for_agent", runId, agentRequest: outcome.request, agentChannel: pendingRun.agentChannel };
84347
+ }
84348
+ removePendingRun(runId);
84349
+ return { status: "error", message: outcome.message };
84350
+ }
84351
+ function registerWorkflowRunTools(mcp) {
84352
+ mcp.tool(
84353
+ "fw_workflow_run",
84354
+ "Run a workflow. If it hits a waitForAgent node, returns the agent request so you can respond. If it completes without pausing, returns the result directly.",
84355
+ {
84356
+ filePath: external_exports.string().describe("Path to the workflow .ts file"),
84357
+ params: external_exports.record(external_exports.unknown()).optional().describe("Input parameters for the workflow"),
84358
+ workflowName: external_exports.string().optional().describe("Specific workflow export name (for multi-workflow files)")
84359
+ },
84360
+ async (args) => {
84361
+ try {
84362
+ const result = await runWorkflowWithAgent(
84363
+ args.filePath,
84364
+ args.params ?? {},
84365
+ args.workflowName
84366
+ );
84367
+ if (result.status === "error") {
84368
+ return makeErrorResult2("EXECUTION_ERROR", result.message);
84369
+ }
84370
+ const { agentChannel: _ac, ...output } = result;
84371
+ return makeToolResult2(output);
84372
+ } catch (err) {
84373
+ return makeErrorResult2(
84374
+ "EXECUTION_ERROR",
84375
+ err instanceof Error ? err.message : String(err)
84376
+ );
84377
+ }
84378
+ }
84379
+ );
84380
+ mcp.tool(
84381
+ "fw_workflow_resume",
84382
+ "Resume a workflow that paused at waitForAgent. Provide the agent result to continue execution.",
84383
+ {
84384
+ runId: external_exports.string().describe("Run ID from fw_workflow_run"),
84385
+ agentResult: external_exports.record(external_exports.unknown()).describe("The agent result to pass back to the workflow")
84386
+ },
84387
+ async (args) => {
84388
+ try {
84389
+ const result = await resumeWorkflow(args.runId, args.agentResult);
84390
+ if (result.status === "error") {
84391
+ return makeErrorResult2("RESUME_ERROR", result.message);
84392
+ }
84393
+ const { agentChannel: _ac, ...output } = result;
84394
+ return makeToolResult2(output);
84395
+ } catch (err) {
84396
+ return makeErrorResult2(
84397
+ "RESUME_ERROR",
84398
+ err instanceof Error ? err.message : String(err)
84399
+ );
84400
+ }
84401
+ }
84402
+ );
84403
+ }
84404
+ var init_tools_workflow_run = __esm({
84405
+ "src/mcp/tools-workflow-run.ts"() {
84406
+ "use strict";
84407
+ init_zod();
84408
+ init_workflow_executor();
84409
+ init_agent_channel();
84410
+ init_run_registry();
84411
+ }
84412
+ });
84413
+
84251
84414
  // src/mcp/tools-context.ts
84252
84415
  function registerContextTools(mcp) {
84253
84416
  mcp.tool(
@@ -84492,6 +84655,7 @@ async function startMcpServer(options) {
84492
84655
  registerDocsTools(mcp);
84493
84656
  registerModelTools(mcp);
84494
84657
  registerDebugTools(mcp);
84658
+ registerWorkflowRunTools(mcp);
84495
84659
  registerContextTools(mcp);
84496
84660
  registerResourceTools(mcp);
84497
84661
  registerPrompts(mcp);
@@ -84528,6 +84692,7 @@ var init_server3 = __esm({
84528
84692
  init_tools_docs();
84529
84693
  init_tools_model();
84530
84694
  init_tools_debug();
84695
+ init_tools_workflow_run();
84531
84696
  init_tools_context();
84532
84697
  init_tools_resources();
84533
84698
  init_prompts();
@@ -89091,7 +89256,7 @@ function parseIntStrict(value) {
89091
89256
  // src/cli/index.ts
89092
89257
  init_logger();
89093
89258
  init_error_utils();
89094
- var version2 = true ? "0.33.0" : "0.0.0-dev";
89259
+ var version2 = true ? "0.33.1" : "0.0.0-dev";
89095
89260
  var program2 = new Command();
89096
89261
  program2.name("fw").description("Flow Weaver Annotations - Compile and validate workflow files").option("-v, --version", "Output the current version").option("--no-color", "Disable colors").option("--color", "Force colors").on("option:version", () => {
89097
89262
  logger.banner(version2);
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.33.0";
1
+ export declare const VERSION = "0.33.1";
2
2
  //# sourceMappingURL=generated-version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by scripts/generate-version.ts — do not edit manually
2
- export const VERSION = '0.33.0';
2
+ export const VERSION = '0.33.1';
3
3
  //# sourceMappingURL=generated-version.js.map
@@ -11,6 +11,7 @@ import { registerDiagramTools } from './tools-diagram.js';
11
11
  import { registerDocsTools } from './tools-docs.js';
12
12
  import { registerModelTools } from './tools-model.js';
13
13
  import { registerDebugTools } from './tools-debug.js';
14
+ import { registerWorkflowRunTools } from './tools-workflow-run.js';
14
15
  import { registerContextTools } from './tools-context.js';
15
16
  import { registerResourceTools } from './tools-resources.js';
16
17
  import { registerPrompts } from './prompts.js';
@@ -31,6 +32,7 @@ export async function startMcpServer(options) {
31
32
  registerDocsTools(mcp);
32
33
  registerModelTools(mcp);
33
34
  registerDebugTools(mcp);
35
+ registerWorkflowRunTools(mcp);
34
36
  registerContextTools(mcp);
35
37
  registerResourceTools(mcp);
36
38
  registerPrompts(mcp);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * MCP tools for running workflows with waitForAgent pause/resume support.
3
+ *
4
+ * fw_workflow_run: Starts a workflow. If it hits waitForAgent, returns the
5
+ * agent request to the MCP caller (e.g. Claude Code) with status "waiting_for_agent".
6
+ * If the workflow completes without pausing, returns the result directly.
7
+ *
8
+ * fw_workflow_resume: Resumes a paused workflow with the agent's result.
9
+ * Returns the final workflow result (or pauses again if another waitForAgent is hit).
10
+ */
11
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
12
+ import { AgentChannel } from './agent-channel.js';
13
+ /** Exposed for testing — run workflow with pause/resume support */
14
+ export declare function runWorkflowWithAgent(filePath: string, params: Record<string, unknown>, workflowName?: string): Promise<{
15
+ status: 'completed';
16
+ result: unknown;
17
+ } | {
18
+ status: 'waiting_for_agent';
19
+ runId: string;
20
+ agentRequest: object;
21
+ agentChannel: AgentChannel;
22
+ } | {
23
+ status: 'error';
24
+ message: string;
25
+ }>;
26
+ /** Exposed for testing — resume a paused workflow with agent result */
27
+ export declare function resumeWorkflow(runId: string, agentResult: Record<string, unknown>): Promise<{
28
+ status: 'completed';
29
+ result: unknown;
30
+ } | {
31
+ status: 'waiting_for_agent';
32
+ runId: string;
33
+ agentRequest: object;
34
+ agentChannel: AgentChannel;
35
+ } | {
36
+ status: 'error';
37
+ message: string;
38
+ }>;
39
+ export declare function registerWorkflowRunTools(mcp: McpServer): void;
40
+ //# sourceMappingURL=tools-workflow-run.d.ts.map
@@ -0,0 +1,150 @@
1
+ /**
2
+ * MCP tools for running workflows with waitForAgent pause/resume support.
3
+ *
4
+ * fw_workflow_run: Starts a workflow. If it hits waitForAgent, returns the
5
+ * agent request to the MCP caller (e.g. Claude Code) with status "waiting_for_agent".
6
+ * If the workflow completes without pausing, returns the result directly.
7
+ *
8
+ * fw_workflow_resume: Resumes a paused workflow with the agent's result.
9
+ * Returns the final workflow result (or pauses again if another waitForAgent is hit).
10
+ */
11
+ import { z } from 'zod';
12
+ import { executeWorkflowFromFile } from './workflow-executor.js';
13
+ import { AgentChannel } from './agent-channel.js';
14
+ import { storePendingRun, getPendingRun, removePendingRun, } from './run-registry.js';
15
+ function makeToolResult(data) {
16
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
17
+ }
18
+ function makeErrorResult(code, message) {
19
+ return {
20
+ content: [{ type: 'text', text: JSON.stringify({ error: code, message }) }],
21
+ isError: true,
22
+ };
23
+ }
24
+ function generateRunId() {
25
+ return `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
26
+ }
27
+ /**
28
+ * Race between workflow completion and agent pause.
29
+ * Returns whichever happens first.
30
+ */
31
+ async function raceAgentPause(executionPromise, agentChannel) {
32
+ try {
33
+ const outcome = await Promise.race([
34
+ executionPromise.then((r) => ({
35
+ type: 'completed',
36
+ result: r?.result ?? r,
37
+ })),
38
+ agentChannel.onPause().then((request) => ({
39
+ type: 'waiting_for_agent',
40
+ request,
41
+ })),
42
+ ]);
43
+ return outcome;
44
+ }
45
+ catch (err) {
46
+ return {
47
+ type: 'error',
48
+ message: err instanceof Error ? err.message : String(err),
49
+ };
50
+ }
51
+ }
52
+ /** Exposed for testing — run workflow with pause/resume support */
53
+ export async function runWorkflowWithAgent(filePath, params, workflowName) {
54
+ const agentChannel = new AgentChannel();
55
+ const runId = generateRunId();
56
+ const executionPromise = executeWorkflowFromFile(filePath, params, {
57
+ workflowName,
58
+ agentChannel,
59
+ includeTrace: true,
60
+ });
61
+ const outcome = await raceAgentPause(executionPromise, agentChannel);
62
+ if (outcome.type === 'completed') {
63
+ return { status: 'completed', result: outcome.result };
64
+ }
65
+ if (outcome.type === 'waiting_for_agent') {
66
+ storePendingRun({
67
+ runId,
68
+ filePath,
69
+ workflowName,
70
+ executionPromise,
71
+ agentChannel,
72
+ request: outcome.request,
73
+ createdAt: Date.now(),
74
+ tmpFiles: [],
75
+ });
76
+ return { status: 'waiting_for_agent', runId, agentRequest: outcome.request, agentChannel };
77
+ }
78
+ return { status: 'error', message: outcome.message };
79
+ }
80
+ /** Exposed for testing — resume a paused workflow with agent result */
81
+ export async function resumeWorkflow(runId, agentResult) {
82
+ const pendingRun = getPendingRun(runId);
83
+ if (!pendingRun) {
84
+ return { status: 'error', message: `No pending run found with ID "${runId}".` };
85
+ }
86
+ pendingRun.agentChannel.resume(agentResult);
87
+ const outcome = await raceAgentPause(pendingRun.executionPromise, pendingRun.agentChannel);
88
+ if (outcome.type === 'completed') {
89
+ removePendingRun(runId);
90
+ return { status: 'completed', result: outcome.result };
91
+ }
92
+ if (outcome.type === 'waiting_for_agent') {
93
+ pendingRun.request = outcome.request;
94
+ return { status: 'waiting_for_agent', runId, agentRequest: outcome.request, agentChannel: pendingRun.agentChannel };
95
+ }
96
+ removePendingRun(runId);
97
+ return { status: 'error', message: outcome.message };
98
+ }
99
+ export function registerWorkflowRunTools(mcp) {
100
+ // -------------------------------------------------------------------------
101
+ // fw_workflow_run - Start a workflow, pause at waitForAgent
102
+ // -------------------------------------------------------------------------
103
+ mcp.tool('fw_workflow_run', 'Run a workflow. If it hits a waitForAgent node, returns the agent request so ' +
104
+ 'you can respond. If it completes without pausing, returns the result directly.', {
105
+ filePath: z.string().describe('Path to the workflow .ts file'),
106
+ params: z
107
+ .record(z.unknown())
108
+ .optional()
109
+ .describe('Input parameters for the workflow'),
110
+ workflowName: z
111
+ .string()
112
+ .optional()
113
+ .describe('Specific workflow export name (for multi-workflow files)'),
114
+ }, async (args) => {
115
+ try {
116
+ const result = await runWorkflowWithAgent(args.filePath, args.params ?? {}, args.workflowName);
117
+ if (result.status === 'error') {
118
+ return makeErrorResult('EXECUTION_ERROR', result.message);
119
+ }
120
+ // Don't leak agentChannel to MCP output
121
+ const { agentChannel: _ac, ...output } = result;
122
+ return makeToolResult(output);
123
+ }
124
+ catch (err) {
125
+ return makeErrorResult('EXECUTION_ERROR', err instanceof Error ? err.message : String(err));
126
+ }
127
+ });
128
+ // -------------------------------------------------------------------------
129
+ // fw_workflow_resume - Resume a paused workflow with agent result
130
+ // -------------------------------------------------------------------------
131
+ mcp.tool('fw_workflow_resume', 'Resume a workflow that paused at waitForAgent. Provide the agent result to continue execution.', {
132
+ runId: z.string().describe('Run ID from fw_workflow_run'),
133
+ agentResult: z
134
+ .record(z.unknown())
135
+ .describe('The agent result to pass back to the workflow'),
136
+ }, async (args) => {
137
+ try {
138
+ const result = await resumeWorkflow(args.runId, args.agentResult);
139
+ if (result.status === 'error') {
140
+ return makeErrorResult('RESUME_ERROR', result.message);
141
+ }
142
+ const { agentChannel: _ac, ...output } = result;
143
+ return makeToolResult(output);
144
+ }
145
+ catch (err) {
146
+ return makeErrorResult('RESUME_ERROR', err instanceof Error ? err.message : String(err));
147
+ }
148
+ });
149
+ }
150
+ //# sourceMappingURL=tools-workflow-run.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.33.0",
3
+ "version": "0.33.1",
4
4
  "description": "Flow Weaver: deterministic TypeScript workflow compiler. Define workflows with JSDoc annotations, compile to standalone functions with zero runtime dependencies.",
5
5
  "private": false,
6
6
  "type": "module",