@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,308 +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
- class ContextBudgetManager {
7
- config;
8
- tokenUsage = /* @__PURE__ */ new Map();
9
- DEFAULT_MAX_TOKENS = 4e3;
10
- TOKEN_CHAR_RATIO = 0.25;
11
- // Rough estimate: 1 token ≈ 4 chars
12
- constructor(config) {
13
- this.config = {
14
- maxTokens: config?.maxTokens || this.DEFAULT_MAX_TOKENS,
15
- priorityWeights: {
16
- task: config?.priorityWeights?.task || 0.3,
17
- recentWork: config?.priorityWeights?.recentWork || 0.25,
18
- feedback: config?.priorityWeights?.feedback || 0.2,
19
- gitHistory: config?.priorityWeights?.gitHistory || 0.15,
20
- dependencies: config?.priorityWeights?.dependencies || 0.1
21
- },
22
- compressionEnabled: config?.compressionEnabled ?? true,
23
- adaptiveBudgeting: config?.adaptiveBudgeting ?? true
24
- };
25
- }
26
- /**
27
- * Estimate tokens for a given text
28
- */
29
- estimateTokens(text) {
30
- if (!text) return 0;
31
- const baseTokens = text.length * this.TOKEN_CHAR_RATIO;
32
- const codeMultiplier = this.detectCodeContent(text) ? 1.2 : 1;
33
- const jsonMultiplier = this.detectJsonContent(text) ? 0.9 : 1;
34
- return Math.ceil(baseTokens * codeMultiplier * jsonMultiplier);
35
- }
36
- /**
37
- * Allocate token budget across different context categories
38
- */
39
- allocateBudget(context) {
40
- const currentTokens = this.calculateCurrentTokens(context);
41
- if (currentTokens <= this.config.maxTokens) {
42
- logger.debug("Context within budget", {
43
- used: currentTokens,
44
- max: this.config.maxTokens
45
- });
46
- return context;
47
- }
48
- logger.info("Context exceeds budget, optimizing...", {
49
- current: currentTokens,
50
- max: this.config.maxTokens
51
- });
52
- if (this.config.adaptiveBudgeting) {
53
- return this.adaptiveBudgetAllocation(context, currentTokens);
54
- }
55
- return this.priorityBasedAllocation(context, currentTokens);
56
- }
57
- /**
58
- * Compress context to fit within budget
59
- */
60
- compressContext(context) {
61
- if (!this.config.compressionEnabled) {
62
- return context;
63
- }
64
- const compressed = {
65
- ...context,
66
- task: this.compressTaskContext(context.task),
67
- history: this.compressHistoryContext(context.history),
68
- environment: this.compressEnvironmentContext(context.environment),
69
- memory: this.compressMemoryContext(context.memory),
70
- tokenCount: 0
71
- };
72
- compressed.tokenCount = this.calculateCurrentTokens(compressed);
73
- logger.debug("Context compressed", {
74
- original: context.tokenCount,
75
- compressed: compressed.tokenCount,
76
- reduction: `${Math.round((1 - compressed.tokenCount / context.tokenCount) * 100)}%`
77
- });
78
- return compressed;
79
- }
80
- /**
81
- * Get current token usage statistics
82
- */
83
- getUsage() {
84
- const categories = {};
85
- let totalUsed = 0;
86
- for (const [category, tokens] of this.tokenUsage) {
87
- categories[category] = tokens;
88
- totalUsed += tokens;
89
- }
90
- return {
91
- used: totalUsed,
92
- available: this.config.maxTokens - totalUsed,
93
- categories
94
- };
95
- }
96
- /**
97
- * Calculate current token count for context
98
- */
99
- calculateCurrentTokens(context) {
100
- this.tokenUsage.clear();
101
- const taskTokens = this.estimateTokens(JSON.stringify(context.task));
102
- const historyTokens = this.estimateTokens(JSON.stringify(context.history));
103
- const envTokens = this.estimateTokens(JSON.stringify(context.environment));
104
- const memoryTokens = this.estimateTokens(JSON.stringify(context.memory));
105
- this.tokenUsage.set("task", taskTokens);
106
- this.tokenUsage.set("history", historyTokens);
107
- this.tokenUsage.set("environment", envTokens);
108
- this.tokenUsage.set("memory", memoryTokens);
109
- return taskTokens + historyTokens + envTokens + memoryTokens;
110
- }
111
- /**
112
- * Adaptive budget allocation based on iteration phase
113
- */
114
- adaptiveBudgetAllocation(context, currentTokens) {
115
- const reductionRatio = this.config.maxTokens / currentTokens;
116
- const phase = this.determinePhase(context.task.currentIteration);
117
- const adjustedWeights = this.getPhaseAdjustedWeights(phase);
118
- return this.applyWeightedReduction(
119
- context,
120
- reductionRatio,
121
- adjustedWeights
122
- );
123
- }
124
- /**
125
- * Priority-based allocation using fixed weights
126
- */
127
- priorityBasedAllocation(context, currentTokens) {
128
- const reductionRatio = this.config.maxTokens / currentTokens;
129
- return this.applyWeightedReduction(
130
- context,
131
- reductionRatio,
132
- this.config.priorityWeights
133
- );
134
- }
135
- /**
136
- * Apply weighted reduction to context
137
- */
138
- applyWeightedReduction(context, reductionRatio, weights) {
139
- const reduced = { ...context };
140
- if (weights.recentWork < 1) {
141
- const keepCount = Math.ceil(
142
- context.history.recentIterations.length * reductionRatio * weights.recentWork
143
- );
144
- reduced.history = {
145
- ...context.history,
146
- recentIterations: context.history.recentIterations.slice(-keepCount)
147
- };
148
- }
149
- if (weights.gitHistory < 1) {
150
- const keepCount = Math.ceil(
151
- context.history.gitCommits.length * reductionRatio * weights.gitHistory
152
- );
153
- reduced.history.gitCommits = context.history.gitCommits.slice(-keepCount);
154
- }
155
- if (weights.dependencies < 1) {
156
- const keepCount = Math.ceil(
157
- context.memory.relevantFrames.length * reductionRatio * weights.dependencies
158
- );
159
- reduced.memory = {
160
- ...context.memory,
161
- relevantFrames: context.memory.relevantFrames.sort((a, b) => (b.created_at || 0) - (a.created_at || 0)).slice(0, keepCount)
162
- };
163
- }
164
- reduced.tokenCount = this.calculateCurrentTokens(reduced);
165
- return reduced;
166
- }
167
- /**
168
- * Compress task context
169
- */
170
- compressTaskContext(task) {
171
- return {
172
- ...task,
173
- description: this.truncateWithEllipsis(task.description, 500),
174
- criteria: task.criteria.slice(0, 5),
175
- // Keep top 5 criteria
176
- feedback: task.feedback ? this.truncateWithEllipsis(task.feedback, 300) : void 0
177
- };
178
- }
179
- /**
180
- * Compress history context
181
- */
182
- compressHistoryContext(history) {
183
- return {
184
- ...history,
185
- recentIterations: history.recentIterations.slice(-5).map((iter) => ({
186
- ...iter,
187
- summary: this.truncateWithEllipsis(iter.summary, 100)
188
- })),
189
- gitCommits: history.gitCommits.slice(-10).map((commit) => ({
190
- ...commit,
191
- message: this.truncateWithEllipsis(commit.message, 80),
192
- files: commit.files.slice(0, 5)
193
- // Keep top 5 files
194
- })),
195
- changedFiles: history.changedFiles.slice(0, 20),
196
- // Keep top 20 files
197
- testResults: history.testResults.slice(-3)
198
- // Keep last 3 test runs
199
- };
200
- }
201
- /**
202
- * Compress environment context
203
- */
204
- compressEnvironmentContext(env) {
205
- return {
206
- ...env,
207
- dependencies: this.compressObject(env.dependencies, 20),
208
- // Keep top 20 deps
209
- configuration: this.compressObject(env.configuration, 10)
210
- // Keep top 10 config items
211
- };
212
- }
213
- /**
214
- * Compress memory context
215
- */
216
- compressMemoryContext(memory) {
217
- return {
218
- ...memory,
219
- relevantFrames: memory.relevantFrames.slice(0, 5),
220
- // Keep top 5 frames
221
- decisions: memory.decisions.filter((d) => d.impact !== "low").slice(-5),
222
- // Keep last 5
223
- patterns: memory.patterns.filter((p) => p.successRate > 0.7).slice(0, 3),
224
- // Keep top 3
225
- blockers: memory.blockers.filter((b) => !b.resolved)
226
- // Keep unresolved only
227
- };
228
- }
229
- /**
230
- * Determine iteration phase
231
- */
232
- determinePhase(iteration) {
233
- if (iteration <= 3) return "early";
234
- if (iteration <= 10) return "middle";
235
- return "late";
236
- }
237
- /**
238
- * Get phase-adjusted weights
239
- */
240
- getPhaseAdjustedWeights(phase) {
241
- switch (phase) {
242
- case "early":
243
- return {
244
- task: 0.4,
245
- recentWork: 0.1,
246
- feedback: 0.2,
247
- gitHistory: 0.2,
248
- dependencies: 0.1
249
- };
250
- case "middle":
251
- return this.config.priorityWeights;
252
- case "late":
253
- return {
254
- task: 0.2,
255
- recentWork: 0.35,
256
- feedback: 0.25,
257
- gitHistory: 0.15,
258
- dependencies: 0.05
259
- };
260
- }
261
- }
262
- /**
263
- * Detect if text contains code
264
- */
265
- detectCodeContent(text) {
266
- const codePatterns = [
267
- /function\s+\w+\s*\(/,
268
- /class\s+\w+/,
269
- /const\s+\w+\s*=/,
270
- /import\s+.*from/,
271
- /\{[\s\S]*\}/
272
- ];
273
- return codePatterns.some((pattern) => pattern.test(text));
274
- }
275
- /**
276
- * Detect if text contains JSON
277
- */
278
- detectJsonContent(text) {
279
- try {
280
- JSON.parse(text);
281
- return true;
282
- } catch {
283
- return text.includes('"') && text.includes(":") && text.includes("{");
284
- }
285
- }
286
- /**
287
- * Truncate text with ellipsis
288
- */
289
- truncateWithEllipsis(text, maxLength) {
290
- if (text.length <= maxLength) return text;
291
- return text.substring(0, maxLength - 3) + "...";
292
- }
293
- /**
294
- * Compress object by keeping only top N entries
295
- */
296
- compressObject(obj, maxEntries) {
297
- const entries = Object.entries(obj);
298
- if (entries.length <= maxEntries) return obj;
299
- const compressed = {};
300
- entries.slice(0, maxEntries).forEach(([key, value]) => {
301
- compressed[key] = value;
302
- });
303
- return compressed;
304
- }
305
- }
306
- export {
307
- ContextBudgetManager
308
- };
@@ -1,391 +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
- import { FrameManager } from "../../../core/context/index.js";
7
- import { sharedContextLayer } from "../../../core/context/shared-context-layer.js";
8
- import { ContextRetriever } from "../../../core/retrieval/context-retriever.js";
9
- import { sessionManager } from "../../../core/session/index.js";
10
- import { ContextBudgetManager } from "./context-budget-manager.js";
11
- class StackMemoryContextLoader {
12
- frameManager;
13
- contextRetriever;
14
- budgetManager;
15
- config;
16
- constructor(config) {
17
- this.config = {
18
- maxTokens: 3200,
19
- // Leave room for task description
20
- lookbackDays: 30,
21
- similarityThreshold: 0.7,
22
- patternDetectionEnabled: true,
23
- includeFailedAttempts: true,
24
- crossSessionSearch: true,
25
- ...config
26
- };
27
- this.budgetManager = new ContextBudgetManager({
28
- maxTokens: this.config.maxTokens,
29
- priorityWeights: {
30
- task: 0.15,
31
- recentWork: 0.3,
32
- patterns: 0.25,
33
- decisions: 0.2,
34
- dependencies: 0.1
35
- }
36
- });
37
- logger.info("StackMemory context loader initialized", {
38
- maxTokens: this.config.maxTokens,
39
- lookbackDays: this.config.lookbackDays,
40
- patternDetection: this.config.patternDetectionEnabled
41
- });
42
- }
43
- async initialize() {
44
- try {
45
- await sessionManager.initialize();
46
- await sharedContextLayer.initialize();
47
- const session = await sessionManager.getOrCreateSession({});
48
- if (session.database) {
49
- this.frameManager = new FrameManager(
50
- session.database,
51
- session.projectId
52
- );
53
- this.contextRetriever = new ContextRetriever(session.database);
54
- }
55
- logger.info("Context loader initialized successfully");
56
- } catch (error) {
57
- logger.error("Failed to initialize context loader", error);
58
- throw error;
59
- }
60
- }
61
- /**
62
- * Load context for Ralph loop initialization
63
- */
64
- async loadInitialContext(request) {
65
- logger.info("Loading initial context for Ralph loop", {
66
- task: request.task.substring(0, 100),
67
- usePatterns: request.usePatterns,
68
- useSimilarTasks: request.useSimilarTasks
69
- });
70
- const sources = [];
71
- let totalTokens = 0;
72
- try {
73
- if (request.useSimilarTasks) {
74
- const similarTasks2 = await this.findSimilarTasks(request.task);
75
- if (similarTasks2.length > 0) {
76
- const tasksContext = await this.extractTaskContext(similarTasks2);
77
- sources.push({
78
- type: "similar_tasks",
79
- weight: 0.3,
80
- content: tasksContext,
81
- tokens: this.budgetManager.estimateTokens(tasksContext)
82
- });
83
- totalTokens += sources[sources.length - 1].tokens;
84
- }
85
- }
86
- if (request.usePatterns) {
87
- const patterns2 = await this.extractRelevantPatterns(request.task);
88
- if (patterns2.length > 0) {
89
- const patternsContext = await this.formatPatterns(patterns2);
90
- sources.push({
91
- type: "historical_patterns",
92
- weight: 0.25,
93
- content: patternsContext,
94
- tokens: this.budgetManager.estimateTokens(patternsContext)
95
- });
96
- totalTokens += sources[sources.length - 1].tokens;
97
- }
98
- }
99
- const decisions = await this.loadRecentDecisions();
100
- if (decisions.length > 0) {
101
- const decisionsContext = this.formatDecisions(decisions);
102
- sources.push({
103
- type: "recent_decisions",
104
- weight: 0.2,
105
- content: decisionsContext,
106
- tokens: this.budgetManager.estimateTokens(decisionsContext)
107
- });
108
- totalTokens += sources[sources.length - 1].tokens;
109
- }
110
- const projectContext = await this.loadProjectContext(request.task);
111
- if (projectContext) {
112
- sources.push({
113
- type: "project_context",
114
- weight: 0.15,
115
- content: projectContext,
116
- tokens: this.budgetManager.estimateTokens(projectContext)
117
- });
118
- totalTokens += sources[sources.length - 1].tokens;
119
- }
120
- const budgetedSources = this.budgetManager.allocateBudget({ sources });
121
- const synthesizedContext = this.synthesizeContext(
122
- budgetedSources.sources
123
- );
124
- logger.info("Context loaded successfully", {
125
- totalSources: sources.length,
126
- totalTokens,
127
- budgetedTokens: budgetedSources.sources.reduce(
128
- (sum, s) => sum + s.tokens,
129
- 0
130
- )
131
- });
132
- return {
133
- context: synthesizedContext,
134
- sources: budgetedSources.sources,
135
- metadata: {
136
- totalTokens: budgetedSources.sources.reduce(
137
- (sum, s) => sum + s.tokens,
138
- 0
139
- ),
140
- sourcesCount: budgetedSources.sources.length,
141
- patterns: request.usePatterns ? patterns : [],
142
- similarTasks: request.useSimilarTasks ? similarTasks : []
143
- }
144
- };
145
- } catch (error) {
146
- logger.error("Failed to load context", error);
147
- throw error;
148
- }
149
- }
150
- /**
151
- * Find similar tasks from StackMemory history
152
- */
153
- async findSimilarTasks(taskDescription) {
154
- if (!this.frameManager || !this.contextRetriever) {
155
- return [];
156
- }
157
- try {
158
- const searchResults = await this.contextRetriever.search(
159
- taskDescription,
160
- {
161
- maxResults: 10,
162
- types: ["task", "subtask"],
163
- timeFilter: {
164
- days: this.config.lookbackDays
165
- }
166
- }
167
- );
168
- const similarities = [];
169
- for (const result of searchResults) {
170
- const similarity = this.calculateTaskSimilarity(
171
- taskDescription,
172
- result.content
173
- );
174
- if (similarity >= this.config.similarityThreshold) {
175
- similarities.push({
176
- frameId: result.frameId,
177
- task: result.content,
178
- similarity,
179
- outcome: await this.determineTaskOutcome(result.frameId),
180
- createdAt: result.timestamp,
181
- sessionId: result.sessionId || "unknown"
182
- });
183
- }
184
- }
185
- return similarities.sort((a, b) => {
186
- const aScore = a.similarity * (a.outcome === "success" ? 1.2 : 1);
187
- const bScore = b.similarity * (b.outcome === "success" ? 1.2 : 1);
188
- return bScore - aScore;
189
- }).slice(0, 5);
190
- } catch (error) {
191
- logger.error("Failed to find similar tasks", error);
192
- return [];
193
- }
194
- }
195
- /**
196
- * Extract relevant patterns from historical data
197
- */
198
- async extractRelevantPatterns(taskDescription) {
199
- try {
200
- const context = await sharedContextLayer.getSharedContext();
201
- if (!context) return [];
202
- const relevantPatterns = [];
203
- for (const pattern of context.globalPatterns) {
204
- const relevance = this.calculatePatternRelevance(
205
- taskDescription,
206
- pattern.pattern
207
- );
208
- if (relevance >= 0.5) {
209
- relevantPatterns.push({
210
- pattern: pattern.pattern,
211
- type: pattern.type,
212
- frequency: pattern.frequency,
213
- lastSeen: pattern.lastSeen,
214
- relevance,
215
- resolution: pattern.resolution,
216
- examples: await this.getPatternExamples(pattern.pattern)
217
- });
218
- }
219
- }
220
- return relevantPatterns.sort(
221
- (a, b) => b.relevance * Math.log(b.frequency + 1) - a.relevance * Math.log(a.frequency + 1)
222
- ).slice(0, 8);
223
- } catch (error) {
224
- logger.error("Failed to extract patterns", error);
225
- return [];
226
- }
227
- }
228
- /**
229
- * Load recent decisions that might be relevant
230
- */
231
- async loadRecentDecisions() {
232
- try {
233
- const context = await sharedContextLayer.getSharedContext();
234
- if (!context) return [];
235
- const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
236
- return context.decisionLog.filter((d) => d.timestamp >= cutoff && d.outcome === "success").sort((a, b) => b.timestamp - a.timestamp).slice(0, 5);
237
- } catch (error) {
238
- logger.error("Failed to load recent decisions", error);
239
- return [];
240
- }
241
- }
242
- /**
243
- * Load project-specific context
244
- */
245
- async loadProjectContext(taskDescription) {
246
- try {
247
- if (!this.contextRetriever) return null;
248
- const projectInfo = await this.contextRetriever.search(taskDescription, {
249
- maxResults: 3,
250
- types: ["task"],
251
- projectSpecific: true
252
- });
253
- if (projectInfo.length === 0) return null;
254
- const contextParts = [];
255
- for (const info of projectInfo) {
256
- contextParts.push(`Project context: ${info.content}`);
257
- }
258
- return contextParts.join("\n\n");
259
- } catch (error) {
260
- logger.error("Failed to load project context", error);
261
- return null;
262
- }
263
- }
264
- /**
265
- * Calculate similarity between task descriptions
266
- */
267
- calculateTaskSimilarity(task1, task2) {
268
- const words1 = new Set(task1.toLowerCase().split(/\s+/));
269
- const words2 = new Set(task2.toLowerCase().split(/\s+/));
270
- const intersection = new Set([...words1].filter((x) => words2.has(x)));
271
- const union = /* @__PURE__ */ new Set([...words1, ...words2]);
272
- return intersection.size / union.size;
273
- }
274
- /**
275
- * Calculate pattern relevance to current task
276
- */
277
- calculatePatternRelevance(taskDescription, pattern) {
278
- const taskWords = taskDescription.toLowerCase().split(/\s+/);
279
- const patternWords = pattern.toLowerCase().split(/\s+/);
280
- let matches = 0;
281
- for (const word of taskWords) {
282
- if (patternWords.some((p) => p.includes(word) || word.includes(p))) {
283
- matches++;
284
- }
285
- }
286
- return matches / taskWords.length;
287
- }
288
- /**
289
- * Extract context from similar tasks
290
- */
291
- async extractTaskContext(similarities) {
292
- const contextParts = [];
293
- contextParts.push("Similar tasks from history:");
294
- for (const sim of similarities) {
295
- contextParts.push(
296
- `
297
- Task: ${sim.task}
298
- Outcome: ${sim.outcome}
299
- Similarity: ${Math.round(sim.similarity * 100)}%
300
- ${sim.outcome === "success" ? "\u2705 Successfully completed" : "\u274C Had issues"}
301
- `.trim()
302
- );
303
- }
304
- return contextParts.join("\n\n");
305
- }
306
- /**
307
- * Format patterns for context inclusion
308
- */
309
- async formatPatterns(patterns2) {
310
- const contextParts = [];
311
- contextParts.push("Relevant patterns from experience:");
312
- for (const pattern of patterns2) {
313
- contextParts.push(
314
- `
315
- Pattern: ${pattern.pattern}
316
- Type: ${pattern.type}
317
- Frequency: ${pattern.frequency} occurrences
318
- ${pattern.resolution ? `Resolution: ${pattern.resolution}` : ""}
319
- Relevance: ${Math.round(pattern.relevance * 100)}%
320
- `.trim()
321
- );
322
- }
323
- return contextParts.join("\n\n");
324
- }
325
- /**
326
- * Format decisions for context inclusion
327
- */
328
- formatDecisions(decisions) {
329
- const contextParts = [];
330
- contextParts.push("Recent successful decisions:");
331
- for (const decision of decisions) {
332
- contextParts.push(
333
- `
334
- Decision: ${decision.decision}
335
- Reasoning: ${decision.reasoning}
336
- Date: ${new Date(decision.timestamp).toLocaleDateString()}
337
- `.trim()
338
- );
339
- }
340
- return contextParts.join("\n\n");
341
- }
342
- /**
343
- * Synthesize all context sources into coherent input
344
- */
345
- synthesizeContext(sources) {
346
- if (sources.length === 0) {
347
- return "No relevant historical context found.";
348
- }
349
- const contextParts = [];
350
- contextParts.push("Context from StackMemory:");
351
- const sortedSources = sources.sort((a, b) => b.weight - a.weight);
352
- for (const source of sortedSources) {
353
- contextParts.push(
354
- `
355
- --- ${source.type.replace("_", " ").toUpperCase()} ---`
356
- );
357
- contextParts.push(source.content);
358
- }
359
- contextParts.push(
360
- "\nUse this context to inform your approach to the current task."
361
- );
362
- return contextParts.join("\n");
363
- }
364
- /**
365
- * Determine task outcome from frame history
366
- */
367
- async determineTaskOutcome(frameId) {
368
- try {
369
- if (!this.frameManager) return "unknown";
370
- const frame = await this.frameManager.getFrame(frameId);
371
- if (!frame) return "unknown";
372
- if (frame.state === "closed" && frame.outputs) {
373
- return "success";
374
- }
375
- return frame.state === "closed" ? "failure" : "unknown";
376
- } catch {
377
- return "unknown";
378
- }
379
- }
380
- /**
381
- * Get examples of a specific pattern
382
- */
383
- async getPatternExamples(_pattern) {
384
- return [];
385
- }
386
- }
387
- const stackMemoryContextLoader = new StackMemoryContextLoader();
388
- export {
389
- StackMemoryContextLoader,
390
- stackMemoryContextLoader
391
- };
@@ -1,17 +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 { RalphStackMemoryBridge } from "./bridge/ralph-stackmemory-bridge.js";
6
- import { ContextBudgetManager } from "./context/context-budget-manager.js";
7
- import { StateReconciler } from "./state/state-reconciler.js";
8
- import { IterationLifecycle } from "./lifecycle/iteration-lifecycle.js";
9
- import { PerformanceOptimizer } from "./performance/performance-optimizer.js";
10
- export * from "./types.js";
11
- export {
12
- ContextBudgetManager,
13
- IterationLifecycle,
14
- PerformanceOptimizer,
15
- RalphStackMemoryBridge,
16
- StateReconciler
17
- };