@synergenius/flowweaver-pack-weaver 0.3.1 → 0.5.0

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.
Files changed (161) hide show
  1. package/dist/bot/dashboard.d.ts +3 -0
  2. package/dist/bot/dashboard.d.ts.map +1 -1
  3. package/dist/bot/dashboard.js +141 -0
  4. package/dist/bot/dashboard.js.map +1 -1
  5. package/dist/bot/index.d.ts +8 -1
  6. package/dist/bot/index.d.ts.map +1 -1
  7. package/dist/bot/index.js +5 -0
  8. package/dist/bot/index.js.map +1 -1
  9. package/dist/bot/notifications.d.ts.map +1 -1
  10. package/dist/bot/notifications.js +18 -0
  11. package/dist/bot/notifications.js.map +1 -1
  12. package/dist/bot/session-state.d.ts +19 -0
  13. package/dist/bot/session-state.d.ts.map +1 -0
  14. package/dist/bot/session-state.js +56 -0
  15. package/dist/bot/session-state.js.map +1 -0
  16. package/dist/bot/steering.d.ts +13 -0
  17. package/dist/bot/steering.d.ts.map +1 -0
  18. package/dist/bot/steering.js +35 -0
  19. package/dist/bot/steering.js.map +1 -0
  20. package/dist/bot/system-prompt.d.ts +1 -0
  21. package/dist/bot/system-prompt.d.ts.map +1 -1
  22. package/dist/bot/system-prompt.js +55 -0
  23. package/dist/bot/system-prompt.js.map +1 -1
  24. package/dist/bot/task-queue.d.ts +26 -0
  25. package/dist/bot/task-queue.d.ts.map +1 -0
  26. package/dist/bot/task-queue.js +87 -0
  27. package/dist/bot/task-queue.js.map +1 -0
  28. package/dist/bot/types.d.ts +37 -1
  29. package/dist/bot/types.d.ts.map +1 -1
  30. package/dist/cli-bridge.d.ts +2 -0
  31. package/dist/cli-bridge.d.ts.map +1 -0
  32. package/dist/cli-bridge.js +31 -0
  33. package/dist/cli-bridge.js.map +1 -0
  34. package/dist/cli-handlers.d.ts +50 -0
  35. package/dist/cli-handlers.d.ts.map +1 -0
  36. package/dist/{cli.js → cli-handlers.js} +413 -181
  37. package/dist/cli-handlers.js.map +1 -0
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +4 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp-tools.d.ts +13 -0
  43. package/dist/mcp-tools.d.ts.map +1 -0
  44. package/dist/mcp-tools.js +175 -0
  45. package/dist/mcp-tools.js.map +1 -0
  46. package/dist/node-types/abort-task.d.ts +22 -0
  47. package/dist/node-types/abort-task.d.ts.map +1 -0
  48. package/dist/node-types/abort-task.js +33 -0
  49. package/dist/node-types/abort-task.js.map +1 -0
  50. package/dist/node-types/approval-gate.d.ts +35 -0
  51. package/dist/node-types/approval-gate.d.ts.map +1 -0
  52. package/dist/node-types/approval-gate.js +62 -0
  53. package/dist/node-types/approval-gate.js.map +1 -0
  54. package/dist/node-types/bot-report.d.ts +22 -0
  55. package/dist/node-types/bot-report.d.ts.map +1 -0
  56. package/dist/node-types/bot-report.js +63 -0
  57. package/dist/node-types/bot-report.js.map +1 -0
  58. package/dist/node-types/build-context.d.ts +29 -0
  59. package/dist/node-types/build-context.d.ts.map +1 -0
  60. package/dist/node-types/build-context.js +73 -0
  61. package/dist/node-types/build-context.js.map +1 -0
  62. package/dist/node-types/detect-provider.d.ts +20 -0
  63. package/dist/node-types/detect-provider.d.ts.map +1 -0
  64. package/dist/node-types/detect-provider.js +72 -0
  65. package/dist/node-types/detect-provider.js.map +1 -0
  66. package/dist/node-types/exec-validate-retry.d.ts +38 -0
  67. package/dist/node-types/exec-validate-retry.d.ts.map +1 -0
  68. package/dist/node-types/exec-validate-retry.js +250 -0
  69. package/dist/node-types/exec-validate-retry.js.map +1 -0
  70. package/dist/node-types/execute-plan.d.ts +34 -0
  71. package/dist/node-types/execute-plan.d.ts.map +1 -0
  72. package/dist/node-types/execute-plan.js +175 -0
  73. package/dist/node-types/execute-plan.js.map +1 -0
  74. package/dist/node-types/execute-target.d.ts +26 -0
  75. package/dist/node-types/execute-target.d.ts.map +1 -0
  76. package/dist/node-types/execute-target.js +312 -0
  77. package/dist/node-types/execute-target.js.map +1 -0
  78. package/dist/node-types/fix-errors.d.ts +32 -0
  79. package/dist/node-types/fix-errors.d.ts.map +1 -0
  80. package/dist/node-types/fix-errors.js +106 -0
  81. package/dist/node-types/fix-errors.js.map +1 -0
  82. package/dist/node-types/git-ops.d.ts +18 -0
  83. package/dist/node-types/git-ops.d.ts.map +1 -0
  84. package/dist/node-types/git-ops.js +65 -0
  85. package/dist/node-types/git-ops.js.map +1 -0
  86. package/dist/node-types/index.d.ts +20 -0
  87. package/dist/node-types/index.d.ts.map +1 -0
  88. package/dist/node-types/index.js +20 -0
  89. package/dist/node-types/index.js.map +1 -0
  90. package/dist/node-types/load-config.d.ts +15 -0
  91. package/dist/node-types/load-config.d.ts.map +1 -0
  92. package/dist/node-types/load-config.js +26 -0
  93. package/dist/node-types/load-config.js.map +1 -0
  94. package/dist/node-types/plan-task.d.ts +32 -0
  95. package/dist/node-types/plan-task.d.ts.map +1 -0
  96. package/dist/node-types/plan-task.js +122 -0
  97. package/dist/node-types/plan-task.js.map +1 -0
  98. package/dist/node-types/read-workflow.d.ts +30 -0
  99. package/dist/node-types/read-workflow.d.ts.map +1 -0
  100. package/dist/node-types/read-workflow.js +72 -0
  101. package/dist/node-types/read-workflow.js.map +1 -0
  102. package/dist/node-types/receive-task.d.ts +31 -0
  103. package/dist/node-types/receive-task.d.ts.map +1 -0
  104. package/dist/node-types/receive-task.js +72 -0
  105. package/dist/node-types/receive-task.js.map +1 -0
  106. package/dist/node-types/report.d.ts +15 -0
  107. package/dist/node-types/report.d.ts.map +1 -0
  108. package/dist/node-types/report.js +25 -0
  109. package/dist/node-types/report.js.map +1 -0
  110. package/dist/node-types/resolve-target.d.ts +24 -0
  111. package/dist/node-types/resolve-target.d.ts.map +1 -0
  112. package/dist/node-types/resolve-target.js +67 -0
  113. package/dist/node-types/resolve-target.js.map +1 -0
  114. package/dist/node-types/route-task.d.ts +26 -0
  115. package/dist/node-types/route-task.d.ts.map +1 -0
  116. package/dist/node-types/route-task.js +29 -0
  117. package/dist/node-types/route-task.js.map +1 -0
  118. package/dist/node-types/send-notify.d.ts +20 -0
  119. package/dist/node-types/send-notify.d.ts.map +1 -0
  120. package/dist/node-types/send-notify.js +75 -0
  121. package/dist/node-types/send-notify.js.map +1 -0
  122. package/dist/node-types/validate-result.d.ts +32 -0
  123. package/dist/node-types/validate-result.d.ts.map +1 -0
  124. package/dist/node-types/validate-result.js +53 -0
  125. package/dist/node-types/validate-result.js.map +1 -0
  126. package/dist/templates/index.d.ts +2 -0
  127. package/dist/templates/index.d.ts.map +1 -1
  128. package/dist/templates/index.js +3 -1
  129. package/dist/templates/index.js.map +1 -1
  130. package/dist/templates/weaver-bot-template.d.ts +3 -0
  131. package/dist/templates/weaver-bot-template.d.ts.map +1 -0
  132. package/dist/templates/weaver-bot-template.js +99 -0
  133. package/dist/templates/weaver-bot-template.js.map +1 -0
  134. package/dist/templates/weaver-template.d.ts.map +1 -1
  135. package/dist/templates/weaver-template.js +15 -653
  136. package/dist/templates/weaver-template.js.map +1 -1
  137. package/dist/workflows/index.d.ts +5 -0
  138. package/dist/workflows/index.d.ts.map +1 -0
  139. package/dist/workflows/index.js +5 -0
  140. package/dist/workflows/index.js.map +1 -0
  141. package/dist/workflows/weaver-bot-batch.d.ts +57 -0
  142. package/dist/workflows/weaver-bot-batch.d.ts.map +1 -0
  143. package/dist/workflows/weaver-bot-batch.js +60 -0
  144. package/dist/workflows/weaver-bot-batch.js.map +1 -0
  145. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  146. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  147. package/dist/workflows/weaver-bot-session.js +68 -0
  148. package/dist/workflows/weaver-bot-session.js.map +1 -0
  149. package/dist/workflows/weaver-bot.d.ts +72 -0
  150. package/dist/workflows/weaver-bot.d.ts.map +1 -0
  151. package/dist/workflows/weaver-bot.js +75 -0
  152. package/dist/workflows/weaver-bot.js.map +1 -0
  153. package/dist/workflows/weaver.d.ts +24 -0
  154. package/dist/workflows/weaver.d.ts.map +1 -0
  155. package/dist/workflows/weaver.js +28 -0
  156. package/dist/workflows/weaver.js.map +1 -0
  157. package/flowweaver.manifest.json +1004 -3
  158. package/package.json +23 -5
  159. package/dist/cli.d.ts +0 -3
  160. package/dist/cli.d.ts.map +0 -1
  161. package/dist/cli.js.map +0 -1
