@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.
- 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 +366 -45
- 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/index.d.ts +1 -0
- package/dist/bot/index.d.ts.map +1 -1
- package/dist/bot/index.js +2 -0
- package/dist/bot/index.js.map +1 -1
- 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 +100 -5
- 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.map +1 -1
- package/dist/cli-bridge.js +2 -1
- package/dist/cli-bridge.js.map +1 -1
- package/dist/cli-handlers.d.ts +9 -1
- package/dist/cli-handlers.d.ts.map +1 -1
- package/dist/cli-handlers.js +77 -8
- 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 +27 -0
- package/package.json +5 -2
- package/src/bot/agent-provider.ts +3 -2
- package/src/bot/approvals.ts +16 -8
- package/src/bot/assistant-core.ts +366 -44
- 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/index.ts +3 -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 +103 -5
- 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 +2 -1
- package/src/cli-handlers.ts +84 -9
- 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,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
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
50
|
-
const
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
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;
|