@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.
- package/dist/bot/agent-loop.d.ts +20 -0
- package/dist/bot/agent-loop.d.ts.map +1 -0
- package/dist/bot/agent-loop.js +331 -0
- package/dist/bot/agent-loop.js.map +1 -0
- package/dist/bot/agent-provider.d.ts.map +1 -1
- package/dist/bot/agent-provider.js +3 -2
- package/dist/bot/agent-provider.js.map +1 -1
- package/dist/bot/approvals.js +17 -8
- package/dist/bot/approvals.js.map +1 -1
- package/dist/bot/assistant-core.d.ts +17 -0
- package/dist/bot/assistant-core.d.ts.map +1 -1
- package/dist/bot/assistant-core.js +418 -60
- package/dist/bot/assistant-core.js.map +1 -1
- package/dist/bot/assistant-tools.d.ts +1 -1
- package/dist/bot/assistant-tools.d.ts.map +1 -1
- package/dist/bot/assistant-tools.js +283 -9
- package/dist/bot/assistant-tools.js.map +1 -1
- package/dist/bot/bot-agent-channel.d.ts.map +1 -1
- package/dist/bot/bot-agent-channel.js +2 -0
- package/dist/bot/bot-agent-channel.js.map +1 -1
- package/dist/bot/bot-manager.d.ts +4 -0
- package/dist/bot/bot-manager.d.ts.map +1 -1
- package/dist/bot/bot-manager.js +72 -27
- package/dist/bot/bot-manager.js.map +1 -1
- package/dist/bot/conversation-store.d.ts +6 -5
- package/dist/bot/conversation-store.d.ts.map +1 -1
- package/dist/bot/conversation-store.js +98 -42
- package/dist/bot/conversation-store.js.map +1 -1
- package/dist/bot/cost-store.d.ts +3 -0
- package/dist/bot/cost-store.d.ts.map +1 -1
- package/dist/bot/cost-store.js +21 -10
- package/dist/bot/cost-store.js.map +1 -1
- package/dist/bot/cost-tracker.d.ts.map +1 -1
- package/dist/bot/cost-tracker.js +14 -1
- package/dist/bot/cost-tracker.js.map +1 -1
- package/dist/bot/cron-parser.d.ts.map +1 -1
- package/dist/bot/cron-parser.js +2 -0
- package/dist/bot/cron-parser.js.map +1 -1
- package/dist/bot/cron-scheduler.d.ts.map +1 -1
- package/dist/bot/cron-scheduler.js +1 -0
- package/dist/bot/cron-scheduler.js.map +1 -1
- package/dist/bot/device-connection.d.ts +13 -0
- package/dist/bot/device-connection.d.ts.map +1 -0
- package/dist/bot/device-connection.js +102 -0
- package/dist/bot/device-connection.js.map +1 -0
- package/dist/bot/error-classifier.d.ts.map +1 -1
- package/dist/bot/error-classifier.js +5 -0
- package/dist/bot/error-classifier.js.map +1 -1
- package/dist/bot/file-lock.d.ts.map +1 -1
- package/dist/bot/file-lock.js +13 -3
- package/dist/bot/file-lock.js.map +1 -1
- package/dist/bot/file-watcher.d.ts.map +1 -1
- package/dist/bot/file-watcher.js +1 -0
- package/dist/bot/file-watcher.js.map +1 -1
- package/dist/bot/genesis-prompt-context.d.ts +5 -0
- package/dist/bot/genesis-prompt-context.d.ts.map +1 -1
- package/dist/bot/genesis-prompt-context.js +55 -0
- package/dist/bot/genesis-prompt-context.js.map +1 -1
- package/dist/bot/genesis-store.d.ts +4 -0
- package/dist/bot/genesis-store.d.ts.map +1 -1
- package/dist/bot/genesis-store.js +79 -12
- package/dist/bot/genesis-store.js.map +1 -1
- package/dist/bot/improve-loop.d.ts +46 -0
- package/dist/bot/improve-loop.d.ts.map +1 -0
- package/dist/bot/improve-loop.js +592 -0
- package/dist/bot/improve-loop.js.map +1 -0
- package/dist/bot/insight-engine.d.ts +12 -0
- package/dist/bot/insight-engine.d.ts.map +1 -0
- package/dist/bot/insight-engine.js +256 -0
- package/dist/bot/insight-engine.js.map +1 -0
- package/dist/bot/knowledge-store.d.ts.map +1 -1
- package/dist/bot/knowledge-store.js +4 -1
- package/dist/bot/knowledge-store.js.map +1 -1
- package/dist/bot/pipeline-runner.d.ts.map +1 -1
- package/dist/bot/pipeline-runner.js +12 -4
- package/dist/bot/pipeline-runner.js.map +1 -1
- package/dist/bot/project-model.d.ts +25 -0
- package/dist/bot/project-model.d.ts.map +1 -0
- package/dist/bot/project-model.js +372 -0
- package/dist/bot/project-model.js.map +1 -0
- package/dist/bot/response-formatter.js +2 -3
- package/dist/bot/response-formatter.js.map +1 -1
- package/dist/bot/run-store.d.ts.map +1 -1
- package/dist/bot/run-store.js +10 -2
- package/dist/bot/run-store.js.map +1 -1
- package/dist/bot/safe-path.d.ts +1 -1
- package/dist/bot/safe-path.d.ts.map +1 -1
- package/dist/bot/safe-path.js +20 -1
- package/dist/bot/safe-path.js.map +1 -1
- package/dist/bot/safety.d.ts +10 -2
- package/dist/bot/safety.d.ts.map +1 -1
- package/dist/bot/safety.js +45 -2
- package/dist/bot/safety.js.map +1 -1
- package/dist/bot/session-state.d.ts +4 -0
- package/dist/bot/session-state.d.ts.map +1 -1
- package/dist/bot/session-state.js +52 -9
- package/dist/bot/session-state.js.map +1 -1
- package/dist/bot/slash-commands.d.ts.map +1 -1
- package/dist/bot/slash-commands.js +109 -3
- package/dist/bot/slash-commands.js.map +1 -1
- package/dist/bot/steering-engine.d.ts +67 -0
- package/dist/bot/steering-engine.d.ts.map +1 -0
- package/dist/bot/steering-engine.js +198 -0
- package/dist/bot/steering-engine.js.map +1 -0
- package/dist/bot/step-executor.d.ts.map +1 -1
- package/dist/bot/step-executor.js +62 -25
- package/dist/bot/step-executor.js.map +1 -1
- package/dist/bot/system-prompt.d.ts.map +1 -1
- package/dist/bot/system-prompt.js +5 -2
- package/dist/bot/system-prompt.js.map +1 -1
- package/dist/bot/task-queue.d.ts +6 -1
- package/dist/bot/task-queue.d.ts.map +1 -1
- package/dist/bot/task-queue.js +43 -4
- package/dist/bot/task-queue.js.map +1 -1
- package/dist/bot/tool-registry.d.ts +1 -1
- package/dist/bot/tool-registry.d.ts.map +1 -1
- package/dist/bot/tool-registry.js +65 -4
- package/dist/bot/tool-registry.js.map +1 -1
- package/dist/bot/trust-calculator.d.ts +34 -0
- package/dist/bot/trust-calculator.d.ts.map +1 -0
- package/dist/bot/trust-calculator.js +67 -0
- package/dist/bot/trust-calculator.js.map +1 -0
- package/dist/bot/types.d.ts +97 -0
- package/dist/bot/types.d.ts.map +1 -1
- package/dist/bot/update-checker.d.ts +21 -0
- package/dist/bot/update-checker.d.ts.map +1 -0
- package/dist/bot/update-checker.js +129 -0
- package/dist/bot/update-checker.js.map +1 -0
- package/dist/bot/weaver-tools.d.ts.map +1 -1
- package/dist/bot/weaver-tools.js +11 -4
- package/dist/bot/weaver-tools.js.map +1 -1
- package/dist/cli-bridge.d.ts +2 -0
- package/dist/cli-bridge.d.ts.map +1 -1
- package/dist/cli-bridge.js +3 -1
- package/dist/cli-bridge.js.map +1 -1
- package/dist/cli-handlers.d.ts +10 -1
- package/dist/cli-handlers.d.ts.map +1 -1
- package/dist/cli-handlers.js +141 -24
- package/dist/cli-handlers.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +749 -0
- package/dist/cli.js.map +1 -0
- package/dist/docs/weaver-config.md +15 -9
- package/dist/handlers/on-execution-completed.d.ts +11 -0
- package/dist/handlers/on-execution-completed.d.ts.map +1 -0
- package/dist/handlers/on-execution-completed.js +25 -0
- package/dist/handlers/on-execution-completed.js.map +1 -0
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js +33 -0
- package/dist/mcp-tools.js.map +1 -1
- package/dist/node-types/genesis-approve.d.ts.map +1 -1
- package/dist/node-types/genesis-approve.js +28 -3
- package/dist/node-types/genesis-approve.js.map +1 -1
- package/dist/node-types/genesis-observe.d.ts.map +1 -1
- package/dist/node-types/genesis-observe.js +23 -13
- package/dist/node-types/genesis-observe.js.map +1 -1
- package/dist/node-types/genesis-propose.d.ts.map +1 -1
- package/dist/node-types/genesis-propose.js +8 -0
- package/dist/node-types/genesis-propose.js.map +1 -1
- package/dist/node-types/genesis-update-history.d.ts.map +1 -1
- package/dist/node-types/genesis-update-history.js +13 -0
- package/dist/node-types/genesis-update-history.js.map +1 -1
- package/dist/templates/weaver-template.d.ts +11 -0
- package/dist/templates/weaver-template.d.ts.map +1 -0
- package/dist/templates/weaver-template.js +53 -0
- package/dist/templates/weaver-template.js.map +1 -0
- package/dist/workflows/weaver-bot-session.d.ts +65 -0
- package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
- package/dist/workflows/weaver-bot-session.js +68 -0
- package/dist/workflows/weaver-bot-session.js.map +1 -0
- package/dist/workflows/weaver.d.ts +24 -0
- package/dist/workflows/weaver.d.ts.map +1 -0
- package/dist/workflows/weaver.js +28 -0
- package/dist/workflows/weaver.js.map +1 -0
- package/flowweaver.manifest.json +28 -1
- package/package.json +6 -3
- package/src/bot/agent-provider.ts +3 -2
- package/src/bot/approvals.ts +16 -8
- package/src/bot/assistant-core.ts +420 -63
- package/src/bot/assistant-tools.ts +291 -9
- package/src/bot/bot-agent-channel.ts +2 -0
- package/src/bot/bot-manager.ts +70 -29
- package/src/bot/conversation-store.ts +87 -42
- package/src/bot/cost-store.ts +20 -9
- package/src/bot/cost-tracker.ts +13 -1
- package/src/bot/cron-parser.ts +1 -0
- package/src/bot/cron-scheduler.ts +1 -0
- package/src/bot/device-connection.ts +102 -0
- package/src/bot/error-classifier.ts +5 -0
- package/src/bot/file-lock.ts +12 -2
- package/src/bot/file-watcher.ts +1 -0
- package/src/bot/genesis-prompt-context.ts +61 -0
- package/src/bot/genesis-store.ts +68 -16
- package/src/bot/improve-loop.ts +651 -0
- package/src/bot/insight-engine.ts +273 -0
- package/src/bot/knowledge-store.ts +4 -1
- package/src/bot/pipeline-runner.ts +11 -6
- package/src/bot/project-model.ts +404 -0
- package/src/bot/response-formatter.ts +2 -3
- package/src/bot/run-store.ts +5 -2
- package/src/bot/safe-path.ts +20 -1
- package/src/bot/safety.ts +57 -3
- package/src/bot/session-state.ts +47 -7
- package/src/bot/slash-commands.ts +111 -3
- package/src/bot/steering-engine.ts +233 -0
- package/src/bot/step-executor.ts +66 -26
- package/src/bot/system-prompt.ts +5 -2
- package/src/bot/task-queue.ts +40 -4
- package/src/bot/tool-registry.ts +67 -5
- package/src/bot/trust-calculator.ts +87 -0
- package/src/bot/types.ts +104 -0
- package/src/bot/update-checker.ts +138 -0
- package/src/bot/weaver-tools.ts +10 -4
- package/src/cli-bridge.ts +4 -1
- package/src/cli-handlers.ts +150 -29
- package/src/handlers/on-execution-completed.ts +30 -0
- package/src/mcp-tools.ts +38 -0
- package/src/node-types/genesis-approve.ts +28 -3
- package/src/node-types/genesis-observe.ts +23 -12
- package/src/node-types/genesis-propose.ts +8 -0
- package/src/node-types/genesis-update-history.ts +12 -0
- package/src/ui/evolution-panel.tsx +96 -0
- package/src/ui/insights-widget.tsx +77 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import type { Insight, ProjectModel } from './types.js';
|
|
3
|
+
|
|
4
|
+
export class InsightEngine {
|
|
5
|
+
analyze(model: ProjectModel): Insight[] {
|
|
6
|
+
const insights = [
|
|
7
|
+
...this.detectRecurringFailures(model),
|
|
8
|
+
...this.detectHealthTrends(model),
|
|
9
|
+
...this.detectCostOptimizations(model),
|
|
10
|
+
...this.detectEvolutionOpportunities(model),
|
|
11
|
+
...this.detectBotPerformance(model),
|
|
12
|
+
...this.detectUnusedWorkflows(model),
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };
|
|
16
|
+
insights.sort((a, b) => {
|
|
17
|
+
const sevA = severityOrder[a.severity] ?? 999;
|
|
18
|
+
const sevB = severityOrder[b.severity] ?? 999;
|
|
19
|
+
const sevDiff = sevA - sevB;
|
|
20
|
+
if (sevDiff !== 0) return sevDiff;
|
|
21
|
+
return b.confidence - a.confidence;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return insights;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private makeId(type: string, title: string): string {
|
|
28
|
+
return createHash('sha256').update(type + title).digest('hex').slice(0, 8);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private detectRecurringFailures(model: ProjectModel): Insight[] {
|
|
32
|
+
return model.failurePatterns
|
|
33
|
+
.filter((fp) => fp.occurrences >= 3)
|
|
34
|
+
.map((fp) => {
|
|
35
|
+
const type = 'failure-pattern' as const;
|
|
36
|
+
const title = `Recurring failure: ${fp.pattern}`;
|
|
37
|
+
const isCritical = !fp.transient && fp.occurrences >= 5;
|
|
38
|
+
return {
|
|
39
|
+
id: this.makeId(type, title),
|
|
40
|
+
type,
|
|
41
|
+
confidence: Math.min(fp.occurrences / 10, 0.95),
|
|
42
|
+
severity: isCritical ? 'critical' as const : 'warning' as const,
|
|
43
|
+
title,
|
|
44
|
+
description: `Pattern "${fp.pattern}" (${fp.category}) has occurred ${fp.occurrences} times across ${fp.workflows.length} workflow(s).`,
|
|
45
|
+
evidence: [
|
|
46
|
+
`Pattern: ${fp.pattern}`,
|
|
47
|
+
`Occurrences: ${fp.occurrences}`,
|
|
48
|
+
],
|
|
49
|
+
suggestion: 'Consider adding error handling or a pre-check step',
|
|
50
|
+
genesisCandidate: !fp.transient,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private detectHealthTrends(model: ProjectModel): Insight[] {
|
|
56
|
+
return (model.health.workflows ?? [])
|
|
57
|
+
.filter((w) => w.trend === 'degrading')
|
|
58
|
+
.map((w) => {
|
|
59
|
+
const type = 'health-trend' as const;
|
|
60
|
+
const title = `Degrading health: ${w.file}`;
|
|
61
|
+
const confidence = Math.min(Math.max(w.totalRuns / 50, 0.3), 0.9);
|
|
62
|
+
return {
|
|
63
|
+
id: this.makeId(type, title),
|
|
64
|
+
type,
|
|
65
|
+
confidence,
|
|
66
|
+
severity: w.score < 50 ? 'critical' as const : 'warning' as const,
|
|
67
|
+
title,
|
|
68
|
+
description: `Workflow ${w.file} has a degrading health trend with a score of ${w.score}.`,
|
|
69
|
+
evidence: [
|
|
70
|
+
`File: ${w.file}`,
|
|
71
|
+
`Score: ${w.score}`,
|
|
72
|
+
`Trend: ${w.trend}`,
|
|
73
|
+
],
|
|
74
|
+
suggestion: 'Investigate recent changes to this workflow',
|
|
75
|
+
genesisCandidate: false,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private detectCostOptimizations(model: ProjectModel): Insight[] {
|
|
81
|
+
const insights: Insight[] = [];
|
|
82
|
+
|
|
83
|
+
if (model.cost.trend === 'increasing') {
|
|
84
|
+
const type = 'cost-optimization' as const;
|
|
85
|
+
const title = 'Cost trend is increasing';
|
|
86
|
+
insights.push({
|
|
87
|
+
id: this.makeId(type, title),
|
|
88
|
+
type,
|
|
89
|
+
confidence: 0.7,
|
|
90
|
+
severity: 'info',
|
|
91
|
+
title,
|
|
92
|
+
description: `Spending is trending upward: $${model.cost.last7Days.toFixed(2)} in the last 7 days, $${model.cost.last30Days.toFixed(2)} in the last 30 days.`,
|
|
93
|
+
evidence: [
|
|
94
|
+
`Trend: ${model.cost.trend}`,
|
|
95
|
+
`Last 7 days: $${model.cost.last7Days.toFixed(2)}`,
|
|
96
|
+
`Last 30 days: $${model.cost.last30Days.toFixed(2)}`,
|
|
97
|
+
],
|
|
98
|
+
suggestion: 'Review high-cost workflows and consider reducing run frequency or optimizing steps',
|
|
99
|
+
genesisCandidate: false,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const bot of model.bots) {
|
|
104
|
+
if (bot.successRate < 0.5 && bot.totalTasksRun > 5) {
|
|
105
|
+
const type = 'cost-optimization' as const;
|
|
106
|
+
const title = `Wasted spend on bot: ${bot.name}`;
|
|
107
|
+
insights.push({
|
|
108
|
+
id: this.makeId(type, title),
|
|
109
|
+
type,
|
|
110
|
+
confidence: 0.8,
|
|
111
|
+
severity: 'warning',
|
|
112
|
+
title,
|
|
113
|
+
description: `Bot "${bot.name}" has a ${(bot.successRate * 100).toFixed(0)}% success rate over ${bot.totalTasksRun} runs, resulting in wasted spend.`,
|
|
114
|
+
evidence: [
|
|
115
|
+
`Bot: ${bot.name}`,
|
|
116
|
+
`Success rate: ${(bot.successRate * 100).toFixed(0)}%`,
|
|
117
|
+
`Total runs: ${bot.totalTasksRun}`,
|
|
118
|
+
],
|
|
119
|
+
suggestion: `Improve the workflow for "${bot.name}" or reduce its run frequency until reliability improves`,
|
|
120
|
+
genesisCandidate: false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (const hw of (model.cost.highCostWorkflows ?? [])) {
|
|
126
|
+
const wf = (model.health.workflows ?? []).find((w) => w.file === hw.workflow);
|
|
127
|
+
if (wf && wf.successRate < 0.5 && wf.totalRuns > 5) {
|
|
128
|
+
const type = 'cost-optimization' as const;
|
|
129
|
+
const title = `Wasted spend on workflow: ${hw.workflow}`;
|
|
130
|
+
insights.push({
|
|
131
|
+
id: this.makeId(type, title),
|
|
132
|
+
type,
|
|
133
|
+
confidence: 0.8,
|
|
134
|
+
severity: 'warning',
|
|
135
|
+
title,
|
|
136
|
+
description: `Workflow "${hw.workflow}" has a ${(wf.successRate * 100).toFixed(0)}% success rate with an average cost of $${hw.avgCost.toFixed(2)} per run.`,
|
|
137
|
+
evidence: [
|
|
138
|
+
`Workflow: ${hw.workflow}`,
|
|
139
|
+
`Success rate: ${(wf.successRate * 100).toFixed(0)}%`,
|
|
140
|
+
`Avg cost: $${hw.avgCost.toFixed(2)}`,
|
|
141
|
+
],
|
|
142
|
+
suggestion: `Fix reliability issues in "${hw.workflow}" before continuing to spend on it`,
|
|
143
|
+
genesisCandidate: false,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return insights;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private detectEvolutionOpportunities(model: ProjectModel): Insight[] {
|
|
152
|
+
const insights: Insight[] = [];
|
|
153
|
+
const type = 'evolution-opportunity' as const;
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
model.evolution.totalCycles === 0 &&
|
|
157
|
+
(model.health.workflows ?? []).length > 0 &&
|
|
158
|
+
model.failurePatterns.length > 0
|
|
159
|
+
) {
|
|
160
|
+
const title = 'Ready for first genesis cycle';
|
|
161
|
+
insights.push({
|
|
162
|
+
id: this.makeId(type, title),
|
|
163
|
+
type,
|
|
164
|
+
confidence: 0.7,
|
|
165
|
+
severity: 'info',
|
|
166
|
+
title,
|
|
167
|
+
description: 'The project has workflows and failure data but has never run a genesis evolution cycle. Consider starting one.',
|
|
168
|
+
evidence: [
|
|
169
|
+
`Workflows: ${model.health.workflows.length}`,
|
|
170
|
+
`Failure patterns: ${model.failurePatterns.length}`,
|
|
171
|
+
`Evolution cycles: 0`,
|
|
172
|
+
],
|
|
173
|
+
suggestion: 'Run a genesis cycle to automatically improve workflows based on failure patterns',
|
|
174
|
+
genesisCandidate: true,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (const [opType, stats] of Object.entries(model.evolution.byOperationType)) {
|
|
179
|
+
if (stats.effectiveness > 0.8) {
|
|
180
|
+
const title = `High-effectiveness operation: ${opType}`;
|
|
181
|
+
insights.push({
|
|
182
|
+
id: this.makeId(type, title),
|
|
183
|
+
type,
|
|
184
|
+
confidence: 0.8,
|
|
185
|
+
severity: 'info',
|
|
186
|
+
title,
|
|
187
|
+
description: `Operation type "${opType}" has an effectiveness of ${(stats.effectiveness * 100).toFixed(0)}% — consider expanding its use.`,
|
|
188
|
+
evidence: [
|
|
189
|
+
`Operation: ${opType}`,
|
|
190
|
+
`Effectiveness: ${(stats.effectiveness * 100).toFixed(0)}%`,
|
|
191
|
+
`Applied: ${stats.applied}`,
|
|
192
|
+
`Rolled back: ${stats.rolledBack}`,
|
|
193
|
+
],
|
|
194
|
+
suggestion: `Consider expanding the use of "${opType}" operations to more workflows`,
|
|
195
|
+
genesisCandidate: true,
|
|
196
|
+
});
|
|
197
|
+
} else if (stats.effectiveness < 0.3) {
|
|
198
|
+
const title = `Low-effectiveness operation: ${opType}`;
|
|
199
|
+
insights.push({
|
|
200
|
+
id: this.makeId(type, title),
|
|
201
|
+
type,
|
|
202
|
+
confidence: 0.6,
|
|
203
|
+
severity: 'warning',
|
|
204
|
+
title,
|
|
205
|
+
description: `Operation type "${opType}" has an effectiveness of only ${(stats.effectiveness * 100).toFixed(0)}% — it may not be worth proposing.`,
|
|
206
|
+
evidence: [
|
|
207
|
+
`Operation: ${opType}`,
|
|
208
|
+
`Effectiveness: ${(stats.effectiveness * 100).toFixed(0)}%`,
|
|
209
|
+
`Applied: ${stats.applied}`,
|
|
210
|
+
`Rolled back: ${stats.rolledBack}`,
|
|
211
|
+
],
|
|
212
|
+
suggestion: `Avoid proposing "${opType}" operations until the underlying issues are understood`,
|
|
213
|
+
genesisCandidate: true,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return insights;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private detectBotPerformance(model: ProjectModel): Insight[] {
|
|
222
|
+
return model.bots
|
|
223
|
+
.filter((bot) => bot.successRate < 0.5 && bot.totalTasksRun > 3)
|
|
224
|
+
.map((bot) => {
|
|
225
|
+
const type = 'bot-performance' as const;
|
|
226
|
+
const title = `Underperforming bot: ${bot.name}`;
|
|
227
|
+
const topFailure = bot.topFailurePatterns.length > 0 ? bot.topFailurePatterns[0] : undefined;
|
|
228
|
+
return {
|
|
229
|
+
id: this.makeId(type, title),
|
|
230
|
+
type,
|
|
231
|
+
confidence: Math.min(Math.max(bot.totalTasksRun / 20, 0.4), 0.9),
|
|
232
|
+
severity: bot.successRate < 0.3 ? 'critical' as const : 'warning' as const,
|
|
233
|
+
title,
|
|
234
|
+
description: `Bot "${bot.name}" has a ${(bot.successRate * 100).toFixed(0)}% success rate over ${bot.totalTasksRun} tasks.${topFailure ? ` Top failure: ${topFailure}` : ''}`,
|
|
235
|
+
evidence: [
|
|
236
|
+
`Bot: ${bot.name}`,
|
|
237
|
+
`Success rate: ${(bot.successRate * 100).toFixed(0)}%`,
|
|
238
|
+
`Tasks run: ${bot.totalTasksRun}`,
|
|
239
|
+
...(bot.topFailurePatterns.length > 0
|
|
240
|
+
? [`Top failures: ${bot.topFailurePatterns.join(', ')}`]
|
|
241
|
+
: []),
|
|
242
|
+
],
|
|
243
|
+
suggestion: 'Consider evolving the bot workflow to handle these failures',
|
|
244
|
+
genesisCandidate: true,
|
|
245
|
+
targetBot: bot.name,
|
|
246
|
+
operationHint: 'addNode:errorHandler',
|
|
247
|
+
};
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private detectUnusedWorkflows(model: ProjectModel): Insight[] {
|
|
252
|
+
return (model.health.workflows ?? [])
|
|
253
|
+
.filter((w) => w.totalRuns === 0)
|
|
254
|
+
.map((w) => {
|
|
255
|
+
const type = 'unused-workflow' as const;
|
|
256
|
+
const title = `Unused workflow: ${w.file}`;
|
|
257
|
+
return {
|
|
258
|
+
id: this.makeId(type, title),
|
|
259
|
+
type,
|
|
260
|
+
confidence: 0.5,
|
|
261
|
+
severity: 'info' as const,
|
|
262
|
+
title,
|
|
263
|
+
description: `Workflow "${w.file}" has never been run.`,
|
|
264
|
+
evidence: [
|
|
265
|
+
`File: ${w.file}`,
|
|
266
|
+
`Total runs: 0`,
|
|
267
|
+
],
|
|
268
|
+
suggestion: 'Consider removing or archiving',
|
|
269
|
+
genesisCandidate: false,
|
|
270
|
+
};
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -54,6 +54,9 @@ export class KnowledgeStore {
|
|
|
54
54
|
private writeAll(entries: KnowledgeEntry[]): void {
|
|
55
55
|
const dir = path.dirname(this.filePath);
|
|
56
56
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
57
|
-
|
|
57
|
+
// Atomic write: write to temp file then rename to avoid partial reads on crash
|
|
58
|
+
const tmpPath = this.filePath + '.tmp.' + process.pid;
|
|
59
|
+
fs.writeFileSync(tmpPath, entries.map(e => JSON.stringify(e)).join('\n') + (entries.length > 0 ? '\n' : ''));
|
|
60
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -114,12 +114,17 @@ export class PipelineRunner {
|
|
|
114
114
|
|
|
115
115
|
let workflowResult: WorkflowResult;
|
|
116
116
|
if (timeout) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
118
|
+
try {
|
|
119
|
+
workflowResult = await Promise.race([
|
|
120
|
+
workflowPromise,
|
|
121
|
+
new Promise<never>((_, reject) => {
|
|
122
|
+
timer = setTimeout(() => reject(new Error(`Stage "${stageId}" timed out after ${timeout}s`)), timeout * 1000);
|
|
123
|
+
}),
|
|
124
|
+
]);
|
|
125
|
+
} finally {
|
|
126
|
+
clearTimeout(timer!);
|
|
127
|
+
}
|
|
123
128
|
} else {
|
|
124
129
|
workflowResult = await workflowPromise;
|
|
125
130
|
}
|