@@ -1,5 +1,6 @@
1
- #!/usr/bin/env node
2
1
  import * as path from 'node:path';
2
+ import * as fs from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
3
4
  import { runWorkflow } from './bot/runner.js';
4
5
  import { RunStore } from './bot/run-store.js';
5
6
  import { CostStore } from './bot/cost-store.js';
@@ -8,64 +9,7 @@ import { WatchDaemon } from './bot/watch-daemon.js';
8
9
  import { PipelineRunner } from './bot/pipeline-runner.js';
9
10
  import { DashboardServer } from './bot/dashboard.js';
10
11
  import { openBrowser } from './bot/utils.js';
11
- const HELP = `
12
- weaver - Autonomous workflow runner for Flow Weaver
13
-
14
- Usage:
15
- weaver <file> Run a workflow file
16
- weaver run <file> Same as above
17
- weaver history List recent runs
18
- weaver history <id> Show details of a specific run
19
- weaver costs Show cost summary
20
- weaver watch <file> Watch file, re-run on change
21
- weaver cron "<schedule>" <file> Run on cron schedule
22
- weaver pipeline <config.json> Run multi-stage pipeline
23
- weaver dashboard [file] Start live dashboard (optionally run file)
24
- weaver providers List available providers
25
- weaver --help Show this help
26
-
27
- Options:
28
- -v, --verbose Show detailed execution info
29
- -n, --dry-run Preview without executing
30
- -p, --params <json> Input parameters as JSON
31
- -c, --config <path> Path to .weaver.json config
32
- --quiet Suppress progress output
33
- --version Show version
34
- --dashboard Enable live dashboard for run
35
- --port <number> Dashboard port (default 4242)
36
- --open Auto-open browser
37
- --approval <mode> Override approval mode
38
-
39
- Watch/Cron options:
40
- --cron "<schedule>" Add cron trigger to watch mode
41
- --debounce <ms> File watch debounce (default 500)
42
- --log <path> Write output to log file
43
-
44
- Pipeline options:
45
- --stage <id> Run single stage + its dependencies
46
-
47
- History options:
48
- --limit <n> Number of entries (default: 20)
49
- --outcome <type> Filter: completed|failed|error|skipped
50
- --workflow <path> Filter by workflow file
51
- --since <date> Show runs after date (ISO-8601)
52
- --json JSON output
53
- --prune Prune old entries (keep 500, 90 days)
54
- --clear Delete all history
55
-
56
- Cost options:
57
- --since <duration|date> Filter: 7d, 30d, or ISO-8601 date
58
- --model <name> Filter by model
59
-
60
- Examples:
61
- weaver my-workflow.ts
62
- weaver run pipeline.ts --verbose --params '{"env":"prod"}'
63
- weaver watch my-workflow.ts --cron "*/5 * * * *"
64
- weaver pipeline deploy.json --stage test
65
- weaver history --outcome failed --limit 10
66
- weaver costs --since 7d
67
- `.trim();
68
- function parseArgs(argv) {
12
+ export function parseArgs(argv) {
69
13
  const result = {
70
14
  command: 'run',
71
15
  file: undefined,
@@ -84,6 +28,7 @@ function parseArgs(argv) {
84
28
  dashboard: false,
85
29
  dashboardPort: 4242,
86
30
  dashboardOpen: false,
31
+ autoApprove: false,
87
32
  };
88
33
  const args = argv.slice(2);
89
34
  let i = 0;
@@ -161,6 +106,9 @@ function parseArgs(argv) {
161
106
  else if (arg === 'providers') {
162
107
  result.command = 'providers';
163
108
  }
109
+ else if (arg === 'eject') {
110
+ result.command = 'eject';
111
+ }
164
112
  else if (arg === 'watch') {
165
113
  result.command = 'watch';
166
114
  }
@@ -209,6 +157,62 @@ function parseArgs(argv) {
209
157
  result.command = 'dashboard';
210
158
  result.dashboard = true;
211
159
  }
160
+ else if (arg === 'bot') {
161
+ result.command = 'bot';
162
+ // Next non-flag arg is the task string
163
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
164
+ i++;
165
+ result.botTask = args[i];
166
+ }
167
+ }
168
+ else if (arg === 'session') {
169
+ result.command = 'session';
170
+ }
171
+ else if (arg === 'steer') {
172
+ result.command = 'steer';
173
+ // Next arg is the subcommand
174
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
175
+ i++;
176
+ result.botTask = args[i];
177
+ // Next arg after redirect/queue is payload
178
+ if ((args[i] === 'redirect' || args[i] === 'queue') && i + 1 < args.length && !args[i + 1].startsWith('-')) {
179
+ i++;
180
+ result.botFile = args[i];
181
+ }
182
+ }
183
+ }
184
+ else if (arg === 'queue') {
185
+ result.command = 'queue';
186
+ // Next arg is action (add/list/clear/remove)
187
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
188
+ i++;
189
+ result.botTask = args[i];
190
+ // Next arg is task/id
191
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
192
+ i++;
193
+ result.botFile = args[i];
194
+ }
195
+ }
196
+ }
197
+ else if (arg === '--file' && i + 1 < args.length) {
198
+ i++;
199
+ result.botFile = args[i];
200
+ }
201
+ else if (arg === '--template' && i + 1 < args.length) {
202
+ i++;
203
+ result.botTemplate = args[i];
204
+ }
205
+ else if (arg === '--batch' && i + 1 < args.length) {
206
+ i++;
207
+ result.botBatch = parseInt(args[i], 10) || undefined;
208
+ }
209
+ else if (arg === '--auto-approve') {
210
+ result.autoApprove = true;
211
+ }
212
+ else if (arg === '--project-dir' && i + 1 < args.length) {
213
+ i++;
214
+ result.file = args[i];
215
+ }
212
216
  else if (arg === 'run') {
213
217
  // skip, next arg is the file
214
218
  }
