@synergenius/flow-weaver-pack-weaver 0.9.7 → 0.9.9

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 (224) hide show
  1. package/dist/bot/agent-loop.d.ts +20 -0
  2. package/dist/bot/agent-loop.d.ts.map +1 -0
  3. package/dist/bot/agent-loop.js +331 -0
  4. package/dist/bot/agent-loop.js.map +1 -0
  5. package/dist/bot/agent-provider.d.ts.map +1 -1
  6. package/dist/bot/agent-provider.js +3 -2
  7. package/dist/bot/agent-provider.js.map +1 -1
  8. package/dist/bot/approvals.js +17 -8
  9. package/dist/bot/approvals.js.map +1 -1
  10. package/dist/bot/assistant-core.d.ts +17 -0
  11. package/dist/bot/assistant-core.d.ts.map +1 -1
  12. package/dist/bot/assistant-core.js +418 -60
  13. package/dist/bot/assistant-core.js.map +1 -1
  14. package/dist/bot/assistant-tools.d.ts +1 -1
  15. package/dist/bot/assistant-tools.d.ts.map +1 -1
  16. package/dist/bot/assistant-tools.js +283 -9
  17. package/dist/bot/assistant-tools.js.map +1 -1
  18. package/dist/bot/bot-agent-channel.d.ts.map +1 -1
  19. package/dist/bot/bot-agent-channel.js +2 -0
  20. package/dist/bot/bot-agent-channel.js.map +1 -1
  21. package/dist/bot/bot-manager.d.ts +4 -0
  22. package/dist/bot/bot-manager.d.ts.map +1 -1
  23. package/dist/bot/bot-manager.js +72 -27
  24. package/dist/bot/bot-manager.js.map +1 -1
  25. package/dist/bot/conversation-store.d.ts +6 -5
  26. package/dist/bot/conversation-store.d.ts.map +1 -1
  27. package/dist/bot/conversation-store.js +98 -42
  28. package/dist/bot/conversation-store.js.map +1 -1
  29. package/dist/bot/cost-store.d.ts +3 -0
  30. package/dist/bot/cost-store.d.ts.map +1 -1
  31. package/dist/bot/cost-store.js +21 -10
  32. package/dist/bot/cost-store.js.map +1 -1
  33. package/dist/bot/cost-tracker.d.ts.map +1 -1
  34. package/dist/bot/cost-tracker.js +14 -1
  35. package/dist/bot/cost-tracker.js.map +1 -1
  36. package/dist/bot/cron-parser.d.ts.map +1 -1
  37. package/dist/bot/cron-parser.js +2 -0
  38. package/dist/bot/cron-parser.js.map +1 -1
  39. package/dist/bot/cron-scheduler.d.ts.map +1 -1
  40. package/dist/bot/cron-scheduler.js +1 -0
  41. package/dist/bot/cron-scheduler.js.map +1 -1
  42. package/dist/bot/device-connection.d.ts +13 -0
  43. package/dist/bot/device-connection.d.ts.map +1 -0
  44. package/dist/bot/device-connection.js +102 -0
  45. package/dist/bot/device-connection.js.map +1 -0
  46. package/dist/bot/error-classifier.d.ts.map +1 -1
  47. package/dist/bot/error-classifier.js +5 -0
  48. package/dist/bot/error-classifier.js.map +1 -1
  49. package/dist/bot/file-lock.d.ts.map +1 -1
  50. package/dist/bot/file-lock.js +13 -3
  51. package/dist/bot/file-lock.js.map +1 -1
  52. package/dist/bot/file-watcher.d.ts.map +1 -1
  53. package/dist/bot/file-watcher.js +1 -0
  54. package/dist/bot/file-watcher.js.map +1 -1
  55. package/dist/bot/genesis-prompt-context.d.ts +5 -0
  56. package/dist/bot/genesis-prompt-context.d.ts.map +1 -1
  57. package/dist/bot/genesis-prompt-context.js +55 -0
  58. package/dist/bot/genesis-prompt-context.js.map +1 -1
  59. package/dist/bot/genesis-store.d.ts +4 -0
  60. package/dist/bot/genesis-store.d.ts.map +1 -1
  61. package/dist/bot/genesis-store.js +79 -12
  62. package/dist/bot/genesis-store.js.map +1 -1
  63. package/dist/bot/improve-loop.d.ts +46 -0
  64. package/dist/bot/improve-loop.d.ts.map +1 -0
  65. package/dist/bot/improve-loop.js +592 -0
  66. package/dist/bot/improve-loop.js.map +1 -0
  67. package/dist/bot/insight-engine.d.ts +12 -0
  68. package/dist/bot/insight-engine.d.ts.map +1 -0
  69. package/dist/bot/insight-engine.js +256 -0
  70. package/dist/bot/insight-engine.js.map +1 -0
  71. package/dist/bot/knowledge-store.d.ts.map +1 -1
  72. package/dist/bot/knowledge-store.js +4 -1
  73. package/dist/bot/knowledge-store.js.map +1 -1
  74. package/dist/bot/pipeline-runner.d.ts.map +1 -1
  75. package/dist/bot/pipeline-runner.js +12 -4
  76. package/dist/bot/pipeline-runner.js.map +1 -1
  77. package/dist/bot/project-model.d.ts +25 -0
  78. package/dist/bot/project-model.d.ts.map +1 -0
  79. package/dist/bot/project-model.js +372 -0
  80. package/dist/bot/project-model.js.map +1 -0
  81. package/dist/bot/response-formatter.js +2 -3
  82. package/dist/bot/response-formatter.js.map +1 -1
  83. package/dist/bot/run-store.d.ts.map +1 -1
  84. package/dist/bot/run-store.js +10 -2
  85. package/dist/bot/run-store.js.map +1 -1
  86. package/dist/bot/safe-path.d.ts +1 -1
  87. package/dist/bot/safe-path.d.ts.map +1 -1
  88. package/dist/bot/safe-path.js +20 -1
  89. package/dist/bot/safe-path.js.map +1 -1
  90. package/dist/bot/safety.d.ts +10 -2
  91. package/dist/bot/safety.d.ts.map +1 -1
  92. package/dist/bot/safety.js +45 -2
  93. package/dist/bot/safety.js.map +1 -1
  94. package/dist/bot/session-state.d.ts +4 -0
  95. package/dist/bot/session-state.d.ts.map +1 -1
  96. package/dist/bot/session-state.js +52 -9
  97. package/dist/bot/session-state.js.map +1 -1
  98. package/dist/bot/slash-commands.d.ts.map +1 -1
  99. package/dist/bot/slash-commands.js +109 -3
  100. package/dist/bot/slash-commands.js.map +1 -1
  101. package/dist/bot/steering-engine.d.ts +67 -0
  102. package/dist/bot/steering-engine.d.ts.map +1 -0
  103. package/dist/bot/steering-engine.js +198 -0
  104. package/dist/bot/steering-engine.js.map +1 -0
  105. package/dist/bot/step-executor.d.ts.map +1 -1
  106. package/dist/bot/step-executor.js +62 -25
  107. package/dist/bot/step-executor.js.map +1 -1
  108. package/dist/bot/system-prompt.d.ts.map +1 -1
  109. package/dist/bot/system-prompt.js +5 -2
  110. package/dist/bot/system-prompt.js.map +1 -1
  111. package/dist/bot/task-queue.d.ts +6 -1
  112. package/dist/bot/task-queue.d.ts.map +1 -1
  113. package/dist/bot/task-queue.js +43 -4
  114. package/dist/bot/task-queue.js.map +1 -1
  115. package/dist/bot/tool-registry.d.ts +1 -1
  116. package/dist/bot/tool-registry.d.ts.map +1 -1
  117. package/dist/bot/tool-registry.js +65 -4
  118. package/dist/bot/tool-registry.js.map +1 -1
  119. package/dist/bot/trust-calculator.d.ts +34 -0
  120. package/dist/bot/trust-calculator.d.ts.map +1 -0
  121. package/dist/bot/trust-calculator.js +67 -0
  122. package/dist/bot/trust-calculator.js.map +1 -0
  123. package/dist/bot/types.d.ts +97 -0
  124. package/dist/bot/types.d.ts.map +1 -1
  125. package/dist/bot/update-checker.d.ts +21 -0
  126. package/dist/bot/update-checker.d.ts.map +1 -0
  127. package/dist/bot/update-checker.js +129 -0
  128. package/dist/bot/update-checker.js.map +1 -0
  129. package/dist/bot/weaver-tools.d.ts.map +1 -1
  130. package/dist/bot/weaver-tools.js +11 -4
  131. package/dist/bot/weaver-tools.js.map +1 -1
  132. package/dist/cli-bridge.d.ts +2 -0
  133. package/dist/cli-bridge.d.ts.map +1 -1
  134. package/dist/cli-bridge.js +3 -1
  135. package/dist/cli-bridge.js.map +1 -1
  136. package/dist/cli-handlers.d.ts +10 -1
  137. package/dist/cli-handlers.d.ts.map +1 -1
  138. package/dist/cli-handlers.js +141 -24
  139. package/dist/cli-handlers.js.map +1 -1
  140. package/dist/cli.d.ts +3 -0
  141. package/dist/cli.d.ts.map +1 -0
  142. package/dist/cli.js +749 -0
  143. package/dist/cli.js.map +1 -0
  144. package/dist/docs/weaver-config.md +15 -9
  145. package/dist/handlers/on-execution-completed.d.ts +11 -0
  146. package/dist/handlers/on-execution-completed.d.ts.map +1 -0
  147. package/dist/handlers/on-execution-completed.js +25 -0
  148. package/dist/handlers/on-execution-completed.js.map +1 -0
  149. package/dist/mcp-tools.d.ts.map +1 -1
  150. package/dist/mcp-tools.js +33 -0
  151. package/dist/mcp-tools.js.map +1 -1
  152. package/dist/node-types/genesis-approve.d.ts.map +1 -1
  153. package/dist/node-types/genesis-approve.js +28 -3
  154. package/dist/node-types/genesis-approve.js.map +1 -1
  155. package/dist/node-types/genesis-observe.d.ts.map +1 -1
  156. package/dist/node-types/genesis-observe.js +23 -13
  157. package/dist/node-types/genesis-observe.js.map +1 -1
  158. package/dist/node-types/genesis-propose.d.ts.map +1 -1
  159. package/dist/node-types/genesis-propose.js +8 -0
  160. package/dist/node-types/genesis-propose.js.map +1 -1
  161. package/dist/node-types/genesis-update-history.d.ts.map +1 -1
  162. package/dist/node-types/genesis-update-history.js +13 -0
  163. package/dist/node-types/genesis-update-history.js.map +1 -1
  164. package/dist/templates/weaver-template.d.ts +11 -0
  165. package/dist/templates/weaver-template.d.ts.map +1 -0
  166. package/dist/templates/weaver-template.js +53 -0
  167. package/dist/templates/weaver-template.js.map +1 -0
  168. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  169. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  170. package/dist/workflows/weaver-bot-session.js +68 -0
  171. package/dist/workflows/weaver-bot-session.js.map +1 -0
  172. package/dist/workflows/weaver.d.ts +24 -0
  173. package/dist/workflows/weaver.d.ts.map +1 -0
  174. package/dist/workflows/weaver.js +28 -0
  175. package/dist/workflows/weaver.js.map +1 -0
  176. package/flowweaver.manifest.json +28 -1
  177. package/package.json +6 -3
  178. package/src/bot/agent-provider.ts +3 -2
  179. package/src/bot/approvals.ts +16 -8
  180. package/src/bot/assistant-core.ts +420 -63
  181. package/src/bot/assistant-tools.ts +291 -9
  182. package/src/bot/bot-agent-channel.ts +2 -0
  183. package/src/bot/bot-manager.ts +70 -29
  184. package/src/bot/conversation-store.ts +87 -42
  185. package/src/bot/cost-store.ts +20 -9
  186. package/src/bot/cost-tracker.ts +13 -1
  187. package/src/bot/cron-parser.ts +1 -0
  188. package/src/bot/cron-scheduler.ts +1 -0
  189. package/src/bot/device-connection.ts +102 -0
  190. package/src/bot/error-classifier.ts +5 -0
  191. package/src/bot/file-lock.ts +12 -2
  192. package/src/bot/file-watcher.ts +1 -0
  193. package/src/bot/genesis-prompt-context.ts +61 -0
  194. package/src/bot/genesis-store.ts +68 -16
  195. package/src/bot/improve-loop.ts +651 -0
  196. package/src/bot/insight-engine.ts +273 -0
  197. package/src/bot/knowledge-store.ts +4 -1
  198. package/src/bot/pipeline-runner.ts +11 -6
  199. package/src/bot/project-model.ts +404 -0
  200. package/src/bot/response-formatter.ts +2 -3
  201. package/src/bot/run-store.ts +5 -2
  202. package/src/bot/safe-path.ts +20 -1
  203. package/src/bot/safety.ts +57 -3
  204. package/src/bot/session-state.ts +47 -7
  205. package/src/bot/slash-commands.ts +111 -3
  206. package/src/bot/steering-engine.ts +233 -0
  207. package/src/bot/step-executor.ts +66 -26
  208. package/src/bot/system-prompt.ts +5 -2
  209. package/src/bot/task-queue.ts +40 -4
  210. package/src/bot/tool-registry.ts +67 -5
  211. package/src/bot/trust-calculator.ts +87 -0
  212. package/src/bot/types.ts +104 -0
  213. package/src/bot/update-checker.ts +138 -0
  214. package/src/bot/weaver-tools.ts +10 -4
  215. package/src/cli-bridge.ts +4 -1
  216. package/src/cli-handlers.ts +150 -29
  217. package/src/handlers/on-execution-completed.ts +30 -0
  218. package/src/mcp-tools.ts +38 -0
  219. package/src/node-types/genesis-approve.ts +28 -3
  220. package/src/node-types/genesis-observe.ts +23 -12
  221. package/src/node-types/genesis-propose.ts +8 -0
  222. package/src/node-types/genesis-update-history.ts +12 -0
  223. package/src/ui/evolution-panel.tsx +96 -0
  224. package/src/ui/insights-widget.tsx +77 -0
