@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.
Files changed (162) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +3 -1
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/codex-sm.js +51 -11
  11. package/dist/src/cli/commands/brain.js +206 -0
  12. package/dist/src/cli/commands/company-os.js +184 -0
  13. package/dist/src/cli/commands/context.js +5 -0
  14. package/dist/src/cli/commands/operator.js +127 -0
  15. package/dist/src/cli/commands/orchestrate.js +2 -0
  16. package/dist/src/cli/commands/orchestrator.js +3 -2
  17. package/dist/src/cli/commands/patterns.js +254 -0
  18. package/dist/src/cli/commands/portal.js +161 -0
  19. package/dist/src/cli/commands/scaffold.js +92 -0
  20. package/dist/src/cli/commands/setup.js +1 -4
  21. package/dist/src/cli/commands/sync.js +253 -0
  22. package/dist/src/cli/commands/tasks.js +130 -1
  23. package/dist/src/cli/commands/vision.js +221 -0
  24. package/dist/src/cli/hermes-sm.js +224 -0
  25. package/dist/src/cli/index.js +15 -10
  26. package/dist/src/cli/utils/real-cli-bin.js +72 -0
  27. package/dist/src/core/brain/brain-store.js +187 -0
  28. package/dist/src/core/brain/brain-sync.js +193 -0
  29. package/dist/src/core/brain/index.js +78 -0
  30. package/dist/src/core/brain/types.js +10 -0
  31. package/dist/src/core/cache/token-estimator.js +24 -1
  32. package/dist/src/core/config/feature-flags.js +2 -6
  33. package/dist/src/core/context/frame-database.js +44 -0
  34. package/dist/src/core/context/recursive-context-manager.js +1 -1
  35. package/dist/src/core/context/rehydration.js +2 -1
  36. package/dist/src/core/database/sqlite-adapter.js +14 -1
  37. package/dist/src/core/models/model-router.js +33 -1
  38. package/dist/src/core/models/provider-pricing.js +58 -4
  39. package/dist/src/core/patterns/index.js +22 -0
  40. package/dist/src/core/patterns/pattern-applier.js +39 -0
  41. package/dist/src/core/patterns/pattern-observer.js +157 -0
  42. package/dist/src/core/patterns/pattern-store.js +259 -0
  43. package/dist/src/core/patterns/types.js +19 -0
  44. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  45. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  46. package/dist/src/core/skill-packs/types.js +14 -1
  47. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  48. package/dist/src/core/storage/cloud-sync.js +574 -0
  49. package/dist/src/core/storage/two-tier-storage.js +5 -1
  50. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  51. package/dist/src/core/tasks/md-task-parser.js +138 -0
  52. package/dist/src/core/vision/index.js +27 -0
  53. package/dist/src/core/vision/signals.js +79 -0
  54. package/dist/src/core/vision/types.js +22 -0
  55. package/dist/src/core/vision/vision-file.js +146 -0
  56. package/dist/src/core/vision/vision-loop.js +220 -0
  57. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  58. package/dist/src/daemon/daemon-config.js +45 -0
  59. package/dist/src/daemon/services/desire-path-service.js +566 -0
  60. package/dist/src/daemon/services/research-stream-service.js +320 -0
  61. package/dist/src/daemon/services/telemetry-service.js +192 -0
  62. package/dist/src/daemon/unified-daemon.js +28 -1
  63. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  64. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  65. package/dist/src/features/operator/adapter-factory.js +62 -0
  66. package/dist/src/features/operator/browser-adapter.js +109 -0
  67. package/dist/src/features/operator/desktop-adapter.js +125 -0
  68. package/dist/src/features/operator/index.js +39 -0
  69. package/dist/src/features/operator/llm-decision.js +137 -0
  70. package/dist/src/features/operator/operator-logger.js +92 -0
  71. package/dist/src/features/operator/overnight-runner.js +327 -0
  72. package/dist/src/features/operator/screen-adapter.js +91 -0
  73. package/dist/src/features/operator/session-manager.js +127 -0
  74. package/dist/src/features/operator/state-machine.js +227 -0
  75. package/dist/src/features/operator/task-queue.js +81 -0
  76. package/dist/src/features/portal/index.js +26 -0
  77. package/dist/src/features/portal/server.js +240 -0
  78. package/dist/src/features/portal/types.js +14 -0
  79. package/dist/src/features/portal/ui.js +195 -0
  80. package/dist/src/features/tasks/task-aware-context.js +2 -1
  81. package/dist/src/features/tui/simple-monitor.js +0 -23
  82. package/dist/src/features/tui/swarm-monitor.js +8 -66
  83. package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
  84. package/dist/src/features/web/client/lib/utils.js +12 -0
  85. package/dist/src/features/web/client/stores/session-store.js +12 -0
  86. package/dist/src/features/web/server/gcp-billing.js +76 -0
  87. package/dist/src/features/web/server/index.js +10 -0
  88. package/dist/src/features/web/server/spend-calculator.js +228 -0
  89. package/dist/src/hooks/schemas.js +4 -1
  90. package/dist/src/integrations/anthropic/client.js +3 -2
  91. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  92. package/dist/src/integrations/claude-code/subagent-client.js +218 -11
  93. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  94. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  95. package/dist/src/integrations/linear/webhook-server.js +18 -22
  96. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  97. package/dist/src/integrations/mcp/handlers/index.js +27 -52
  98. package/dist/src/integrations/mcp/server.js +122 -335
  99. package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
  100. package/dist/src/integrations/mcp/tool-definitions.js +111 -510
  101. package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
  102. package/dist/src/orchestrators/multimodal/determinism.js +2 -1
  103. package/dist/src/orchestrators/multimodal/harness.js +2 -1
  104. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  105. package/dist/src/utils/process-cleanup.js +1 -7
  106. package/docs/README.md +42 -0
  107. package/docs/guides/README_INSTALL.md +208 -0
  108. package/package.json +18 -9
  109. package/scripts/claude-code-wrapper.sh +11 -0
  110. package/scripts/claude-sm-setup.sh +12 -1
  111. package/scripts/codex-wrapper.sh +11 -0
  112. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  113. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  114. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  115. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  116. package/scripts/hooks/cleanup-shell.sh +12 -1
  117. package/scripts/hooks/task-complete.sh +12 -1
  118. package/scripts/install-code-execution-hooks.sh +12 -1
  119. package/scripts/install-sweep-hook.sh +12 -0
  120. package/scripts/install.sh +11 -0
  121. package/scripts/opencode-wrapper.sh +11 -0
  122. package/scripts/portal/cloud-init.yaml +69 -0
  123. package/scripts/portal/setup.sh +69 -0
  124. package/scripts/portal/stackmemory-portal.service +34 -0
  125. package/scripts/setup-claude-integration.sh +12 -1
  126. package/scripts/smoke-init-db.sh +23 -0
  127. package/scripts/stackmemory-daemon.sh +11 -0
  128. package/scripts/verify-dist.cjs +11 -4
  129. package/dist/src/cli/commands/ralph.js +0 -1053
  130. package/dist/src/hooks/diffmem-hooks.js +0 -376
  131. package/dist/src/integrations/diffmem/client.js +0 -208
  132. package/dist/src/integrations/diffmem/config.js +0 -14
  133. package/dist/src/integrations/greptile/client.js +0 -101
  134. package/dist/src/integrations/greptile/config.js +0 -14
  135. package/dist/src/integrations/greptile/index.js +0 -11
  136. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
  137. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  138. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  139. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  140. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  141. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  142. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
  143. package/dist/src/integrations/ralph/index.js +0 -17
  144. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
  145. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  146. package/dist/src/integrations/ralph/loopmax.js +0 -488
  147. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  148. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  149. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  150. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  151. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  152. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  153. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  154. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  155. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  156. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  157. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
  158. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  159. package/scripts/ralph-loop-implementation.js +0 -404
  160. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  161. /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
  162. /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