@@ -222,14 +226,15 @@ function parseArgs(argv) {
222
226
  }
223
227
  else {
224
228
  console.error(`[weaver] Unknown option: ${arg}`);
225
- console.error('Run "weaver --help" for usage');
229
+ console.error('Run "flow-weaver weaver --help" for usage');
226
230
  process.exit(1);
227
231
  }
228
232
  i++;
229
233
  }
230
234
  return result;
231
235
  }
232
- function formatDuration(ms) {
236
+ // --- Formatting helpers ---
237
+ export function formatDuration(ms) {
233
238
  if (ms < 1000)
234
239
  return `${ms}ms`;
235
240
  return `${(ms / 1000).toFixed(1)}s`;
@@ -246,7 +251,13 @@ const OUTCOME_COLORS = {
246
251
  skipped: '\x1b[33m',
247
252
  };
248
253
  const RESET = '\x1b[0m';
249
- // --- History ---
254
+ const STAGE_ICONS = {
255
+ running: '\x1b[36m>\x1b[0m',
256
+ completed: '\x1b[32m+\x1b[0m',
257
+ failed: '\x1b[31mx\x1b[0m',
258
+ skipped: '\x1b[33m-\x1b[0m',
259
+ cancelled: '\x1b[33m~\x1b[0m',
260
+ };
250
261
  function printRunTable(records) {
251
262
  console.log('ID'.padEnd(10) +
252
263
  'OUTCOME'.padEnd(12) +
@@ -289,7 +300,57 @@ function printRunDetail(r) {
289
300
  }
290
301
  console.log('');
291
302
  }
292
- async function handleHistory(opts) {
303
+ function parseSince(spec) {
304
+ if (!spec)
305
+ return undefined;
306
+ const match = spec.match(/^(\d+)([dhm])$/);
307
+ if (match) {
308
+ const n = parseInt(match[1], 10);
309
+ const unit = match[2];
310
+ const ms = unit === 'd' ? n * 86_400_000 : unit === 'h' ? n * 3_600_000 : n * 60_000;
311
+ return Date.now() - ms;
312
+ }
313
+ const ts = new Date(spec).getTime();
314
+ return isNaN(ts) ? undefined : ts;
315
+ }
316
+ function formatCostTable(summary) {
317
+ const lines = [];
318
+ lines.push(`Weaver Cost Summary (${summary.totalRuns} runs)`);
319
+ lines.push(`Total: ~$${summary.totalCost.toFixed(4)}`);
320
+ lines.push(`Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
321
+ const models = Object.entries(summary.byModel);
322
+ if (models.length > 0) {
323
+ lines.push('');
324
+ lines.push('By model:');
325
+ for (const [model, data] of models) {
326
+ lines.push(` ${model}: ${data.runs} runs, ~$${data.cost.toFixed(4)}, ${data.inputTokens.toLocaleString()} in / ${data.outputTokens.toLocaleString()} out`);
327
+ }
328
+ }
329
+ return lines.join('\n');
330
+ }
331
+ function formatRunCost(cost) {
332
+ const inp = cost.totalInputTokens.toLocaleString();
333
+ const out = cost.totalOutputTokens.toLocaleString();
334
+ const usd = cost.totalCost < 0.01
335
+ ? `$${cost.totalCost.toFixed(4)}`
336
+ : `$${cost.totalCost.toFixed(2)}`;
337
+ return `tokens: ${inp} in / ${out} out | cost: ~${usd} (${cost.model})`;
338
+ }
339
+ async function loadConfig(configPath) {
340
+ if (!configPath)
341
+ return undefined;
342
+ try {
343
+ const { readFileSync } = await import('node:fs');
344
+ return JSON.parse(readFileSync(path.resolve(configPath), 'utf-8'));
345
+ }
346
+ catch (err) {
347
+ const msg = err instanceof Error ? err.message : String(err);
348
+ console.error(`[weaver] Failed to read config: ${msg}`);
349
+ process.exit(1);
350
+ }
351
+ }
352
+ // --- Handlers ---
353
+ export async function handleHistory(opts) {
293
354
  const store = new RunStore();
294
355
  if (opts.historyClear) {
295
356
  const deleted = store.clear();
@@ -332,44 +393,7 @@ async function handleHistory(opts) {
332
393
  printRunTable(records);
333
394
  }
334
395
  }
335
- // --- Costs ---
336
- function parseSince(spec) {
337
- if (!spec)
338
- return undefined;
339
- const match = spec.match(/^(\d+)([dhm])$/);
340
- if (match) {
341
- const n = parseInt(match[1], 10);
342
- const unit = match[2];
343
- const ms = unit === 'd' ? n * 86_400_000 : unit === 'h' ? n * 3_600_000 : n * 60_000;
344
- return Date.now() - ms;
345
- }
346
- const ts = new Date(spec).getTime();
347
- return isNaN(ts) ? undefined : ts;
348
- }
349
- function formatCostTable(summary) {
350
- const lines = [];
351
- lines.push(`Weaver Cost Summary (${summary.totalRuns} runs)`);
352
- lines.push(`Total: ~$${summary.totalCost.toFixed(4)}`);
353
- lines.push(`Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
354
- const models = Object.entries(summary.byModel);
355
- if (models.length > 0) {
356
- lines.push('');
357
- lines.push('By model:');
358
- for (const [model, data] of models) {
359
- lines.push(` ${model}: ${data.runs} runs, ~$${data.cost.toFixed(4)}, ${data.inputTokens.toLocaleString()} in / ${data.outputTokens.toLocaleString()} out`);
360
- }
361
- }
362
- return lines.join('\n');
363
- }
364
- function formatRunCost(cost) {
365
- const inp = cost.totalInputTokens.toLocaleString();
366
- const out = cost.totalOutputTokens.toLocaleString();
367
- const usd = cost.totalCost < 0.01
368
- ? `$${cost.totalCost.toFixed(4)}`
369
- : `$${cost.totalCost.toFixed(2)}`;
370
- return `tokens: ${inp} in / ${out} out | cost: ~${usd} (${cost.model})`;
371
- }
372
- async function handleCosts(opts) {
396
+ export async function handleCosts(opts) {
373
397
  const store = new CostStore();
374
398
  const sinceTs = parseSince(opts.costsSince);
375
399
  const summary = store.summarize({ since: sinceTs, model: opts.costsModel });
@@ -379,21 +403,7 @@ async function handleCosts(opts) {
379
403
  }
380
404
  console.log(formatCostTable(summary));
381
405
  }
382
- async function loadConfig(configPath) {
383
- if (!configPath)
384
- return undefined;
385
- try {
386
- const { readFileSync } = await import('node:fs');
387
- return JSON.parse(readFileSync(path.resolve(configPath), 'utf-8'));
388
- }
389
- catch (err) {
390
- const msg = err instanceof Error ? err.message : String(err);
391
- console.error(`[weaver] Failed to read config: ${msg}`);
392
- process.exit(1);
393
- }
394
- }
395
- // --- Watch/Cron ---
396
- async function handleWatch(opts) {
406
+ export async function handleWatch(opts) {
397
407
  if (!opts.file) {
398
408
  console.error('[weaver] No workflow file specified for watch');
399
409
  process.exit(1);
@@ -412,10 +422,10 @@ async function handleWatch(opts) {
412
422
  });
413
423
  await daemon.start();
414
424
  }
415
- async function handleCron(opts) {
425
+ export async function handleCron(opts) {
416
426
  if (!opts.cronSchedule) {
417
427
  console.error('[weaver] No cron schedule specified');
418
- console.error('Usage: weaver cron "*/5 * * * *" <file>');
428
+ console.error('Usage: flow-weaver weaver cron "*/5 * * * *" <file>');
419
429
  process.exit(1);
420
430
  }
421
431
  if (!opts.file) {
@@ -436,18 +446,10 @@ async function handleCron(opts) {
436
446
  });
437
447
  await daemon.start();
438
448
  }
439
- // --- Pipeline ---
440
- const STAGE_ICONS = {
441
- running: '\x1b[36m>\x1b[0m',
442
- completed: '\x1b[32m+\x1b[0m',
443
- failed: '\x1b[31mx\x1b[0m',
444
- skipped: '\x1b[33m-\x1b[0m',
445
- cancelled: '\x1b[33m~\x1b[0m',
446
- };
447
- async function handlePipeline(opts) {
449
+ export async function handlePipeline(opts) {
448
450
  if (!opts.file) {
449
451
  console.error('[weaver] No pipeline config specified');
450
- console.error('Usage: weaver pipeline <config.json>');
452
+ console.error('Usage: flow-weaver weaver pipeline <config.json>');
451
453
  process.exit(1);
452
454
  }
453
455
  let config;
@@ -508,8 +510,7 @@ async function handlePipeline(opts) {
508
510
  process.exit(1);
509
511
  }
510
512
  }
511
- // --- Dashboard ---
512
- async function handleDashboard(opts) {
513
+ export async function handleDashboard(opts) {
513
514
  const dashboard = new DashboardServer({ port: opts.dashboardPort });
514
515
  const port = await dashboard.start();
515
516
  const url = dashboard.getUrl();
@@ -596,8 +597,7 @@ async function handleDashboard(opts) {
596
597
  process.exit(1);
597
598
  }
598
599
  }
599
- // --- Providers ---
600
- async function handleProviders() {
600
+ export async function handleProviders() {
601
601
  await discoverProviders(defaultRegistry);
602
602
  const providers = defaultRegistry.list();
603
603
  if (providers.length === 0) {
@@ -622,64 +622,94 @@ async function handleProviders() {
622
622
  console.log('');
623
623
  }
624
624
  }
625
- // --- Main ---
626
- async function main() {
627
- const opts = parseArgs(process.argv);
628
- // Recover orphaned runs from previous crashes
625
+ export async function handleEject() {
626
+ // Resolve the pack's own workflows/weaver.ts relative to this file
627
+ const packRoot = new URL('..', import.meta.url);
628
+ const srcPath = new URL('src/workflows/weaver.ts', packRoot);
629
+ let source;
629
630
  try {
630
- const store = new RunStore();
631
- const orphans = store.checkOrphans();
632
- for (const orphan of orphans) {
633
- console.error(`[weaver] Recovered orphaned run ${orphan.id.slice(0, 8)} (${orphan.workflowFile}) killed at PID ${orphan.pid}`);
634
- }
635
- }
636
- catch { /* non-fatal */ }
637
- if (opts.showHelp) {
638
- console.log(HELP);
639
- process.exit(0);
631
+ source = fs.readFileSync(srcPath, 'utf-8');
640
632
  }
641
- if (opts.showVersion) {
633
+ catch {
634
+ // Fallback: try dist location (when running from compiled output)
635
+ const distPath = new URL('dist/workflows/weaver.ts', packRoot);
642
636
  try {
643
- const pkgPath = new URL('../package.json', import.meta.url);
644
- const { default: pkg } = await import(pkgPath.href, { with: { type: 'json' } });
645
- console.log(`weaver v${pkg.version}`);
637
+ source = fs.readFileSync(distPath, 'utf-8');
646
638
  }
647
639
  catch {
648
- console.log('weaver (version unknown)');
640
+ // Last resort: read the .js and note it
641
+ const jsPath = new URL('dist/workflows/weaver.js', packRoot);
642
+ try {
643
+ source = fs.readFileSync(jsPath, 'utf-8');
644
+ }
645
+ catch (err) {
646
+ const msg = err instanceof Error ? err.message : String(err);
647
+ console.error(`[weaver] Could not find managed workflow source: ${msg}`);
648
+ process.exit(1);
649
+ return;
650
+ }
649
651
  }
650
- process.exit(0);
651
652
  }
652
- if (opts.command === 'history') {
653
- await handleHistory(opts);
654
- process.exit(0);
655
- }
656
- if (opts.command === 'costs') {
657
- await handleCosts(opts);
658
- process.exit(0);
659
- }
660
- if (opts.command === 'providers') {
661
- await handleProviders();
662
- process.exit(0);
663
- }
664
- if (opts.command === 'watch') {
665
- await handleWatch(opts);
666
- process.exit(0);
667
- }
668
- if (opts.command === 'cron') {
669
- await handleCron(opts);
670
- process.exit(0);
671
- }
672
- if (opts.command === 'pipeline') {
673
- await handlePipeline(opts);
674
- return;
653
+ // Replace pack-relative imports with package imports
654
+ const rewritten = source
655
+ .replace(/from\s+['"]\.\.\/node-types\/load-config\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
656
+ .replace(/from\s+['"]\.\.\/node-types\/detect-provider\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
657
+ .replace(/from\s+['"]\.\.\/node-types\/resolve-target\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
658
+ .replace(/from\s+['"]\.\.\/node-types\/execute-target\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
659
+ .replace(/from\s+['"]\.\.\/node-types\/send-notify\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
660
+ .replace(/from\s+['"]\.\.\/node-types\/report\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'");
661
+ // Deduplicate import lines: collapse multiple imports from the same module
662
+ const lines = rewritten.split('\n');
663
+ const importMap = new Map();
664
+ const nonImportLines = [];
665
+ let pastImports = false;
666
+ for (const line of lines) {
667
+ const importMatch = line.match(/^import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?\s*$/);
668
+ if (importMatch && !pastImports) {
669
+ const names = importMatch[1].split(',').map((s) => s.trim()).filter(Boolean);
670
+ const mod = importMatch[2];
671
+ if (!importMap.has(mod))
672
+ importMap.set(mod, new Set());
673
+ for (const n of names)
674
+ importMap.get(mod).add(n);
675
+ }
676
+ else {
677
+ if (line.trim() !== '' && !line.match(/^import\s/))
678
+ pastImports = true;
679
+ nonImportLines.push(line);
680
+ }
675
681
  }
676
- if (opts.command === 'dashboard' || opts.dashboard) {
677
- await handleDashboard(opts);
678
- return;
682
+ const dedupedImports = [];
683
+ for (const [mod, names] of importMap) {
684
+ dedupedImports.push(`import { ${[...names].join(', ')} } from '${mod}';`);
679
685
  }
686
+ const finalSource = [...dedupedImports, ...nonImportLines].join('\n');
687
+ const destPath = path.resolve(process.cwd(), 'weaver.ts');
688
+ fs.writeFileSync(destPath, finalSource, 'utf-8');
689
+ // Read pack version
690
+ let packVersion = 'unknown';
691
+ try {
692
+ const pkgPath = new URL('package.json', packRoot);
693
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
694
+ packVersion = pkg.version;
695
+ }
696
+ catch { /* ignore */ }
697
+ // Write/update .weaver-meta.json
698
+ const metaPath = path.resolve(process.cwd(), '.weaver-meta.json');
699
+ const meta = {
700
+ ejected: true,
701
+ packVersion,
702
+ workflowFile: 'weaver.ts',
703
+ };
704
+ fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2) + '\n', 'utf-8');
705
+ console.log(`[weaver] Ejected managed workflow to ${destPath}`);
706
+ console.log(`[weaver] Metadata written to ${metaPath}`);
707
+ console.log('[weaver] You can now customize weaver.ts freely.');
708
+ }
709
+ export async function handleRun(opts) {
680
710
  if (!opts.file) {
681
711
  console.error('[weaver] No workflow file specified');
682
- console.error('Run "weaver --help" for usage');
712
+ console.error('Run "flow-weaver weaver --help" for usage');
683
713
  process.exit(1);
684
714
  }
685
715
  const filePath = path.resolve(opts.file);
@@ -745,5 +775,207 @@ async function main() {
745
775
  process.exit(1);
746
776
  }
747
777
  }
748
- main();
749
- //# sourceMappingURL=cli.js.map
778
+ export async function handleBot(opts) {
779
+ if (!opts.botTask) {
780
+ console.error('[weaver] No task specified');
781
+ console.error('Usage: flow-weaver weaver bot "Create a workflow that..."');
782
+ process.exit(1);
783
+ }
784
+ const task = {
785
+ instruction: opts.botTask,
786
+ mode: opts.botFile ? 'modify' : 'create',
787
+ targets: opts.botFile ? [opts.botFile] : undefined,
788
+ options: {
789
+ template: opts.botTemplate,
790
+ batchCount: opts.botBatch,
791
+ dryRun: opts.dryRun,
792
+ autoApprove: opts.autoApprove,
793
+ },
794
+ };
795
+ // Use the batch workflow if --batch specified
796
+ const workflowName = opts.botBatch ? 'weaver-bot-batch' : 'weaver-bot';
797
+ // Find the workflow file in the pack
798
+ const packRoot = new URL('..', import.meta.url);
799
+ let workflowPath;
800
+ try {
801
+ workflowPath = fileURLToPath(new URL(`src/workflows/${workflowName}.ts`, packRoot));
802
+ const { existsSync } = await import('node:fs');
803
+ if (!existsSync(workflowPath)) {
804
+ workflowPath = fileURLToPath(new URL(`dist/workflows/${workflowName}.js`, packRoot));
805
+ }
806
+ }
807
+ catch {
808
+ workflowPath = fileURLToPath(new URL(`dist/workflows/${workflowName}.js`, packRoot));
809
+ }
810
+ const config = await loadConfig(opts.configPath);
811
+ const nodeTimings = new Map();
812
+ // Start dashboard if requested
813
+ let dashboard = null;
814
+ if (opts.dashboard) {
815
+ dashboard = new DashboardServer({ port: opts.dashboardPort ?? 4242 });
816
+ const port = await dashboard.start();
817
+ console.log(`[weaver] Dashboard: http://127.0.0.1:${port}`);
818
+ openBrowser(`http://127.0.0.1:${port}`);
819
+ dashboard.broadcastWorkflowStart(workflowPath);
820
+ }
821
+ const onEvent = opts.quiet
822
+ ? undefined
823
+ : (event) => {
824
+ const icon = STATUS_ICONS[event.type] ?? ' ';
825
+ const label = event.nodeType ? `${event.nodeId} (${event.nodeType})` : event.nodeId;
826
+ if (dashboard)
827
+ dashboard.broadcastExecution(event);
828
+ if (event.type === 'node-start') {
829
+ nodeTimings.set(event.nodeId, event.timestamp);
830
+ if (opts.verbose)
831
+ console.log(` ${icon} ${label}`);
832
+ }
833
+ else if (event.type === 'node-complete') {
834
+ const start = nodeTimings.get(event.nodeId);
835
+ const dur = start ? ` ${formatDuration(event.timestamp - start)}` : '';
836
+ console.log(` ${icon} ${label}${dur}`);
837
+ }
838
+ else if (event.type === 'node-error') {
839
+ console.log(` ${icon} ${label}: ${event.error ?? 'unknown error'}`);
840
+ }
841
+ };
842
+ const startTime = Date.now();
843
+ if (!opts.quiet) {
844
+ console.log(`[weaver] Bot: ${opts.botTask.slice(0, 80)}`);
845
+ }
846
+ try {
847
+ const result = await runWorkflow(workflowPath, {
848
+ params: { taskJson: JSON.stringify(task), projectDir: opts.file ?? process.cwd() },
849
+ verbose: opts.verbose,
850
+ dryRun: opts.dryRun,
851
+ config,
852
+ onEvent,
853
+ onNotificationError: (channel, _event, error) => {
854
+ console.error(`[weaver] Notification error (${channel}): ${error}`);
855
+ },
856
+ });
857
+ const elapsed = formatDuration(Date.now() - startTime);
858
+ if (!opts.quiet) {
859
+ const color = result.success ? '\x1b[32m' : '\x1b[31m';
860
+ console.log(`\n${color}Bot: ${result.outcome}\x1b[0m (${elapsed})`);
861
+ console.log(` ${result.summary}`);
862
+ }
863
+ if (dashboard) {
864
+ dashboard.broadcastWorkflowComplete(result.summary ?? '', result.success);
865
+ await dashboard.stop();
866
+ }
867
+ process.exit(result.success ? 0 : 1);
868
+ }
869
+ catch (err) {
870
+ const msg = err instanceof Error ? err.message : String(err);
871
+ console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
872
+ if (dashboard) {
873
+ dashboard.broadcastWorkflowError(msg);
874
+ await dashboard.stop();
875
+ }
876
+ process.exit(1);
877
+ }
878
+ }
879
+ export async function handleSession(opts) {
880
+ const packRoot = new URL('..', import.meta.url);
881
+ let workflowPath;
882
+ try {
883
+ workflowPath = fileURLToPath(new URL('src/workflows/weaver-bot-session.ts', packRoot));
884
+ const { existsSync } = await import('node:fs');
885
+ if (!existsSync(workflowPath)) {
886
+ workflowPath = fileURLToPath(new URL('dist/workflows/weaver-bot-session.js', packRoot));
887
+ }
888
+ }
889
+ catch {
890
+ workflowPath = fileURLToPath(new URL('dist/workflows/weaver-bot-session.js', packRoot));
891
+ }
892
+ const config = await loadConfig(opts.configPath);
893
+ if (!opts.quiet) {
894
+ console.log('[weaver] Starting bot session (Ctrl+C to stop)');
895
+ console.log('[weaver] Add tasks with: flow-weaver weaver queue add "task"');
896
+ }
897
+ try {
898
+ const result = await runWorkflow(workflowPath, {
899
+ params: { projectDir: opts.file ?? process.cwd() },
900
+ verbose: opts.verbose,
901
+ dryRun: opts.dryRun,
902
+ config,
903
+ });
904
+ if (!opts.quiet) {
905
+ const color = result.success ? '\x1b[32m' : '\x1b[31m';
906
+ console.log(`${color}Session: ${result.outcome}\x1b[0m`);
907
+ }
908
+ process.exit(result.success ? 0 : 1);
909
+ }
910
+ catch (err) {
911
+ const msg = err instanceof Error ? err.message : String(err);
912
+ console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
913
+ process.exit(1);
914
+ }
915
+ }
916
+ export async function handleSteer(opts) {
917
+ const { SteeringController } = await import('./bot/steering.js');
918
+ const controller = new SteeringController();
919
+ const subcommand = opts.botTask;
920
+ if (!subcommand || !['pause', 'resume', 'cancel', 'redirect', 'queue'].includes(subcommand)) {
921
+ console.error('[weaver] Usage: flow-weaver weaver steer <pause|resume|cancel|redirect|queue> [payload]');
922
+ process.exit(1);
923
+ }
924
+ const command = {
925
+ command: subcommand,
926
+ payload: opts.botFile,
927
+ timestamp: Date.now(),
928
+ };
929
+ controller.write(command);
930
+ console.log(`[weaver] Steering command sent: ${subcommand}${opts.botFile ? ' "' + opts.botFile + '"' : ''}`);
931
+ }
932
+ export async function handleQueue(opts) {
933
+ const { TaskQueue } = await import('./bot/task-queue.js');
934
+ const queue = new TaskQueue();
935
+ const action = opts.botTask;
936
+ if (!action || !['add', 'list', 'clear', 'remove'].includes(action)) {
937
+ console.error('[weaver] Usage: flow-weaver weaver queue <add|list|clear|remove> [task|id]');
938
+ process.exit(1);
939
+ }
940
+ switch (action) {
941
+ case 'add': {
942
+ const instruction = opts.botFile;
943
+ if (!instruction) {
944
+ console.error('[weaver] Usage: flow-weaver weaver queue add "task instruction"');
945
+ process.exit(1);
946
+ }
947
+ const id = queue.add({ instruction, priority: 0 });
948
+ console.log(`[weaver] Task added: ${id}`);
949
+ break;
950
+ }
951
+ case 'list': {
952
+ const tasks = queue.list();
953
+ if (tasks.length === 0) {
954
+ console.log('No tasks in queue.');
955
+ }
956
+ else {
957
+ console.log('ID'.padEnd(10) + 'STATUS'.padEnd(12) + 'INSTRUCTION');
958
+ for (const t of tasks) {
959
+ console.log(t.id.padEnd(10) + t.status.padEnd(12) + t.instruction.slice(0, 60));
960
+ }
961
+ }
962
+ break;
963
+ }
964
+ case 'clear': {
965
+ const count = queue.clear();
966
+ console.log(`Cleared ${count} task(s).`);
967
+ break;
968
+ }
969
+ case 'remove': {
970
+ const id = opts.botFile;
971
+ if (!id) {
972
+ console.error('[weaver] Usage: flow-weaver weaver queue remove <id>');
973
+ process.exit(1);
974
+ }
975
+ const removed = queue.remove(id);
976
+ console.log(removed ? `Removed task ${id}.` : `No task found with id "${id}".`);
977
+ break;
978
+ }
979
+ }
980
+ }
981
+ //# sourceMappingURL=cli-handlers.js.map