@synergenius/flow-weaver-pack-weaver 0.8.3 → 0.9.3

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 (265) hide show
  1. package/dist/bot/ai-client.d.ts +22 -2
  2. package/dist/bot/ai-client.d.ts.map +1 -1
  3. package/dist/bot/ai-client.js +168 -20
  4. package/dist/bot/ai-client.js.map +1 -1
  5. package/dist/bot/assistant-core.d.ts +25 -0
  6. package/dist/bot/assistant-core.d.ts.map +1 -0
  7. package/dist/bot/assistant-core.js +265 -0
  8. package/dist/bot/assistant-core.js.map +1 -0
  9. package/dist/bot/assistant-tools.d.ts +9 -0
  10. package/dist/bot/assistant-tools.d.ts.map +1 -0
  11. package/dist/bot/assistant-tools.js +602 -0
  12. package/dist/bot/assistant-tools.js.map +1 -0
  13. package/dist/bot/audit-logger.d.ts.map +1 -1
  14. package/dist/bot/audit-logger.js +9 -5
  15. package/dist/bot/audit-logger.js.map +1 -1
  16. package/dist/bot/audit-store.d.ts.map +1 -1
  17. package/dist/bot/audit-store.js +3 -11
  18. package/dist/bot/audit-store.js.map +1 -1
  19. package/dist/bot/bot-manager.d.ts +49 -0
  20. package/dist/bot/bot-manager.d.ts.map +1 -0
  21. package/dist/bot/bot-manager.js +279 -0
  22. package/dist/bot/bot-manager.js.map +1 -0
  23. package/dist/bot/child-process-tracker.d.ts +6 -0
  24. package/dist/bot/child-process-tracker.d.ts.map +1 -0
  25. package/dist/bot/child-process-tracker.js +35 -0
  26. package/dist/bot/child-process-tracker.js.map +1 -0
  27. package/dist/bot/cli-provider.d.ts.map +1 -1
  28. package/dist/bot/cli-provider.js +13 -8
  29. package/dist/bot/cli-provider.js.map +1 -1
  30. package/dist/bot/conversation-store.d.ts +40 -0
  31. package/dist/bot/conversation-store.d.ts.map +1 -0
  32. package/dist/bot/conversation-store.js +182 -0
  33. package/dist/bot/conversation-store.js.map +1 -0
  34. package/dist/bot/cost-store.d.ts.map +1 -1
  35. package/dist/bot/cost-store.js +10 -14
  36. package/dist/bot/cost-store.js.map +1 -1
  37. package/dist/bot/error-guide.d.ts +10 -0
  38. package/dist/bot/error-guide.d.ts.map +1 -0
  39. package/dist/bot/error-guide.js +34 -0
  40. package/dist/bot/error-guide.js.map +1 -0
  41. package/dist/bot/genesis-store.d.ts.map +1 -1
  42. package/dist/bot/genesis-store.js +11 -20
  43. package/dist/bot/genesis-store.js.map +1 -1
  44. package/dist/bot/index.d.ts +3 -0
  45. package/dist/bot/index.d.ts.map +1 -1
  46. package/dist/bot/index.js +3 -0
  47. package/dist/bot/index.js.map +1 -1
  48. package/dist/bot/knowledge-store.d.ts +17 -0
  49. package/dist/bot/knowledge-store.d.ts.map +1 -0
  50. package/dist/bot/knowledge-store.js +53 -0
  51. package/dist/bot/knowledge-store.js.map +1 -0
  52. package/dist/bot/pipeline-runner.d.ts.map +1 -1
  53. package/dist/bot/pipeline-runner.js +8 -1
  54. package/dist/bot/pipeline-runner.js.map +1 -1
  55. package/dist/bot/retry-utils.d.ts +19 -0
  56. package/dist/bot/retry-utils.d.ts.map +1 -0
  57. package/dist/bot/retry-utils.js +64 -0
  58. package/dist/bot/retry-utils.js.map +1 -0
  59. package/dist/bot/run-store.d.ts.map +1 -1
  60. package/dist/bot/run-store.js +2 -10
  61. package/dist/bot/run-store.js.map +1 -1
  62. package/dist/bot/runner.d.ts.map +1 -1
  63. package/dist/bot/runner.js +24 -3
  64. package/dist/bot/runner.js.map +1 -1
  65. package/dist/bot/safe-json.d.ts +32 -0
  66. package/dist/bot/safe-json.d.ts.map +1 -0
  67. package/dist/bot/safe-json.js +56 -0
  68. package/dist/bot/safe-json.js.map +1 -0
  69. package/dist/bot/safe-path.d.ts +18 -0
  70. package/dist/bot/safe-path.d.ts.map +1 -0
  71. package/dist/bot/safe-path.js +40 -0
  72. package/dist/bot/safe-path.js.map +1 -0
  73. package/dist/bot/session-state.d.ts.map +1 -1
  74. package/dist/bot/session-state.js +3 -1
  75. package/dist/bot/session-state.js.map +1 -1
  76. package/dist/bot/steering.js +1 -1
  77. package/dist/bot/steering.js.map +1 -1
  78. package/dist/bot/step-executor.d.ts +10 -5
  79. package/dist/bot/step-executor.d.ts.map +1 -1
  80. package/dist/bot/step-executor.js +252 -3
  81. package/dist/bot/step-executor.js.map +1 -1
  82. package/dist/bot/system-prompt.d.ts +1 -1
  83. package/dist/bot/system-prompt.d.ts.map +1 -1
  84. package/dist/bot/system-prompt.js +69 -43
  85. package/dist/bot/system-prompt.js.map +1 -1
  86. package/dist/bot/task-decomposer.d.ts +24 -0
  87. package/dist/bot/task-decomposer.d.ts.map +1 -0
  88. package/dist/bot/task-decomposer.js +75 -0
  89. package/dist/bot/task-decomposer.js.map +1 -0
  90. package/dist/bot/task-queue.d.ts +17 -4
  91. package/dist/bot/task-queue.d.ts.map +1 -1
  92. package/dist/bot/task-queue.js +102 -14
  93. package/dist/bot/task-queue.js.map +1 -1
  94. package/dist/bot/terminal-renderer.d.ts +60 -0
  95. package/dist/bot/terminal-renderer.d.ts.map +1 -0
  96. package/dist/bot/terminal-renderer.js +205 -0
  97. package/dist/bot/terminal-renderer.js.map +1 -0
  98. package/dist/bot/types.d.ts +7 -0
  99. package/dist/bot/types.d.ts.map +1 -1
  100. package/dist/bot/weaver-tools.d.ts +18 -0
  101. package/dist/bot/weaver-tools.d.ts.map +1 -0
  102. package/dist/bot/weaver-tools.js +215 -0
  103. package/dist/bot/weaver-tools.js.map +1 -0
  104. package/dist/cli-bridge.d.ts.map +1 -1
  105. package/dist/cli-bridge.js +10 -3
  106. package/dist/cli-bridge.js.map +1 -1
  107. package/dist/cli-handlers.d.ts +15 -1
  108. package/dist/cli-handlers.d.ts.map +1 -1
  109. package/dist/cli-handlers.js +742 -28
  110. package/dist/cli-handlers.js.map +1 -1
  111. package/dist/handlers/on-bot-completed.d.ts +21 -0
  112. package/dist/handlers/on-bot-completed.d.ts.map +1 -0
  113. package/dist/handlers/on-bot-completed.js +28 -0
  114. package/dist/handlers/on-bot-completed.js.map +1 -0
  115. package/dist/handlers/on-execution-failure.d.ts +23 -0
  116. package/dist/handlers/on-execution-failure.d.ts.map +1 -0
  117. package/dist/handlers/on-execution-failure.js +28 -0
  118. package/dist/handlers/on-execution-failure.js.map +1 -0
  119. package/dist/handlers/scheduled-run.d.ts +24 -0
  120. package/dist/handlers/scheduled-run.d.ts.map +1 -0
  121. package/dist/handlers/scheduled-run.js +25 -0
  122. package/dist/handlers/scheduled-run.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +4 -0
  126. package/dist/index.js.map +1 -1
  127. package/dist/mcp-tools.js +2 -2
  128. package/dist/mcp-tools.js.map +1 -1
  129. package/dist/node-types/abort-task.d.ts.map +1 -1
  130. package/dist/node-types/abort-task.js +4 -3
  131. package/dist/node-types/abort-task.js.map +1 -1
  132. package/dist/node-types/agent-execute.d.ts +38 -0
  133. package/dist/node-types/agent-execute.d.ts.map +1 -0
  134. package/dist/node-types/agent-execute.js +256 -0
  135. package/dist/node-types/agent-execute.js.map +1 -0
  136. package/dist/node-types/bot-report.d.ts +5 -3
  137. package/dist/node-types/bot-report.d.ts.map +1 -1
  138. package/dist/node-types/bot-report.js +39 -7
  139. package/dist/node-types/bot-report.js.map +1 -1
  140. package/dist/node-types/build-context.d.ts +3 -3
  141. package/dist/node-types/build-context.d.ts.map +1 -1
  142. package/dist/node-types/build-context.js +108 -24
  143. package/dist/node-types/build-context.js.map +1 -1
  144. package/dist/node-types/detect-provider.d.ts +2 -2
  145. package/dist/node-types/detect-provider.d.ts.map +1 -1
  146. package/dist/node-types/detect-provider.js +3 -1
  147. package/dist/node-types/detect-provider.js.map +1 -1
  148. package/dist/node-types/exec-validate-retry.d.ts.map +1 -1
  149. package/dist/node-types/exec-validate-retry.js +43 -6
  150. package/dist/node-types/exec-validate-retry.js.map +1 -1
  151. package/dist/node-types/execute-plan.d.ts.map +1 -1
  152. package/dist/node-types/execute-plan.js +31 -8
  153. package/dist/node-types/execute-plan.js.map +1 -1
  154. package/dist/node-types/execute-target.d.ts.map +1 -1
  155. package/dist/node-types/execute-target.js +3 -1
  156. package/dist/node-types/execute-target.js.map +1 -1
  157. package/dist/node-types/fix-errors.d.ts.map +1 -1
  158. package/dist/node-types/fix-errors.js +21 -5
  159. package/dist/node-types/fix-errors.js.map +1 -1
  160. package/dist/node-types/genesis-observe.d.ts.map +1 -1
  161. package/dist/node-types/genesis-observe.js +3 -1
  162. package/dist/node-types/genesis-observe.js.map +1 -1
  163. package/dist/node-types/genesis-report.js +4 -1
  164. package/dist/node-types/genesis-report.js.map +1 -1
  165. package/dist/node-types/git-ops.d.ts.map +1 -1
  166. package/dist/node-types/git-ops.js +98 -4
  167. package/dist/node-types/git-ops.js.map +1 -1
  168. package/dist/node-types/index.d.ts +2 -0
  169. package/dist/node-types/index.d.ts.map +1 -1
  170. package/dist/node-types/index.js +2 -0
  171. package/dist/node-types/index.js.map +1 -1
  172. package/dist/node-types/load-config.d.ts +2 -2
  173. package/dist/node-types/load-config.d.ts.map +1 -1
  174. package/dist/node-types/load-config.js.map +1 -1
  175. package/dist/node-types/plan-task.d.ts.map +1 -1
  176. package/dist/node-types/plan-task.js +14 -2
  177. package/dist/node-types/plan-task.js.map +1 -1
  178. package/dist/node-types/read-workflow.js +8 -2
  179. package/dist/node-types/read-workflow.js.map +1 -1
  180. package/dist/node-types/receive-task.d.ts.map +1 -1
  181. package/dist/node-types/receive-task.js +35 -26
  182. package/dist/node-types/receive-task.js.map +1 -1
  183. package/dist/node-types/send-notify.js +2 -1
  184. package/dist/node-types/send-notify.js.map +1 -1
  185. package/dist/node-types/validate-gate.d.ts +18 -0
  186. package/dist/node-types/validate-gate.d.ts.map +1 -0
  187. package/dist/node-types/validate-gate.js +96 -0
  188. package/dist/node-types/validate-gate.js.map +1 -0
  189. package/dist/workflows/genesis-task.d.ts +20 -12
  190. package/dist/workflows/genesis-task.d.ts.map +1 -1
  191. package/dist/workflows/genesis-task.js +20 -12
  192. package/dist/workflows/genesis-task.js.map +1 -1
  193. package/dist/workflows/weaver-agent.d.ts +35 -0
  194. package/dist/workflows/weaver-agent.d.ts.map +1 -0
  195. package/dist/workflows/weaver-agent.js +777 -0
  196. package/dist/workflows/weaver-agent.js.map +1 -0
  197. package/dist/workflows/weaver-bot-batch.d.ts +19 -26
  198. package/dist/workflows/weaver-bot-batch.d.ts.map +1 -1
  199. package/dist/workflows/weaver-bot-batch.js +1043 -27
  200. package/dist/workflows/weaver-bot-batch.js.map +1 -1
  201. package/dist/workflows/weaver-bot.d.ts +21 -35
  202. package/dist/workflows/weaver-bot.d.ts.map +1 -1
  203. package/dist/workflows/weaver-bot.js +1119 -36
  204. package/dist/workflows/weaver-bot.js.map +1 -1
  205. package/flowweaver.manifest.json +113 -2
  206. package/package.json +5 -2
  207. package/src/bot/ai-client.ts +180 -19
  208. package/src/bot/assistant-core.ts +306 -0
  209. package/src/bot/assistant-tools.ts +605 -0
  210. package/src/bot/audit-logger.ts +6 -5
  211. package/src/bot/audit-store.ts +3 -12
  212. package/src/bot/bot-manager.ts +293 -0
  213. package/src/bot/child-process-tracker.ts +40 -0
  214. package/src/bot/cli-provider.ts +13 -8
  215. package/src/bot/conversation-store.ts +222 -0
  216. package/src/bot/cost-store.ts +11 -12
  217. package/src/bot/error-guide.ts +34 -0
  218. package/src/bot/genesis-store.ts +11 -17
  219. package/src/bot/index.ts +5 -0
  220. package/src/bot/knowledge-store.ts +59 -0
  221. package/src/bot/pipeline-runner.ts +7 -1
  222. package/src/bot/retry-utils.ts +76 -0
  223. package/src/bot/run-store.ts +2 -11
  224. package/src/bot/runner.ts +26 -3
  225. package/src/bot/safe-json.ts +76 -0
  226. package/src/bot/safe-path.ts +44 -0
  227. package/src/bot/session-state.ts +2 -1
  228. package/src/bot/steering.ts +1 -1
  229. package/src/bot/step-executor.ts +313 -5
  230. package/src/bot/system-prompt.ts +70 -47
  231. package/src/bot/task-decomposer.ts +100 -0
  232. package/src/bot/task-queue.ts +119 -15
  233. package/src/bot/terminal-renderer.ts +241 -0
  234. package/src/bot/types.ts +8 -0
  235. package/src/bot/weaver-tools.ts +225 -0
  236. package/src/cli-bridge.ts +14 -3
  237. package/src/cli-handlers.ts +760 -29
  238. package/src/handlers/on-bot-completed.ts +48 -0
  239. package/src/handlers/on-execution-failure.ts +42 -0
  240. package/src/handlers/scheduled-run.ts +42 -0
  241. package/src/index.ts +5 -0
  242. package/src/mcp-tools.ts +2 -2
  243. package/src/node-types/abort-task.ts +5 -4
  244. package/src/node-types/agent-execute.ts +306 -0
  245. package/src/node-types/bot-report.ts +40 -9
  246. package/src/node-types/build-context.ts +112 -25
  247. package/src/node-types/detect-provider.ts +4 -3
  248. package/src/node-types/exec-validate-retry.ts +47 -8
  249. package/src/node-types/execute-plan.ts +32 -8
  250. package/src/node-types/execute-target.ts +2 -1
  251. package/src/node-types/fix-errors.ts +20 -5
  252. package/src/node-types/genesis-observe.ts +2 -1
  253. package/src/node-types/genesis-report.ts +1 -1
  254. package/src/node-types/git-ops.ts +93 -4
  255. package/src/node-types/index.ts +2 -0
  256. package/src/node-types/load-config.ts +3 -3
  257. package/src/node-types/plan-task.ts +15 -3
  258. package/src/node-types/read-workflow.ts +2 -2
  259. package/src/node-types/receive-task.ts +31 -26
  260. package/src/node-types/send-notify.ts +1 -1
  261. package/src/node-types/validate-gate.ts +112 -0
  262. package/src/workflows/genesis-task.ts +20 -12
  263. package/src/workflows/weaver-agent.ts +799 -0
  264. package/src/workflows/weaver-bot-batch.ts +1049 -27
  265. package/src/workflows/weaver-bot.ts +1123 -36
