@stackmemoryai/stackmemory 1.10.5 → 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 (225) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +107 -24
  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/claude-sm.js +266 -84
  11. package/dist/src/cli/codex-sm.js +225 -33
  12. package/dist/src/cli/commands/bench.js +209 -2
  13. package/dist/src/cli/commands/brain.js +206 -0
  14. package/dist/src/cli/commands/cache.js +126 -0
  15. package/dist/src/cli/commands/company-os.js +184 -0
  16. package/dist/src/cli/commands/context.js +5 -0
  17. package/dist/src/cli/commands/daemon.js +41 -0
  18. package/dist/src/cli/commands/handoff.js +40 -9
  19. package/dist/src/cli/commands/onboard.js +70 -3
  20. package/dist/src/cli/commands/operator.js +127 -0
  21. package/dist/src/cli/commands/optimize.js +117 -0
  22. package/dist/src/cli/commands/orchestrate.js +232 -5
  23. package/dist/src/cli/commands/orchestrator.js +315 -26
  24. package/dist/src/cli/commands/pack.js +322 -0
  25. package/dist/src/cli/commands/patterns.js +254 -0
  26. package/dist/src/cli/commands/portal.js +161 -0
  27. package/dist/src/cli/commands/scaffold.js +92 -0
  28. package/dist/src/cli/commands/search.js +40 -1
  29. package/dist/src/cli/commands/setup.js +178 -11
  30. package/dist/src/cli/commands/skills.js +10 -1
  31. package/dist/src/cli/commands/state.js +265 -0
  32. package/dist/src/cli/commands/sync.js +253 -0
  33. package/dist/src/cli/commands/tasks.js +130 -1
  34. package/dist/src/cli/commands/vision.js +221 -0
  35. package/dist/src/cli/gemini-sm.js +19 -29
  36. package/dist/src/cli/hermes-sm.js +224 -0
  37. package/dist/src/cli/index.js +105 -39
  38. package/dist/src/cli/opencode-sm.js +38 -21
  39. package/dist/src/cli/utils/determinism-watcher.js +66 -0
  40. package/dist/src/cli/utils/real-cli-bin.js +116 -0
  41. package/dist/src/core/brain/brain-store.js +187 -0
  42. package/dist/src/core/brain/brain-sync.js +193 -0
  43. package/dist/src/core/brain/index.js +78 -0
  44. package/dist/src/core/brain/types.js +10 -0
  45. package/dist/src/core/cache/content-cache.js +238 -0
  46. package/dist/src/{integrations/diffmem → core/cache}/index.js +5 -5
  47. package/dist/src/core/cache/token-estimator.js +39 -0
  48. package/dist/src/core/config/feature-flags.js +2 -6
  49. package/dist/src/core/context/frame-database.js +79 -27
  50. package/dist/src/core/context/recursive-context-manager.js +1 -1
  51. package/dist/src/core/context/rehydration.js +2 -1
  52. package/dist/src/core/cross-search/cross-project-search.js +269 -0
  53. package/dist/src/core/cross-search/index.js +10 -0
  54. package/dist/src/core/database/sqlite-adapter.js +14 -84
  55. package/dist/src/core/extensions/provider-adapter.js +5 -0
  56. package/dist/src/core/models/model-router.js +54 -2
  57. package/dist/src/core/models/provider-pricing.js +58 -4
  58. package/dist/src/core/monitoring/logger.js +2 -1
  59. package/dist/src/core/optimization/trace-optimizer.js +413 -0
  60. package/dist/src/core/patterns/index.js +22 -0
  61. package/dist/src/core/patterns/pattern-applier.js +39 -0
  62. package/dist/src/core/patterns/pattern-observer.js +157 -0
  63. package/dist/src/core/patterns/pattern-store.js +259 -0
  64. package/dist/src/core/patterns/types.js +19 -0
  65. package/dist/src/core/provenance/confidence-scorer.js +128 -0
  66. package/dist/src/core/provenance/index.js +40 -0
  67. package/dist/src/core/provenance/provenance-store.js +194 -0
  68. package/dist/src/core/provenance/types.js +82 -0
  69. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  70. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  71. package/dist/src/core/session/project-handoff.js +64 -0
  72. package/dist/src/core/session/session-manager.js +28 -0
  73. package/dist/src/core/shared-state/canonical-store.js +564 -0
  74. package/dist/src/core/skill-packs/index.js +18 -0
  75. package/dist/src/core/skill-packs/parser.js +42 -0
  76. package/dist/src/core/skill-packs/registry.js +224 -0
  77. package/dist/src/core/skill-packs/types.js +79 -0
  78. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  79. package/dist/src/core/storage/cloud-sync.js +574 -0
  80. package/dist/src/core/storage/two-tier-storage.js +5 -1
  81. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  82. package/dist/src/core/tasks/md-task-parser.js +138 -0
  83. package/dist/src/core/trace/trace-event-store.js +282 -0
  84. package/dist/src/core/vision/index.js +27 -0
  85. package/dist/src/core/vision/signals.js +79 -0
  86. package/dist/src/core/vision/types.js +22 -0
  87. package/dist/src/core/vision/vision-file.js +146 -0
  88. package/dist/src/core/vision/vision-loop.js +220 -0
  89. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  90. package/dist/src/daemon/daemon-config.js +52 -0
  91. package/dist/src/daemon/services/desire-path-service.js +566 -0
  92. package/dist/src/daemon/services/github-service.js +126 -0
  93. package/dist/src/daemon/services/research-stream-service.js +320 -0
  94. package/dist/src/daemon/services/telemetry-service.js +192 -0
  95. package/dist/src/daemon/unified-daemon.js +58 -1
  96. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  97. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  98. package/dist/src/features/operator/adapter-factory.js +62 -0
  99. package/dist/src/features/operator/browser-adapter.js +109 -0
  100. package/dist/src/features/operator/desktop-adapter.js +125 -0
  101. package/dist/src/features/operator/index.js +39 -0
  102. package/dist/src/features/operator/llm-decision.js +137 -0
  103. package/dist/src/features/operator/operator-logger.js +92 -0
  104. package/dist/src/features/operator/overnight-runner.js +327 -0
  105. package/dist/src/features/operator/screen-adapter.js +91 -0
  106. package/dist/src/features/operator/session-manager.js +127 -0
  107. package/dist/src/features/operator/state-machine.js +227 -0
  108. package/dist/src/features/operator/task-queue.js +81 -0
  109. package/dist/src/features/portal/index.js +26 -0
  110. package/dist/src/features/portal/server.js +240 -0
  111. package/dist/src/features/portal/types.js +14 -0
  112. package/dist/src/features/portal/ui.js +195 -0
  113. package/dist/src/features/sweep/pty-wrapper.js +13 -5
  114. package/dist/src/features/tasks/task-aware-context.js +2 -1
  115. package/dist/src/features/tui/simple-monitor.js +0 -23
  116. package/dist/src/features/tui/swarm-monitor.js +8 -66
  117. package/dist/src/features/web/client/hooks/use-socket.js +12 -0
  118. package/dist/src/{core/merge/index.js → features/web/client/lib/utils.js} +8 -4
  119. package/dist/src/features/web/client/next-env.d.js +4 -0
  120. package/dist/src/features/web/client/stores/session-store.js +12 -0
  121. package/dist/src/features/web/server/gcp-billing.js +76 -0
  122. package/dist/src/features/web/server/index.js +10 -0
  123. package/dist/src/features/web/server/spend-calculator.js +228 -0
  124. package/dist/src/hooks/schemas.js +6 -1
  125. package/dist/src/integrations/anthropic/client.js +3 -2
  126. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  127. package/dist/src/integrations/claude-code/subagent-client.js +307 -11
  128. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  129. package/dist/src/integrations/github/pr-state.js +158 -0
  130. package/dist/src/integrations/linear/client.js +4 -1
  131. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  132. package/dist/src/integrations/linear/webhook-server.js +18 -22
  133. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  134. package/dist/src/integrations/mcp/handlers/index.js +40 -84
  135. package/dist/src/integrations/mcp/server.js +542 -641
  136. package/dist/src/integrations/mcp/tool-alias-registry.js +297 -0
  137. package/dist/src/integrations/mcp/tool-definitions.js +152 -682
  138. package/dist/src/mcp/stackmemory-mcp-server.js +571 -231
  139. package/dist/src/orchestrators/multimodal/determinism.js +244 -0
  140. package/dist/src/orchestrators/multimodal/harness.js +149 -78
  141. package/dist/src/orchestrators/multimodal/providers.js +44 -3
  142. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  143. package/dist/src/utils/hook-installer.js +0 -8
  144. package/dist/src/utils/process-cleanup.js +1 -7
  145. package/docs/README.md +42 -0
  146. package/docs/guides/README_INSTALL.md +208 -0
  147. package/package.json +27 -9
  148. package/packs/coding/python-fastapi/instructions.md +60 -0
  149. package/packs/coding/python-fastapi/pack.yaml +28 -0
  150. package/packs/coding/typescript-react/instructions.md +47 -0
  151. package/packs/coding/typescript-react/pack.yaml +28 -0
  152. package/packs/core/commands/capture.md +32 -0
  153. package/packs/core/commands/learn.md +73 -0
  154. package/packs/core/commands/next.md +36 -0
  155. package/packs/core/commands/restart.md +58 -0
  156. package/packs/core/commands/restore.md +29 -0
  157. package/packs/core/commands/start.md +57 -0
  158. package/packs/core/commands/stop.md +65 -0
  159. package/packs/core/commands/summary.md +40 -0
  160. package/packs/core/manifest.json +24 -0
  161. package/packs/ops/decision-recovery/instructions.md +65 -0
  162. package/packs/ops/decision-recovery/pack.yaml +89 -0
  163. package/scripts/claude-code-wrapper.sh +11 -0
  164. package/scripts/claude-sm-setup.sh +12 -1
  165. package/scripts/codex-wrapper.sh +11 -0
  166. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  167. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  168. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  169. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  170. package/scripts/hooks/cleanup-shell.sh +12 -1
  171. package/scripts/hooks/task-complete.sh +12 -1
  172. package/scripts/install-code-execution-hooks.sh +12 -1
  173. package/scripts/install-sweep-hook.sh +12 -0
  174. package/scripts/install.sh +11 -0
  175. package/scripts/opencode-wrapper.sh +11 -0
  176. package/scripts/portal/cloud-init.yaml +69 -0
  177. package/scripts/portal/setup.sh +69 -0
  178. package/scripts/portal/stackmemory-portal.service +34 -0
  179. package/scripts/setup-claude-integration.sh +12 -1
  180. package/scripts/smoke-init-db.sh +23 -0
  181. package/scripts/stackmemory-daemon.sh +11 -0
  182. package/scripts/verify-dist.cjs +11 -4
  183. package/dist/src/cli/commands/ralph.js +0 -1053
  184. package/dist/src/cli/commands/team.js +0 -168
  185. package/dist/src/core/context/shared-context-layer.js +0 -620
  186. package/dist/src/core/context/stack-merge-resolver.js +0 -748
  187. package/dist/src/core/merge/conflict-detector.js +0 -430
  188. package/dist/src/core/merge/resolution-engine.js +0 -557
  189. package/dist/src/core/merge/stack-diff.js +0 -531
  190. package/dist/src/core/merge/unified-merge-resolver.js +0 -302
  191. package/dist/src/hooks/diffmem-hooks.js +0 -376
  192. package/dist/src/integrations/diffmem/client.js +0 -208
  193. package/dist/src/integrations/diffmem/config.js +0 -14
  194. package/dist/src/integrations/greptile/client.js +0 -101
  195. package/dist/src/integrations/greptile/config.js +0 -14
  196. package/dist/src/integrations/greptile/index.js +0 -11
  197. package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
  198. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  199. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  200. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  201. package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
  202. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  203. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  204. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -391
  205. package/dist/src/integrations/ralph/index.js +0 -17
  206. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -435
  207. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  208. package/dist/src/integrations/ralph/loopmax.js +0 -488
  209. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  210. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  211. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  212. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  213. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  214. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  215. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  216. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  217. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  218. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  219. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1007
  220. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  221. package/scripts/ralph-loop-implementation.js +0 -404
  222. /package/dist/src/core/{merge → cache}/types.js +0 -0
  223. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  224. /package/dist/src/{integrations/greptile/types.js → core/trace/trace-event.js} +0 -0
  225. /package/dist/src/{integrations/ralph → features/operator}/types.js +0 -0
