@synergenius/flow-weaver-pack-weaver 0.9.8 → 0.9.10

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 (228) 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 +366 -45
  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/index.d.ts +1 -0
  68. package/dist/bot/index.d.ts.map +1 -1
  69. package/dist/bot/index.js +2 -0
  70. package/dist/bot/index.js.map +1 -1
  71. package/dist/bot/insight-engine.d.ts +12 -0
  72. package/dist/bot/insight-engine.d.ts.map +1 -0
  73. package/dist/bot/insight-engine.js +256 -0
  74. package/dist/bot/insight-engine.js.map +1 -0
  75. package/dist/bot/knowledge-store.d.ts.map +1 -1
  76. package/dist/bot/knowledge-store.js +4 -1
  77. package/dist/bot/knowledge-store.js.map +1 -1
  78. package/dist/bot/pipeline-runner.d.ts.map +1 -1
  79. package/dist/bot/pipeline-runner.js +12 -4
  80. package/dist/bot/pipeline-runner.js.map +1 -1
  81. package/dist/bot/project-model.d.ts +25 -0
  82. package/dist/bot/project-model.d.ts.map +1 -0
  83. package/dist/bot/project-model.js +372 -0
  84. package/dist/bot/project-model.js.map +1 -0
  85. package/dist/bot/response-formatter.js +2 -3
  86. package/dist/bot/response-formatter.js.map +1 -1
  87. package/dist/bot/run-store.d.ts.map +1 -1
  88. package/dist/bot/run-store.js +10 -2
  89. package/dist/bot/run-store.js.map +1 -1
  90. package/dist/bot/safe-path.d.ts +1 -1
  91. package/dist/bot/safe-path.d.ts.map +1 -1
  92. package/dist/bot/safe-path.js +20 -1
  93. package/dist/bot/safe-path.js.map +1 -1
  94. package/dist/bot/safety.d.ts +10 -2
  95. package/dist/bot/safety.d.ts.map +1 -1
  96. package/dist/bot/safety.js +45 -2
  97. package/dist/bot/safety.js.map +1 -1
  98. package/dist/bot/session-state.d.ts +4 -0
  99. package/dist/bot/session-state.d.ts.map +1 -1
  100. package/dist/bot/session-state.js +52 -9
  101. package/dist/bot/session-state.js.map +1 -1
  102. package/dist/bot/slash-commands.d.ts.map +1 -1
  103. package/dist/bot/slash-commands.js +100 -5
  104. package/dist/bot/slash-commands.js.map +1 -1
  105. package/dist/bot/steering-engine.d.ts +67 -0
  106. package/dist/bot/steering-engine.d.ts.map +1 -0
  107. package/dist/bot/steering-engine.js +198 -0
  108. package/dist/bot/steering-engine.js.map +1 -0
  109. package/dist/bot/step-executor.d.ts.map +1 -1
  110. package/dist/bot/step-executor.js +62 -25
  111. package/dist/bot/step-executor.js.map +1 -1
  112. package/dist/bot/system-prompt.d.ts.map +1 -1
  113. package/dist/bot/system-prompt.js +5 -2
  114. package/dist/bot/system-prompt.js.map +1 -1
  115. package/dist/bot/task-queue.d.ts +6 -1
  116. package/dist/bot/task-queue.d.ts.map +1 -1
  117. package/dist/bot/task-queue.js +43 -4
  118. package/dist/bot/task-queue.js.map +1 -1
  119. package/dist/bot/tool-registry.d.ts +1 -1
  120. package/dist/bot/tool-registry.d.ts.map +1 -1
  121. package/dist/bot/tool-registry.js +65 -4
  122. package/dist/bot/tool-registry.js.map +1 -1
  123. package/dist/bot/trust-calculator.d.ts +34 -0
  124. package/dist/bot/trust-calculator.d.ts.map +1 -0
  125. package/dist/bot/trust-calculator.js +67 -0
  126. package/dist/bot/trust-calculator.js.map +1 -0
  127. package/dist/bot/types.d.ts +97 -0
  128. package/dist/bot/types.d.ts.map +1 -1
  129. package/dist/bot/update-checker.d.ts +21 -0
  130. package/dist/bot/update-checker.d.ts.map +1 -0
  131. package/dist/bot/update-checker.js +129 -0
  132. package/dist/bot/update-checker.js.map +1 -0
  133. package/dist/bot/weaver-tools.d.ts.map +1 -1
  134. package/dist/bot/weaver-tools.js +11 -4
  135. package/dist/bot/weaver-tools.js.map +1 -1
  136. package/dist/cli-bridge.d.ts.map +1 -1
  137. package/dist/cli-bridge.js +2 -1
  138. package/dist/cli-bridge.js.map +1 -1
  139. package/dist/cli-handlers.d.ts +9 -1
  140. package/dist/cli-handlers.d.ts.map +1 -1
  141. package/dist/cli-handlers.js +77 -8
  142. package/dist/cli-handlers.js.map +1 -1
  143. package/dist/cli.d.ts +3 -0
  144. package/dist/cli.d.ts.map +1 -0
  145. package/dist/cli.js +749 -0
  146. package/dist/cli.js.map +1 -0
  147. package/dist/docs/weaver-config.md +15 -9
  148. package/dist/handlers/on-execution-completed.d.ts +11 -0
  149. package/dist/handlers/on-execution-completed.d.ts.map +1 -0
  150. package/dist/handlers/on-execution-completed.js +25 -0
  151. package/dist/handlers/on-execution-completed.js.map +1 -0
  152. package/dist/mcp-tools.d.ts.map +1 -1
  153. package/dist/mcp-tools.js +33 -0
  154. package/dist/mcp-tools.js.map +1 -1
  155. package/dist/node-types/genesis-approve.d.ts.map +1 -1
  156. package/dist/node-types/genesis-approve.js +28 -3
  157. package/dist/node-types/genesis-approve.js.map +1 -1
  158. package/dist/node-types/genesis-observe.d.ts.map +1 -1
  159. package/dist/node-types/genesis-observe.js +23 -13
  160. package/dist/node-types/genesis-observe.js.map +1 -1
  161. package/dist/node-types/genesis-propose.d.ts.map +1 -1
  162. package/dist/node-types/genesis-propose.js +8 -0
  163. package/dist/node-types/genesis-propose.js.map +1 -1
  164. package/dist/node-types/genesis-update-history.d.ts.map +1 -1
  165. package/dist/node-types/genesis-update-history.js +13 -0
  166. package/dist/node-types/genesis-update-history.js.map +1 -1
  167. package/dist/templates/weaver-template.d.ts +11 -0
  168. package/dist/templates/weaver-template.d.ts.map +1 -0
  169. package/dist/templates/weaver-template.js +53 -0
  170. package/dist/templates/weaver-template.js.map +1 -0
  171. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  172. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  173. package/dist/workflows/weaver-bot-session.js +68 -0
  174. package/dist/workflows/weaver-bot-session.js.map +1 -0
  175. package/dist/workflows/weaver.d.ts +24 -0
  176. package/dist/workflows/weaver.d.ts.map +1 -0
  177. package/dist/workflows/weaver.js +28 -0
  178. package/dist/workflows/weaver.js.map +1 -0
  179. package/flowweaver.manifest.json +27 -0
  180. package/package.json +5 -2
  181. package/src/bot/agent-provider.ts +3 -2
  182. package/src/bot/approvals.ts +16 -8
  183. package/src/bot/assistant-core.ts +366 -44
  184. package/src/bot/assistant-tools.ts +291 -9
  185. package/src/bot/bot-agent-channel.ts +2 -0
  186. package/src/bot/bot-manager.ts +70 -29
  187. package/src/bot/conversation-store.ts +87 -42
  188. package/src/bot/cost-store.ts +20 -9
  189. package/src/bot/cost-tracker.ts +13 -1
  190. package/src/bot/cron-parser.ts +1 -0
  191. package/src/bot/cron-scheduler.ts +1 -0
  192. package/src/bot/device-connection.ts +102 -0
  193. package/src/bot/error-classifier.ts +5 -0
  194. package/src/bot/file-lock.ts +12 -2
  195. package/src/bot/file-watcher.ts +1 -0
  196. package/src/bot/genesis-prompt-context.ts +61 -0
  197. package/src/bot/genesis-store.ts +68 -16
  198. package/src/bot/improve-loop.ts +651 -0
  199. package/src/bot/index.ts +3 -0
  200. package/src/bot/insight-engine.ts +273 -0
  201. package/src/bot/knowledge-store.ts +4 -1
  202. package/src/bot/pipeline-runner.ts +11 -6
  203. package/src/bot/project-model.ts +404 -0
  204. package/src/bot/response-formatter.ts +2 -3
  205. package/src/bot/run-store.ts +5 -2
  206. package/src/bot/safe-path.ts +20 -1
  207. package/src/bot/safety.ts +57 -3
  208. package/src/bot/session-state.ts +47 -7
  209. package/src/bot/slash-commands.ts +103 -5
  210. package/src/bot/steering-engine.ts +233 -0
  211. package/src/bot/step-executor.ts +66 -26
  212. package/src/bot/system-prompt.ts +5 -2
  213. package/src/bot/task-queue.ts +40 -4
  214. package/src/bot/tool-registry.ts +67 -5
  215. package/src/bot/trust-calculator.ts +87 -0
  216. package/src/bot/types.ts +104 -0
  217. package/src/bot/update-checker.ts +138 -0
  218. package/src/bot/weaver-tools.ts +10 -4
  219. package/src/cli-bridge.ts +2 -1
  220. package/src/cli-handlers.ts +84 -9
  221. package/src/handlers/on-execution-completed.ts +30 -0
  222. package/src/mcp-tools.ts +38 -0
  223. package/src/node-types/genesis-approve.ts +28 -3
  224. package/src/node-types/genesis-observe.ts +23 -12
  225. package/src/node-types/genesis-propose.ts +8 -0
  226. package/src/node-types/genesis-update-history.ts +12 -0
  227. package/src/ui/evolution-panel.tsx +96 -0
  228. package/src/ui/insights-widget.tsx +77 -0