@@ -14,7 +14,7 @@ import type { ExecutionEvent, WeaverConfig, RunRecord, RunOutcome, RunCostSummar
14
14
  import { AuditStore } from './bot/audit-store.js';
15
15
 
16
16
  export interface ParsedArgs {
17
- command: 'run' | 'history' | 'costs' | 'providers' | 'watch' | 'cron' | 'pipeline' | 'dashboard' | 'eject' | 'bot' | 'session' | 'steer' | 'queue' | 'status' | 'genesis' | 'audit' | 'init' | 'assistant' | 'examples' | 'doctor';
17
+ command: 'run' | 'history' | 'costs' | 'providers' | 'watch' | 'cron' | 'pipeline' | 'dashboard' | 'eject' | 'bot' | 'session' | 'steer' | 'queue' | 'status' | 'genesis' | 'audit' | 'init' | 'assistant' | 'examples' | 'doctor' | 'improve';
18
18
  file?: string;
19
19
  verbose: boolean;
20
20
  dryRun: boolean;
@@ -69,6 +69,15 @@ export interface ParsedArgs {
69
69
  assistantList?: boolean;
70
70
  assistantDelete?: string;
71
71
  assistantWatch?: string;
72
+ assistantMessage?: string;
73
+ assistantDebug?: boolean;
74
+ assistantDebugMessages?: string[];
75
+ // improve
76
+ improveMaxCycles?: number;
77
+ improveMaxFailures?: number;
78
+ improveProtected?: string[];
79
+ improveTestCmd?: string;
80
+ improveBuildCmd?: string;
72
81
  }
73
82
 
74
83
  export function parseArgs(argv: string[]): ParsedArgs {
@@ -257,6 +266,8 @@ export function parseArgs(argv: string[]): ParsedArgs {
257
266
  }
258
267
  } else if (arg === 'genesis') {
259
268
  result.command = 'genesis';
269
+ } else if (arg === 'improve') {
270
+ result.command = 'improve';
260
271
  } else if (arg === 'init') {
261
272
  result.command = 'init';
262
273
  } else if (arg === '--init') {
@@ -266,8 +277,13 @@ export function parseArgs(argv: string[]): ParsedArgs {
266
277
  } else if (arg === '--watch-dir' && i + 1 < args.length) {
267
278
  i++;
268
279
  result.assistantWatch = args[i];
280
+ } else if ((arg === '-m' || arg === '--message') && i + 1 < args.length) {
281
+ i++;
282
+ result.assistantMessage = args[i];
269
283
  } else if (arg === '--new') {
270
284
  result.assistantNew = true;
285
+ } else if (arg === '--debug') {
286
+ result.assistantDebug = true;
271
287
  } else if (arg === '--resume' && i + 1 < args.length) {
272
288
  i++;
273
289
  result.assistantResume = args[i];
@@ -290,6 +306,21 @@ export function parseArgs(argv: string[]): ParsedArgs {
290
306
  } else if (arg === '--project-dir' && i + 1 < args.length) {
291
307
  i++;
292
308
  result.file = args[i];
309
+ } else if (arg === '--max-cycles' && i + 1 < args.length) {
310
+ i++;
311
+ result.improveMaxCycles = parseInt(args[i]!, 10) || undefined;
312
+ } else if (arg === '--max-failures' && i + 1 < args.length) {
313
+ i++;
314
+ result.improveMaxFailures = parseInt(args[i]!, 10) || undefined;
315
+ } else if (arg === '--protected' && i + 1 < args.length) {
316
+ i++;
317
+ result.improveProtected = args[i]!.split(',').map(s => s.trim());
318
+ } else if (arg === '--test-cmd' && i + 1 < args.length) {
319
+ i++;
320
+ result.improveTestCmd = args[i];
321
+ } else if (arg === '--build-cmd' && i + 1 < args.length) {
322
+ i++;
323
+ result.improveBuildCmd = args[i];
293
324
  } else if (arg === 'run') {
294
325
  // skip, next arg is the file
295
326
  } else if (!arg.startsWith('-')) {
@@ -1620,7 +1651,7 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1620
1651
  if (opts.assistantDelete) {
1621
1652
  const { ConversationStore } = await import('./bot/conversation-store.js');
1622
1653
  const store = new ConversationStore();
1623
- store.delete(opts.assistantDelete);
1654
+ await store.delete(opts.assistantDelete);
1624
1655
  console.log(` Deleted conversation ${opts.assistantDelete}`);
1625
1656
  return;
1626
1657
  }
@@ -1659,7 +1690,14 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1659
1690
  }) as import('@synergenius/flow-weaver/agent').AgentProvider;
1660
1691
  } else if (providerType === 'anthropic' || (providerType === 'auto' && process.env.ANTHROPIC_API_KEY)) {
1661
1692
  const apiKey = process.env.ANTHROPIC_API_KEY ?? (typeof providerSetting === 'object' ? (providerSetting as { apiKey?: string }).apiKey : undefined);
1662
- if (!apiKey) { console.error('ANTHROPIC_API_KEY required for anthropic provider'); process.exit(1); }
1693
+ if (!apiKey) {
1694
+ console.error('\n No API key found.\n');
1695
+ console.error(' Set one of:');
1696
+ console.error(' export ANTHROPIC_API_KEY=sk-...');
1697
+ console.error(' fw login (platform credentials)');
1698
+ console.error(' flow-weaver weaver init (auto-detect provider)\n');
1699
+ process.exit(1);
1700
+ }
1663
1701
  provider = createAnthropicProvider({ apiKey, model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
1664
1702
  } else {
1665
1703
  provider = createClaudeCliProvider({ model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
@@ -1669,6 +1707,51 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1669
1707
  const { runAssistant } = await import('./bot/assistant-core.js');
1670
1708
  const executor = createAssistantExecutor(projectDir);
1671
1709
 
1710
+ // Debug mode: pass messages as inputMessages, enable structured output
1711
+ // Must be checked BEFORE single-message mode since both use -m flag
1712
+ if (opts.assistantDebug) {
1713
+ const messages = opts.assistantMessage ? [opts.assistantMessage] : [];
1714
+ // Read additional messages from stdin if not a TTY
1715
+ if (!process.stdin.isTTY) {
1716
+ const chunks: string[] = [];
1717
+ for await (const chunk of process.stdin) {
1718
+ chunks.push(typeof chunk === 'string' ? chunk : chunk.toString());
1719
+ }
1720
+ const stdinMessages = chunks.join('').trim().split('\n').filter(Boolean);
1721
+ messages.push(...stdinMessages);
1722
+ }
1723
+ if (messages.length === 0) {
1724
+ console.error('Debug mode requires messages via -m "msg" or stdin (one per line)');
1725
+ process.exit(1);
1726
+ }
1727
+ await runAssistant({
1728
+ provider,
1729
+ tools: ASSISTANT_TOOLS,
1730
+ executor,
1731
+ projectDir,
1732
+ inputMessages: messages,
1733
+ resumeId: opts.assistantResume,
1734
+ newConversation: !opts.assistantResume,
1735
+ debug: true,
1736
+ });
1737
+ return;
1738
+ }
1739
+
1740
+ // Single message mode: -m "message" — run one message, print result, exit
1741
+ if (opts.assistantMessage) {
1742
+ const { runAgentLoop } = await import('@synergenius/flow-weaver/agent');
1743
+ const result = await runAgentLoop(provider, ASSISTANT_TOOLS, executor, [{ role: 'user', content: opts.assistantMessage }], {
1744
+ maxIterations: 20,
1745
+ onStreamEvent: (e) => { if (e.type === 'text_delta') process.stdout.write(e.text); },
1746
+ onToolEvent: (e) => {
1747
+ if (e.type === 'tool_call_start') process.stderr.write(`\n ◆ ${e.name}\n`);
1748
+ if (e.type === 'tool_call_result') process.stderr.write(` → ${(e.result ?? '').replace(/\n/g, ' ').slice(0, 200)}\n`);
1749
+ },
1750
+ });
1751
+ process.stdout.write('\n');
1752
+ process.exit(result.success ? 0 : 1);
1753
+ }
1754
+
1672
1755
  await runAssistant({
1673
1756
  provider,
1674
1757
  tools: ASSISTANT_TOOLS,
@@ -1965,6 +2048,9 @@ const COMMAND_HELP: Record<string, string> = {
1965
2048
  eject: 'eject [--workflow bot|genesis] Export managed workflows',
1966
2049
  audit: 'audit [runId] [--limit N] View audit log',
1967
2050
  assistant: 'assistant AI-powered assistant for managing bots and workflows',
2051
+ examples: 'examples Show example tasks and commands',
2052
+ doctor: 'doctor Validate setup and check connectivity',
2053
+ status: 'status Get bot session status',
1968
2054
  };
1969
2055
 
1970
2056
  export function printHelp(command?: string): void {
@@ -1975,26 +2061,50 @@ export function printHelp(command?: string): void {
1975
2061
  }
1976
2062
 
1977
2063
  console.log(`
1978
- Weaver — AI-powered workflow automation for Flow Weaver
1979
-
1980
- Usage: flow-weaver weaver <command> [options]
1981
-
1982
- Commands:
1983
- ${Object.values(COMMAND_HELP).join('\n ')}
1984
-
1985
- Global options:
1986
- -h, --help Show help
1987
- -v, --verbose Show detailed output
1988
- -n, --dry-run Preview without executing
1989
- --quiet Suppress output
1990
- -p, --params <json> Input parameters as JSON
1991
- -c, --config <path> Path to .weaver.json config
1992
- --approval <mode> Override approval mode (auto|prompt|web|timeout-auto)
1993
-
1994
- Quick start:
1995
- flow-weaver weaver init # create .weaver.json
1996
- flow-weaver weaver providers # check available AI providers
1997
- flow-weaver weaver bot "Create a hello world workflow" # create your first workflow
2064
+ Weaver — AI-powered workflow automation for Flow Weaver
2065
+
2066
+ Usage: flow-weaver weaver <command> [options]
2067
+
2068
+ Get started:
2069
+ assistant AI assistant for managing bots and workflows
2070
+ bot <task> Create or modify a workflow from a task
2071
+ init Create .weaver.json config
2072
+ doctor Validate setup and check connectivity
2073
+
2074
+ Workflows:
2075
+ run <file> Execute a workflow with AI agent channel
2076
+ watch <file> Re-run on file changes
2077
+ genesis [--init] Self-evolution cycle on a workflow
2078
+
2079
+ Management:
2080
+ session Start continuous task queue processing
2081
+ queue <cmd> [task] Manage task queue (add, list, clear, remove)
2082
+ status Get bot session status
2083
+ steer <cmd> Control a running session (pause, resume, cancel)
2084
+
2085
+ Info:
2086
+ history [id] Show execution history
2087
+ costs [--since 7d] Show AI token usage and costs
2088
+ audit [runId] View audit log
2089
+ examples Show example tasks and commands
2090
+ providers List available AI providers
2091
+
2092
+ Advanced:
2093
+ pipeline <config.json> Run multi-stage pipeline
2094
+ cron <schedule> <file> Schedule workflow execution
2095
+ dashboard [file] Start live execution dashboard
2096
+ eject [--workflow name] Export managed workflows
2097
+
2098
+ Options:
2099
+ -h, --help Show help
2100
+ -v, --verbose Show detailed output
2101
+ -c, --config <path> Path to .weaver.json config
2102
+ --approval <mode> Approval mode (auto|prompt|web|timeout-auto)
2103
+
2104
+ Quick start:
2105
+ flow-weaver weaver init
2106
+ flow-weaver weaver bot "Create a hello world workflow"
2107
+ flow-weaver weaver assistant
1998
2108
  `);
1999
2109
  }
2000
2110
 
@@ -2123,16 +2233,27 @@ export async function handleInit(opts: ParsedArgs): Promise<void> {
2123
2233
  console.log(` provider: ${provider}`);
2124
2234
  console.log(' approval: auto');
2125
2235
  console.log('');
2126
- console.log(' Try it now:');
2127
- console.log(' \x1b[36mweaver bot "Create a hello world workflow"\x1b[0m');
2128
- console.log(' \x1b[36mweaver assistant\x1b[0m');
2236
+ console.log(' \x1b[1mNext step:\x1b[0m');
2237
+ console.log(' \x1b[36mweaver assistant\x1b[0m \x1b[2m# start your AI companion\x1b[0m');
2129
2238
  console.log('');
2130
- console.log(' Learn more:');
2131
- console.log(' weaver examples \x1b[2m# see what weaver can do\x1b[0m');
2132
- console.log(' weaver doctor \x1b[2m# validate your setup\x1b[0m');
2239
+ console.log(' The assistant will read your project and help you create');
2240
+ console.log(' your first workflow. Just tell it what you want to build.');
2133
2241
  console.log('');
2134
2242
  }
2135
2243
 
2244
+ export async function handleImprove(opts: ParsedArgs): Promise<void> {
2245
+ const projectDir = opts.file ? path.resolve(opts.file) : process.cwd();
2246
+ const { runImproveLoop, DEFAULT_PROTECTED } = await import('./bot/improve-loop.js');
2247
+ await runImproveLoop({
2248
+ maxCycles: opts.improveMaxCycles ?? 0,
2249
+ maxConsecutiveFailures: opts.improveMaxFailures ?? 5,
2250
+ protectedPatterns: opts.improveProtected ?? DEFAULT_PROTECTED,
2251
+ testCommand: opts.improveTestCmd ?? 'npx vitest run',
2252
+ buildCommand: opts.improveBuildCmd,
2253
+ projectDir,
2254
+ });
2255
+ }
2256
+
2136
2257
  export async function handleExamples(_opts: ParsedArgs): Promise<void> {
2137
2258
  console.log('');
2138
2259
  console.log(' \x1b[1mWeaver Examples\x1b[0m');
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Platform event handler: invalidates project model cache when executions complete.
3
+ * Registered in flowweaver.manifest.json as an event subscription.
4
+ */
5
+
6
+ import * as crypto from 'node:crypto';
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import * as os from 'node:os';
10
+
11
+ export async function onExecutionCompleted(event: {
12
+ deploymentId?: string;
13
+ wsPath?: string;
14
+ status?: string;
15
+ executionTimeMs?: number;
16
+ }): Promise<void> {
17
+ const projectDir = event.wsPath;
18
+ if (!projectDir) return;
19
+
20
+ // Invalidate project model cache directly (same logic as ProjectModelStore.invalidate)
21
+ try {
22
+ const hash8 = crypto.createHash('sha256').update(projectDir).digest('hex').slice(0, 8);
23
+ const modelPath = path.join(os.homedir(), '.weaver', 'projects', hash8, 'model.json');
24
+ if (fs.existsSync(modelPath)) {
25
+ fs.unlinkSync(modelPath);
26
+ }
27
+ } catch {
28
+ // Non-fatal — cache will be rebuilt on next access
29
+ }
30
+ }
package/src/mcp-tools.ts CHANGED
@@ -271,4 +271,42 @@ export async function registerMcpTools(mcp: McpServer): Promise<void> {
271
271
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
272
272
  },
273
273
  );
274
+
275
+ mcp.tool(
276
+ 'fw_weaver_insights',
277
+ 'Get project health, insights, trust level, and cost summary. Returns structured JSON with actionable recommendations.',
278
+ {
279
+ projectDir: z.string().describe('Project directory path'),
280
+ },
281
+ async (args) => {
282
+ try {
283
+ const { ProjectModelStore } = await import('./bot/project-model.js');
284
+ const { InsightEngine } = await import('./bot/insight-engine.js');
285
+ const pms = new ProjectModelStore(args.projectDir as string);
286
+ const model = await pms.getOrBuild();
287
+ const engine = new InsightEngine();
288
+ const insights = engine.analyze(model);
289
+ return {
290
+ content: [{
291
+ type: 'text',
292
+ text: JSON.stringify({
293
+ health: model.health,
294
+ bots: model.bots,
295
+ insights: insights.slice(0, 10),
296
+ trust: model.trust,
297
+ cost: model.cost,
298
+ evolution: {
299
+ totalCycles: model.evolution.totalCycles,
300
+ successRate: model.evolution.successRate,
301
+ },
302
+ }, null, 2),
303
+ }],
304
+ };
305
+ } catch (err: unknown) {
306
+ return {
307
+ content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
308
+ };
309
+ }
310
+ },
311
+ );
274
312
  }
@@ -66,8 +66,33 @@ export async function genesisApprove(
66
66
  return { onSuccess: true, onFailure: false, ctx: JSON.stringify(context) };
67
67
  }
68
68
 
69
- // Non-auto modes reject in non-interactive context
70
- console.log('\x1b[33m→ Rejected (approval required, non-auto mode)\x1b[0m');
71
- context.approved = false;
69
+ // Non-auto modes: try interactive approval, fall back to reject
70
+ let approved = false;
71
+ let rejectionReason = 'Non-interactive environment';
72
+
73
+ if (approvalMode === 'prompt') {
74
+ try {
75
+ const readline = await import('node:readline');
76
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
77
+ const answer = await new Promise<string>(resolve => {
78
+ rl.question('\x1b[33m? Approve this proposal? (y/N/reason): \x1b[0m', resolve);
79
+ });
80
+ rl.close();
81
+ const trimmed = answer.trim().toLowerCase();
82
+ if (trimmed === 'y' || trimmed === 'yes') {
83
+ approved = true;
84
+ } else {
85
+ rejectionReason = trimmed && trimmed !== 'n' && trimmed !== 'no' ? answer.trim() : 'User rejected';
86
+ }
87
+ } catch {
88
+ // Non-interactive — fall through to reject
89
+ }
90
+ }
91
+
92
+ context.approved = approved;
93
+ context.rejectionReason = approved ? undefined : rejectionReason;
94
+ console.log(approved
95
+ ? '\x1b[32m→ Approved by user\x1b[0m'
96
+ : `\x1b[33m→ Rejected: ${rejectionReason}\x1b[0m`);
72
97
  return { onSuccess: true, onFailure: false, ctx: JSON.stringify(context) };
73
98
  }
@@ -46,22 +46,28 @@ export async function genesisObserve(
46
46
 
47
47
  try {
48
48
  const files: Record<string, string> = {};
49
- const dirsToScan = [projectDir];
50
- const srcDir = path.join(projectDir, 'src');
51
- if (fs.existsSync(srcDir) && fs.statSync(srcDir).isDirectory()) dirsToScan.push(srcDir);
49
+ const fileContents: Record<string, string> = {};
50
+ const SKIP_DIRS = new Set(['node_modules', 'dist', '.git', 'coverage', '.next', '.turbo']);
52
51
 
53
- for (const dir of dirsToScan) {
52
+ function walkDir(dir: string): void {
54
53
  const entries = fs.readdirSync(dir, { withFileTypes: true });
55
54
  for (const entry of entries) {
56
- if (entry.isFile() && entry.name.endsWith('.ts')) {
55
+ if (entry.isDirectory()) {
56
+ if (!SKIP_DIRS.has(entry.name)) {
57
+ walkDir(path.join(dir, entry.name));
58
+ }
59
+ } else if (entry.isFile() && entry.name.endsWith('.ts')) {
57
60
  const filePath = path.join(dir, entry.name);
58
61
  const relPath = path.relative(projectDir, filePath);
59
62
  const content = fs.readFileSync(filePath, 'utf-8');
63
+ fileContents[relPath] = content;
60
64
  files[relPath] = crypto.createHash('sha256').update(content).digest('hex');
61
65
  }
62
66
  }
63
67
  }
64
68
 
69
+ walkDir(projectDir);
70
+
65
71
  let packageJson: Record<string, unknown> | null = null;
66
72
  const pkgPath = path.join(projectDir, 'package.json');
67
73
  if (fs.existsSync(pkgPath)) {
@@ -83,17 +89,20 @@ export async function genesisObserve(
83
89
  }
84
90
 
85
91
  const existingWorkflows: string[] = [];
86
- for (const [relPath, _hash] of Object.entries(files)) {
87
- const filePath = path.join(projectDir, relPath);
88
- const content = fs.readFileSync(filePath, 'utf-8');
92
+ for (const [relPath, content] of Object.entries(fileContents)) {
89
93
  if (content.includes('@flowWeaver workflow')) {
90
94
  existingWorkflows.push(relPath);
91
95
  }
92
96
  }
93
97
 
94
- const targetPath = path.resolve(projectDir, config.targetWorkflow);
95
- const targetContent = fs.readFileSync(targetPath, 'utf-8');
96
- const workflowHash = crypto.createHash('sha256').update(targetContent).digest('hex');
98
+ let workflowHash = '';
99
+ let targetPath = '';
100
+ if (config.targetWorkflow) {
101
+ targetPath = path.resolve(projectDir, config.targetWorkflow);
102
+ const targetRelPath = path.relative(projectDir, targetPath);
103
+ const targetContent = fileContents[targetRelPath] ?? fs.readFileSync(targetPath, 'utf-8');
104
+ workflowHash = crypto.createHash('sha256').update(targetContent).digest('hex');
105
+ }
97
106
 
98
107
  const fingerprint: GenesisFingerprint = {
99
108
  timestamp: new Date().toISOString(),
@@ -108,7 +117,9 @@ export async function genesisObserve(
108
117
  console.log(`\x1b[36m→ Fingerprint: ${Object.keys(files).length} files, ${existingWorkflows.length} workflows\x1b[0m`);
109
118
 
110
119
  context.fingerprintJson = JSON.stringify(fingerprint);
111
- context.workflowDescription = await getWorkflowDescription(targetPath);
120
+ if (targetPath) {
121
+ context.workflowDescription = await getWorkflowDescription(targetPath);
122
+ }
112
123
 
113
124
  return { onSuccess: true, onFailure: false, ctx: JSON.stringify(context) };
114
125
  } catch (err: unknown) {
@@ -40,10 +40,18 @@ export async function genesisPropose(
40
40
  graceRemaining: context.escrowGraceRemaining ?? 0,
41
41
  });
42
42
 
43
+ // Inject project intelligence
44
+ let insightContext = '';
45
+ try {
46
+ const { getGenesisInsightContext } = await import('../bot/genesis-prompt-context.js');
47
+ insightContext = await getGenesisInsightContext(env.projectDir);
48
+ } catch { /* insights not available */ }
49
+
43
50
  const userPrompt = [
44
51
  '## Current Workflow Structure',
45
52
  context.workflowDescription || '(no description available)',
46
53
  '',
54
+ ...(insightContext ? [insightContext, ''] : []),
47
55
  '## Project Diff Since Last Cycle',
48
56
  JSON.stringify(diff, null, 2),
49
57
  '',
@@ -60,6 +60,18 @@ export function genesisUpdateHistory(ctx: string): { ctx: string } {
60
60
  if (fingerprint) {
61
61
  store.saveFingerprint(fingerprint);
62
62
  }
63
+
64
+ // Invalidate project model cache so next access rebuilds with fresh data
65
+ try {
66
+ // Use sync require-like approach: delete the cached model.json directly
67
+ const crypto = require('node:crypto') as typeof import('node:crypto');
68
+ const fsMod = require('node:fs') as typeof import('node:fs');
69
+ const pathMod = require('node:path') as typeof import('node:path');
70
+ const osMod = require('node:os') as typeof import('node:os');
71
+ const hash8 = crypto.createHash('sha256').update(env.projectDir).digest('hex').slice(0, 8);
72
+ const modelPath = pathMod.join(osMod.homedir(), '.weaver', 'projects', hash8, 'model.json');
73
+ if (fsMod.existsSync(modelPath)) fsMod.unlinkSync(modelPath);
74
+ } catch { /* project model not available */ }
63
75
  } catch (err: unknown) {
64
76
  const msg = err instanceof Error ? err.message : String(err);
65
77
  console.error(`\x1b[31m→ Failed to save history: ${msg}\x1b[0m`);
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Weaver Evolution Panel — shows Genesis cycle history and operation effectiveness.
3
+ * Loaded dynamically by the platform's pack UI contributions loader.
4
+ */
5
+
6
+ import React, { useEffect, useState } from 'react';
7
+
8
+ interface EvolutionData {
9
+ evolution: {
10
+ totalCycles: number;
11
+ successRate: number;
12
+ byOperationType: Record<string, { proposed: number; applied: number; effectiveness: number }>;
13
+ recentCycles: Array<{ id: string; outcome: string; proposal?: { summary: string; impactLevel: string } }>;
14
+ };
15
+ trust: { phase: number; score: number };
16
+ }
17
+
18
+ export function WeaverEvolutionPanel({ projectDir }: { projectDir?: string }) {
19
+ const [data, setData] = useState<EvolutionData | null>(null);
20
+ const [error, setError] = useState<string | null>(null);
21
+
22
+ useEffect(() => {
23
+ if (!projectDir) return;
24
+ fetch(`/api/mcp/fw_weaver_insights?projectDir=${encodeURIComponent(projectDir)}`)
25
+ .then(r => r.json())
26
+ .then(setData)
27
+ .catch(e => setError(e.message));
28
+ }, [projectDir]);
29
+
30
+ if (error) return <div style={{ padding: 16, color: '#ef4444' }}>Error: {error}</div>;
31
+ if (!data) return <div style={{ padding: 16, opacity: 0.5 }}>Loading evolution data...</div>;
32
+
33
+ const { evolution, trust } = data;
34
+ const outcomeColor: Record<string, string> = {
35
+ applied: '#22c55e',
36
+ 'rolled-back': '#ef4444',
37
+ rejected: '#f59e0b',
38
+ 'no-change': '#6b7280',
39
+ error: '#ef4444',
40
+ };
41
+
42
+ return (
43
+ <div style={{ padding: 16, fontFamily: 'system-ui, sans-serif', fontSize: 13 }}>
44
+ <div style={{ marginBottom: 16 }}>
45
+ <div style={{ fontWeight: 600, marginBottom: 4 }}>Trust Level</div>
46
+ <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
47
+ <span style={{ fontSize: 20, fontWeight: 700 }}>Phase {trust.phase}</span>
48
+ <span style={{ opacity: 0.5 }}>Score: {trust.score}/100</span>
49
+ </div>
50
+ </div>
51
+
52
+ <div style={{ marginBottom: 16 }}>
53
+ <div style={{ fontWeight: 600, marginBottom: 4 }}>
54
+ Genesis Cycles: {evolution.totalCycles} ({evolution.totalCycles > 0 ? Math.round(evolution.successRate * 100) : 0}% success)
55
+ </div>
56
+ </div>
57
+
58
+ {Object.keys(evolution.byOperationType).length > 0 && (
59
+ <div style={{ marginBottom: 16 }}>
60
+ <div style={{ fontWeight: 600, marginBottom: 4 }}>Operation Effectiveness</div>
61
+ {Object.entries(evolution.byOperationType).map(([op, stats]) => (
62
+ <div key={op} style={{ padding: '2px 0', display: 'flex', justifyContent: 'space-between' }}>
63
+ <span>{op}</span>
64
+ <span style={{ opacity: 0.7 }}>{Math.round(stats.effectiveness * 100)}% ({stats.applied}/{stats.proposed})</span>
65
+ </div>
66
+ ))}
67
+ </div>
68
+ )}
69
+
70
+ {evolution.recentCycles.length > 0 && (
71
+ <div>
72
+ <div style={{ fontWeight: 600, marginBottom: 4 }}>Recent Cycles</div>
73
+ {evolution.recentCycles.slice(-5).reverse().map((cycle) => (
74
+ <div key={cycle.id} style={{ padding: '4px 0', borderBottom: '1px solid rgba(128,128,128,0.1)' }}>
75
+ <span style={{ color: outcomeColor[cycle.outcome] ?? '#6b7280', fontWeight: 600, marginRight: 8 }}>
76
+ {cycle.outcome}
77
+ </span>
78
+ <span style={{ opacity: 0.7 }}>{cycle.id}</span>
79
+ {cycle.proposal && (
80
+ <div style={{ opacity: 0.6, paddingLeft: 8 }}>{cycle.proposal.summary}</div>
81
+ )}
82
+ </div>
83
+ ))}
84
+ </div>
85
+ )}
86
+
87
+ {evolution.totalCycles === 0 && (
88
+ <div style={{ opacity: 0.5, textAlign: 'center', padding: 20 }}>
89
+ No genesis cycles yet. Use /genesis in the assistant to start evolving bot workflows.
90
+ </div>
91
+ )}
92
+ </div>
93
+ );
94
+ }
95
+
96
+ export default WeaverEvolutionPanel;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Weaver Insights Dashboard Widget — shows project health, insights, and cost summary.
3
+ * Loaded dynamically by the platform's pack UI contributions loader.
4
+ */
5
+
6
+ import React, { useEffect, useState } from 'react';
7
+
8
+ interface InsightsData {
9
+ health: { overall: number; workflows: Array<{ file: string; score: number; trend: string }> };
10
+ bots: Array<{ name: string; ejected: boolean; successRate: number; totalTasksRun: number }>;
11
+ insights: Array<{ severity: string; title: string; description: string; confidence: number }>;
12
+ cost: { last7Days: number; trend: string };
13
+ trust: { phase: number; score: number };
14
+ }
15
+
16
+ export function WeaverInsightsWidget({ projectDir }: { projectDir?: string }) {
17
+ const [data, setData] = useState<InsightsData | null>(null);
18
+ const [error, setError] = useState<string | null>(null);
19
+
20
+ useEffect(() => {
21
+ if (!projectDir) return;
22
+ fetch(`/api/mcp/fw_weaver_insights?projectDir=${encodeURIComponent(projectDir)}`)
23
+ .then(r => r.json())
24
+ .then(setData)
25
+ .catch(e => setError(e.message));
26
+ }, [projectDir]);
27
+
28
+ if (error) return <div style={{ padding: 16, color: '#ef4444' }}>Error: {error}</div>;
29
+ if (!data) return <div style={{ padding: 16, opacity: 0.5 }}>Loading insights...</div>;
30
+
31
+ const severityColor: Record<string, string> = {
32
+ critical: '#ef4444',
33
+ warning: '#f59e0b',
34
+ info: '#6b7280',
35
+ };
36
+
37
+ return (
38
+ <div style={{ padding: 16, fontFamily: 'system-ui, sans-serif', fontSize: 13 }}>
39
+ <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12 }}>
40
+ <span style={{ fontSize: 28, fontWeight: 700 }}>{data.health.overall}</span>
41
+ <span style={{ opacity: 0.6 }}>/100 health</span>
42
+ <span style={{ marginLeft: 'auto', opacity: 0.5 }}>
43
+ Phase {data.trust.phase} · ${data.cost.last7Days.toFixed(2)}/7d ({data.cost.trend})
44
+ </span>
45
+ </div>
46
+
47
+ {data.insights.length > 0 && (
48
+ <div style={{ marginBottom: 12 }}>
49
+ <div style={{ fontWeight: 600, marginBottom: 6 }}>Insights</div>
50
+ {data.insights.slice(0, 3).map((insight, i) => (
51
+ <div key={i} style={{ padding: '4px 0', borderBottom: '1px solid rgba(128,128,128,0.1)' }}>
52
+ <span style={{ color: severityColor[insight.severity] ?? '#6b7280', fontWeight: 600, marginRight: 8 }}>
53
+ {insight.severity.toUpperCase()}
54
+ </span>
55
+ <span>{insight.title}</span>
56
+ <span style={{ opacity: 0.5, marginLeft: 8 }}>{Math.round(insight.confidence * 100)}%</span>
57
+ </div>
58
+ ))}
59
+ </div>
60
+ )}
61
+
62
+ {data.bots.length > 0 && (
63
+ <div>
64
+ <div style={{ fontWeight: 600, marginBottom: 6 }}>Bots</div>
65
+ {data.bots.map((bot, i) => (
66
+ <div key={i} style={{ padding: '2px 0' }}>
67
+ {bot.name}: {Math.round(bot.successRate * 100)}% success ({bot.totalTasksRun} tasks)
68
+ {bot.ejected && <span style={{ opacity: 0.5 }}> · ejected</span>}
69
+ </div>
70
+ ))}
71
+ </div>
72
+ )}
73
+ </div>
74
+ );
75
+ }
76
+
77
+ export default WeaverInsightsWidget;