- switch (name) {
355
- case "create_task": {
356
- const taskArgs = args;
357
- if (!claudeFrameId) {
358
- claudeFrameId = frameManager.createFrame({
359
- type: "task",
360
- name: "Claude AI Session",
361
- inputs: { source: "mcp", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
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
- const taskId = taskStore.createTask({
365
- title: taskArgs.title,
366
- description: taskArgs.description,
367
- priority: taskArgs.priority || "medium",
368
- frameId: claudeFrameId,
369
- tags: taskArgs.tags || ["claude-generated"]
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
- case "execute_task": {
398
- const execArgs = args;
399
- if (!claudeFrameId) {
400
- claudeFrameId = frameManager.createFrame({
401
- type: "task",
402
- name: "Claude Task Execution",
403
- inputs: { taskId: execArgs.taskId }
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
- execArgs.taskId,
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: `Started agent session: ${session.id}
419
- Task: ${execArgs.taskId}
420
- Max turns: ${session.maxTurns}
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
- case "agent_turn": {
427
- const turnArgs = args;
428
- const result = await agentTaskManager.executeTurn(
429
- turnArgs.sessionId,
430
- turnArgs.action,
431
- turnArgs.context || {}
432
- );
433
- const verificationSummary = result.verificationResults.map((v) => `${v.passed ? "\u2713" : "\u2717"} ${v.verifierId}: ${v.message}`).join("\n");
434
- return {
435
- content: [
436
- {
437
- type: "text",
438
- text: `Turn executed:
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: `Active tasks (${activeTasks.length}):
482
- ${taskList || "No active tasks"}`
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
- case "save_context": {
488
- const saveArgs = args;
489
- if (!claudeFrameId) {
490
- claudeFrameId = frameManager.createFrame({
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: saveArgs.type,
500
- content: saveArgs.content,
501
- importance: saveArgs.importance || 0.5,
502
- source: "claude-mcp",
503
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
504
- },
505
- claudeFrameId
506
- );
507
- return {
508
- content: [
509
- {
510
- type: "text",
511
- text: `Context saved to frame ${claudeFrameId} as event ${eventId}`
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
- case "load_context": {
517
- const loadArgs = args;
518
- const frames = frameManager.getActiveFramePath();
519
- const limit = loadArgs.limit || 10;
520
- const events = loadArgs.frameId ? frameManager.getFrameEvents(loadArgs.frameId, limit) : [];
521
- const contextText = frames.map(
522
- (frame) => `[Frame ${frame.type}] ${frame.name}: ${frame.digest_text || "No digest"}`
523
- ).concat(
524
- events.map(
525
- (event) => `[Event ${event.event_type}] ${new Date(event.ts).toLocaleString()}: ${JSON.stringify(
526
- event.payload
527
- ).substring(0, 100)}...`
528
- )
529
- ).join("\n\n");
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: `Query: ${loadArgs.query}
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
- case "breakdown_task": {
543
- const breakdownArgs = args;
544
- const task = taskStore.getTask(breakdownArgs.taskId);
545
- if (!task) {
546
- return {
547
- content: [
548
- { type: "text", text: `Task ${breakdownArgs.taskId} not found` }
549
- ]
550
- };
551
- }
552
- const subtasks = [
553
- `1. Analyze: ${task.title} - Understand requirements (2 turns)`,
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
- case "list_active_sessions": {
573
- const sessions = agentTaskManager.getActiveSessions();
574
- const sessionList = sessions.map(
575
- (s) => `- ${s.sessionId}: Task ${s.taskId} (Turn ${s.turnCount}, ${s.status})`
576
- ).join("\n");
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: `Active sessions (${sessions.length}):
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
- case "retry_session": {
588
- const retryArgs = args;
589
- const newSession = await agentTaskManager.retrySession(
590
- retryArgs.sessionId
591
- );
592
- if (!newSession) {
593
- return {
594
- content: [
595
- {
596
- type: "text",
597
- text: "Cannot retry session (max retries reached or session is still active)"
598
- }
599
- ]
600
- };
601
- }
602
- _claudeSessionId = newSession.id;
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: `Retry session started: ${newSession.id}
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
- case "session_feedback": {
615
- const feedbackArgs = args;
616
- const sessions = agentTaskManager.getActiveSessions();
617
- const session = sessions.find(
618
- (s) => s.sessionId === feedbackArgs.sessionId
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
- // ── Content Cache handlers ──────────────────────────────────────
644
- case "cache_lookup": {
645
- const { content, source } = args;
646
- const result = contentCache.lookup(content, source ?? "mcp");
647
- if (!result.hit) {
648
- contentCache.put(content, source ?? "mcp");
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
- case "cache_stats": {
660
- const stats = contentCache.getStats();
661
- return {
662
- content: [
663
- {
664
- type: "text",
665
- text: `Content Cache Stats:
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
- // ── Skill Pack handlers ─────────────────────────────────────────
676
- case "pack_list": {
677
- const { namespace } = args;
678
- const packs = packRegistry.list(namespace ? { namespace } : void 0);
679
- if (packs.length === 0) {
680
- return {
681
- content: [{ type: "text", text: "No packs installed." }]
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
- case "pack_search": {
699
- const { query } = args;
700
- const results = packRegistry.search(query);
701
- if (results.length === 0) {
702
- return {
703
- content: [{ type: "text", text: `No packs matching "${query}".` }]
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
- case "pack_get": {
720
- const { name: packName } = args;
721
- const pack = packRegistry.get(packName);
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
- return {
732
- content: [
733
- {
734
- type: "text",
735
- text: [
736
- `${m.name} v${m.version}`,
737
- m.description,
738
- `Author: ${m.author} | License: ${m.license}`,
739
- `Runtime: ${m.runtime?.type ?? "local"}`,
740
- tools ? `
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
- examples ? `
779
+ examples ? `
744
780
  Examples:
745
781
  ${examples}` : "",
746
- pack.instructions ? `
782
+ pack.instructions ? `
747
783
  Instructions:
748
784
  ${pack.instructions}` : ""
749
- ].filter(Boolean).join("\n")
750
- }
751
- ]
752
- };
753
- }
754
- // ── Provenance handlers ─────────────────────────────────────────
755
- case "record_trace": {
756
- const a = args;
757
- const event = {
758
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
759
- traceId: a["traceId"],
760
- sessionId: a["sessionId"],
761
- tenantId: a["tenantId"],
762
- operation: a["operation"],
763
- actor: {
764
- host: a["host"] || "unknown",
765
- agent: "mcp",
766
- user: "unknown"
767
- },
768
- inputs: a["inputs"] ?? null,
769
- outputs: a["outputs"] ?? null,
770
- tokensIn: a["tokensIn"] || 0,
771
- tokensOut: a["tokensOut"] || 0,
772
- costUsd: a["costUsd"] || 0,
773
- provenance: {
774
- sources: (a["sources"] || []).map((s) => ({
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
- derivation: [],
781
- confidence: a["confidence"] || 0
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
- if (a["feedback"]) {
791
- event.feedback = a["feedback"];
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
- case "score_confidence": {
804
- const { text, actor, replyCount } = args;
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
- default:
817
- throw new Error(`Unknown tool: ${name}`);
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
- } catch (error) {
820
- logger.error(
821
- "MCP tool execution failed",
822
- error instanceof Error ? error : void 0
823
- );
824
- return {
825
- content: [
826
- {
827
- type: "text",
828
- text: `Error: ${error instanceof Error ? error.message : String(error)}`
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();