@stackmemoryai/stackmemory 1.12.0 → 1.14.0
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/LICENSE +131 -64
- package/README.md +3 -1
- package/bin/claude-sm +16 -1
- package/bin/claude-smd +16 -1
- package/bin/codex-smd +16 -1
- package/bin/gemini-sm +16 -1
- package/bin/hermes-sm +21 -0
- package/bin/hermes-smd +21 -0
- package/bin/opencode-sm +16 -1
- package/dist/src/cli/codex-sm.js +51 -11
- package/dist/src/cli/commands/brain.js +206 -0
- package/dist/src/cli/commands/company-os.js +184 -0
- package/dist/src/cli/commands/context.js +5 -0
- package/dist/src/cli/commands/operator.js +127 -0
- package/dist/src/cli/commands/orchestrate.js +2 -0
- package/dist/src/cli/commands/orchestrator.js +3 -2
- package/dist/src/cli/commands/patterns.js +254 -0
- package/dist/src/cli/commands/portal.js +161 -0
- package/dist/src/cli/commands/scaffold.js +92 -0
- package/dist/src/cli/commands/setup.js +1 -4
- package/dist/src/cli/commands/sync.js +253 -0
- package/dist/src/cli/commands/tasks.js +130 -1
- package/dist/src/cli/commands/vision.js +221 -0
- package/dist/src/cli/hermes-sm.js +224 -0
- package/dist/src/cli/index.js +15 -10
- package/dist/src/cli/utils/real-cli-bin.js +72 -0
- package/dist/src/core/brain/brain-store.js +187 -0
- package/dist/src/core/brain/brain-sync.js +193 -0
- package/dist/src/core/brain/index.js +78 -0
- package/dist/src/core/brain/types.js +10 -0
- package/dist/src/core/cache/token-estimator.js +24 -1
- package/dist/src/core/config/feature-flags.js +2 -6
- package/dist/src/core/context/frame-database.js +44 -0
- package/dist/src/core/context/recursive-context-manager.js +1 -1
- package/dist/src/core/context/rehydration.js +2 -1
- package/dist/src/core/database/sqlite-adapter.js +14 -1
- package/dist/src/core/models/model-router.js +33 -1
- package/dist/src/core/models/provider-pricing.js +58 -4
- package/dist/src/core/patterns/index.js +22 -0
- package/dist/src/core/patterns/pattern-applier.js +39 -0
- package/dist/src/core/patterns/pattern-observer.js +157 -0
- package/dist/src/core/patterns/pattern-store.js +259 -0
- package/dist/src/core/patterns/types.js +19 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
- package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
- package/dist/src/core/skill-packs/types.js +14 -1
- package/dist/src/core/storage/cloud-sync-manager.js +116 -0
- package/dist/src/core/storage/cloud-sync.js +574 -0
- package/dist/src/core/storage/two-tier-storage.js +5 -1
- package/dist/src/core/tasks/master-tasks-template.js +43 -0
- package/dist/src/core/tasks/md-task-parser.js +138 -0
- package/dist/src/core/vision/index.js +27 -0
- package/dist/src/core/vision/signals.js +79 -0
- package/dist/src/core/vision/types.js +22 -0
- package/dist/src/core/vision/vision-file.js +146 -0
- package/dist/src/core/vision/vision-loop.js +220 -0
- package/dist/src/core/wiki/wiki-compiler.js +103 -1
- package/dist/src/daemon/daemon-config.js +45 -0
- package/dist/src/daemon/services/desire-path-service.js +566 -0
- package/dist/src/daemon/services/research-stream-service.js +320 -0
- package/dist/src/daemon/services/telemetry-service.js +192 -0
- package/dist/src/daemon/unified-daemon.js +28 -1
- package/dist/src/features/browser/cli-browser-agent.js +417 -0
- package/dist/src/features/browser/stagehand-workflows.js +578 -0
- package/dist/src/features/operator/adapter-factory.js +62 -0
- package/dist/src/features/operator/browser-adapter.js +109 -0
- package/dist/src/features/operator/desktop-adapter.js +125 -0
- package/dist/src/features/operator/index.js +39 -0
- package/dist/src/features/operator/llm-decision.js +137 -0
- package/dist/src/features/operator/operator-logger.js +92 -0
- package/dist/src/features/operator/overnight-runner.js +327 -0
- package/dist/src/features/operator/screen-adapter.js +91 -0
- package/dist/src/features/operator/session-manager.js +127 -0
- package/dist/src/features/operator/state-machine.js +227 -0
- package/dist/src/features/operator/task-queue.js +81 -0
- package/dist/src/features/portal/index.js +26 -0
- package/dist/src/features/portal/server.js +240 -0
- package/dist/src/features/portal/types.js +14 -0
- package/dist/src/features/portal/ui.js +195 -0
- package/dist/src/features/tasks/task-aware-context.js +2 -1
- package/dist/src/features/tui/simple-monitor.js +0 -23
- package/dist/src/features/tui/swarm-monitor.js +8 -66
- package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
- package/dist/src/features/web/client/lib/utils.js +12 -0
- package/dist/src/features/web/client/stores/session-store.js +12 -0
- package/dist/src/features/web/server/gcp-billing.js +76 -0
- package/dist/src/features/web/server/index.js +10 -0
- package/dist/src/features/web/server/spend-calculator.js +228 -0
- package/dist/src/hooks/schemas.js +4 -1
- package/dist/src/integrations/anthropic/client.js +3 -2
- package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
- package/dist/src/integrations/claude-code/subagent-client.js +218 -11
- package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
- package/dist/src/integrations/linear/webhook-retry.js +196 -0
- package/dist/src/integrations/linear/webhook-server.js +18 -22
- package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
- package/dist/src/integrations/mcp/handlers/index.js +27 -52
- package/dist/src/integrations/mcp/server.js +122 -335
- package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
- package/dist/src/integrations/mcp/tool-definitions.js +111 -510
- package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
- package/dist/src/orchestrators/multimodal/determinism.js +2 -1
- package/dist/src/orchestrators/multimodal/harness.js +2 -1
- package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
- package/dist/src/utils/process-cleanup.js +1 -7
- package/docs/README.md +42 -0
- package/docs/guides/README_INSTALL.md +208 -0
- package/package.json +18 -9
- package/scripts/claude-code-wrapper.sh +11 -0
- package/scripts/claude-sm-setup.sh +12 -1
- package/scripts/codex-wrapper.sh +11 -0
- package/scripts/git-hooks/branch-context-manager.sh +11 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
- package/scripts/hooks/cleanup-shell.sh +12 -1
- package/scripts/hooks/task-complete.sh +12 -1
- package/scripts/install-code-execution-hooks.sh +12 -1
- package/scripts/install-sweep-hook.sh +12 -0
- package/scripts/install.sh +11 -0
- package/scripts/opencode-wrapper.sh +11 -0
- package/scripts/portal/cloud-init.yaml +69 -0
- package/scripts/portal/setup.sh +69 -0
- package/scripts/portal/stackmemory-portal.service +34 -0
- package/scripts/setup-claude-integration.sh +12 -1
- package/scripts/smoke-init-db.sh +23 -0
- package/scripts/stackmemory-daemon.sh +11 -0
- package/scripts/verify-dist.cjs +11 -4
- package/dist/src/cli/commands/ralph.js +0 -1053
- package/dist/src/hooks/diffmem-hooks.js +0 -376
- package/dist/src/integrations/diffmem/client.js +0 -208
- package/dist/src/integrations/diffmem/config.js +0 -14
- package/dist/src/integrations/greptile/client.js +0 -101
- package/dist/src/integrations/greptile/config.js +0 -14
- package/dist/src/integrations/greptile/index.js +0 -11
- package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
- package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
- package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
- package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
- package/dist/src/integrations/ralph/index.js +0 -17
- package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
- package/dist/src/integrations/ralph/loopmax.js +0 -488
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
- package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
- package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
- package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
- package/scripts/ralph-loop-implementation.js +0 -404
- /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
- /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
- /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
|
@@ -22,6 +22,7 @@ import { ContentCache } from "../core/cache/content-cache.js";
|
|
|
22
22
|
import { getSkillPackRegistry } from "../core/skill-packs/index.js";
|
|
23
23
|
import { ProvenanceStore } from "../core/provenance/provenance-store.js";
|
|
24
24
|
import { scoreConfidence } from "../core/provenance/confidence-scorer.js";
|
|
25
|
+
import { Raindrop } from "raindrop-ai";
|
|
25
26
|
const PROJECT_ROOT = process.env["STACKMEMORY_PROJECT"] || process.cwd();
|
|
26
27
|
const stackmemoryDir = join(PROJECT_ROOT, ".stackmemory");
|
|
27
28
|
if (!existsSync(stackmemoryDir)) {
|
|
@@ -36,6 +37,8 @@ const contentCache = new ContentCache(contentCacheDb);
|
|
|
36
37
|
const provenanceDb = new Database(join(stackmemoryDir, "provenance.db"));
|
|
37
38
|
const provenanceStore = new ProvenanceStore(provenanceDb);
|
|
38
39
|
const packRegistry = getSkillPackRegistry();
|
|
40
|
+
const raindropEndpoint = process.env["RAINDROP_LOCAL_DEBUGGER"] || process.env["RAINDROP_ENDPOINT"];
|
|
41
|
+
const raindrop = raindropEndpoint ? new Raindrop({ endpoint: raindropEndpoint }) : null;
|
|
39
42
|
let _claudeSessionId = null;
|
|
40
43
|
let claudeFrameId = null;
|
|
41
44
|
const TOOLS = [
|
|
@@ -350,92 +353,122 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
350
353
|
]
|
|
351
354
|
};
|
|
352
355
|
}
|
|
356
|
+
const interaction = raindrop?.begin({
|
|
357
|
+
eventId: `mcp-${name}-${Date.now()}`,
|
|
358
|
+
event: name,
|
|
359
|
+
userId: "mcp-server",
|
|
360
|
+
input: JSON.stringify(args).slice(0, 2e3),
|
|
361
|
+
properties: { tool: name, host: "stackmemory-mcp" }
|
|
362
|
+
});
|
|
353
363
|
try {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
364
|
+
const result = await handleTool(name, args);
|
|
365
|
+
const outputText = result.content?.[0]?.text;
|
|
366
|
+
interaction?.finish({ output: outputText?.slice(0, 2e3) });
|
|
367
|
+
return result;
|
|
368
|
+
} catch (error) {
|
|
369
|
+
interaction?.finish({
|
|
370
|
+
output: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
371
|
+
});
|
|
372
|
+
logger.error(
|
|
373
|
+
"MCP tool execution failed",
|
|
374
|
+
error instanceof Error ? error : void 0
|
|
375
|
+
);
|
|
376
|
+
return {
|
|
377
|
+
content: [
|
|
378
|
+
{
|
|
379
|
+
type: "text",
|
|
380
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
363
381
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
382
|
+
]
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
async function handleTool(name, args) {
|
|
387
|
+
switch (name) {
|
|
388
|
+
case "create_task": {
|
|
389
|
+
const taskArgs = args;
|
|
390
|
+
if (!claudeFrameId) {
|
|
391
|
+
claudeFrameId = frameManager.createFrame({
|
|
392
|
+
type: "task",
|
|
393
|
+
name: "Claude AI Session",
|
|
394
|
+
inputs: { source: "mcp", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
370
395
|
});
|
|
371
|
-
if (taskArgs.autoExecute) {
|
|
372
|
-
const session = await agentTaskManager.startTaskSession(
|
|
373
|
-
taskId,
|
|
374
|
-
claudeFrameId
|
|
375
|
-
);
|
|
376
|
-
_claudeSessionId = session.id;
|
|
377
|
-
return {
|
|
378
|
-
content: [
|
|
379
|
-
{
|
|
380
|
-
type: "text",
|
|
381
|
-
text: `Task created: ${taskId}
|
|
382
|
-
Agent session started: ${session.id}
|
|
383
|
-
Ready for execution with ${session.maxTurns} turns available.`
|
|
384
|
-
}
|
|
385
|
-
]
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
return {
|
|
389
|
-
content: [
|
|
390
|
-
{
|
|
391
|
-
type: "text",
|
|
392
|
-
text: `Task created successfully: ${taskId}`
|
|
393
|
-
}
|
|
394
|
-
]
|
|
395
|
-
};
|
|
396
396
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
397
|
+
const taskId = taskStore.createTask({
|
|
398
|
+
title: taskArgs.title,
|
|
399
|
+
description: taskArgs.description,
|
|
400
|
+
priority: taskArgs.priority || "medium",
|
|
401
|
+
frameId: claudeFrameId,
|
|
402
|
+
tags: taskArgs.tags || ["claude-generated"]
|
|
403
|
+
});
|
|
404
|
+
if (taskArgs.autoExecute) {
|
|
406
405
|
const session = await agentTaskManager.startTaskSession(
|
|
407
|
-
|
|
406
|
+
taskId,
|
|
408
407
|
claudeFrameId
|
|
409
408
|
);
|
|
410
|
-
if (execArgs.maxTurns) {
|
|
411
|
-
session.maxTurns = execArgs.maxTurns;
|
|
412
|
-
}
|
|
413
409
|
_claudeSessionId = session.id;
|
|
414
410
|
return {
|
|
415
411
|
content: [
|
|
416
412
|
{
|
|
417
413
|
type: "text",
|
|
418
|
-
text: `
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
Use 'agent_turn' to execute actions.`
|
|
414
|
+
text: `Task created: ${taskId}
|
|
415
|
+
Agent session started: ${session.id}
|
|
416
|
+
Ready for execution with ${session.maxTurns} turns available.`
|
|
422
417
|
}
|
|
423
418
|
]
|
|
424
419
|
};
|
|
425
420
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
421
|
+
return {
|
|
422
|
+
content: [
|
|
423
|
+
{
|
|
424
|
+
type: "text",
|
|
425
|
+
text: `Task created successfully: ${taskId}`
|
|
426
|
+
}
|
|
427
|
+
]
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
case "execute_task": {
|
|
431
|
+
const execArgs = args;
|
|
432
|
+
if (!claudeFrameId) {
|
|
433
|
+
claudeFrameId = frameManager.createFrame({
|
|
434
|
+
type: "task",
|
|
435
|
+
name: "Claude Task Execution",
|
|
436
|
+
inputs: { taskId: execArgs.taskId }
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
const session = await agentTaskManager.startTaskSession(
|
|
440
|
+
execArgs.taskId,
|
|
441
|
+
claudeFrameId
|
|
442
|
+
);
|
|
443
|
+
if (execArgs.maxTurns) {
|
|
444
|
+
session.maxTurns = execArgs.maxTurns;
|
|
445
|
+
}
|
|
446
|
+
_claudeSessionId = session.id;
|
|
447
|
+
return {
|
|
448
|
+
content: [
|
|
449
|
+
{
|
|
450
|
+
type: "text",
|
|
451
|
+
text: `Started agent session: ${session.id}
|
|
452
|
+
Task: ${execArgs.taskId}
|
|
453
|
+
Max turns: ${session.maxTurns}
|
|
454
|
+
Use 'agent_turn' to execute actions.`
|
|
455
|
+
}
|
|
456
|
+
]
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
case "agent_turn": {
|
|
460
|
+
const turnArgs = args;
|
|
461
|
+
const result = await agentTaskManager.executeTurn(
|
|
462
|
+
turnArgs.sessionId,
|
|
463
|
+
turnArgs.action,
|
|
464
|
+
turnArgs.context || {}
|
|
465
|
+
);
|
|
466
|
+
const verificationSummary = result.verificationResults.map((v) => `${v.passed ? "\u2713" : "\u2717"} ${v.verifierId}: ${v.message}`).join("\n");
|
|
467
|
+
return {
|
|
468
|
+
content: [
|
|
469
|
+
{
|
|
470
|
+
type: "text",
|
|
471
|
+
text: `Turn executed:
|
|
439
472
|
Success: ${result.success}
|
|
440
473
|
Should Continue: ${result.shouldContinue}
|
|
441
474
|
|
|
@@ -444,393 +477,384 @@ ${result.feedback}
|
|
|
444
477
|
|
|
445
478
|
Verifications:
|
|
446
479
|
${verificationSummary}`
|
|
447
|
-
}
|
|
448
|
-
]
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
case "task_status": {
|
|
452
|
-
const statusArgs = args;
|
|
453
|
-
if (statusArgs.taskId) {
|
|
454
|
-
const task = taskStore.getTask(statusArgs.taskId);
|
|
455
|
-
if (!task) {
|
|
456
|
-
return {
|
|
457
|
-
content: [
|
|
458
|
-
{ type: "text", text: `Task ${statusArgs.taskId} not found` }
|
|
459
|
-
]
|
|
460
|
-
};
|
|
461
480
|
}
|
|
481
|
+
]
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
case "task_status": {
|
|
485
|
+
const statusArgs = args;
|
|
486
|
+
if (statusArgs.taskId) {
|
|
487
|
+
const task = taskStore.getTask(statusArgs.taskId);
|
|
488
|
+
if (!task) {
|
|
462
489
|
return {
|
|
463
490
|
content: [
|
|
464
|
-
{
|
|
465
|
-
type: "text",
|
|
466
|
-
text: `Task: ${task.title}
|
|
467
|
-
Status: ${task.status}
|
|
468
|
-
Priority: ${task.priority}
|
|
469
|
-
Created: ${new Date(task.created_at * 1e3).toLocaleString()}
|
|
470
|
-
Description: ${task.description || "N/A"}`
|
|
471
|
-
}
|
|
491
|
+
{ type: "text", text: `Task ${statusArgs.taskId} not found` }
|
|
472
492
|
]
|
|
473
493
|
};
|
|
474
494
|
}
|
|
475
|
-
const activeTasks = taskStore.getActiveTasks();
|
|
476
|
-
const taskList = activeTasks.map((t) => `- ${t.id}: ${t.title} (${t.status}, ${t.priority})`).join("\n");
|
|
477
495
|
return {
|
|
478
496
|
content: [
|
|
479
497
|
{
|
|
480
498
|
type: "text",
|
|
481
|
-
text: `
|
|
482
|
-
${
|
|
499
|
+
text: `Task: ${task.title}
|
|
500
|
+
Status: ${task.status}
|
|
501
|
+
Priority: ${task.priority}
|
|
502
|
+
Created: ${new Date(task.created_at * 1e3).toLocaleString()}
|
|
503
|
+
Description: ${task.description || "N/A"}`
|
|
483
504
|
}
|
|
484
505
|
]
|
|
485
506
|
};
|
|
486
507
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
type: "task",
|
|
492
|
-
name: "Claude Context",
|
|
493
|
-
inputs: { source: "mcp" }
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
const eventId = frameManager.addEvent(
|
|
497
|
-
"observation",
|
|
508
|
+
const activeTasks = taskStore.getActiveTasks();
|
|
509
|
+
const taskList = activeTasks.map((t) => `- ${t.id}: ${t.title} (${t.status}, ${t.priority})`).join("\n");
|
|
510
|
+
return {
|
|
511
|
+
content: [
|
|
498
512
|
{
|
|
499
|
-
type:
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
};
|
|
513
|
+
type: "text",
|
|
514
|
+
text: `Active tasks (${activeTasks.length}):
|
|
515
|
+
${taskList || "No active tasks"}`
|
|
516
|
+
}
|
|
517
|
+
]
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
case "save_context": {
|
|
521
|
+
const saveArgs = args;
|
|
522
|
+
if (!claudeFrameId) {
|
|
523
|
+
claudeFrameId = frameManager.createFrame({
|
|
524
|
+
type: "task",
|
|
525
|
+
name: "Claude Context",
|
|
526
|
+
inputs: { source: "mcp" }
|
|
527
|
+
});
|
|
515
528
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
529
|
+
const eventId = frameManager.addEvent(
|
|
530
|
+
"observation",
|
|
531
|
+
{
|
|
532
|
+
type: saveArgs.type,
|
|
533
|
+
content: saveArgs.content,
|
|
534
|
+
importance: saveArgs.importance || 0.5,
|
|
535
|
+
source: "claude-mcp",
|
|
536
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
537
|
+
},
|
|
538
|
+
claudeFrameId
|
|
539
|
+
);
|
|
540
|
+
return {
|
|
541
|
+
content: [
|
|
542
|
+
{
|
|
543
|
+
type: "text",
|
|
544
|
+
text: `Context saved to frame ${claudeFrameId} as event ${eventId}`
|
|
545
|
+
}
|
|
546
|
+
]
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
case "load_context": {
|
|
550
|
+
const loadArgs = args;
|
|
551
|
+
const frames = frameManager.getActiveFramePath();
|
|
552
|
+
const limit = loadArgs.limit || 10;
|
|
553
|
+
const events = loadArgs.frameId ? frameManager.getFrameEvents(loadArgs.frameId, limit) : [];
|
|
554
|
+
const contextText = frames.map(
|
|
555
|
+
(frame) => `[Frame ${frame.type}] ${frame.name}: ${frame.digest_text || "No digest"}`
|
|
556
|
+
).concat(
|
|
557
|
+
events.map(
|
|
558
|
+
(event) => `[Event ${event.event_type}] ${new Date(event.ts).toLocaleString()}: ${JSON.stringify(
|
|
559
|
+
event.payload
|
|
560
|
+
).substring(0, 100)}...`
|
|
561
|
+
)
|
|
562
|
+
).join("\n\n");
|
|
563
|
+
return {
|
|
564
|
+
content: [
|
|
565
|
+
{
|
|
566
|
+
type: "text",
|
|
567
|
+
text: `Query: ${loadArgs.query}
|
|
568
|
+
Found ${frames.length} frames and ${events.length} events:
|
|
569
|
+
|
|
570
|
+
${contextText || "No matching context found"}`
|
|
571
|
+
}
|
|
572
|
+
]
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
case "breakdown_task": {
|
|
576
|
+
const breakdownArgs = args;
|
|
577
|
+
const task = taskStore.getTask(breakdownArgs.taskId);
|
|
578
|
+
if (!task) {
|
|
530
579
|
return {
|
|
531
580
|
content: [
|
|
532
581
|
{
|
|
533
582
|
type: "text",
|
|
534
|
-
text: `
|
|
535
|
-
Found ${frames.length} frames and ${events.length} events:
|
|
536
|
-
|
|
537
|
-
${contextText || "No matching context found"}`
|
|
583
|
+
text: `Task ${breakdownArgs.taskId} not found`
|
|
538
584
|
}
|
|
539
585
|
]
|
|
540
586
|
};
|
|
541
587
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
`2. Design: ${task.title} - Create implementation plan (2 turns)`,
|
|
555
|
-
`3. Implement: ${task.title} - Build core functionality (5 turns)`,
|
|
556
|
-
`4. Test: ${task.title} - Validate and verify (3 turns)`,
|
|
557
|
-
`5. Polish: ${task.title} - Documentation and cleanup (1 turn)`
|
|
558
|
-
].join("\n");
|
|
559
|
-
return {
|
|
560
|
-
content: [
|
|
561
|
-
{
|
|
562
|
-
type: "text",
|
|
563
|
-
text: `Task breakdown for: ${task.title}
|
|
588
|
+
const subtasks = [
|
|
589
|
+
`1. Analyze: ${task.title} - Understand requirements (2 turns)`,
|
|
590
|
+
`2. Design: ${task.title} - Create implementation plan (2 turns)`,
|
|
591
|
+
`3. Implement: ${task.title} - Build core functionality (5 turns)`,
|
|
592
|
+
`4. Test: ${task.title} - Validate and verify (3 turns)`,
|
|
593
|
+
`5. Polish: ${task.title} - Documentation and cleanup (1 turn)`
|
|
594
|
+
].join("\n");
|
|
595
|
+
return {
|
|
596
|
+
content: [
|
|
597
|
+
{
|
|
598
|
+
type: "text",
|
|
599
|
+
text: `Task breakdown for: ${task.title}
|
|
564
600
|
|
|
565
601
|
${subtasks}
|
|
566
602
|
|
|
567
603
|
Total estimated turns: 13`
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
604
|
+
}
|
|
605
|
+
]
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
case "list_active_sessions": {
|
|
609
|
+
const sessions = agentTaskManager.getActiveSessions();
|
|
610
|
+
const sessionList = sessions.map(
|
|
611
|
+
(s) => `- ${s.sessionId}: Task ${s.taskId} (Turn ${s.turnCount}, ${s.status})`
|
|
612
|
+
).join("\n");
|
|
613
|
+
return {
|
|
614
|
+
content: [
|
|
615
|
+
{
|
|
616
|
+
type: "text",
|
|
617
|
+
text: `Active sessions (${sessions.length}):
|
|
618
|
+
${sessionList || "No active sessions"}`
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
case "retry_session": {
|
|
624
|
+
const retryArgs = args;
|
|
625
|
+
const newSession = await agentTaskManager.retrySession(
|
|
626
|
+
retryArgs.sessionId
|
|
627
|
+
);
|
|
628
|
+
if (!newSession) {
|
|
577
629
|
return {
|
|
578
630
|
content: [
|
|
579
631
|
{
|
|
580
632
|
type: "text",
|
|
581
|
-
text:
|
|
582
|
-
${sessionList || "No active sessions"}`
|
|
633
|
+
text: "Cannot retry session (max retries reached or session is still active)"
|
|
583
634
|
}
|
|
584
635
|
]
|
|
585
636
|
};
|
|
586
637
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
638
|
+
_claudeSessionId = newSession.id;
|
|
639
|
+
return {
|
|
640
|
+
content: [
|
|
641
|
+
{
|
|
642
|
+
type: "text",
|
|
643
|
+
text: `Retry session started: ${newSession.id}
|
|
644
|
+
Task: ${newSession.taskId}
|
|
645
|
+
Incorporating learned context from previous attempts.`
|
|
646
|
+
}
|
|
647
|
+
]
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
case "session_feedback": {
|
|
651
|
+
const feedbackArgs = args;
|
|
652
|
+
const sessions = agentTaskManager.getActiveSessions();
|
|
653
|
+
const session = sessions.find(
|
|
654
|
+
(s) => s.sessionId === feedbackArgs.sessionId
|
|
655
|
+
);
|
|
656
|
+
if (!session) {
|
|
603
657
|
return {
|
|
604
658
|
content: [
|
|
605
659
|
{
|
|
606
660
|
type: "text",
|
|
607
|
-
text: `
|
|
608
|
-
Task: ${newSession.taskId}
|
|
609
|
-
Incorporating learned context from previous attempts.`
|
|
661
|
+
text: `Session ${feedbackArgs.sessionId} not found or not active`
|
|
610
662
|
}
|
|
611
663
|
]
|
|
612
664
|
};
|
|
613
665
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
);
|
|
620
|
-
if (!session) {
|
|
621
|
-
return {
|
|
622
|
-
content: [
|
|
623
|
-
{
|
|
624
|
-
type: "text",
|
|
625
|
-
text: `Session ${feedbackArgs.sessionId} not found or not active`
|
|
626
|
-
}
|
|
627
|
-
]
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
return {
|
|
631
|
-
content: [
|
|
632
|
-
{
|
|
633
|
-
type: "text",
|
|
634
|
-
text: `Session ${feedbackArgs.sessionId}:
|
|
666
|
+
return {
|
|
667
|
+
content: [
|
|
668
|
+
{
|
|
669
|
+
type: "text",
|
|
670
|
+
text: `Session ${feedbackArgs.sessionId}:
|
|
635
671
|
Turn: ${session.turnCount}
|
|
636
672
|
Status: ${session.status}
|
|
637
673
|
|
|
638
674
|
Ready for next action.`
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
return {
|
|
651
|
-
content: [
|
|
652
|
-
{
|
|
653
|
-
type: "text",
|
|
654
|
-
text: result.hit ? `Cache HIT (hash: ${result.hash.slice(0, 12)}...). Tokens saved: ${result.tokensSaved}. Total hits: ${result.entry?.hitCount ?? 0}.` : `Cache MISS (hash: ${result.hash.slice(0, 12)}...). Content cached for future dedup.`
|
|
655
|
-
}
|
|
656
|
-
]
|
|
657
|
-
};
|
|
675
|
+
}
|
|
676
|
+
]
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
// ── Content Cache handlers ──────────────────────────────────────
|
|
680
|
+
case "cache_lookup": {
|
|
681
|
+
const { content, source } = args;
|
|
682
|
+
const result = contentCache.lookup(content, source ?? "mcp");
|
|
683
|
+
if (!result.hit) {
|
|
684
|
+
contentCache.put(content, source ?? "mcp");
|
|
658
685
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
{
|
|
664
|
-
|
|
665
|
-
|
|
686
|
+
return {
|
|
687
|
+
content: [
|
|
688
|
+
{
|
|
689
|
+
type: "text",
|
|
690
|
+
text: result.hit ? `Cache HIT (hash: ${result.hash.slice(0, 12)}...). Tokens saved: ${result.tokensSaved}. Total hits: ${result.entry?.hitCount ?? 0}.` : `Cache MISS (hash: ${result.hash.slice(0, 12)}...). Content cached for future dedup.`
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
case "cache_stats": {
|
|
696
|
+
const stats = contentCache.getStats();
|
|
697
|
+
return {
|
|
698
|
+
content: [
|
|
699
|
+
{
|
|
700
|
+
type: "text",
|
|
701
|
+
text: `Content Cache Stats:
|
|
666
702
|
Entries: ${stats.totalEntries}
|
|
667
703
|
Tokens cached: ${stats.totalTokensCached}
|
|
668
704
|
Tokens saved: ${stats.totalTokensSaved}
|
|
669
705
|
Hit rate: ${(stats.hitRate * 100).toFixed(1)}%
|
|
670
706
|
Top sources: ${stats.topSources.map((s) => `${s.source} (${s.tokensSaved} saved)`).join(", ") || "none"}`
|
|
671
|
-
|
|
672
|
-
|
|
707
|
+
}
|
|
708
|
+
]
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
// ── Skill Pack handlers ─────────────────────────────────────────
|
|
712
|
+
case "pack_list": {
|
|
713
|
+
const { namespace } = args;
|
|
714
|
+
const packs = packRegistry.list(namespace ? { namespace } : void 0);
|
|
715
|
+
if (packs.length === 0) {
|
|
716
|
+
return {
|
|
717
|
+
content: [{ type: "text", text: "No packs installed." }]
|
|
673
718
|
};
|
|
674
719
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
const list = packs.map((p) => {
|
|
685
|
-
const tools = p.manifest.mcp?.tools?.length ?? 0;
|
|
686
|
-
return `- ${p.manifest.name} v${p.manifest.version} (${tools} tools) \u2014 ${p.manifest.description}`;
|
|
687
|
-
}).join("\n");
|
|
688
|
-
return {
|
|
689
|
-
content: [
|
|
690
|
-
{
|
|
691
|
-
type: "text",
|
|
692
|
-
text: `${packs.length} pack(s) installed:
|
|
720
|
+
const list = packs.map((p) => {
|
|
721
|
+
const tools = p.manifest.mcp?.tools?.length ?? 0;
|
|
722
|
+
return `- ${p.manifest.name} v${p.manifest.version} (${tools} tools) \u2014 ${p.manifest.description}`;
|
|
723
|
+
}).join("\n");
|
|
724
|
+
return {
|
|
725
|
+
content: [
|
|
726
|
+
{
|
|
727
|
+
type: "text",
|
|
728
|
+
text: `${packs.length} pack(s) installed:
|
|
693
729
|
${list}`
|
|
694
|
-
|
|
695
|
-
|
|
730
|
+
}
|
|
731
|
+
]
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
case "pack_search": {
|
|
735
|
+
const { query } = args;
|
|
736
|
+
const results = packRegistry.search(query);
|
|
737
|
+
if (results.length === 0) {
|
|
738
|
+
return {
|
|
739
|
+
content: [{ type: "text", text: `No packs matching "${query}".` }]
|
|
696
740
|
};
|
|
697
741
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
const list = results.map(
|
|
707
|
-
(p) => `- ${p.manifest.name} v${p.manifest.version} \u2014 ${p.manifest.description}`
|
|
708
|
-
).join("\n");
|
|
709
|
-
return {
|
|
710
|
-
content: [
|
|
711
|
-
{
|
|
712
|
-
type: "text",
|
|
713
|
-
text: `${results.length} result(s) for "${query}":
|
|
742
|
+
const list = results.map(
|
|
743
|
+
(p) => `- ${p.manifest.name} v${p.manifest.version} \u2014 ${p.manifest.description}`
|
|
744
|
+
).join("\n");
|
|
745
|
+
return {
|
|
746
|
+
content: [
|
|
747
|
+
{
|
|
748
|
+
type: "text",
|
|
749
|
+
text: `${results.length} result(s) for "${query}":
|
|
714
750
|
${list}`
|
|
715
|
-
|
|
716
|
-
|
|
751
|
+
}
|
|
752
|
+
]
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
case "pack_get": {
|
|
756
|
+
const { name: packName } = args;
|
|
757
|
+
const pack = packRegistry.get(packName);
|
|
758
|
+
if (!pack) {
|
|
759
|
+
return {
|
|
760
|
+
content: [{ type: "text", text: `Pack "${packName}" not found.` }]
|
|
717
761
|
};
|
|
718
762
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (!pack) {
|
|
723
|
-
return {
|
|
724
|
-
content: [{ type: "text", text: `Pack "${packName}" not found.` }]
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
const m = pack.manifest;
|
|
728
|
-
const tools = m.mcp?.tools?.map((t) => ` - ${t.name}: ${t.description}`).join("\n");
|
|
729
|
-
const examples = m.examples?.map((e) => ` Q: ${e.input}
|
|
763
|
+
const m = pack.manifest;
|
|
764
|
+
const tools = m.mcp?.tools?.map((t) => ` - ${t.name}: ${t.description}`).join("\n");
|
|
765
|
+
const examples = m.examples?.map((e) => ` Q: ${e.input}
|
|
730
766
|
A: ${e.output}`).join("\n\n");
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
767
|
+
return {
|
|
768
|
+
content: [
|
|
769
|
+
{
|
|
770
|
+
type: "text",
|
|
771
|
+
text: [
|
|
772
|
+
`${m.name} v${m.version}`,
|
|
773
|
+
m.description,
|
|
774
|
+
`Author: ${m.author} | License: ${m.license}`,
|
|
775
|
+
`Runtime: ${m.runtime?.type ?? "local"}`,
|
|
776
|
+
tools ? `
|
|
741
777
|
MCP Tools:
|
|
742
778
|
${tools}` : "",
|
|
743
|
-
|
|
779
|
+
examples ? `
|
|
744
780
|
Examples:
|
|
745
781
|
${examples}` : "",
|
|
746
|
-
|
|
782
|
+
pack.instructions ? `
|
|
747
783
|
Instructions:
|
|
748
784
|
${pack.instructions}` : ""
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
785
|
+
].filter(Boolean).join("\n")
|
|
786
|
+
}
|
|
787
|
+
]
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
// ── Provenance handlers ─────────────────────────────────────────
|
|
791
|
+
case "record_trace": {
|
|
792
|
+
const a = args;
|
|
793
|
+
const event = {
|
|
794
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
795
|
+
traceId: a["traceId"],
|
|
796
|
+
sessionId: a["sessionId"],
|
|
797
|
+
tenantId: a["tenantId"],
|
|
798
|
+
operation: a["operation"],
|
|
799
|
+
actor: {
|
|
800
|
+
host: a["host"] || "unknown",
|
|
801
|
+
agent: "mcp",
|
|
802
|
+
user: "unknown"
|
|
803
|
+
},
|
|
804
|
+
inputs: a["inputs"] ?? null,
|
|
805
|
+
outputs: a["outputs"] ?? null,
|
|
806
|
+
tokensIn: a["tokensIn"] || 0,
|
|
807
|
+
tokensOut: a["tokensOut"] || 0,
|
|
808
|
+
costUsd: a["costUsd"] || 0,
|
|
809
|
+
provenance: {
|
|
810
|
+
sources: (a["sources"] || []).map(
|
|
811
|
+
(s) => ({
|
|
775
812
|
system: s["system"] ?? "",
|
|
776
813
|
externalId: s["externalId"] ?? "",
|
|
777
814
|
url: s["url"],
|
|
778
815
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
779
|
-
})
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
};
|
|
784
|
-
if (a["parentTraceId"]) {
|
|
785
|
-
event.parentTraceId = a["parentTraceId"];
|
|
786
|
-
}
|
|
787
|
-
if (a["score"] !== void 0) {
|
|
788
|
-
event.score = a["score"];
|
|
816
|
+
})
|
|
817
|
+
),
|
|
818
|
+
derivation: [],
|
|
819
|
+
confidence: a["confidence"] || 0
|
|
789
820
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
provenanceStore.record(event);
|
|
794
|
-
return {
|
|
795
|
-
content: [
|
|
796
|
-
{
|
|
797
|
-
type: "text",
|
|
798
|
-
text: `Trace recorded: ${event.traceId} (${event.operation}, confidence: ${event.provenance.confidence})`
|
|
799
|
-
}
|
|
800
|
-
]
|
|
801
|
-
};
|
|
821
|
+
};
|
|
822
|
+
if (a["parentTraceId"]) {
|
|
823
|
+
event.parentTraceId = a["parentTraceId"];
|
|
802
824
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
const result = scoreConfidence(text, { actor, replyCount });
|
|
806
|
-
return {
|
|
807
|
-
content: [
|
|
808
|
-
{
|
|
809
|
-
type: "text",
|
|
810
|
-
text: `Confidence: ${result.confidence.toFixed(2)} (${result.classification})
|
|
811
|
-
Signals: ${JSON.stringify(result.signals)}`
|
|
812
|
-
}
|
|
813
|
-
]
|
|
814
|
-
};
|
|
825
|
+
if (a["score"] !== void 0) {
|
|
826
|
+
event.score = a["score"];
|
|
815
827
|
}
|
|
816
|
-
|
|
817
|
-
|
|
828
|
+
if (a["feedback"]) {
|
|
829
|
+
event.feedback = a["feedback"];
|
|
830
|
+
}
|
|
831
|
+
provenanceStore.record(event);
|
|
832
|
+
return {
|
|
833
|
+
content: [
|
|
834
|
+
{
|
|
835
|
+
type: "text",
|
|
836
|
+
text: `Trace recorded: ${event.traceId} (${event.operation}, confidence: ${event.provenance.confidence})`
|
|
837
|
+
}
|
|
838
|
+
]
|
|
839
|
+
};
|
|
818
840
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
}
|
|
841
|
+
case "score_confidence": {
|
|
842
|
+
const { text, actor, replyCount } = args;
|
|
843
|
+
const result = scoreConfidence(text, { actor, replyCount });
|
|
844
|
+
return {
|
|
845
|
+
content: [
|
|
846
|
+
{
|
|
847
|
+
type: "text",
|
|
848
|
+
text: `Confidence: ${result.confidence.toFixed(2)} (${result.classification})
|
|
849
|
+
Signals: ${JSON.stringify(result.signals)}`
|
|
850
|
+
}
|
|
851
|
+
]
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
default:
|
|
855
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
832
856
|
}
|
|
833
|
-
}
|
|
857
|
+
}
|
|
834
858
|
async function main() {
|
|
835
859
|
const transport = new StdioServerTransport();
|
|
836
860
|
await server.connect(transport);
|
|
@@ -854,6 +878,7 @@ process.on("SIGINT", async () => {
|
|
|
854
878
|
);
|
|
855
879
|
}
|
|
856
880
|
}
|
|
881
|
+
raindrop?.forceFlush();
|
|
857
882
|
db.close();
|
|
858
883
|
contentCacheDb.close();
|
|
859
884
|
provenanceDb.close();
|