@@ -32,6 +32,7 @@ export function parseArgs(argv) {
32
32
  autoApprove: false,
33
33
  genesisInit: false,
34
34
  genesisWatch: false,
35
+ sessionContinuous: false,
35
36
  };
36
37
  const args = argv.slice(2);
37
38
  let i = 0;
@@ -176,6 +177,18 @@ export function parseArgs(argv) {
176
177
  else if (arg === 'session') {
177
178
  result.command = 'session';
178
179
  }
180
+ else if (arg === 'assistant') {
181
+ result.command = 'assistant';
182
+ }
183
+ else if (arg === 'examples') {
184
+ result.command = 'examples';
185
+ }
186
+ else if (arg === 'doctor') {
187
+ result.command = 'doctor';
188
+ }
189
+ else if (arg === 'status') {
190
+ result.command = 'status';
191
+ }
179
192
  else if (arg === 'steer') {
180
193
  result.command = 'steer';
181
194
  // Next arg is the subcommand
@@ -228,12 +241,44 @@ export function parseArgs(argv) {
228
241
  else if (arg === 'genesis') {
229
242
  result.command = 'genesis';
230
243
  }
244
+ else if (arg === 'init') {
245
+ result.command = 'init';
246
+ }
231
247
  else if (arg === '--init') {
232
248
  result.genesisInit = true;
233
249
  }
234
250
  else if (arg === '--watch') {
235
251
  result.genesisWatch = true;
236
252
  }
253
+ else if (arg === '--new') {
254
+ result.assistantNew = true;
255
+ }
256
+ else if (arg === '--resume' && i + 1 < args.length) {
257
+ i++;
258
+ result.assistantResume = args[i];
259
+ }
260
+ else if (arg === '--list') {
261
+ result.assistantList = true;
262
+ }
263
+ else if (arg === '--delete' && i + 1 < args.length) {
264
+ i++;
265
+ result.assistantDelete = args[i];
266
+ }
267
+ else if (arg === '--continuous') {
268
+ result.sessionContinuous = true;
269
+ }
270
+ else if (arg === '--until' && i + 1 < args.length) {
271
+ i++;
272
+ result.sessionUntil = args[i];
273
+ }
274
+ else if (arg === '--max-tasks' && i + 1 < args.length) {
275
+ i++;
276
+ result.sessionMaxTasks = parseInt(args[i], 10) || undefined;
277
+ }
278
+ else if (arg === '--parallel' && i + 1 < args.length) {
279
+ i++;
280
+ result.sessionParallel = Math.min(Math.max(parseInt(args[i], 10) || 1, 1), 5);
281
+ }
237
282
  else if (arg === '--project-dir' && i + 1 < args.length) {
238
283
  i++;
239
284
  result.file = args[i];
@@ -323,6 +368,14 @@ function printRunDetail(r) {
323
368
  if (r.params) {
324
369
  console.log(` Params: ${JSON.stringify(r.params)}`);
325
370
  }
371
+ if (r.stepLog && r.stepLog.length > 0) {
372
+ console.log(`\n Steps (${r.stepLog.length}):`);
373
+ for (const entry of r.stepLog) {
374
+ const icon = entry.status === 'ok' ? '\x1b[32m+\x1b[0m' : entry.status === 'blocked' ? '\x1b[33m⚠\x1b[0m' : '\x1b[31m✗\x1b[0m';
375
+ const detail = entry.detail ? ` — ${entry.detail}` : '';
376
+ console.log(` ${icon} ${entry.step}${detail}`);
377
+ }
378
+ }
326
379
  console.log('');
327
380
  }
328
381
  function parseSince(spec) {
@@ -423,10 +476,20 @@ export async function handleCosts(opts) {
423
476
  const sinceTs = parseSince(opts.costsSince);
424
477
  const summary = store.summarize({ since: sinceTs, model: opts.costsModel });
425
478
  if (summary.totalRuns === 0) {
426
- console.log('No cost data found.');
479
+ if (opts.historyJson) {
480
+ console.log(JSON.stringify(summary, null, 2));
481
+ }
482
+ else {
483
+ console.log('No cost data found.');
484
+ }
427
485
  return;
428
486
  }
429
- console.log(formatCostTable(summary));
487
+ if (opts.historyJson) {
488
+ console.log(JSON.stringify(summary, null, 2));
489
+ }
490
+ else {
491
+ console.log(formatCostTable(summary));
492
+ }
430
493
  }
431
494
  export async function handleWatch(opts) {
432
495
  if (!opts.file) {
@@ -650,6 +713,7 @@ export async function handleProviders() {
650
713
  // --- Workflow map for eject and resolution ---
651
714
  const MANAGED_WORKFLOWS = {
652
715
  bot: 'weaver-bot',
716
+ agent: 'weaver-agent',
653
717
  batch: 'weaver-bot-batch',
654
718
  genesis: 'genesis-task',
655
719
  };
@@ -1127,31 +1191,305 @@ export async function handleBot(opts) {
1127
1191
  }
1128
1192
  }
1129
1193
  export async function handleSession(opts) {
1130
- const workflowPath = resolveWorkflowPath('bot', opts.file ?? process.cwd());
1194
+ const projectDir = opts.file ?? process.cwd();
1195
+ // Set project dir for per-project queue isolation
1196
+ process.env.WEAVER_PROJECT_DIR = projectDir;
1131
1197
  const config = await loadConfig(opts.configPath);
1132
- if (!opts.quiet) {
1133
- console.log('[weaver] Starting bot session (Ctrl+C to stop)');
1134
- console.log('[weaver] Add tasks with: flow-weaver weaver queue add "task"');
1135
- }
1198
+ const workflowPath = resolveWorkflowPath('agent', projectDir);
1199
+ // Create terminal renderer for all session output
1200
+ const { TerminalRenderer } = await import('./bot/terminal-renderer.js');
1201
+ const renderer = new TerminalRenderer({ verbose: opts.verbose, quiet: opts.quiet });
1202
+ // Parse --until HH:MM into a deadline timestamp
1203
+ let deadline;
1204
+ let deadlineStr;
1205
+ if (opts.sessionUntil) {
1206
+ const match = opts.sessionUntil.match(/^(\d{1,2}):(\d{2})$/);
1207
+ if (match) {
1208
+ const now = new Date();
1209
+ const target = new Date(now);
1210
+ target.setHours(parseInt(match[1], 10), parseInt(match[2], 10), 0, 0);
1211
+ if (target.getTime() <= now.getTime())
1212
+ target.setDate(target.getDate() + 1);
1213
+ deadline = target.getTime();
1214
+ deadlineStr = target.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
1215
+ }
1216
+ }
1217
+ const maxTasks = opts.sessionMaxTasks ?? Infinity;
1218
+ const continuous = opts.sessionContinuous || !!opts.sessionUntil || maxTasks < Infinity;
1219
+ const parallelism = opts.sessionParallel ?? 1;
1220
+ // Crash recovery
1221
+ if (continuous) {
1222
+ const { TaskQueue } = await import('./bot/task-queue.js');
1223
+ const recoveryQueue = new TaskQueue();
1224
+ const recovered = await recoveryQueue.recoverOrphans();
1225
+ if (recovered > 0)
1226
+ renderer.info(`Recovered ${recovered} orphaned task(s)`);
1227
+ }
1228
+ // Clean stale cache files
1136
1229
  try {
1137
- const result = await runWorkflow(workflowPath, {
1138
- params: { projectDir: opts.file ?? process.cwd() },
1139
- verbose: opts.verbose,
1140
- dryRun: opts.dryRun,
1141
- config,
1142
- });
1143
- if (!opts.quiet) {
1144
- const color = result.success ? '\x1b[32m' : '\x1b[31m';
1145
- console.log(`${color}Session: ${result.outcome}\x1b[0m`);
1230
+ const { execSync: execSyncClean } = await import('node:child_process');
1231
+ const staleOutput = execSyncClean(`find "${projectDir}" -name "fw-exec-*" -type f`, { encoding: 'utf-8', timeout: 5000 }).trim();
1232
+ if (staleOutput) {
1233
+ const staleFiles = staleOutput.split('\n').filter(Boolean);
1234
+ for (const f of staleFiles) {
1235
+ try {
1236
+ fs.unlinkSync(f);
1237
+ }
1238
+ catch { }
1239
+ }
1146
1240
  }
1147
- process.exit(result.success ? 0 : 1);
1148
1241
  }
1149
- catch (err) {
1150
- const msg = err instanceof Error ? err.message : String(err);
1151
- console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
1152
- process.exit(1);
1242
+ catch { /* non-fatal */ }
1243
+ // Detect provider label for session start
1244
+ const providerType = config?.provider ?? 'auto';
1245
+ const providerLabel = typeof providerType === 'object' ? providerType.name : String(providerType);
1246
+ const sessionStartTime = Date.now();
1247
+ renderer.sessionStart({ provider: providerLabel, parallel: parallelism, deadline: deadlineStr });
1248
+ // Single-run mode (backwards compatible)
1249
+ if (!continuous) {
1250
+ try {
1251
+ const result = await runWorkflow(workflowPath, {
1252
+ params: { projectDir },
1253
+ verbose: opts.verbose,
1254
+ dryRun: opts.dryRun,
1255
+ config,
1256
+ });
1257
+ if (!opts.quiet) {
1258
+ const color = result.success ? '\x1b[32m' : '\x1b[31m';
1259
+ console.log(`${color}Session: ${result.outcome}\x1b[0m`);
1260
+ }
1261
+ process.exit(result.success ? 0 : 1);
1262
+ }
1263
+ catch (err) {
1264
+ const msg = err instanceof Error ? err.message : String(err);
1265
+ console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
1266
+ process.exit(1);
1267
+ }
1268
+ return;
1269
+ }
1270
+ // Continuous mode: loop until deadline/maxTasks/interrupt
1271
+ const { TaskQueue } = await import('./bot/task-queue.js');
1272
+ const { isTransientError } = await import('./bot/retry-utils.js');
1273
+ const { getErrorGuidance } = await import('./bot/error-guide.js');
1274
+ const queue = new TaskQueue();
1275
+ let taskCount = 0;
1276
+ let interrupted = false;
1277
+ let consecutiveErrors = 0;
1278
+ let consecutiveNoOps = 0;
1279
+ const MAX_CONSECUTIVE_ERRORS = 3;
1280
+ const MAX_CONSECUTIVE_NO_OPS = 5;
1281
+ // Session stats
1282
+ let sessionCompleted = 0, sessionFailed = 0, sessionNoOp = 0;
1283
+ let sessionInputTokens = 0, sessionOutputTokens = 0, sessionCost = 0;
1284
+ process.on('SIGINT', () => { interrupted = true; });
1285
+ process.on('SIGTERM', () => { interrupted = true; });
1286
+ // Parallel task tracking
1287
+ const running = new Map();
1288
+ const filesInUse = new Set();
1289
+ const processTask = async (task) => {
1290
+ try {
1291
+ const result = await runWorkflow(workflowPath, {
1292
+ params: { projectDir, taskJson: JSON.stringify(task) },
1293
+ verbose: opts.verbose,
1294
+ dryRun: opts.dryRun,
1295
+ config,
1296
+ });
1297
+ // Classify outcome: the summary contains "no changes" or "0 files" for no-ops
1298
+ const isNoOp = result.success && (result.summary.includes('no changes') ||
1299
+ result.summary.includes('0 file') ||
1300
+ result.summary.includes("doesn't exist") ||
1301
+ result.summary.includes('does not exist') ||
1302
+ result.summary.includes('nothing to') ||
1303
+ result.outcome === 'no-op');
1304
+ if (isNoOp) {
1305
+ await queue.markNoOp(task.id);
1306
+ sessionNoOp++;
1307
+ consecutiveNoOps++;
1308
+ consecutiveErrors = 0;
1309
+ }
1310
+ else if (result.success) {
1311
+ await queue.markComplete(task.id);
1312
+ sessionCompleted++;
1313
+ consecutiveErrors = 0;
1314
+ consecutiveNoOps = 0;
1315
+ }
1316
+ else {
1317
+ await queue.markFailed(task.id, result.summary || result.outcome || 'unknown error');
1318
+ sessionFailed++;
1319
+ consecutiveErrors++;
1320
+ consecutiveNoOps = 0;
1321
+ }
1322
+ // Track cost from workflow result
1323
+ if (result.cost) {
1324
+ sessionInputTokens += result.cost.totalInputTokens ?? 0;
1325
+ sessionOutputTokens += result.cost.totalOutputTokens ?? 0;
1326
+ sessionCost += result.cost.totalCost ?? 0;
1327
+ }
1328
+ }
1329
+ catch (err) {
1330
+ const msg = err instanceof Error ? err.message : String(err);
1331
+ const guidance = getErrorGuidance(msg);
1332
+ renderer.error(`Task ${task.id.slice(0, 8)} error`, guidance ? `${msg}\n Hint: ${guidance}` : msg);
1333
+ await queue.markFailed(task.id, msg);
1334
+ sessionFailed++;
1335
+ if (!isTransientError(err)) {
1336
+ consecutiveErrors++;
1337
+ }
1338
+ }
1339
+ finally {
1340
+ for (const f of task.targets ?? [])
1341
+ filesInUse.delete(f);
1342
+ running.delete(task.id);
1343
+ }
1344
+ };
1345
+ while (taskCount < maxTasks && !interrupted) {
1346
+ if (deadline && Date.now() >= deadline) {
1347
+ renderer.info('Deadline reached, stopping session.');
1348
+ break;
1349
+ }
1350
+ if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
1351
+ renderer.error('Session stopped', `${MAX_CONSECUTIVE_ERRORS} consecutive errors — check your API key or provider config.`);
1352
+ break;
1353
+ }
1354
+ // Pause on consecutive no-ops (bot is spinning without doing anything)
1355
+ if (consecutiveNoOps >= MAX_CONSECUTIVE_NO_OPS) {
1356
+ renderer.warn(`${MAX_CONSECUTIVE_NO_OPS} consecutive no-op tasks — pausing 60s`);
1357
+ await new Promise(r => setTimeout(r, 60_000));
1358
+ consecutiveNoOps = 0;
1359
+ }
1360
+ // Wait if at capacity
1361
+ if (running.size >= parallelism) {
1362
+ await Promise.race(running.values());
1363
+ continue;
1364
+ }
1365
+ const task = await queue.next();
1366
+ if (!task) {
1367
+ if (running.size > 0) {
1368
+ // Tasks still running — wait for one to finish
1369
+ await Promise.race(running.values());
1370
+ continue;
1371
+ }
1372
+ // No pending or running tasks — wait and retry
1373
+ await new Promise(r => setTimeout(r, 5_000));
1374
+ continue;
1375
+ }
1376
+ // Auto-decompose broad tasks into per-file tasks
1377
+ const { decomposeTask } = await import('./bot/task-decomposer.js');
1378
+ const { decomposed, tasks: subtasks } = decomposeTask(task, projectDir);
1379
+ if (decomposed && subtasks.length > 1) {
1380
+ // Replace the broad task with per-file tasks
1381
+ await queue.markComplete(task.id);
1382
+ let decomposedCount = 0;
1383
+ for (const st of subtasks) {
1384
+ const { duplicate } = await queue.add({ instruction: st.instruction, mode: st.mode, targets: st.targets, priority: st.priority ?? 0 });
1385
+ if (!duplicate)
1386
+ decomposedCount++;
1387
+ }
1388
+ renderer.info(`Decomposed into ${subtasks.length} per-file tasks`);
1389
+ continue;
1390
+ }
1391
+ // File conflict check: if task targets overlap with files in use, wait
1392
+ const taskTargets = task.targets ?? [];
1393
+ const hasConflict = taskTargets.some(f => filesInUse.has(f));
1394
+ if (hasConflict && running.size > 0) {
1395
+ await Promise.race(running.values());
1396
+ continue;
1397
+ }
1398
+ taskCount++;
1399
+ if (opts.verbose)
1400
+ process.env.WEAVER_VERBOSE = '1';
1401
+ renderer.taskStart(taskCount, task.instruction ?? task.id);
1402
+ await queue.markRunning(task.id);
1403
+ // Reserve files
1404
+ for (const f of taskTargets)
1405
+ filesInUse.add(f);
1406
+ // Launch task (parallel or sequential based on parallelism setting)
1407
+ const promise = processTask(task);
1408
+ running.set(task.id, promise);
1409
+ // In sequential mode (parallelism=1), await immediately
1410
+ if (parallelism <= 1) {
1411
+ await promise;
1412
+ }
1413
+ }
1414
+ // Wait for all remaining parallel tasks
1415
+ if (running.size > 0) {
1416
+ await Promise.allSettled(running.values());
1417
+ }
1418
+ const elapsed = Date.now() - sessionStartTime;
1419
+ renderer.sessionEnd({
1420
+ tasks: taskCount,
1421
+ completed: sessionCompleted,
1422
+ failed: sessionFailed,
1423
+ totalInputTokens: sessionInputTokens,
1424
+ totalOutputTokens: sessionOutputTokens,
1425
+ totalCost: sessionCost,
1426
+ elapsed,
1427
+ });
1428
+ // Desktop notification on session end (cross-platform)
1429
+ if (taskCount > 0) {
1430
+ try {
1431
+ const { sendDesktopNotification } = await import('./bot/bot-manager.js');
1432
+ sendDesktopNotification('Weaver Session Complete', `${sessionCompleted} done, ${sessionFailed} failed, ${sessionNoOp} no-op`);
1433
+ }
1434
+ catch { /* non-fatal */ }
1153
1435
  }
1154
1436
  }
1437
+ export async function handleAssistant(opts) {
1438
+ const projectDir = opts.file ?? process.cwd();
1439
+ // Handle --list and --delete before creating provider
1440
+ if (opts.assistantList) {
1441
+ const { ConversationStore } = await import('./bot/conversation-store.js');
1442
+ const { formatTokens, formatElapsed } = await import('./bot/terminal-renderer.js');
1443
+ const store = new ConversationStore();
1444
+ const convos = store.list();
1445
+ if (convos.length === 0) {
1446
+ console.log(' No conversations yet.');
1447
+ return;
1448
+ }
1449
+ console.log(` Conversations (${convos.length}):\n`);
1450
+ for (const c of convos) {
1451
+ const ago = formatElapsed(Date.now() - c.lastMessageAt) + ' ago';
1452
+ const title = c.title ? `"${c.title}"` : '(untitled)';
1453
+ console.log(` ${c.id} ${title.padEnd(45)} ${String(c.messageCount).padStart(3)} msgs ${formatTokens(c.totalTokens).padStart(5)} tokens ${ago}`);
1454
+ }
1455
+ return;
1456
+ }
1457
+ if (opts.assistantDelete) {
1458
+ const { ConversationStore } = await import('./bot/conversation-store.js');
1459
+ const store = new ConversationStore();
1460
+ store.delete(opts.assistantDelete);
1461
+ console.log(` Deleted conversation ${opts.assistantDelete}`);
1462
+ return;
1463
+ }
1464
+ const config = await loadConfig(opts.configPath);
1465
+ // Create provider
1466
+ const { createAnthropicProvider, createClaudeCliProvider } = await import('@synergenius/flow-weaver/agent');
1467
+ const providerSetting = config?.provider ?? 'auto';
1468
+ const providerType = typeof providerSetting === 'object' ? providerSetting.name : String(providerSetting);
1469
+ let provider;
1470
+ if (providerType === 'anthropic' || (providerType === 'auto' && process.env.ANTHROPIC_API_KEY)) {
1471
+ const apiKey = process.env.ANTHROPIC_API_KEY ?? (typeof providerSetting === 'object' ? providerSetting.apiKey : undefined);
1472
+ if (!apiKey) {
1473
+ console.error('ANTHROPIC_API_KEY required for anthropic provider');
1474
+ process.exit(1);
1475
+ }
1476
+ provider = createAnthropicProvider({ apiKey, model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
1477
+ }
1478
+ else {
1479
+ provider = createClaudeCliProvider({ model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
1480
+ }
1481
+ const { ASSISTANT_TOOLS, createAssistantExecutor } = await import('./bot/assistant-tools.js');
1482
+ const { runAssistant } = await import('./bot/assistant-core.js');
1483
+ const executor = createAssistantExecutor(projectDir);
1484
+ await runAssistant({
1485
+ provider,
1486
+ tools: ASSISTANT_TOOLS,
1487
+ executor,
1488
+ projectDir,
1489
+ resumeId: opts.assistantResume,
1490
+ newConversation: opts.assistantNew,
1491
+ });
1492
+ }
1155
1493
  export async function handleSteer(opts) {
1156
1494
  const { SteeringController } = await import('./bot/steering.js');
1157
1495
  const controller = new SteeringController();
@@ -1172,8 +1510,8 @@ export async function handleQueue(opts) {
1172
1510
  const { TaskQueue } = await import('./bot/task-queue.js');
1173
1511
  const queue = new TaskQueue();
1174
1512
  const action = opts.botTask;
1175
- if (!action || !['add', 'list', 'clear', 'remove'].includes(action)) {
1176
- console.error('[weaver] Usage: flow-weaver weaver queue <add|list|clear|remove> [task|id]');
1513
+ if (!action || !['add', 'list', 'clear', 'remove', 'retry'].includes(action)) {
1514
+ console.error('[weaver] Usage: flow-weaver weaver queue <add|list|clear|remove|retry> [task|id]');
1177
1515
  process.exit(1);
1178
1516
  }
1179
1517
  switch (action) {
@@ -1183,19 +1521,27 @@ export async function handleQueue(opts) {
1183
1521
  console.error('[weaver] Usage: flow-weaver weaver queue add "task instruction"');
1184
1522
  process.exit(1);
1185
1523
  }
1186
- const id = await queue.add({ instruction, priority: 0 });
1187
- console.log(`[weaver] Task added: ${id}`);
1524
+ const { id, duplicate } = await queue.add({ instruction, priority: 0 });
1525
+ if (duplicate) {
1526
+ console.log(`[weaver] Task already queued (${id}).`);
1527
+ }
1528
+ else {
1529
+ console.log(`[weaver] Task added: ${id}`);
1530
+ }
1188
1531
  break;
1189
1532
  }
1190
1533
  case 'list': {
1191
1534
  const tasks = await queue.list();
1192
- if (tasks.length === 0) {
1535
+ if (opts.historyJson) {
1536
+ console.log(JSON.stringify(tasks, null, 2));
1537
+ }
1538
+ else if (tasks.length === 0) {
1193
1539
  console.log('No tasks in queue.');
1194
1540
  }
1195
1541
  else {
1196
- console.log('ID'.padEnd(10) + 'STATUS'.padEnd(12) + 'INSTRUCTION');
1542
+ console.log('ID'.padEnd(10) + 'STATUS'.padEnd(12) + 'PRIORITY'.padEnd(10) + 'INSTRUCTION');
1197
1543
  for (const t of tasks) {
1198
- console.log(t.id.padEnd(10) + t.status.padEnd(12) + t.instruction.slice(0, 60));
1544
+ console.log(t.id.padEnd(10) + t.status.padEnd(12) + String(t.priority).padEnd(10) + t.instruction.slice(0, 60));
1199
1545
  }
1200
1546
  }
1201
1547
  break;
@@ -1215,7 +1561,60 @@ export async function handleQueue(opts) {
1215
1561
  console.log(removed ? `Removed task ${id}.` : `No task found with id "${id}".`);
1216
1562
  break;
1217
1563
  }
1564
+ case 'retry': {
1565
+ const id = opts.botFile;
1566
+ if (id) {
1567
+ // Retry a specific task
1568
+ const retried = await queue.retry(id);
1569
+ console.log(retried ? `Task ${id} reset to pending.` : `No failed/running task found with id "${id}".`);
1570
+ }
1571
+ else {
1572
+ // Retry all failed tasks
1573
+ const count = await queue.retryAll();
1574
+ console.log(`Reset ${count} failed task(s) to pending.`);
1575
+ }
1576
+ break;
1577
+ }
1578
+ }
1579
+ }
1580
+ export async function handleStatus(opts) {
1581
+ const store = new RunStore();
1582
+ const { TaskQueue } = await import('./bot/task-queue.js');
1583
+ const queue = new TaskQueue();
1584
+ const orphans = store.checkOrphans();
1585
+ const recentRuns = store.list({ limit: 5 });
1586
+ const tasks = await queue.list();
1587
+ const pending = tasks.filter(t => t.status === 'pending').length;
1588
+ const running = tasks.filter(t => t.status === 'running').length;
1589
+ const completed = tasks.filter(t => t.status === 'completed').length;
1590
+ const failed = tasks.filter(t => t.status === 'failed').length;
1591
+ if (opts.historyJson) {
1592
+ console.log(JSON.stringify({
1593
+ queue: { pending, running, completed, failed, total: tasks.length },
1594
+ orphanedRuns: orphans.length,
1595
+ recentRuns: recentRuns.map(r => ({
1596
+ id: r.id, outcome: r.outcome, summary: r.summary,
1597
+ startedAt: r.startedAt, durationMs: r.durationMs,
1598
+ })),
1599
+ }, null, 2));
1600
+ return;
1601
+ }
1602
+ console.log('\n\x1b[1mWeaver Status\x1b[0m\n');
1603
+ console.log(` Queue: ${pending} pending, ${running} running, ${completed} completed, ${failed} failed`);
1604
+ if (orphans.length > 0) {
1605
+ console.log(` \x1b[33mOrphaned runs: ${orphans.length} (recovered)\x1b[0m`);
1606
+ }
1607
+ if (recentRuns.length > 0) {
1608
+ console.log(`\n Recent runs:`);
1609
+ for (const r of recentRuns) {
1610
+ const icon = r.success ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
1611
+ console.log(` ${icon} ${r.id.slice(0, 8)} ${r.outcome.padEnd(9)} ${formatDuration(r.durationMs).padEnd(8)} ${r.summary.slice(0, 60)}`);
1612
+ }
1218
1613
  }
1614
+ else {
1615
+ console.log('\n No recent runs.');
1616
+ }
1617
+ console.log('');
1219
1618
  }
1220
1619
  export async function handleGenesis(opts) {
1221
1620
  const projectDir = opts.file ?? process.cwd();
@@ -1332,4 +1731,319 @@ function printAuditEvents(events, json) {
1332
1731
  console.log(`${time} [${e.type}]${dataStr}`);
1333
1732
  }
1334
1733
  }
1734
+ // --- Help ---
1735
+ const COMMAND_HELP = {
1736
+ run: 'run <workflow.ts> Execute a workflow with AI agent channel',
1737
+ bot: 'bot "task description" Create or modify a workflow from a task',
1738
+ init: 'init Create a .weaver.json config file',
1739
+ history: 'history [id] [--limit N] Show execution history',
1740
+ costs: 'costs [--since 7d] Show AI token usage and costs',
1741
+ providers: 'providers List available AI providers',
1742
+ watch: 'watch <workflow.ts> Re-run on file changes',
1743
+ cron: 'cron "*/5 * * * *" <file> Schedule workflow execution',
1744
+ pipeline: 'pipeline <config.json> Run multi-stage pipeline',
1745
+ dashboard: 'dashboard <file> [--port N] Start live execution dashboard',
1746
+ session: 'session Start continuous task queue processing',
1747
+ queue: 'queue <add|list|clear> [task] Manage task queue',
1748
+ steer: 'steer <pause|resume|cancel> Control a running session',
1749
+ genesis: 'genesis [--init] [--watch] Run self-evolution cycle',
1750
+ eject: 'eject [--workflow bot|genesis] Export managed workflows',
1751
+ audit: 'audit [runId] [--limit N] View audit log',
1752
+ assistant: 'assistant AI-powered assistant for managing bots and workflows',
1753
+ };
1754
+ export function printHelp(command) {
1755
+ if (command && command !== 'help' && COMMAND_HELP[command]) {
1756
+ console.log(`\nUsage: flow-weaver weaver ${COMMAND_HELP[command]}\n`);
1757
+ printCommandHelp(command);
1758
+ return;
1759
+ }
1760
+ console.log(`
1761
+ Weaver — AI-powered workflow automation for Flow Weaver
1762
+
1763
+ Usage: flow-weaver weaver <command> [options]
1764
+
1765
+ Commands:
1766
+ ${Object.values(COMMAND_HELP).join('\n ')}
1767
+
1768
+ Global options:
1769
+ -h, --help Show help
1770
+ -v, --verbose Show detailed output
1771
+ -n, --dry-run Preview without executing
1772
+ --quiet Suppress output
1773
+ -p, --params <json> Input parameters as JSON
1774
+ -c, --config <path> Path to .weaver.json config
1775
+ --approval <mode> Override approval mode (auto|prompt|web|timeout-auto)
1776
+
1777
+ Quick start:
1778
+ flow-weaver weaver init # create .weaver.json
1779
+ flow-weaver weaver providers # check available AI providers
1780
+ flow-weaver weaver bot "Create a hello world workflow" # create your first workflow
1781
+ `);
1782
+ }
1783
+ function printCommandHelp(command) {
1784
+ const help = {
1785
+ run: `Options:
1786
+ --dashboard Enable live dashboard
1787
+ --port <n> Dashboard port (default: 4242)`,
1788
+ bot: `Options:
1789
+ --file <path> Target file for modification (switches to modify mode)
1790
+ --template <name> Use a template for scaffolding
1791
+ --batch <n> Process multiple tasks
1792
+ --auto-approve Skip approval gate
1793
+ --dashboard Enable live dashboard`,
1794
+ history: `Options:
1795
+ --limit <n> Number of records (default: 20)
1796
+ --outcome <type> Filter: completed, failed, error, skipped
1797
+ --workflow <path> Filter by workflow file
1798
+ --since <range> Time range: 7d, 2h, or ISO date
1799
+ --json Output as JSON
1800
+ --prune Remove old records
1801
+ --clear Delete all history`,
1802
+ costs: `Options:
1803
+ --since <range> Time range: 7d, 30d, or ISO date
1804
+ --model <name> Filter by model`,
1805
+ genesis: `Options:
1806
+ --init Initialize .genesis/config.json
1807
+ --watch Run multiple evolution cycles
1808
+ --project-dir <p> Project directory`,
1809
+ watch: `Options:
1810
+ --debounce <ms> Debounce interval (default: 500)
1811
+ --log <path> Log file for daemon output`,
1812
+ pipeline: `Options:
1813
+ --stage <id> Run a specific stage only`,
1814
+ queue: `Actions:
1815
+ add "task" Add task to queue
1816
+ list Show queue contents
1817
+ clear Remove all tasks
1818
+ remove <id> Remove a specific task`,
1819
+ steer: `Commands:
1820
+ pause Pause current execution
1821
+ resume Resume paused execution
1822
+ cancel Cancel current execution
1823
+ redirect "task" Switch to a different task
1824
+ queue "task" Add task to queue from steer`,
1825
+ };
1826
+ if (help[command]) {
1827
+ console.log(help[command]);
1828
+ console.log('');
1829
+ }
1830
+ }
1831
+ // --- Init ---
1832
+ export async function handleInit(opts) {
1833
+ const dir = opts.file ? path.resolve(opts.file) : process.cwd();
1834
+ const configPath = path.join(dir, '.weaver.json');
1835
+ if (fs.existsSync(configPath)) {
1836
+ console.log(`[weaver] Config already exists: ${configPath}`);
1837
+ console.log(' Edit it directly or delete it to regenerate.');
1838
+ return;
1839
+ }
1840
+ // Detect best available provider (priority: Anthropic API > OpenAI API > Claude CLI > Copilot CLI)
1841
+ let provider = 'auto';
1842
+ const detected = [];
1843
+ try {
1844
+ if (process.env.ANTHROPIC_API_KEY) {
1845
+ provider = 'anthropic';
1846
+ detected.push('Anthropic API (ANTHROPIC_API_KEY)');
1847
+ }
1848
+ if (process.env.OPENAI_API_KEY) {
1849
+ if (provider === 'auto')
1850
+ provider = 'openai';
1851
+ detected.push('OpenAI API (OPENAI_API_KEY)');
1852
+ }
1853
+ const { execFileSync } = await import('node:child_process');
1854
+ try {
1855
+ execFileSync('claude', ['--version'], { stdio: 'pipe' });
1856
+ if (provider === 'auto')
1857
+ provider = 'claude-cli';
1858
+ detected.push('Claude CLI');
1859
+ }
1860
+ catch { /* not found */ }
1861
+ try {
1862
+ execFileSync('copilot', ['--version'], { stdio: 'pipe' });
1863
+ if (provider === 'auto')
1864
+ provider = 'copilot-cli';
1865
+ detected.push('Copilot CLI');
1866
+ }
1867
+ catch { /* not found */ }
1868
+ }
1869
+ catch {
1870
+ // Stay with auto
1871
+ }
1872
+ const config = {
1873
+ provider: provider === 'auto' ? 'auto' : { name: provider },
1874
+ approval: 'auto',
1875
+ };
1876
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
1877
+ console.log('');
1878
+ console.log(' \x1b[1mWelcome to Weaver\x1b[0m — your AI workflow companion.');
1879
+ console.log('');
1880
+ console.log(' \x1b[2mDetecting providers...\x1b[0m');
1881
+ if (detected.length > 0) {
1882
+ for (const d of detected)
1883
+ console.log(` \x1b[32m✓\x1b[0m ${d}`);
1884
+ }
1885
+ else {
1886
+ console.log(' \x1b[33m⚠\x1b[0m No provider detected');
1887
+ console.log(' Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or install Claude CLI');
1888
+ }
1889
+ console.log('');
1890
+ // Test connection if possible
1891
+ if (provider === 'claude-cli') {
1892
+ try {
1893
+ const { execFileSync: testExec } = await import('node:child_process');
1894
+ testExec('claude', ['--version'], { stdio: 'pipe', timeout: 5000 });
1895
+ console.log(' \x1b[2mTesting connection...\x1b[0m');
1896
+ console.log(' \x1b[32m✓\x1b[0m Claude CLI: connected');
1897
+ }
1898
+ catch {
1899
+ console.log(' \x1b[33m⚠\x1b[0m Could not verify Claude CLI connection');
1900
+ }
1901
+ }
1902
+ console.log('');
1903
+ console.log(` \x1b[32m✓\x1b[0m Config written to .weaver.json`);
1904
+ console.log(` provider: ${provider}`);
1905
+ console.log(' approval: auto');
1906
+ console.log('');
1907
+ console.log(' Try it now:');
1908
+ console.log(' \x1b[36mweaver bot "Create a hello world workflow"\x1b[0m');
1909
+ console.log(' \x1b[36mweaver assistant\x1b[0m');
1910
+ console.log('');
1911
+ console.log(' Learn more:');
1912
+ console.log(' weaver examples \x1b[2m# see what weaver can do\x1b[0m');
1913
+ console.log(' weaver doctor \x1b[2m# validate your setup\x1b[0m');
1914
+ console.log('');
1915
+ }
1916
+ export async function handleExamples(_opts) {
1917
+ console.log('');
1918
+ console.log(' \x1b[1mWeaver Examples\x1b[0m');
1919
+ console.log('');
1920
+ console.log(' \x1b[36mCreate workflows:\x1b[0m');
1921
+ console.log(' weaver bot "Create a workflow that validates user input and sends email"');
1922
+ console.log(' weaver bot "Create a data pipeline that reads CSV, transforms, and writes JSON"');
1923
+ console.log(' weaver bot "Create an AI agent with retry and fallback providers"');
1924
+ console.log(' weaver bot "Create a webhook handler that processes Stripe events"');
1925
+ console.log(' weaver bot "Create a RAG pipeline with document chunking and embedding"');
1926
+ console.log('');
1927
+ console.log(' \x1b[36mModify existing workflows:\x1b[0m');
1928
+ console.log(' weaver bot "Add error handling to my-workflow.ts" --file src/my-workflow.ts');
1929
+ console.log(' weaver bot "Add a validation step before the API call" --file src/pipeline.ts');
1930
+ console.log(' weaver bot "Make the retry node use exponential backoff" --file src/agent.ts');
1931
+ console.log('');
1932
+ console.log(' \x1b[36mInteractive assistant:\x1b[0m');
1933
+ console.log(' weaver assistant \x1b[2m# AI assistant with tools\x1b[0m');
1934
+ console.log(' weaver assistant --new \x1b[2m# fresh conversation\x1b[0m');
1935
+ console.log(' weaver assistant --list \x1b[2m# saved conversations\x1b[0m');
1936
+ console.log('');
1937
+ console.log(' \x1b[36mAutonomous mode:\x1b[0m');
1938
+ console.log(' weaver session --continuous \x1b[2m# process task queue\x1b[0m');
1939
+ console.log(' weaver queue add "Fix all validation errors"');
1940
+ console.log(' weaver session --continuous --until 10:00 --parallel 3');
1941
+ console.log('');
1942
+ console.log(' \x1b[36mInspect and debug:\x1b[0m');
1943
+ console.log(' flow-weaver validate src/*.ts \x1b[2m# check all workflows\x1b[0m');
1944
+ console.log(' flow-weaver diagram src/my-workflow.ts \x1b[2m# visual diagram\x1b[0m');
1945
+ console.log(' flow-weaver describe src/my-workflow.ts \x1b[2m# natural language description\x1b[0m');
1946
+ console.log('');
1947
+ console.log(' \x1b[36mCustomize the bot:\x1b[0m');
1948
+ console.log(' weaver eject \x1b[2m# get editable bot workflow\x1b[0m');
1949
+ console.log(' weaver eject --workflow bot \x1b[2m# eject specific workflow\x1b[0m');
1950
+ console.log('');
1951
+ }
1952
+ export async function handleDoctor(opts) {
1953
+ const dir = opts.file ?? process.cwd();
1954
+ const checks = [];
1955
+ // Config check
1956
+ const configPath = path.join(dir, '.weaver.json');
1957
+ if (fs.existsSync(configPath)) {
1958
+ checks.push({ label: 'Config', status: 'ok', detail: '.weaver.json found' });
1959
+ }
1960
+ else {
1961
+ checks.push({ label: 'Config', status: 'warn', detail: 'No .weaver.json — run "weaver init"' });
1962
+ }
1963
+ // Provider check
1964
+ const config = await loadConfig(opts.configPath);
1965
+ const providerSetting = config?.provider ?? 'auto';
1966
+ const providerName = typeof providerSetting === 'object' ? providerSetting.name : String(providerSetting);
1967
+ let providerDetail = providerName;
1968
+ if (providerName === 'anthropic' || process.env.ANTHROPIC_API_KEY) {
1969
+ providerDetail = 'anthropic (API key set)';
1970
+ checks.push({ label: 'Provider', status: 'ok', detail: providerDetail });
1971
+ }
1972
+ else {
1973
+ try {
1974
+ const { execFileSync: provCheck } = await import('node:child_process');
1975
+ provCheck('claude', ['--version'], { stdio: 'pipe', timeout: 5000 });
1976
+ providerDetail = 'claude-cli';
1977
+ checks.push({ label: 'Provider', status: 'ok', detail: providerDetail });
1978
+ }
1979
+ catch {
1980
+ checks.push({ label: 'Provider', status: 'fail', detail: 'No provider found — set ANTHROPIC_API_KEY or install Claude CLI' });
1981
+ }
1982
+ }
1983
+ // Connection test
1984
+ if (providerName === 'claude-cli' || (!process.env.ANTHROPIC_API_KEY && providerName === 'auto')) {
1985
+ try {
1986
+ const { execFileSync: connCheck } = await import('node:child_process');
1987
+ const start = Date.now();
1988
+ connCheck('claude', ['-p', '--max-turns', '1', 'say ok'], { stdio: 'pipe', timeout: 15000 });
1989
+ checks.push({ label: 'Connection', status: 'ok', detail: `OK (${((Date.now() - start) / 1000).toFixed(1)}s)` });
1990
+ }
1991
+ catch {
1992
+ checks.push({ label: 'Connection', status: 'warn', detail: 'Could not verify (Claude CLI may need auth)' });
1993
+ }
1994
+ }
1995
+ else if (process.env.ANTHROPIC_API_KEY) {
1996
+ checks.push({ label: 'Connection', status: 'ok', detail: 'API key configured' });
1997
+ }
1998
+ else {
1999
+ checks.push({ label: 'Connection', status: 'warn', detail: 'Not tested' });
2000
+ }
2001
+ // Flow Weaver version
2002
+ try {
2003
+ const { execFileSync: fwCheck } = await import('node:child_process');
2004
+ const version = fwCheck('npx', ['flow-weaver', '--version'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 10000, cwd: dir }).trim();
2005
+ checks.push({ label: 'Flow Weaver', status: 'ok', detail: version });
2006
+ }
2007
+ catch {
2008
+ checks.push({ label: 'Flow Weaver', status: 'fail', detail: 'Not installed — run "npm install @synergenius/flow-weaver"' });
2009
+ }
2010
+ // Queue status
2011
+ try {
2012
+ const { TaskQueue } = await import('./bot/task-queue.js');
2013
+ process.env.WEAVER_PROJECT_DIR = dir;
2014
+ const queue = new TaskQueue();
2015
+ const tasks = await queue.list();
2016
+ const pending = tasks.filter(t => t.status === 'pending').length;
2017
+ const running = tasks.filter(t => t.status === 'running').length;
2018
+ checks.push({ label: 'Queue', status: 'ok', detail: `${pending} pending, ${running} running` });
2019
+ }
2020
+ catch {
2021
+ checks.push({ label: 'Queue', status: 'ok', detail: 'Empty (no queue file)' });
2022
+ }
2023
+ // Plan file
2024
+ const planPath = path.join(dir, '.weaver-plan.md');
2025
+ if (fs.existsSync(planPath)) {
2026
+ checks.push({ label: 'Plan', status: 'ok', detail: '.weaver-plan.md found' });
2027
+ }
2028
+ else {
2029
+ checks.push({ label: 'Plan', status: 'warn', detail: 'No .weaver-plan.md — optional, guides bot behavior' });
2030
+ }
2031
+ // Output
2032
+ console.log('');
2033
+ console.log(' \x1b[1mWeaver Doctor\x1b[0m');
2034
+ console.log('');
2035
+ const icons = { ok: '\x1b[32m✓\x1b[0m', warn: '\x1b[33m⚠\x1b[0m', fail: '\x1b[31m✗\x1b[0m' };
2036
+ for (const check of checks) {
2037
+ console.log(` ${icons[check.status]} ${check.label.padEnd(14)} ${check.detail}`);
2038
+ }
2039
+ console.log('');
2040
+ const failures = checks.filter(c => c.status === 'fail');
2041
+ if (failures.length > 0) {
2042
+ console.log(` \x1b[31m${failures.length} issue(s) found.\x1b[0m`);
2043
+ }
2044
+ else {
2045
+ console.log(' \x1b[32mAll checks passed.\x1b[0m');
2046
+ }
2047
+ console.log('');
2048
+ }
1335
2049
  //# sourceMappingURL=cli-handlers.js.map