@@ -18,6 +18,11 @@ import {
18
18
  import { FrameManager } from "../core/context/index.js";
19
19
  import { AgentTaskManager } from "../agents/core/agent-task-manager.js";
20
20
  import { logger } from "../core/monitoring/logger.js";
21
+ import { ContentCache } from "../core/cache/content-cache.js";
22
+ import { getSkillPackRegistry } from "../core/skill-packs/index.js";
23
+ import { ProvenanceStore } from "../core/provenance/provenance-store.js";
24
+ import { scoreConfidence } from "../core/provenance/confidence-scorer.js";
25
+ import { Raindrop } from "raindrop-ai";
21
26
  const PROJECT_ROOT = process.env["STACKMEMORY_PROJECT"] || process.cwd();
22
27
  const stackmemoryDir = join(PROJECT_ROOT, ".stackmemory");
23
28
  if (!existsSync(stackmemoryDir)) {
@@ -27,6 +32,13 @@ const db = new Database(join(stackmemoryDir, "cache.db"));
27
32
  const taskStore = new LinearTaskManager(PROJECT_ROOT, db);
28
33
  const frameManager = new FrameManager(db, PROJECT_ROOT, void 0);
29
34
  const agentTaskManager = new AgentTaskManager(taskStore, frameManager);
35
+ const contentCacheDb = new Database(join(stackmemoryDir, "content-cache.db"));
36
+ const contentCache = new ContentCache(contentCacheDb);
37
+ const provenanceDb = new Database(join(stackmemoryDir, "provenance.db"));
38
+ const provenanceStore = new ProvenanceStore(provenanceDb);
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;
30
42
  let _claudeSessionId = null;
31
43
  let claudeFrameId = null;
32
44
  const TOOLS = [
@@ -182,6 +194,137 @@ const TOOLS = [
182
194
  },
183
195
  required: ["sessionId"]
184
196
  }
197
+ },
198
+ // ── Content Cache ───────────────────────────────────────────────────
199
+ {
200
+ name: "cache_lookup",
201
+ description: "Check if content has been seen before. Returns cache hit/miss and token savings.",
202
+ inputSchema: {
203
+ type: "object",
204
+ properties: {
205
+ content: { type: "string", description: "Content to check/cache" },
206
+ source: {
207
+ type: "string",
208
+ description: 'Where this content came from (e.g. "file:src/index.ts")'
209
+ }
210
+ },
211
+ required: ["content"]
212
+ }
213
+ },
214
+ {
215
+ name: "cache_stats",
216
+ description: "Get content cache statistics: total entries, tokens cached, tokens saved, hit rate.",
217
+ inputSchema: {
218
+ type: "object",
219
+ properties: {}
220
+ }
221
+ },
222
+ // ── Skill Packs ─────────────────────────────────────────────────────
223
+ {
224
+ name: "pack_list",
225
+ description: "List installed skill packs, optionally filtered by namespace.",
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: {
229
+ namespace: {
230
+ type: "string",
231
+ description: 'Filter by namespace (e.g. "coding", "ops")'
232
+ }
233
+ }
234
+ }
235
+ },
236
+ {
237
+ name: "pack_search",
238
+ description: "Search installed skill packs by keyword.",
239
+ inputSchema: {
240
+ type: "object",
241
+ properties: {
242
+ query: { type: "string", description: "Search keyword" }
243
+ },
244
+ required: ["query"]
245
+ }
246
+ },
247
+ {
248
+ name: "pack_get",
249
+ description: "Get full details of a skill pack including instructions and MCP tools.",
250
+ inputSchema: {
251
+ type: "object",
252
+ properties: {
253
+ name: {
254
+ type: "string",
255
+ description: 'Pack name (e.g. "coding/typescript-react")'
256
+ }
257
+ },
258
+ required: ["name"]
259
+ }
260
+ },
261
+ // ── Provenance ──────────────────────────────────────────────────────
262
+ {
263
+ name: "record_trace",
264
+ description: "Record a provenance-tracked trace event with actor, operation, and source lineage.",
265
+ inputSchema: {
266
+ type: "object",
267
+ properties: {
268
+ traceId: { type: "string", description: "Unique trace ID" },
269
+ sessionId: { type: "string", description: "Session ID" },
270
+ tenantId: { type: "string", description: "Tenant ID" },
271
+ operation: {
272
+ type: "string",
273
+ description: 'What happened (e.g. "query", "decision", "edit")'
274
+ },
275
+ host: {
276
+ type: "string",
277
+ description: 'Agent host (e.g. "claude-code", "cursor")'
278
+ },
279
+ inputs: { type: "object", description: "Operation inputs" },
280
+ outputs: { type: "object", description: "Operation outputs" },
281
+ tokensIn: { type: "number", description: "Input tokens" },
282
+ tokensOut: { type: "number", description: "Output tokens" },
283
+ costUsd: { type: "number", description: "Cost in USD" },
284
+ parentTraceId: { type: "string", description: "Parent trace ID" },
285
+ score: { type: "number", description: "Numeric evaluation score" },
286
+ feedback: {
287
+ type: "string",
288
+ description: "Textual feedback for optimization"
289
+ },
290
+ confidence: {
291
+ type: "number",
292
+ description: "Confidence level (0-1)",
293
+ minimum: 0,
294
+ maximum: 1
295
+ },
296
+ sources: {
297
+ type: "array",
298
+ items: {
299
+ type: "object",
300
+ properties: {
301
+ system: { type: "string" },
302
+ externalId: { type: "string" },
303
+ url: { type: "string" }
304
+ },
305
+ required: ["system", "externalId"]
306
+ },
307
+ description: "Source references for provenance"
308
+ }
309
+ },
310
+ required: ["traceId", "sessionId", "tenantId", "operation"]
311
+ }
312
+ },
313
+ {
314
+ name: "score_confidence",
315
+ description: "Score text for decision confidence. Returns confidence (0-1), signals, and classification (accept/review/discard).",
316
+ inputSchema: {
317
+ type: "object",
318
+ properties: {
319
+ text: { type: "string", description: "Text to score" },
320
+ actor: { type: "string", description: "Who said it (boosts score)" },
321
+ replyCount: {
322
+ type: "number",
323
+ description: "Thread reply count (boosts if >2)"
324
+ }
325
+ },
326
+ required: ["text"]
327
+ }
185
328
  }