@@ -8,7 +8,7 @@ import type { ToolDefinition } from '@synergenius/flow-weaver/agent';
8
8
 
9
9
  export interface WeaverTool extends ToolDefinition {
10
10
  verboseOutput?: boolean;
11
- category: 'bot-management' | 'queue' | 'flow-weaver' | 'project' | 'knowledge' | 'conversation' | 'ci' | 'web';
11
+ category: 'bot-management' | 'queue' | 'flow-weaver' | 'project' | 'knowledge' | 'conversation' | 'ci' | 'web' | 'overseer';
12
12
  contexts: Array<'bot' | 'assistant'>;
13
13
  }
14
14
 
@@ -290,7 +290,7 @@ export const ALL_TOOLS: WeaverTool[] = [
290
290
  required: ['file', 'patches'],
291
291
  },
292
292
  category: 'project',
293
- contexts: ['bot'],
293
+ contexts: ['bot', 'assistant'],
294
294
  },
295
295
  {
296
296
  name: 'write_file',
@@ -304,7 +304,7 @@ export const ALL_TOOLS: WeaverTool[] = [
304
304
  required: ['file', 'content'],
305
305
  },
306
306
  category: 'project',
307
- contexts: ['bot'],
307
+ contexts: ['bot', 'assistant'],
308
308
  },
