@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
@@ -1,302 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { v4 as uuidv4 } from "uuid";
6
- import { ConflictDetector } from "./conflict-detector.js";
7
- import { StackDiffVisualizer } from "./stack-diff.js";
8
- import { ResolutionEngine } from "./resolution-engine.js";
9
- import { logger } from "../monitoring/logger.js";
10
- class UnifiedMergeResolver {
11
- conflictDetector;
12
- diffVisualizer;
13
- resolutionEngine;
14
- activeSessions = /* @__PURE__ */ new Map();
15
- rollbackSnapshots = /* @__PURE__ */ new Map();
16
- statistics = {
17
- totalConflicts: 0,
18
- resolvedConflicts: 0,
19
- averageResolutionTime: 0,
20
- successRate: 0,
21
- rollbackCount: 0
22
- };
23
- constructor() {
24
- this.conflictDetector = new ConflictDetector();
25
- this.diffVisualizer = new StackDiffVisualizer();
26
- this.resolutionEngine = new ResolutionEngine();
27
- logger.debug("UnifiedMergeResolver initialized");
28
- }
29
- /**
30
- * Start a new merge session with automatic conflict detection
31
- */
32
- async startMergeSession(stack1, stack2, options) {
33
- const sessionId = `unified-merge-${Date.now()}-${uuidv4().substring(0, 8)}`;
34
- const conflicts = this.conflictDetector.detectConflicts(stack1, stack2);
35
- let rollbackPoint;
36
- if (options?.preserveRollback !== false) {
37
- rollbackPoint = this.createRollbackSnapshot(sessionId, stack1, stack2);
38
- }
39
- const session = {
40
- sessionId,
41
- stack1,
42
- stack2,
43
- conflicts,
44
- status: "analyzing",
45
- rollbackPoint,
46
- startedAt: Date.now(),
47
- metadata: {
48
- totalFrames: stack1.frames.length + stack2.frames.length,
49
- conflictCount: conflicts.length,
50
- resolvedCount: 0
51
- }
52
- };
53
- this.activeSessions.set(sessionId, session);
54
- this.statistics.totalConflicts += conflicts.length;
55
- logger.info(`Merge session started: ${sessionId}`, {
56
- stack1Id: stack1.id,
57
- stack2Id: stack2.id,
58
- conflictCount: conflicts.length
59
- });
60
- if (options?.autoResolve && conflicts.length > 0 && options.context) {
61
- const defaultStrategy = options.strategy || "ai_suggest";
62
- await this.resolveConflicts(sessionId, defaultStrategy, options.context);
63
- }
64
- return sessionId;
65
- }
66
- /**
67
- * Generate a preview of the merge result
68
- */
69
- async generatePreview(sessionId, strategy) {
70
- const session = this.activeSessions.get(sessionId);
71
- if (!session) {
72
- throw new Error(`Session not found: ${sessionId}`);
73
- }
74
- const preview = this.diffVisualizer.generateMergePreview(
75
- session.stack1,
76
- session.stack2,
77
- strategy
78
- );
79
- session.preview = preview;
80
- session.status = "preview";
81
- session.metadata.strategyUsed = strategy;
82
- this.activeSessions.set(sessionId, session);
83
- logger.info(`Preview generated for session: ${sessionId}`, {
84
- mergedFrameCount: preview.mergedFrames.length,
85
- estimatedSuccess: preview.estimatedSuccess
86
- });
87
- return preview;
88
- }
89
- /**
90
- * Resolve conflicts using the specified strategy
91
- */
92
- async resolveConflicts(sessionId, strategy, context) {
93
- const session = this.activeSessions.get(sessionId);
94
- if (!session) {
95
- throw new Error(`Session not found: ${sessionId}`);
96
- }
97
- session.status = "resolving";
98
- try {
99
- const result = await this.resolutionEngine.resolveConflicts(
100
- session.stack1,
101
- session.stack2,
102
- strategy,
103
- context
104
- );
105
- session.resolution = result.resolution;
106
- session.status = result.success ? "completed" : "failed";
107
- session.completedAt = Date.now();
108
- session.metadata.resolvedCount = session.conflicts.filter(
109
- (c) => c.resolution !== void 0
110
- ).length;
111
- session.metadata.strategyUsed = strategy;
112
- this.activeSessions.set(sessionId, session);
113
- if (result.success) {
114
- this.statistics.resolvedConflicts += session.metadata.resolvedCount;
115
- this.updateSuccessRate();
116
- this.updateAverageResolutionTime(session);
117
- }
118
- logger.info(`Conflicts resolved for session: ${sessionId}`, {
119
- success: result.success,
120
- strategy,
121
- resolvedCount: session.metadata.resolvedCount
122
- });
123
- return result;
124
- } catch (error) {
125
- session.status = "failed";
126
- this.activeSessions.set(sessionId, session);
127
- logger.error(
128
- `Failed to resolve conflicts for session: ${sessionId}`,
129
- error
130
- );
131
- throw error;
132
- }
133
- }
134
- /**
135
- * Rollback a merge to its original state
136
- */
137
- async rollback(sessionId) {
138
- const session = this.activeSessions.get(sessionId);
139
- if (!session || !session.rollbackPoint) {
140
- logger.warn(`Cannot rollback session: ${sessionId} - no rollback point`);
141
- return false;
142
- }
143
- const snapshot = this.rollbackSnapshots.get(session.rollbackPoint);
144
- if (!snapshot) {
145
- logger.error(`Rollback snapshot not found: ${session.rollbackPoint}`);
146
- return false;
147
- }
148
- session.stack1 = snapshot.stack1;
149
- session.stack2 = snapshot.stack2;
150
- session.status = "rolled_back";
151
- session.resolution = void 0;
152
- session.conflicts = this.conflictDetector.detectConflicts(
153
- snapshot.stack1,
154
- snapshot.stack2
155
- );
156
- session.metadata.resolvedCount = 0;
157
- this.activeSessions.set(sessionId, session);
158
- this.statistics.rollbackCount++;
159
- logger.info(`Session rolled back: ${sessionId}`);
160
- return true;
161
- }
162
- /**
163
- * Get merge session details
164
- */
165
- getSession(sessionId) {
166
- return this.activeSessions.get(sessionId);
167
- }
168
- /**
169
- * List all active merge sessions
170
- */
171
- listActiveSessions() {
172
- return Array.from(this.activeSessions.values()).filter(
173
- (s) => s.status !== "completed" && s.status !== "rolled_back" && s.status !== "failed"
174
- );
175
- }
176
- /**
177
- * Get merge statistics
178
- */
179
- getStatistics() {
180
- return { ...this.statistics };
181
- }
182
- /**
183
- * Analyze parallel solutions across stacks
184
- */
185
- analyzeParallelSolutions(frames) {
186
- const solutions = this.conflictDetector.analyzeParallelSolutions(frames);
187
- const recommendations = [];
188
- if (solutions.length > 1) {
189
- const grouped = /* @__PURE__ */ new Map();
190
- for (const sol of solutions) {
191
- const key = sol.approach.toLowerCase();
192
- if (!grouped.has(key)) {
193
- grouped.set(key, []);
194
- }
195
- grouped.get(key).push(sol);
196
- }
197
- for (const [approach, group] of grouped) {
198
- if (group.length > 1) {
199
- const avgEffectiveness = group.reduce((sum, s) => sum + (s.effectiveness || 0), 0) / group.length;
200
- recommendations.push(
201
- `${group.length} parallel solutions using "${approach}" approach (avg effectiveness: ${(avgEffectiveness * 100).toFixed(1)}%)`
202
- );
203
- }
204
- }
205
- const best = solutions.reduce(
206
- (a, b) => (a.effectiveness || 0) > (b.effectiveness || 0) ? a : b,
207
- solutions[0]
208
- );
209
- if (best && best.effectiveness && best.effectiveness > 0.7) {
210
- recommendations.push(
211
- `Recommended: Use solution from frame "${best.frameId}" (${(best.effectiveness * 100).toFixed(1)}% effectiveness)`
212
- );
213
- }
214
- }
215
- return {
216
- solutions: solutions.map((s) => ({
217
- frameId: s.frameId,
218
- approach: s.approach,
219
- effectiveness: s.effectiveness || 0
220
- })),
221
- recommendations
222
- };
223
- }
224
- /**
225
- * Create a visual diff between two stacks
226
- */
227
- createVisualDiff(baseFrame, stack1, stack2) {
228
- const diff = this.diffVisualizer.visualizeDivergence(
229
- baseFrame,
230
- stack1,
231
- stack2
232
- );
233
- const conflicts = this.conflictDetector.detectConflicts(stack1, stack2);
234
- return {
235
- nodes: diff.nodes.map((n) => ({
236
- id: n.id,
237
- type: n.type,
238
- depth: n.frame?.depth
239
- })),
240
- edges: diff.edges.map((e) => ({
241
- source: e.source,
242
- target: e.target,
243
- type: e.type
244
- })),
245
- conflicts: conflicts.map((c) => ({
246
- frameId1: c.frameId1,
247
- frameId2: c.frameId2,
248
- severity: c.severity
249
- }))
250
- };
251
- }
252
- /**
253
- * Close a merge session and clean up resources
254
- */
255
- closeSession(sessionId) {
256
- const session = this.activeSessions.get(sessionId);
257
- if (session) {
258
- if (session.rollbackPoint) {
259
- this.rollbackSnapshots.delete(session.rollbackPoint);
260
- }
261
- this.activeSessions.delete(sessionId);
262
- logger.debug(`Session closed: ${sessionId}`);
263
- }
264
- }
265
- // Private helpers
266
- createRollbackSnapshot(sessionId, stack1, stack2) {
267
- const snapshotId = `rollback-${sessionId}`;
268
- this.rollbackSnapshots.set(snapshotId, {
269
- stack1: this.deepCloneStack(stack1),
270
- stack2: this.deepCloneStack(stack2)
271
- });
272
- return snapshotId;
273
- }
274
- deepCloneStack(stack) {
275
- return {
276
- ...stack,
277
- frames: stack.frames.map((f) => ({ ...f })),
278
- events: stack.events.map((e) => ({ ...e }))
279
- };
280
- }
281
- updateSuccessRate() {
282
- if (this.statistics.totalConflicts > 0) {
283
- this.statistics.successRate = this.statistics.resolvedConflicts / this.statistics.totalConflicts;
284
- }
285
- }
286
- updateAverageResolutionTime(session) {
287
- if (session.completedAt && session.startedAt) {
288
- const duration = session.completedAt - session.startedAt;
289
- const completedSessions = Array.from(this.activeSessions.values()).filter(
290
- (s) => s.completedAt
291
- ).length;
292
- if (completedSessions === 1) {
293
- this.statistics.averageResolutionTime = duration;
294
- } else {
295
- this.statistics.averageResolutionTime = (this.statistics.averageResolutionTime * (completedSessions - 1) + duration) / completedSessions;
296
- }
297
- }
298
- }
299
- }
300
- export {
301
- UnifiedMergeResolver
302
- };
@@ -1,376 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { logger } from "../core/monitoring/logger.js";
6
- const DEFAULT_CONFIG = {
7
- enabled: !!process.env.DIFFMEM_ENDPOINT,
8
- endpoint: process.env.DIFFMEM_ENDPOINT || "http://localhost:3100",
9
- autoFetchCategories: ["preference", "expertise", "pattern"],
10
- autoLearnEnabled: true,
11
- learningConfidenceThreshold: 0.7,
12
- maxMemoriesPerSession: 50
13
- };
14
- class DiffMemHooks {
15
- config;
16
- fetchedMemories = [];
17
- learningBuffer = [];
18
- isConnected = false;
19
- frameManager;
20
- sessionStartTime = 0;
21
- constructor(config = {}) {
22
- this.config = { ...DEFAULT_CONFIG, ...config };
23
- }
24
- /**
25
- * Register session hooks with the event emitter
26
- */
27
- register(emitter, frameManager) {
28
- this.frameManager = frameManager;
29
- if (!this.config.enabled) {
30
- logger.debug("DiffMem hooks disabled - skipping registration");
31
- return;
32
- }
33
- emitter.registerHandler("session_start", this.onSessionStart.bind(this));
34
- emitter.registerHandler("session_end", this.onSessionEnd.bind(this));
35
- logger.info("DiffMem hooks registered", {
36
- endpoint: this.config.endpoint,
37
- autoFetchCategories: this.config.autoFetchCategories,
38
- autoLearnEnabled: this.config.autoLearnEnabled
39
- });
40
- }
41
- /**
42
- * Handle session start - fetch user knowledge
43
- */
44
- async onSessionStart(event) {
45
- const sessionEvent = event;
46
- this.sessionStartTime = Date.now();
47
- try {
48
- const status = await this.checkStatus();
49
- this.isConnected = status.connected;
50
- if (!this.isConnected) {
51
- logger.debug("DiffMem not available - skipping memory fetch");
52
- return;
53
- }
54
- const query = {
55
- categories: this.config.autoFetchCategories,
56
- limit: this.config.maxMemoriesPerSession,
57
- minConfidence: this.config.learningConfidenceThreshold
58
- };
59
- this.fetchedMemories = await this.fetchMemories(query);
60
- if (this.frameManager && this.fetchedMemories.length > 0) {
61
- await this.injectAsAnchors(sessionEvent.data.sessionId);
62
- }
63
- logger.info("DiffMem session start completed", {
64
- memoriesFetched: this.fetchedMemories.length,
65
- sessionId: sessionEvent.data.sessionId
66
- });
67
- } catch (error) {
68
- logger.warn("DiffMem session start failed", {
69
- error: error instanceof Error ? error.message : String(error)
70
- });
71
- this.isConnected = false;
72
- }
73
- }
74
- /**
75
- * Handle session end - sync buffered learnings
76
- */
77
- async onSessionEnd(event) {
78
- const sessionEvent = event;
79
- if (!this.config.autoLearnEnabled || this.learningBuffer.length === 0) {
80
- logger.debug("No learnings to sync on session end");
81
- return;
82
- }
83
- if (!this.isConnected) {
84
- const status = await this.checkStatus();
85
- if (!status.connected) {
86
- logger.warn("DiffMem not available - learnings not synced", {
87
- bufferedCount: this.learningBuffer.length
88
- });
89
- return;
90
- }
91
- this.isConnected = true;
92
- }
93
- try {
94
- await this.syncLearnings();
95
- const sessionDuration = Date.now() - this.sessionStartTime;
96
- logger.info("DiffMem session end completed", {
97
- learningSynced: this.learningBuffer.length,
98
- sessionId: sessionEvent.data.sessionId,
99
- sessionDurationMs: sessionDuration
100
- });
101
- this.learningBuffer = [];
102
- } catch (error) {
103
- logger.warn("DiffMem session end sync failed", {
104
- error: error instanceof Error ? error.message : String(error),
105
- bufferedCount: this.learningBuffer.length
106
- });
107
- }
108
- }
109
- /**
110
- * Record a learning during session
111
- */
112
- recordLearning(insight) {
113
- if (!this.config.autoLearnEnabled) {
114
- return;
115
- }
116
- if (insight.confidence < this.config.learningConfidenceThreshold) {
117
- logger.debug("Learning below confidence threshold", {
118
- confidence: insight.confidence,
119
- threshold: this.config.learningConfidenceThreshold
120
- });
121
- return;
122
- }
123
- const learning = {
124
- ...insight,
125
- timestamp: Date.now()
126
- };
127
- this.learningBuffer.push(learning);
128
- logger.debug("Learning recorded", {
129
- category: learning.category,
130
- confidence: learning.confidence,
131
- bufferSize: this.learningBuffer.length
132
- });
133
- }
134
- /**
135
- * Get fetched memories
136
- */
137
- getUserKnowledge() {
138
- return [...this.fetchedMemories];
139
- }
140
- /**
141
- * Format memories for LLM context with token budget
142
- */
143
- formatForContext(maxTokens = 2e3) {
144
- if (this.fetchedMemories.length === 0) {
145
- return "";
146
- }
147
- const sortedMemories = [...this.fetchedMemories].sort((a, b) => {
148
- if (b.confidence !== a.confidence) {
149
- return b.confidence - a.confidence;
150
- }
151
- return b.timestamp - a.timestamp;
152
- });
153
- const sections = /* @__PURE__ */ new Map();
154
- for (const memory of sortedMemories) {
155
- const category = memory.category;
156
- if (!sections.has(category)) {
157
- sections.set(category, []);
158
- }
159
- const categoryMemories = sections.get(category);
160
- if (categoryMemories) {
161
- categoryMemories.push(memory.content);
162
- }
163
- }
164
- const lines = ["## User Knowledge"];
165
- let estimatedTokens = 5;
166
- const categoryLabels = {
167
- preference: "Preferences",
168
- expertise: "Expertise",
169
- project_knowledge: "Project Knowledge",
170
- pattern: "Patterns",
171
- correction: "Corrections"
172
- };
173
- for (const [category, contents] of sections) {
174
- const label = categoryLabels[category] || category;
175
- const categoryHeader = `
176
- ### ${label}`;
177
- const headerTokens = Math.ceil(categoryHeader.length / 4);
178
- if (estimatedTokens + headerTokens > maxTokens) {
179
- break;
180
- }
181
- lines.push(categoryHeader);
182
- estimatedTokens += headerTokens;
183
- for (const content of contents) {
184
- const contentLine = `- ${content}`;
185
- const contentTokens = Math.ceil(contentLine.length / 4);
186
- if (estimatedTokens + contentTokens > maxTokens) {
187
- lines.push("- (additional items truncated for token budget)");
188
- break;
189
- }
190
- lines.push(contentLine);
191
- estimatedTokens += contentTokens;
192
- }
193
- }
194
- return lines.join("\n");
195
- }
196
- /**
197
- * Get current connection status
198
- */
199
- getStatus() {
200
- return {
201
- connected: this.isConnected,
202
- memoriesLoaded: this.fetchedMemories.length,
203
- learningsBuffered: this.learningBuffer.length
204
- };
205
- }
206
- /**
207
- * Update configuration
208
- */
209
- updateConfig(config) {
210
- this.config = { ...this.config, ...config };
211
- logger.debug("DiffMem config updated", { config: this.config });
212
- }
213
- // Private methods
214
- /**
215
- * Check DiffMem service status
216
- */
217
- async checkStatus() {
218
- try {
219
- const controller = new AbortController();
220
- const timeoutId = setTimeout(() => controller.abort(), 3e3);
221
- const response = await fetch(`${this.config.endpoint}/status`, {
222
- method: "GET",
223
- signal: controller.signal
224
- });
225
- clearTimeout(timeoutId);
226
- if (!response.ok) {
227
- return { connected: false, memoryCount: 0, lastSync: null };
228
- }
229
- const status = await response.json();
230
- return {
231
- connected: true,
232
- memoryCount: status.memoryCount || 0,
233
- lastSync: status.lastSync || null,
234
- version: status.version
235
- };
236
- } catch {
237
- return { connected: false, memoryCount: 0, lastSync: null };
238
- }
239
- }
240
- /**
241
- * Fetch memories from DiffMem
242
- */
243
- async fetchMemories(query) {
244
- try {
245
- const controller = new AbortController();
246
- const timeoutId = setTimeout(() => controller.abort(), 5e3);
247
- const response = await fetch(`${this.config.endpoint}/memories/query`, {
248
- method: "POST",
249
- headers: { "Content-Type": "application/json" },
250
- body: JSON.stringify(query),
251
- signal: controller.signal
252
- });
253
- clearTimeout(timeoutId);
254
- if (!response.ok) {
255
- logger.warn("DiffMem query failed", { status: response.status });
256
- return [];
257
- }
258
- const data = await response.json();
259
- return data.memories || [];
260
- } catch (error) {
261
- logger.debug("DiffMem fetch failed", {
262
- error: error instanceof Error ? error.message : String(error)
263
- });
264
- return [];
265
- }
266
- }
267
- /**
268
- * Sync buffered learnings to DiffMem
269
- */
270
- async syncLearnings() {
271
- if (this.learningBuffer.length === 0) {
272
- return;
273
- }
274
- const controller = new AbortController();
275
- const timeoutId = setTimeout(() => controller.abort(), 1e4);
276
- try {
277
- const response = await fetch(`${this.config.endpoint}/memories/learn`, {
278
- method: "POST",
279
- headers: { "Content-Type": "application/json" },
280
- body: JSON.stringify({ insights: this.learningBuffer }),
281
- signal: controller.signal
282
- });
283
- clearTimeout(timeoutId);
284
- if (!response.ok) {
285
- throw new Error(`Sync failed with status ${response.status}`);
286
- }
287
- logger.info("Learnings synced to DiffMem", {
288
- count: this.learningBuffer.length
289
- });
290
- } catch (error) {
291
- clearTimeout(timeoutId);
292
- throw error;
293
- }
294
- }
295
- /**
296
- * Inject fetched memories as frame anchors
297
- */
298
- async injectAsAnchors(sessionId) {
299
- if (!this.frameManager || this.fetchedMemories.length === 0) {
300
- return;
301
- }
302
- try {
303
- const byCategory = /* @__PURE__ */ new Map();
304
- for (const memory of this.fetchedMemories) {
305
- if (!byCategory.has(memory.category)) {
306
- byCategory.set(memory.category, []);
307
- }
308
- const categoryList = byCategory.get(memory.category);
309
- if (categoryList) {
310
- categoryList.push(memory);
311
- }
312
- }
313
- for (const [category, memories] of byCategory) {
314
- const highConfidence = memories.filter((m) => m.confidence >= 0.8);
315
- for (const memory of highConfidence.slice(0, 5)) {
316
- const anchorType = this.categoryToAnchorType(category);
317
- const priority = Math.round(memory.confidence * 10);
318
- this.frameManager.addAnchor(anchorType, memory.content, priority, {
319
- source: "diffmem",
320
- category: memory.category,
321
- memoryId: memory.id,
322
- confidence: memory.confidence,
323
- sessionId
324
- });
325
- }
326
- }
327
- logger.debug("Memories injected as anchors", {
328
- totalMemories: this.fetchedMemories.length,
329
- anchorsCreated: Math.min(
330
- this.fetchedMemories.filter((m) => m.confidence >= 0.8).length,
331
- 25
332
- )
333
- });
334
- } catch (error) {
335
- logger.warn("Failed to inject memories as anchors", {
336
- error: error instanceof Error ? error.message : String(error)
337
- });
338
- }
339
- }
340
- /**
341
- * Map memory category to anchor type
342
- */
343
- categoryToAnchorType(category) {
344
- switch (category) {
345
- case "preference":
346
- return "CONSTRAINT";
347
- case "expertise":
348
- return "FACT";
349
- case "project_knowledge":
350
- return "FACT";
351
- case "pattern":
352
- return "INTERFACE_CONTRACT";
353
- case "correction":
354
- return "DECISION";
355
- default:
356
- return "FACT";
357
- }
358
- }
359
- }
360
- let instance = null;
361
- function getDiffMemHooks(config) {
362
- if (!instance) {
363
- instance = new DiffMemHooks(config);
364
- } else if (config) {
365
- instance.updateConfig(config);
366
- }
367
- return instance;
368
- }
369
- function resetDiffMemHooks() {
370
- instance = null;
371
- }
372
- export {
373
- DiffMemHooks,
374
- getDiffMemHooks,
375
- resetDiffMemHooks
376
- };