186
329
  ];
187
330
  const server = new Server(
@@ -210,92 +353,122 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
210
353
  ]
211
354
  };
212
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
+ });
213
363
  try {
214
- switch (name) {
215
- case "create_task": {
216
- const taskArgs = args;
217
- if (!claudeFrameId) {
218
- claudeFrameId = frameManager.createFrame({
219
- type: "task",
220
- name: "Claude AI Session",
221
- inputs: { source: "mcp", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
222
- });
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)}`
223
381
  }
224
- const taskId = taskStore.createTask({
225
- title: taskArgs.title,
226
- description: taskArgs.description,
227
- priority: taskArgs.priority || "medium",
228
- frameId: claudeFrameId,
229
- 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() }
230
395
  });
231
- if (taskArgs.autoExecute) {
232
- const session = await agentTaskManager.startTaskSession(
233
- taskId,
234
- claudeFrameId
235
- );
236
- _claudeSessionId = session.id;
237
- return {
238
- content: [
239
- {
240
- type: "text",
241
- text: `Task created: ${taskId}
242
- Agent session started: ${session.id}
243
- Ready for execution with ${session.maxTurns} turns available.`
244
- }
245
- ]
246
- };
247
- }
248
- return {
249
- content: [
250
- {
251
- type: "text",
252
- text: `Task created successfully: ${taskId}`
253
- }
254
- ]
255
- };
256
396
  }
257
- case "execute_task": {
258
- const execArgs = args;
259
- if (!claudeFrameId) {
260
- claudeFrameId = frameManager.createFrame({
261
- type: "task",
262
- name: "Claude Task Execution",
263
- inputs: { taskId: execArgs.taskId }
264
- });
265
- }
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) {
266
405
  const session = await agentTaskManager.startTaskSession(
267
- execArgs.taskId,
406
+ taskId,
268
407
  claudeFrameId
269
408
  );
270
- if (execArgs.maxTurns) {
271
- session.maxTurns = execArgs.maxTurns;
272
- }
273
409
  _claudeSessionId = session.id;
274
410
  return {
275
411
  content: [
276
412
  {
277
413
  type: "text",
278
- text: `Started agent session: ${session.id}
279
- Task: ${execArgs.taskId}
280
- Max turns: ${session.maxTurns}
281
- 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.`
282
417
  }
283
418
  ]
284
419
  };
285
420
  }
286
- case "agent_turn": {
287
- const turnArgs = args;
288
- const result = await agentTaskManager.executeTurn(
289
- turnArgs.sessionId,
290
- turnArgs.action,
291
- turnArgs.context || {}
292
- );
293
- const verificationSummary = result.verificationResults.map((v) => `${v.passed ? "\u2713" : "\u2717"} ${v.verifierId}: ${v.message}`).join("\n");
294
- return {
295
- content: [
296
- {
297
- type: "text",
298
- 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:
299
472
  Success: ${result.success}
300
473
  Should Continue: ${result.shouldContinue}
301
474
 
@@ -304,220 +477,384 @@ ${result.feedback}
304
477
 
305
478
  Verifications:
306
479
  ${verificationSummary}`
307
- }
308
- ]
309
- };
310
- }
311
- case "task_status": {
312
- const statusArgs = args;
313
- if (statusArgs.taskId) {
314
- const task = taskStore.getTask(statusArgs.taskId);
315
- if (!task) {
316
- return {
317
- content: [
318
- { type: "text", text: `Task ${statusArgs.taskId} not found` }
319
- ]
320
- };
321
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) {
322
489
  return {
323
490
  content: [
324
- {
325
- type: "text",
326
- text: `Task: ${task.title}
327
- Status: ${task.status}
328
- Priority: ${task.priority}
329
- Created: ${new Date(task.created_at * 1e3).toLocaleString()}
330
- Description: ${task.description || "N/A"}`
331
- }
491
+ { type: "text", text: `Task ${statusArgs.taskId} not found` }
332
492
  ]
333
493
  };
334
494
  }
335
- const activeTasks = taskStore.getActiveTasks();
336
- const taskList = activeTasks.map((t) => `- ${t.id}: ${t.title} (${t.status}, ${t.priority})`).join("\n");
337
495
  return {
338
496
  content: [
339
497
  {
340
498
  type: "text",
341
- text: `Active tasks (${activeTasks.length}):
342
- ${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"}`
343
504
  }
344
505
  ]
345
506
  };
346
507
  }
347
- case "save_context": {
348
- const saveArgs = args;
349
- if (!claudeFrameId) {
350
- claudeFrameId = frameManager.createFrame({
351
- type: "task",
352
- name: "Claude Context",
353
- inputs: { source: "mcp" }
354
- });
355
- }
356
- const eventId = frameManager.addEvent(
357
- "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: [
358
512
  {
359
- type: saveArgs.type,
360
- content: saveArgs.content,
361
- importance: saveArgs.importance || 0.5,
362
- source: "claude-mcp",
363
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
364
- },
365
- claudeFrameId
366
- );
367
- return {
368
- content: [
369
- {
370
- type: "text",
371
- text: `Context saved to frame ${claudeFrameId} as event ${eventId}`
372
- }
373
- ]
374
- };
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
+ });
375
528
  }
