@stackmemoryai/stackmemory 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +3 -1
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/codex-sm.js +51 -11
  11. package/dist/src/cli/commands/brain.js +206 -0
  12. package/dist/src/cli/commands/company-os.js +184 -0
  13. package/dist/src/cli/commands/context.js +5 -0
  14. package/dist/src/cli/commands/operator.js +127 -0
  15. package/dist/src/cli/commands/orchestrate.js +2 -0
  16. package/dist/src/cli/commands/orchestrator.js +3 -2
  17. package/dist/src/cli/commands/patterns.js +254 -0
  18. package/dist/src/cli/commands/portal.js +161 -0
  19. package/dist/src/cli/commands/scaffold.js +92 -0
  20. package/dist/src/cli/commands/setup.js +1 -4
  21. package/dist/src/cli/commands/sync.js +253 -0
  22. package/dist/src/cli/commands/tasks.js +130 -1
  23. package/dist/src/cli/commands/vision.js +221 -0
  24. package/dist/src/cli/hermes-sm.js +224 -0
  25. package/dist/src/cli/index.js +15 -10
  26. package/dist/src/cli/utils/real-cli-bin.js +72 -0
  27. package/dist/src/core/brain/brain-store.js +187 -0
  28. package/dist/src/core/brain/brain-sync.js +193 -0
  29. package/dist/src/core/brain/index.js +78 -0
  30. package/dist/src/core/brain/types.js +10 -0
  31. package/dist/src/core/cache/token-estimator.js +24 -1
  32. package/dist/src/core/config/feature-flags.js +2 -6
  33. package/dist/src/core/context/frame-database.js +44 -0
  34. package/dist/src/core/context/recursive-context-manager.js +1 -1
  35. package/dist/src/core/context/rehydration.js +2 -1
  36. package/dist/src/core/database/sqlite-adapter.js +14 -1
  37. package/dist/src/core/models/model-router.js +33 -1
  38. package/dist/src/core/models/provider-pricing.js +58 -4
  39. package/dist/src/core/patterns/index.js +22 -0
  40. package/dist/src/core/patterns/pattern-applier.js +39 -0
  41. package/dist/src/core/patterns/pattern-observer.js +157 -0
  42. package/dist/src/core/patterns/pattern-store.js +259 -0
  43. package/dist/src/core/patterns/types.js +19 -0
  44. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  45. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  46. package/dist/src/core/skill-packs/types.js +14 -1
  47. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  48. package/dist/src/core/storage/cloud-sync.js +574 -0
  49. package/dist/src/core/storage/two-tier-storage.js +5 -1
  50. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  51. package/dist/src/core/tasks/md-task-parser.js +138 -0
  52. package/dist/src/core/vision/index.js +27 -0
  53. package/dist/src/core/vision/signals.js +79 -0
  54. package/dist/src/core/vision/types.js +22 -0
  55. package/dist/src/core/vision/vision-file.js +146 -0
  56. package/dist/src/core/vision/vision-loop.js +220 -0
  57. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  58. package/dist/src/daemon/daemon-config.js +45 -0
  59. package/dist/src/daemon/services/desire-path-service.js +566 -0
  60. package/dist/src/daemon/services/research-stream-service.js +320 -0
  61. package/dist/src/daemon/services/telemetry-service.js +192 -0
  62. package/dist/src/daemon/unified-daemon.js +28 -1
  63. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  64. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  65. package/dist/src/features/operator/adapter-factory.js +62 -0
  66. package/dist/src/features/operator/browser-adapter.js +109 -0
  67. package/dist/src/features/operator/desktop-adapter.js +125 -0
  68. package/dist/src/features/operator/index.js +39 -0
  69. package/dist/src/features/operator/llm-decision.js +137 -0
  70. package/dist/src/features/operator/operator-logger.js +92 -0
  71. package/dist/src/features/operator/overnight-runner.js +327 -0
  72. package/dist/src/features/operator/screen-adapter.js +91 -0
  73. package/dist/src/features/operator/session-manager.js +127 -0
  74. package/dist/src/features/operator/state-machine.js +227 -0
  75. package/dist/src/features/operator/task-queue.js +81 -0
  76. package/dist/src/features/portal/index.js +26 -0
  77. package/dist/src/features/portal/server.js +240 -0
  78. package/dist/src/features/portal/types.js +14 -0
  79. package/dist/src/features/portal/ui.js +195 -0
  80. package/dist/src/features/tasks/task-aware-context.js +2 -1
  81. package/dist/src/features/tui/simple-monitor.js +0 -23
  82. package/dist/src/features/tui/swarm-monitor.js +8 -66
  83. package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
  84. package/dist/src/features/web/client/lib/utils.js +12 -0
  85. package/dist/src/features/web/client/stores/session-store.js +12 -0
  86. package/dist/src/features/web/server/gcp-billing.js +76 -0
  87. package/dist/src/features/web/server/index.js +10 -0
  88. package/dist/src/features/web/server/spend-calculator.js +228 -0
  89. package/dist/src/hooks/schemas.js +4 -1
  90. package/dist/src/integrations/anthropic/client.js +3 -2
  91. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  92. package/dist/src/integrations/claude-code/subagent-client.js +218 -11
  93. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  94. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  95. package/dist/src/integrations/linear/webhook-server.js +18 -22
  96. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  97. package/dist/src/integrations/mcp/handlers/index.js +27 -52
  98. package/dist/src/integrations/mcp/server.js +122 -335
  99. package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
  100. package/dist/src/integrations/mcp/tool-definitions.js +111 -510
  101. package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
  102. package/dist/src/orchestrators/multimodal/determinism.js +2 -1
  103. package/dist/src/orchestrators/multimodal/harness.js +2 -1
  104. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  105. package/dist/src/utils/process-cleanup.js +1 -7
  106. package/docs/README.md +42 -0
  107. package/docs/guides/README_INSTALL.md +208 -0
  108. package/package.json +18 -9
  109. package/scripts/claude-code-wrapper.sh +11 -0
  110. package/scripts/claude-sm-setup.sh +12 -1
  111. package/scripts/codex-wrapper.sh +11 -0
  112. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  113. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  114. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  115. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  116. package/scripts/hooks/cleanup-shell.sh +12 -1
  117. package/scripts/hooks/task-complete.sh +12 -1
  118. package/scripts/install-code-execution-hooks.sh +12 -1
  119. package/scripts/install-sweep-hook.sh +12 -0
  120. package/scripts/install.sh +11 -0
  121. package/scripts/opencode-wrapper.sh +11 -0
  122. package/scripts/portal/cloud-init.yaml +69 -0
  123. package/scripts/portal/setup.sh +69 -0
  124. package/scripts/portal/stackmemory-portal.service +34 -0
  125. package/scripts/setup-claude-integration.sh +12 -1
  126. package/scripts/smoke-init-db.sh +23 -0
  127. package/scripts/stackmemory-daemon.sh +11 -0
  128. package/scripts/verify-dist.cjs +11 -4
  129. package/dist/src/cli/commands/ralph.js +0 -1053
  130. package/dist/src/hooks/diffmem-hooks.js +0 -376
  131. package/dist/src/integrations/diffmem/client.js +0 -208
  132. package/dist/src/integrations/diffmem/config.js +0 -14
  133. package/dist/src/integrations/greptile/client.js +0 -101
  134. package/dist/src/integrations/greptile/config.js +0 -14
  135. package/dist/src/integrations/greptile/index.js +0 -11
  136. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
  137. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  138. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  139. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  140. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  141. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  142. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
  143. package/dist/src/integrations/ralph/index.js +0 -17
  144. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
  145. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  146. package/dist/src/integrations/ralph/loopmax.js +0 -488
  147. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  148. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  149. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  150. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  151. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  152. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  153. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  154. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  155. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  156. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  157. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
  158. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  159. package/scripts/ralph-loop-implementation.js +0 -404
  160. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  161. /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
  162. /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