309
309
  {
310
310
  name: 'tsc_check',
@@ -312,7 +312,7 @@ export const ALL_TOOLS: WeaverTool[] = [
312
312
  inputSchema: { type: 'object', properties: {}, required: [] },
313
313
  verboseOutput: true,
314
314
  category: 'project',
315
- contexts: ['bot'],
315
+ contexts: ['bot', 'assistant'],
316
316
  },
317
317
  {
318
318
  name: 'run_tests',
@@ -320,7 +320,7 @@ export const ALL_TOOLS: WeaverTool[] = [
320
320
  inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: 'Test file pattern (optional)' } }, required: [] },
321
321
  verboseOutput: true,
322
322
  category: 'project',
323
- contexts: ['bot'],
323
+ contexts: ['bot', 'assistant'],
324
324
  },
325
325
  {
326
326
  name: 'project_list',
@@ -434,6 +434,68 @@ export const ALL_TOOLS: WeaverTool[] = [
434
434
  contexts: ['bot', 'assistant'],
435
435
  },
436
436
 
437
+ // ── Overseer tools (assistant only) ─────────────────────────────
438
+ {
439
+ name: 'project_health',
440
+ description: 'Get project health: workflow scores, bot performance, failure patterns, cost trends, trust level.',
441
+ inputSchema: { type: 'object', properties: {}, required: [] },
442
+ category: 'overseer',
443
+ contexts: ['assistant'],
444
+ },
445
+ {
446
+ name: 'project_insights',
447
+ description: 'Get actionable insights: recurring failures, degrading workflows, cost optimizations, evolution opportunities.',
448
+ inputSchema: {
449
+ type: 'object',
450
+ properties: { limit: { type: 'number', description: 'Max insights (default 5)' } },
451
+ required: [],
452
+ },
453
+ category: 'overseer',
454
+ contexts: ['assistant'],
455
+ },
456
+ {
457
+ name: 'evolution_status',
458
+ description: 'Get genesis evolution history: cycle outcomes, operation effectiveness, recent proposals.',
459
+ inputSchema: { type: 'object', properties: {}, required: [] },
460
+ category: 'overseer',
461
+ contexts: ['assistant'],
462
+ },
463
+ {
464
+ name: 'genesis_propose',
465
+ description: 'Generate a Genesis evolution proposal for a bot workflow based on project insights. Auto-ejects bot if needed.',
466
+ inputSchema: {
467
+ type: 'object',
468
+ properties: {
469
+ bot: { type: 'string', description: 'Bot name (default: weaver-bot)' },
470
+ focus: { type: 'string', description: 'Optional focus area for the proposal' },
471
+ budget: { type: 'number', description: 'Cost unit budget (default: from config)' },
472
+ },
473
+ required: [],
474
+ },
475
+ category: 'overseer',
476
+ contexts: ['assistant'],
477
+ },
478
+ {
479
+ name: 'improve_status',
480
+ description: 'Get status of the current or most recent weaver improve run — cycles, commits, successes, failures.',
481
+ inputSchema: { type: 'object', properties: {}, required: [] },
482
+ category: 'overseer',
483
+ contexts: ['assistant'],
484
+ },
485
+ {
486
+ name: 'genesis_apply',
487
+ description: 'Apply an approved Genesis proposal to the bot workflow.',
488
+ inputSchema: {
489
+ type: 'object',
490
+ properties: {
491
+ proposal_id: { type: 'string', description: 'Proposal ID from genesis_propose' },
492
+ },
493
+ required: ['proposal_id'],
494
+ },
495
+ category: 'overseer',
496
+ contexts: ['assistant'],
497
+ },
498
+
437
499
  // ── Bot-only interactive ─────────────────────────────────────────
438
500
  {
439
501
  name: 'ask_user',
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Trust Calculator — pure function that derives a trust level from the project model.
3
+ *
4
+ * Trust phases:
5
+ * Phase 1: Insights + suggestions (default)
6
+ * Phase 2: Proposals with explanation
7
+ * Phase 3: Proposals with visual diff
8
+ * Phase 4: Auto-apply COSMETIC changes
9
+ */
10
+
11
+ import type { TrustLevel } from './types.js';
12
+
13
+ interface TrustInput {
14
+ health: { workflows: Array<{ lastRun: string | null }> };
15
+ userPreferences: { approvalHistory: Array<{ approved: boolean; impactLevel: string }> };
16
+ evolution: { totalCycles: number; successRate: number };
17
+ cost: { last7Days: number };
18
+ _conversationCount?: number;
19
+ }
20
+
21
+ export function computeTrustLevel(model: TrustInput): TrustLevel {
22
+ const conversationCount = model._conversationCount ?? 0;
23
+ const approvalHistory = model.userPreferences.approvalHistory;
24
+ const approvalCount = approvalHistory.length;
25
+ const approvalRate = approvalCount > 0
26
+ ? approvalHistory.filter(a => a.approved).length / approvalCount
27
+ : 0;
28
+ const genesisSuccessRate = model.evolution.totalCycles > 0 ? model.evolution.successRate : 0;
29
+
30
+ // Estimate days since first use from earliest workflow run
31
+ const timestamps: number[] = [];
32
+ for (const w of model.health.workflows) {
33
+ if (w.lastRun) timestamps.push(new Date(w.lastRun).getTime());
34
+ }
35
+ const earliest = timestamps.length > 0 ? Math.min(...timestamps) : Date.now();
36
+ const daysSinceFirstUse = Math.max(0, Math.round((Date.now() - earliest) / 86_400_000));
37
+
38
+ // COSMETIC-specific approval rate
39
+ const cosmeticApprovals = approvalHistory.filter(a => a.impactLevel === 'COSMETIC');
40
+ const cosmeticApprovalRate = cosmeticApprovals.length > 0
41
+ ? cosmeticApprovals.filter(a => a.approved).length / cosmeticApprovals.length
42
+ : 0;
43
+
44
+ // Weighted score (0-100)
45
+ const score = Math.round(
46
+ Math.min(conversationCount / 30, 1) * 25 +
47
+ approvalRate * 25 +
48
+ genesisSuccessRate * 25 +
49
+ Math.min(daysSinceFirstUse / 30, 1) * 25,
50
+ );
51
+
52
+ // Phase thresholds
53
+ let phase: 1 | 2 | 3 | 4 = 1;
54
+ if (
55
+ conversationCount >= 30 &&
56
+ cosmeticApprovalRate >= 0.85 &&
57
+ cosmeticApprovals.length >= 3 &&
58
+ daysSinceFirstUse >= 7
59
+ ) {
60
+ phase = 4;
61
+ } else if (
62
+ conversationCount >= 15 &&
63
+ approvalRate >= 0.7 &&
64
+ approvalCount >= 5 &&
65
+ model.evolution.totalCycles >= 3 &&
66
+ genesisSuccessRate >= 0.5
67
+ ) {
68
+ phase = 3;
69
+ } else if (
70
+ conversationCount >= 5 &&
71
+ approvalCount >= 3 &&
72
+ approvalRate >= 0.6
73
+ ) {
74
+ phase = 2;
75
+ }
76
+
77
+ return {
78
+ score,
79
+ phase,
80
+ factors: {
81
+ conversationCount,
82
+ approvalConsistency: approvalRate,
83
+ genesisSuccessRate,
84
+ daysSinceFirstUse,
85
+ },
86
+ };
87
+ }
package/src/bot/types.ts CHANGED
@@ -471,6 +471,108 @@ export interface GenesisFingerprint {
471
471
  existingWorkflows: string[];
472
472
  }
473
473
 
474
+ // --- Project Model (Overseer) ---
475
+
476
+ export interface WorkflowHealth {
477
+ file: string;
478
+ score: number;
479
+ totalRuns: number;
480
+ successRate: number;
481
+ avgDurationMs: number;
482
+ lastRun: string | null;
483
+ trend: 'improving' | 'stable' | 'degrading';
484
+ }
485
+
486
+ export interface FailurePattern {
487
+ pattern: string;
488
+ category: string;
489
+ occurrences: number;
490
+ lastSeen: string;
491
+ workflows: string[];
492
+ transient: boolean;
493
+ }
494
+
495
+ export interface ApprovalDecision {
496
+ timestamp: string;
497
+ proposalSummary: string;
498
+ impactLevel: string;
499
+ approved: boolean;
500
+ reason?: string;
501
+ }
502
+
503
+ export interface OperationEffectiveness {
504
+ proposed: number;
505
+ applied: number;
506
+ rolledBack: number;
507
+ effectiveness: number;
508
+ }
509
+
510
+ export interface TrustLevel {
511
+ score: number;
512
+ phase: 1 | 2 | 3 | 4;
513
+ factors: {
514
+ conversationCount: number;
515
+ approvalConsistency: number;
516
+ genesisSuccessRate: number;
517
+ daysSinceFirstUse: number;
518
+ };
519
+ }
520
+
521
+ export interface BotProfile {
522
+ name: string;
523
+ workflowFile: string;
524
+ ejected: boolean;
525
+ totalTasksRun: number;
526
+ successRate: number;
527
+ avgTaskDurationMs: number;
528
+ topFailurePatterns: FailurePattern[];
529
+ }
530
+
531
+ export interface ProjectModel {
532
+ projectDir: string;
533
+ builtAt: number;
534
+ health: {
535
+ overall: number;
536
+ workflows: WorkflowHealth[];
537
+ };
538
+ bots: BotProfile[];
539
+ failurePatterns: FailurePattern[];
540
+ userPreferences: {
541
+ approvalHistory: ApprovalDecision[];
542
+ autoApprovePatterns: string[];
543
+ neverApprovePatterns: string[];
544
+ };
545
+ evolution: {
546
+ totalCycles: number;
547
+ successRate: number;
548
+ byOperationType: Record<string, OperationEffectiveness>;
549
+ recentCycles: GenesisCycleRecord[];
550
+ };
551
+ cost: {
552
+ totalSpent: number;
553
+ last7Days: number;
554
+ last30Days: number;
555
+ trend: 'increasing' | 'stable' | 'decreasing';
556
+ costPerSuccessfulRun: number;
557
+ highCostWorkflows: Array<{ workflow: string; avgCost: number }>;
558
+ };
559
+ trust: TrustLevel;
560
+ }
561
+
562
+ export interface Insight {
563
+ id: string;
564
+ type: 'failure-pattern' | 'health-trend' | 'cost-optimization' | 'evolution-opportunity' | 'unused-workflow' | 'bot-performance' | 'update-available';
565
+ confidence: number;
566
+ severity: 'info' | 'warning' | 'critical';
567
+ title: string;
568
+ description: string;
569
+ evidence: string[];
570
+ suggestion?: string;
571
+ genesisCandidate: boolean;
572
+ targetBot?: string;
573
+ operationHint?: string;
574
+ }
575
+
474
576
  export interface GenesisCycleRecord {
475
577
  id: string;
476
578
  timestamp: string;
@@ -483,6 +585,7 @@ export interface GenesisCycleRecord {
483
585
  approved: boolean | null;
484
586
  error: string | null;
485
587
  snapshotFile: string | null;
588
+ rejectionReason?: string;
486
589
  }
487
590
 
488
591
  export interface GenesisHistory {
@@ -519,6 +622,7 @@ export interface GenesisContext {
519
622
  workflowDiffJson?: string;
520
623
  approvalRequired?: boolean;
521
624
  approved?: boolean;
625
+ rejectionReason?: string;
522
626
  commitResultJson?: string;
523
627
  cycleRecordJson?: string;
524
628
  workflowDescription?: string;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Update Checker — checks npm registry for newer versions of installed packs.
3
+ * Results are cached for 24 hours to avoid spamming the registry.
4
+ */
5
+
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import * as os from 'node:os';
9
+ import { safeJsonParse } from './safe-json.js';
10
+
11
+ export interface UpdateInfo {
12
+ packageName: string;
13
+ currentVersion: string;
14
+ latestVersion: string;
15
+ updateAvailable: boolean;
16
+ }
17
+
18
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
19
+ const CACHE_DIR = path.join(os.homedir(), '.weaver');
20
+ const CACHE_FILE = path.join(CACHE_DIR, 'update-cache.json');
21
+
22
+ interface CacheEntry {
23
+ checkedAt: number;
24
+ updates: UpdateInfo[];
25
+ }
26
+
27
+ function readCache(): CacheEntry | null {
28
+ try {
29
+ if (!fs.existsSync(CACHE_FILE)) return null;
30
+ const text = fs.readFileSync(CACHE_FILE, 'utf-8');
31
+ const parsed = safeJsonParse<CacheEntry>(text, 'update-cache');
32
+ if (!parsed.ok) {
33
+ console.error(`[weaver] ${parsed.error}`);
34
+ return null;
35
+ }
36
+ if (Date.now() - parsed.value.checkedAt < CACHE_TTL_MS) return parsed.value;
37
+ return null; // stale
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ function writeCache(entry: CacheEntry): void {
44
+ try {
45
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
46
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(entry, null, 2), 'utf-8');
47
+ } catch { /* non-fatal */ }
48
+ }
49
+
50
+ export function compareVersions(a: string, b: string): number {
51
+ const pa = a.replace(/^v/, '').split('.').map(s => parseInt(s, 10) || 0);
52
+ const pb = b.replace(/^v/, '').split('.').map(s => parseInt(s, 10) || 0);
53
+ for (let i = 0; i < 3; i++) {
54
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
55
+ if (diff !== 0) return diff;
56
+ }
57
+ return 0;
58
+ }
59
+
60
+ async function fetchLatestVersion(packageName: string): Promise<string | null> {
61
+ try {
62
+ const encoded = packageName.replace('/', '%2f');
63
+ const resp = await fetch(`https://registry.npmjs.org/${encoded}/latest`, {
64
+ signal: AbortSignal.timeout(5000),
65
+ });
66
+ if (!resp.ok) return null;
67
+ const data = await resp.json() as { version?: string };
68
+ return data.version ?? null;
69
+ } catch {
70
+ return null; // network error, timeout, etc.
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Check for updates on installed packs. Returns cached result if fresh.
76
+ * Checks: the weaver pack itself, and any flow-weaver-pack-* in node_modules.
77
+ */
78
+ export async function checkForUpdates(projectDir: string): Promise<UpdateInfo[]> {
79
+ // Return cached if fresh
80
+ const cached = readCache();
81
+ if (cached) return cached.updates;
82
+
83
+ const updates: UpdateInfo[] = [];
84
+
85
+ // Check the weaver pack itself
86
+ try {
87
+ const packPkgPath = path.resolve(projectDir, 'node_modules', '@synergenius', 'flow-weaver-pack-weaver', 'package.json');
88
+ if (fs.existsSync(packPkgPath)) {
89
+ const text = fs.readFileSync(packPkgPath, 'utf-8');
90
+ const parsed = safeJsonParse<{ name: string; version: string }>(text, 'pack-weaver package.json');
91
+ if (!parsed.ok) {
92
+ console.error(`[weaver] ${parsed.error}`);
93
+ } else {
94
+ const pkg = parsed.value;
95
+ const current = pkg.version;
96
+ const latest = await fetchLatestVersion(pkg.name);
97
+ if (latest && compareVersions(latest, current) > 0) {
98
+ updates.push({ packageName: pkg.name, currentVersion: current, latestVersion: latest, updateAvailable: true });
99
+ } else if (latest) {
100
+ updates.push({ packageName: pkg.name, currentVersion: current, latestVersion: latest, updateAvailable: false });
101
+ }
102
+ }
103
+ }
104
+ } catch { /* not installed or unreadable */ }
105
+
106
+ // Check flow-weaver core
107
+ try {
108
+ const corePkgPath = path.resolve(projectDir, 'node_modules', '@synergenius', 'flow-weaver', 'package.json');
109
+ if (fs.existsSync(corePkgPath)) {
110
+ const text = fs.readFileSync(corePkgPath, 'utf-8');
111
+ const parsed = safeJsonParse<{ name: string; version: string }>(text, 'flow-weaver package.json');
112
+ if (!parsed.ok) {
113
+ console.error(`[weaver] ${parsed.error}`);
114
+ } else {
115
+ const pkg = parsed.value;
116
+ const current = pkg.version;
117
+ const latest = await fetchLatestVersion(pkg.name);
118
+ if (latest && compareVersions(latest, current) > 0) {
119
+ updates.push({ packageName: pkg.name, currentVersion: current, latestVersion: latest, updateAvailable: true });
120
+ }
121
+ }
122
+ }
123
+ } catch { /* not installed */ }
124
+
125
+ // Cache result
126
+ writeCache({ checkedAt: Date.now(), updates });
127
+ return updates;
128
+ }
129
+
130
+ /**
131
+ * Format update info as a brief notification string.
132
+ */
133
+ export function formatUpdateNotification(updates: UpdateInfo[]): string | null {
134
+ const available = updates.filter(u => u.updateAvailable);
135
+ if (available.length === 0) return null;
136
+ const lines = available.map(u => `${u.packageName}: ${u.currentVersion} → ${u.latestVersion}`);
137
+ return `Updates available:\n${lines.join('\n')}\nRun: npm update`;
138
+ }
@@ -41,9 +41,14 @@ export function createWeaverExecutor(projectDir: string) {
41
41
  if (isBlockedUrl(url)) {
42
42
  return { result: 'Blocked: cannot fetch internal/localhost URLs.', isError: true };
43
43
  }
44
- const resp = await fetch(url, { method: (args.method as string) ?? 'GET', signal: AbortSignal.timeout(15_000) });
45
- const text = await resp.text();
46
- return { result: text.slice(0, 10_000), isError: !resp.ok };
44
+ try {
45
+ const resp = await fetch(url, { method: (args.method as string) ?? 'GET', signal: AbortSignal.timeout(15_000) });
46
+ const text = await resp.text();
47
+ return { result: text.slice(0, 10_000), isError: !resp.ok };
48
+ } catch (err: unknown) {
49
+ const msg = err instanceof Error ? err.message : String(err);
50
+ return { result: `Fetch error: ${msg}`, isError: true };
51
+ }
47
52
  }
48
53
 
49
54
  case 'tsc_check': {
@@ -68,7 +73,8 @@ export function createWeaverExecutor(projectDir: string) {
68
73
  const failures = (json.testResults ?? []).filter((t: any) => t.status === 'failed').map((t: any) => t.name).slice(0, 10);
69
74
  return { result: JSON.stringify({ passed, failed, total: passed + failed, failures }), isError: failed > 0 };
70
75
  } catch {
71
- return { result: output.slice(0, 5000), isError: false };
76
+ // JSON parse failed — output is not structured, flag as error
77
+ return { result: output.slice(0, 5000), isError: true };
72
78
  }
73
79
  } catch (err: any) {
74
80
  return { result: (err.stdout ?? err.stderr ?? err.message ?? '').slice(0, 5000), isError: true };
package/src/cli-bridge.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  handleCron, handlePipeline, handleDashboard, handleProviders,
5
5
  handleEject, handleBot, handleSession, handleSteer, handleQueue,
6
6
  handleStatus, handleGenesis, handleAudit, handleInit, handleAssistant,
7
- handleExamples, handleDoctor,
7
+ handleExamples, handleDoctor, handleImprove,
8
8
  printHelp,
9
9
  } from './cli-handlers.js';
10
10
 
@@ -29,6 +29,7 @@ const handlers: Record<string, (opts: ParsedArgs) => Promise<void>> = {
29
29
  assistant: handleAssistant,
30
30
  examples: handleExamples,
31
31
  doctor: handleDoctor,
32
+ improve: handleImprove,
32
33
  };
33
34
 
34
35
  export { printHelp };
@@ -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;
@@ -70,6 +70,14 @@ export interface ParsedArgs {
70
70
  assistantDelete?: string;
71
71
  assistantWatch?: string;
72
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;
73
81
  }
74
82
 
75
83
  export function parseArgs(argv: string[]): ParsedArgs {
@@ -258,6 +266,8 @@ export function parseArgs(argv: string[]): ParsedArgs {
258
266
  }
259
267
  } else if (arg === 'genesis') {
260
268
  result.command = 'genesis';
269
+ } else if (arg === 'improve') {
270
+ result.command = 'improve';
261
271
  } else if (arg === 'init') {
262
272
  result.command = 'init';
263
273
  } else if (arg === '--init') {
@@ -272,6 +282,8 @@ export function parseArgs(argv: string[]): ParsedArgs {
272
282
  result.assistantMessage = args[i];
273
283
  } else if (arg === '--new') {
274
284
  result.assistantNew = true;
285
+ } else if (arg === '--debug') {
286
+ result.assistantDebug = true;
275
287
  } else if (arg === '--resume' && i + 1 < args.length) {
276
288
  i++;
277
289
  result.assistantResume = args[i];
@@ -294,6 +306,21 @@ export function parseArgs(argv: string[]): ParsedArgs {
294
306
  } else if (arg === '--project-dir' && i + 1 < args.length) {
295
307
  i++;
296
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];
297
324
  } else if (arg === 'run') {
298
325
  // skip, next arg is the file
299
326
  } else if (!arg.startsWith('-')) {
@@ -1624,7 +1651,7 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1624
1651
  if (opts.assistantDelete) {
1625
1652
  const { ConversationStore } = await import('./bot/conversation-store.js');
1626
1653
  const store = new ConversationStore();
1627
- store.delete(opts.assistantDelete);
1654
+ await store.delete(opts.assistantDelete);
1628
1655
  console.log(` Deleted conversation ${opts.assistantDelete}`);
1629
1656
  return;
1630
1657
  }
@@ -1663,7 +1690,14 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1663
1690
  }) as import('@synergenius/flow-weaver/agent').AgentProvider;
1664
1691
  } else if (providerType === 'anthropic' || (providerType === 'auto' && process.env.ANTHROPIC_API_KEY)) {
1665
1692
  const apiKey = process.env.ANTHROPIC_API_KEY ?? (typeof providerSetting === 'object' ? (providerSetting as { apiKey?: string }).apiKey : undefined);
1666
- 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
+ }
1667
1701
  provider = createAnthropicProvider({ apiKey, model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
1668
1702
  } else {
1669
1703
  provider = createClaudeCliProvider({ model: typeof providerSetting === 'object' ? providerSetting.model : undefined });
@@ -1673,6 +1707,36 @@ export async function handleAssistant(opts: ParsedArgs): Promise<void> {
1673
1707
  const { runAssistant } = await import('./bot/assistant-core.js');
1674
1708
  const executor = createAssistantExecutor(projectDir);
1675
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
+
1676
1740
  // Single message mode: -m "message" — run one message, print result, exit
1677
1741
  if (opts.assistantMessage) {
1678
1742
  const { runAgentLoop } = await import('@synergenius/flow-weaver/agent');
@@ -2169,16 +2233,27 @@ export async function handleInit(opts: ParsedArgs): Promise<void> {
2169
2233
  console.log(` provider: ${provider}`);
2170
2234
  console.log(' approval: auto');
2171
2235
  console.log('');
2172
- console.log(' Try it now:');
2173
- console.log(' \x1b[36mweaver bot "Create a hello world workflow"\x1b[0m');
2174
- 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');
2175
2238
  console.log('');
2176
- console.log(' Learn more:');
2177
- console.log(' weaver examples \x1b[2m# see what weaver can do\x1b[0m');
2178
- 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.');
2179
2241
  console.log('');
2180
2242
  }
2181
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
+
2182
2257
  export async function handleExamples(_opts: ParsedArgs): Promise<void> {
2183
2258
  console.log('');
2184
2259
  console.log(' \x1b[1mWeaver Examples\x1b[0m');