376
- case "load_context": {
377
- const loadArgs = args;
378
- const frames = frameManager.getActiveFramePath();
379
- const limit = loadArgs.limit || 10;
380
- const events = loadArgs.frameId ? frameManager.getFrameEvents(loadArgs.frameId, limit) : [];
381
- const contextText = frames.map(
382
- (frame) => `[Frame ${frame.type}] ${frame.name}: ${frame.digest_text || "No digest"}`
383
- ).concat(
384
- events.map(
385
- (event) => `[Event ${event.event_type}] ${new Date(event.ts).toLocaleString()}: ${JSON.stringify(
386
- event.payload
387
- ).substring(0, 100)}...`
388
- )
389
- ).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) {
390
579
  return {
391
580
  content: [
392
581
  {
393
582
  type: "text",
394
- text: `Query: ${loadArgs.query}
395
- Found ${frames.length} frames and ${events.length} events:
396
-
397
- ${contextText || "No matching context found"}`
583
+ text: `Task ${breakdownArgs.taskId} not found`
398
584
  }
399
585
  ]
400
586
  };
401
587
  }
402
- case "breakdown_task": {
403
- const breakdownArgs = args;
404
- const task = taskStore.getTask(breakdownArgs.taskId);
405
- if (!task) {
406
- return {
407
- content: [
408
- { type: "text", text: `Task ${breakdownArgs.taskId} not found` }
409
- ]
410
- };
411
- }
412
- const subtasks = [
413
- `1. Analyze: ${task.title} - Understand requirements (2 turns)`,
414
- `2. Design: ${task.title} - Create implementation plan (2 turns)`,
415
- `3. Implement: ${task.title} - Build core functionality (5 turns)`,
416
- `4. Test: ${task.title} - Validate and verify (3 turns)`,
417
- `5. Polish: ${task.title} - Documentation and cleanup (1 turn)`
418
- ].join("\n");
419
- return {
420
- content: [
421
- {
422
- type: "text",
423
- 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}
424
600
 
425
601
  ${subtasks}
426
602
 
427
603
  Total estimated turns: 13`
428
- }
429
- ]
430
- };
431
- }
432
- case "list_active_sessions": {
433
- const sessions = agentTaskManager.getActiveSessions();
434
- const sessionList = sessions.map(
435
- (s) => `- ${s.sessionId}: Task ${s.taskId} (Turn ${s.turnCount}, ${s.status})`
436
- ).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) {
437
629
  return {
438
630
  content: [
439
631
  {
440
632
  type: "text",
441
- text: `Active sessions (${sessions.length}):
442
- ${sessionList || "No active sessions"}`
633
+ text: "Cannot retry session (max retries reached or session is still active)"
443
634
  }
444
635
  ]
445
636
  };
446
637
  }
447
- case "retry_session": {
448
- const retryArgs = args;
449
- const newSession = await agentTaskManager.retrySession(
450
- retryArgs.sessionId
451
- );
452
- if (!newSession) {
453
- return {
454
- content: [
455
- {
456
- type: "text",
457
- text: "Cannot retry session (max retries reached or session is still active)"
458
- }
459
- ]
460
- };
461
- }
462
- _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) {
463
657
  return {
464
658
  content: [
465
659
  {
466
660
  type: "text",
467
- text: `Retry session started: ${newSession.id}
468
- Task: ${newSession.taskId}
469
- Incorporating learned context from previous attempts.`
661
+ text: `Session ${feedbackArgs.sessionId} not found or not active`
470
662
  }
471
663
  ]
472
664
  };
473
665
  }
474
- case "session_feedback": {
475
- const feedbackArgs = args;
476
- const sessions = agentTaskManager.getActiveSessions();
477
- const session = sessions.find(
478
- (s) => s.sessionId === feedbackArgs.sessionId
479
- );
480
- if (!session) {
481
- return {
482
- content: [
483
- {
484
- type: "text",
485
- text: `Session ${feedbackArgs.sessionId} not found or not active`
486
- }
487
- ]
488
- };
489
- }
490
- return {
491
- content: [
492
- {
493
- type: "text",
494
- text: `Session ${feedbackArgs.sessionId}:
666
+ return {
667
+ content: [
668
+ {
669
+ type: "text",
670
+ text: `Session ${feedbackArgs.sessionId}:
495
671
  Turn: ${session.turnCount}
496
672
  Status: ${session.status}
497
673
 
498
674
  Ready for next action.`
499
- }
500
- ]
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");
685
+ }
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:
702
+ Entries: ${stats.totalEntries}
703
+ Tokens cached: ${stats.totalTokensCached}
704
+ Tokens saved: ${stats.totalTokensSaved}
705
+ Hit rate: ${(stats.hitRate * 100).toFixed(1)}%
706
+ Top sources: ${stats.topSources.map((s) => `${s.source} (${s.tokensSaved} saved)`).join(", ") || "none"}`
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." }]
501
718
  };
502
719
  }
503
- default:
504
- throw new Error(`Unknown tool: ${name}`);
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:
729
+ ${list}`
730
+ }
731
+ ]
732
+ };
505
733
  }