@@ -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,354 +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 { ContextRetriever } from "../../../core/retrieval/context-retriever.js";
8
- import { sessionManager } from "../../../core/session/index.js";
9
- import { ContextBudgetManager } from "./context-budget-manager.js";
10
- class StackMemoryContextLoader {
11
- frameManager;
12
- contextRetriever;
13
- budgetManager;
14
- config;
15
- constructor(config) {
16
- this.config = {
17
- maxTokens: 3200,
18
- // Leave room for task description
19
- lookbackDays: 30,
20
- similarityThreshold: 0.7,
21
- patternDetectionEnabled: true,
22
- includeFailedAttempts: true,
23
- crossSessionSearch: true,
24
- ...config
25
- };
26
- this.budgetManager = new ContextBudgetManager({
27
- maxTokens: this.config.maxTokens,
28
- priorityWeights: {
29
- task: 0.15,
30
- recentWork: 0.3,
31
- patterns: 0.25,
32
- decisions: 0.2,
33
- dependencies: 0.1
34
- }
35
- });
36
- logger.info("StackMemory context loader initialized", {
37
- maxTokens: this.config.maxTokens,
38
- lookbackDays: this.config.lookbackDays,
39
- patternDetection: this.config.patternDetectionEnabled
40
- });
41
- }
42
- async initialize() {
43
- try {
44
- await sessionManager.initialize();
45
- const session = await sessionManager.getOrCreateSession({});
46
- if (session.database) {
47
- this.frameManager = new FrameManager(
48
- session.database,
49
- session.projectId
50
- );
51
- this.contextRetriever = new ContextRetriever(session.database);
52
- }
53
- logger.info("Context loader initialized successfully");
54
- } catch (error) {
55
- logger.error("Failed to initialize context loader", error);
56
- throw error;
57
- }
58
- }
59
- /**
60
- * Load context for Ralph loop initialization
61
- */
62
- async loadInitialContext(request) {
63
- logger.info("Loading initial context for Ralph loop", {
64
- task: request.task.substring(0, 100),
65
- usePatterns: request.usePatterns,
66
- useSimilarTasks: request.useSimilarTasks
67
- });
68
- const sources = [];
69
- let totalTokens = 0;
70
- try {
71
- if (request.useSimilarTasks) {
72
- const similarTasks2 = await this.findSimilarTasks(request.task);
73
- if (similarTasks2.length > 0) {
74
- const tasksContext = await this.extractTaskContext(similarTasks2);
75
- sources.push({
76
- type: "similar_tasks",
77
- weight: 0.3,
78
- content: tasksContext,
79
- tokens: this.budgetManager.estimateTokens(tasksContext)
80
- });
81
- totalTokens += sources[sources.length - 1].tokens;
82
- }
83
- }
84
- if (request.usePatterns) {
85
- const patterns2 = await this.extractRelevantPatterns(request.task);
86
- if (patterns2.length > 0) {
87
- const patternsContext = await this.formatPatterns(patterns2);
88
- sources.push({
89
- type: "historical_patterns",
90
- weight: 0.25,
91
- content: patternsContext,
92
- tokens: this.budgetManager.estimateTokens(patternsContext)
93
- });
94
- totalTokens += sources[sources.length - 1].tokens;
95
- }
96
- }
97
- const decisions = await this.loadRecentDecisions();
98
- if (decisions.length > 0) {
99
- const decisionsContext = this.formatDecisions(decisions);
100
- sources.push({
101
- type: "recent_decisions",
102
- weight: 0.2,
103
- content: decisionsContext,
104
- tokens: this.budgetManager.estimateTokens(decisionsContext)
105
- });
106
- totalTokens += sources[sources.length - 1].tokens;
107
- }
108
- const projectContext = await this.loadProjectContext(request.task);
109
- if (projectContext) {
110
- sources.push({
111
- type: "project_context",
112
- weight: 0.15,
113
- content: projectContext,
114
- tokens: this.budgetManager.estimateTokens(projectContext)
115
- });
116
- totalTokens += sources[sources.length - 1].tokens;
117
- }
118
- const budgetedSources = this.budgetManager.allocateBudget({ sources });
119
- const synthesizedContext = this.synthesizeContext(
120
- budgetedSources.sources
121
- );
122
- logger.info("Context loaded successfully", {
123
- totalSources: sources.length,
124
- totalTokens,
125
- budgetedTokens: budgetedSources.sources.reduce(
126
- (sum, s) => sum + s.tokens,
127
- 0
128
- )
129
- });
130
- return {
131
- context: synthesizedContext,
132
- sources: budgetedSources.sources,
133
- metadata: {
134
- totalTokens: budgetedSources.sources.reduce(
135
- (sum, s) => sum + s.tokens,
136
- 0
137
- ),
138
- sourcesCount: budgetedSources.sources.length,
139
- patterns: request.usePatterns ? patterns : [],
140
- similarTasks: request.useSimilarTasks ? similarTasks : []
141
- }
142
- };
143
- } catch (error) {
144
- logger.error("Failed to load context", error);
145
- throw error;
146
- }
147
- }
148
- /**
149
- * Find similar tasks from StackMemory history
150
- */
151
- async findSimilarTasks(taskDescription) {
152
- if (!this.frameManager || !this.contextRetriever) {
153
- return [];
154
- }
155
- try {
156
- const searchResults = await this.contextRetriever.search(
157
- taskDescription,
158
- {
159
- maxResults: 10,
160
- types: ["task", "subtask"],
161
- timeFilter: {
162
- days: this.config.lookbackDays
163
- }
164
- }
165
- );
166
- const similarities = [];
167
- for (const result of searchResults) {
168
- const similarity = this.calculateTaskSimilarity(
169
- taskDescription,
170
- result.content
171
- );
172
- if (similarity >= this.config.similarityThreshold) {
173
- similarities.push({
174
- frameId: result.frameId,
175
- task: result.content,
176
- similarity,
177
- outcome: await this.determineTaskOutcome(result.frameId),
178
- createdAt: result.timestamp,
179
- sessionId: result.sessionId || "unknown"
180
- });
181
- }
182
- }
183
- return similarities.sort((a, b) => {
184
- const aScore = a.similarity * (a.outcome === "success" ? 1.2 : 1);
185
- const bScore = b.similarity * (b.outcome === "success" ? 1.2 : 1);
186
- return bScore - aScore;
187
- }).slice(0, 5);
188
- } catch (error) {
189
- logger.error("Failed to find similar tasks", error);
190
- return [];
191
- }
192
- }
193
- /**
194
- * Extract relevant patterns from historical data
195
- */
196
- async extractRelevantPatterns(_taskDescription) {
197
- return [];
198
- }
199
- /**
200
- * Load recent decisions that might be relevant
201
- */
202
- async loadRecentDecisions() {
203
- return [];
204
- }
205
- /**
206
- * Load project-specific context
207
- */
208
- async loadProjectContext(taskDescription) {
209
- try {
210
- if (!this.contextRetriever) return null;
211
- const projectInfo = await this.contextRetriever.search(taskDescription, {
212
- maxResults: 3,
213
- types: ["task"],
214
- projectSpecific: true
215
- });
216
- if (projectInfo.length === 0) return null;
217
- const contextParts = [];
218
- for (const info of projectInfo) {
219
- contextParts.push(`Project context: ${info.content}`);
220
- }
221
- return contextParts.join("\n\n");
222
- } catch (error) {
223
- logger.error("Failed to load project context", error);
224
- return null;
225
- }
226
- }
227
- /**
228
- * Calculate similarity between task descriptions
229
- */
230
- calculateTaskSimilarity(task1, task2) {
231
- const words1 = new Set(task1.toLowerCase().split(/\s+/));
232
- const words2 = new Set(task2.toLowerCase().split(/\s+/));
233
- const intersection = new Set([...words1].filter((x) => words2.has(x)));
234
- const union = /* @__PURE__ */ new Set([...words1, ...words2]);
235
- return intersection.size / union.size;
236
- }
237
- /**
238
- * Calculate pattern relevance to current task
239
- */
240
- calculatePatternRelevance(taskDescription, pattern) {
241
- const taskWords = taskDescription.toLowerCase().split(/\s+/);
242
- const patternWords = pattern.toLowerCase().split(/\s+/);
243
- let matches = 0;
244
- for (const word of taskWords) {
245
- if (patternWords.some((p) => p.includes(word) || word.includes(p))) {
246
- matches++;
247
- }
248
- }
249
- return matches / taskWords.length;
250
- }
251
- /**
252
- * Extract context from similar tasks
253
- */
254
- async extractTaskContext(similarities) {
255
- const contextParts = [];
256
- contextParts.push("Similar tasks from history:");
257
- for (const sim of similarities) {
258
- contextParts.push(
259
- `
260
- Task: ${sim.task}
261
- Outcome: ${sim.outcome}
262
- Similarity: ${Math.round(sim.similarity * 100)}%
263
- ${sim.outcome === "success" ? "\u2705 Successfully completed" : "\u274C Had issues"}
264
- `.trim()
265
- );
266
- }
267
- return contextParts.join("\n\n");
268
- }
269
- /**
270
- * Format patterns for context inclusion
271
- */
272
- async formatPatterns(patterns2) {
273
- const contextParts = [];
274
- contextParts.push("Relevant patterns from experience:");
275
- for (const pattern of patterns2) {
276
- contextParts.push(
277
- `
278
- Pattern: ${pattern.pattern}
279
- Type: ${pattern.type}
280
- Frequency: ${pattern.frequency} occurrences
281
- ${pattern.resolution ? `Resolution: ${pattern.resolution}` : ""}
282
- Relevance: ${Math.round(pattern.relevance * 100)}%
283
- `.trim()
284
- );
285
- }
286
- return contextParts.join("\n\n");
287
- }
288
- /**
289
- * Format decisions for context inclusion
290
- */
291
- formatDecisions(decisions) {
292
- const contextParts = [];
293
- contextParts.push("Recent successful decisions:");
294
- for (const decision of decisions) {
295
- contextParts.push(
296
- `
297
- Decision: ${decision.decision}
298
- Reasoning: ${decision.reasoning}
299
- Date: ${new Date(decision.timestamp).toLocaleDateString()}
300
- `.trim()
301
- );
302
- }
303
- return contextParts.join("\n\n");
304
- }
305
- /**
306
- * Synthesize all context sources into coherent input
307
- */
308
- synthesizeContext(sources) {
309
- if (sources.length === 0) {
310
- return "No relevant historical context found.";
311
- }
312
- const contextParts = [];
313
- contextParts.push("Context from StackMemory:");
314
- const sortedSources = sources.sort((a, b) => b.weight - a.weight);
315
- for (const source of sortedSources) {
316
- contextParts.push(
317
- `
318
- --- ${source.type.replace("_", " ").toUpperCase()} ---`
319
- );
320
- contextParts.push(source.content);
321
- }
322
- contextParts.push(
323
- "\nUse this context to inform your approach to the current task."
324
- );
325
- return contextParts.join("\n");
326
- }
327
- /**
328
- * Determine task outcome from frame history
329
- */
330
- async determineTaskOutcome(frameId) {
331
- try {
332
- if (!this.frameManager) return "unknown";
333
- const frame = await this.frameManager.getFrame(frameId);
334
- if (!frame) return "unknown";
335
- if (frame.state === "closed" && frame.outputs) {
336
- return "success";
337
- }
338
- return frame.state === "closed" ? "failure" : "unknown";
339
- } catch {
340
- return "unknown";
341
- }
342
- }
343
- /**
344
- * Get examples of a specific pattern
345
- */
346
- async getPatternExamples(_pattern) {
347
- return [];
348
- }
349
- }
350
- const stackMemoryContextLoader = new StackMemoryContextLoader();
351
- export {
352
- StackMemoryContextLoader,
353
- stackMemoryContextLoader
354
- };
@@ -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
- };