506
- } catch (error) {
507
- logger.error(
508
- "MCP tool execution failed",
509
- error instanceof Error ? error : void 0
510
- );
511
- return {
512
- content: [
513
- {
514
- type: "text",
515
- text: `Error: ${error instanceof Error ? error.message : String(error)}`
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}".` }]
740
+ };
741
+ }
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}":
750
+ ${list}`
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.` }]
761
+ };
762
+ }
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}
766
+ A: ${e.output}`).join("\n\n");
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 ? `
777
+ MCP Tools:
778
+ ${tools}` : "",
779
+ examples ? `
780
+ Examples:
781
+ ${examples}` : "",
782
+ pack.instructions ? `
783
+ Instructions:
784
+ ${pack.instructions}` : ""
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) => ({
812
+ system: s["system"] ?? "",
813
+ externalId: s["externalId"] ?? "",
814
+ url: s["url"],
815
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
816
+ })
817
+ ),
818
+ derivation: [],
819
+ confidence: a["confidence"] || 0
516
820
  }
517
- ]
518
- };
821
+ };
822
+ if (a["parentTraceId"]) {
823
+ event.parentTraceId = a["parentTraceId"];
824
+ }
825
+ if (a["score"] !== void 0) {
826
+ event.score = a["score"];
827
+ }
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
+ };
840
+ }
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}`);
519
856
  }
520
- });
857
+ }
521
858
  async function main() {
522
859
  const transport = new StdioServerTransport();
523
860
  await server.connect(transport);
@@ -541,7 +878,10 @@ process.on("SIGINT", async () => {
541
878
  );
542
879
  }
543
880
  }
881
+ raindrop?.forceFlush();
544
882
  db.close();
883
+ contentCacheDb.close();
884
+ provenanceDb.close();
545
885
  process.exit(0);
546
886
  });
547
887
  main().catch((error) => {