@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,635 +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 * as fs from "fs/promises";
6
- import * as path from "path";
7
- import { logger } from "../../../core/monitoring/logger.js";
8
- import { FrameManager } from "../../../core/context/index.js";
9
- import { sessionManager } from "../../../core/session/index.js";
10
- class RalphDebugger {
11
- frameManager;
12
- activeSessions = /* @__PURE__ */ new Map();
13
- config;
14
- constructor(config) {
15
- this.config = {
16
- enableRealTimeMonitoring: true,
17
- captureDetailedTrace: true,
18
- generateVisualization: true,
19
- exportFormat: "html",
20
- maxTraceDepth: 50,
21
- ...config
22
- };
23
- logger.info("Ralph debugger initialized", this.config);
24
- }
25
- async initialize() {
26
- try {
27
- await sessionManager.initialize();
28
- const session = await sessionManager.getOrCreateSession({});
29
- if (session.database) {
30
- this.frameManager = new FrameManager(
31
- session.database,
32
- session.projectId
33
- );
34
- }
35
- logger.info("Debugger initialized successfully");
36
- } catch (error) {
37
- logger.error("Failed to initialize debugger", error);
38
- throw error;
39
- }
40
- }
41
- /**
42
- * Start debugging a Ralph loop
43
- */
44
- async startDebugSession(loopId, ralphDir) {
45
- logger.info("Starting debug session", { loopId, ralphDir });
46
- const session = {
47
- id: `debug-${Date.now()}`,
48
- loopId,
49
- ralphDir,
50
- startTime: Date.now(),
51
- iterations: [],
52
- contextFlow: [],
53
- performance: {
54
- iterationTimes: [],
55
- memoryUsage: [],
56
- contextSizes: [],
57
- averageIterationTime: 0,
58
- peakMemory: 0,
59
- contextEfficiency: 0
60
- },
61
- realTimeMonitoring: this.config.enableRealTimeMonitoring
62
- };
63
- this.activeSessions.set(loopId, session);
64
- if (this.config.enableRealTimeMonitoring) {
65
- await this.startRealTimeMonitoring(session);
66
- }
67
- return session;
68
- }
69
- /**
70
- * Generate comprehensive debug report
71
- */
72
- async generateDebugReport(loopId) {
73
- const session = this.activeSessions.get(loopId);
74
- if (!session) {
75
- throw new Error(`No debug session found for loop ${loopId}`);
76
- }
77
- logger.info("Generating debug report", { loopId });
78
- const report = {
79
- sessionId: session.id,
80
- loopId,
81
- generatedAt: Date.now(),
82
- summary: await this.generateSummary(session),
83
- iterationAnalysis: await this.analyzeIterations(session),
84
- contextAnalysis: await this.analyzeContextFlow(session),
85
- performanceAnalysis: await this.analyzePerformance(session),
86
- visualization: this.config.generateVisualization ? await this.generateVisualization(session) : void 0,
87
- recommendations: await this.generateRecommendations(session),
88
- exportPath: ""
89
- };
90
- const exportPath = await this.exportReport(report);
91
- report.exportPath = exportPath;
92
- logger.info("Debug report generated", { loopId, exportPath });
93
- return report;
94
- }
95
- /**
96
- * Create visual timeline of loop execution
97
- */
98
- async generateLoopTimeline(loopId) {
99
- const session = this.activeSessions.get(loopId);
100
- if (!session) {
101
- throw new Error(`No debug session found for loop ${loopId}`);
102
- }
103
- const timeline = {
104
- title: `Ralph Loop Timeline: ${loopId}`,
105
- startTime: session.startTime,
106
- iterations: session.iterations.map((iter) => ({
107
- iteration: iter.iteration,
108
- startTime: iter.startTime,
109
- endTime: iter.endTime,
110
- duration: iter.endTime - iter.startTime,
111
- success: iter.success,
112
- changes: iter.changes?.length || 0,
113
- errors: iter.errors?.length || 0,
114
- contextSize: iter.contextSize,
115
- phase: iter.phase
116
- })),
117
- totalDuration: session.performance.iterationTimes.reduce(
118
- (sum, time) => sum + time,
119
- 0
120
- )
121
- };
122
- const html = await this.generateTimelineHTML(timeline);
123
- const timelinePath = path.join(".ralph-debug", `timeline-${loopId}.html`);
124
- await fs.mkdir(path.dirname(timelinePath), { recursive: true });
125
- await fs.writeFile(timelinePath, html);
126
- return timelinePath;
127
- }
128
- /**
129
- * Create context flow diagram
130
- */
131
- async generateContextFlowDiagram(loopId) {
132
- const session = this.activeSessions.get(loopId);
133
- if (!session) {
134
- throw new Error(`No debug session found for loop ${loopId}`);
135
- }
136
- const diagram = {
137
- id: `context-flow-${loopId}`,
138
- nodes: [],
139
- edges: [],
140
- metrics: {
141
- totalNodes: 0,
142
- totalEdges: 0,
143
- avgContextSize: 0,
144
- maxContextSize: 0
145
- }
146
- };
147
- for (let i = 0; i < session.iterations.length; i++) {
148
- const iteration = session.iterations[i];
149
- diagram.nodes.push({
150
- id: `iter-${iteration.iteration}`,
151
- type: "iteration",
152
- label: `Iteration ${iteration.iteration}`,
153
- size: iteration.contextSize || 100,
154
- color: iteration.success ? "#4CAF50" : "#F44336",
155
- metadata: {
156
- duration: iteration.endTime - iteration.startTime,
157
- changes: iteration.changes?.length || 0,
158
- errors: iteration.errors?.length || 0
159
- }
160
- });
161
- if (i < session.iterations.length - 1) {
162
- diagram.edges.push({
163
- id: `edge-${i}-${i + 1}`,
164
- from: `iter-${iteration.iteration}`,
165
- to: `iter-${session.iterations[i + 1].iteration}`,
166
- type: "sequence",
167
- weight: iteration.contextSize || 1
168
- });
169
- }
170
- }
171
- diagram.metrics = {
172
- totalNodes: diagram.nodes.length,
173
- totalEdges: diagram.edges.length,
174
- avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce(
175
- (sum, size) => sum + size,
176
- 0
177
- ) / session.performance.contextSizes.length : 0,
178
- maxContextSize: Math.max(...session.performance.contextSizes)
179
- };
180
- return diagram;
181
- }
182
- /**
183
- * Real-time monitoring of loop execution
184
- */
185
- async startRealTimeMonitoring(session) {
186
- const monitoringInterval = setInterval(async () => {
187
- try {
188
- await this.captureIterationTrace(session);
189
- await this.updatePerformanceMetrics(session);
190
- } catch (error) {
191
- logger.error("Monitoring error", error);
192
- }
193
- }, 1e3);
194
- session.monitoringInterval = monitoringInterval;
195
- }
196
- /**
197
- * Capture detailed trace of current iteration
198
- */
199
- async captureIterationTrace(session) {
200
- try {
201
- const statePath = path.join(session.ralphDir, "state.json");
202
- const iterationPath = path.join(session.ralphDir, "iteration.txt");
203
- let _currentState = {};
204
- let currentIteration = 0;
205
- try {
206
- const stateData = await fs.readFile(statePath, "utf8");
207
- _currentState = JSON.parse(stateData);
208
- const iterData = await fs.readFile(iterationPath, "utf8");
209
- currentIteration = parseInt(iterData.trim()) || 0;
210
- } catch {
211
- return;
212
- }
213
- const lastTrace = session.iterations[session.iterations.length - 1];
214
- if (lastTrace?.iteration === currentIteration) {
215
- return;
216
- }
217
- const trace = {
218
- iteration: currentIteration,
219
- startTime: Date.now(),
220
- endTime: Date.now(),
221
- // Will be updated when iteration completes
222
- phase: this.determineIterationPhase(session.ralphDir),
223
- contextSize: await this.calculateContextSize(session.ralphDir),
224
- success: false,
225
- // Will be updated
226
- changes: [],
227
- errors: [],
228
- memoryUsage: process.memoryUsage().heapUsed,
229
- stackTrace: this.captureStackTrace()
230
- };
231
- session.iterations.push(trace);
232
- } catch (error) {
233
- logger.debug("Failed to capture iteration trace", error);
234
- }
235
- }
236
- /**
237
- * Update performance metrics
238
- */
239
- async updatePerformanceMetrics(session) {
240
- const currentMemory = process.memoryUsage().heapUsed;
241
- session.performance.memoryUsage.push(currentMemory);
242
- session.performance.peakMemory = Math.max(
243
- session.performance.peakMemory,
244
- currentMemory
245
- );
246
- const contextSize = await this.calculateContextSize(session.ralphDir);
247
- session.performance.contextSizes.push(contextSize);
248
- if (session.performance.iterationTimes.length > 0) {
249
- session.performance.averageIterationTime = session.performance.iterationTimes.reduce(
250
- (sum, time) => sum + time,
251
- 0
252
- ) / session.performance.iterationTimes.length;
253
- }
254
- if (session.performance.contextSizes.length > 0) {
255
- const avgContextSize = session.performance.contextSizes.reduce((sum, size) => sum + size, 0) / session.performance.contextSizes.length;
256
- session.performance.contextEfficiency = Math.max(
257
- 0,
258
- 1 - avgContextSize / 1e4
259
- );
260
- }
261
- }
262
- /**
263
- * Generate executive summary
264
- */
265
- async generateSummary(session) {
266
- const totalIterations = session.iterations.length;
267
- const successfulIterations = session.iterations.filter(
268
- (i) => i.success
269
- ).length;
270
- const totalDuration = session.performance.iterationTimes.reduce(
271
- (sum, time) => sum + time,
272
- 0
273
- );
274
- return {
275
- loopId: session.loopId,
276
- totalIterations,
277
- successfulIterations,
278
- successRate: totalIterations > 0 ? successfulIterations / totalIterations : 0,
279
- totalDuration,
280
- averageIterationTime: session.performance.averageIterationTime,
281
- peakMemoryUsage: session.performance.peakMemory,
282
- contextEfficiency: session.performance.contextEfficiency,
283
- status: totalIterations > 0 && session.iterations[session.iterations.length - 1].success ? "completed" : "in_progress"
284
- };
285
- }
286
- /**
287
- * Analyze iteration patterns
288
- */
289
- async analyzeIterations(session) {
290
- if (session.iterations.length === 0) return { patterns: [], insights: [] };
291
- const patterns = [];
292
- const insights = [];
293
- const durations = session.iterations.map((i) => i.endTime - i.startTime);
294
- const avgDuration = durations.reduce((sum, d) => sum + d, 0) / durations.length;
295
- if (durations.some((d) => d > avgDuration * 2)) {
296
- patterns.push("Variable iteration times detected");
297
- insights.push(
298
- "Some iterations took significantly longer than average - investigate bottlenecks"
299
- );
300
- }
301
- const consecutiveFailures = this.findConsecutiveFailures(
302
- session.iterations
303
- );
304
- if (consecutiveFailures.length > 2) {
305
- patterns.push("Multiple consecutive failures detected");
306
- insights.push(
307
- "Consider adjusting approach or criteria after consecutive failures"
308
- );
309
- }
310
- if (session.performance.contextSizes.length > 1) {
311
- const contextGrowth = session.performance.contextSizes[session.performance.contextSizes.length - 1] - session.performance.contextSizes[0];
312
- if (contextGrowth > 1e3) {
313
- patterns.push("Significant context growth");
314
- insights.push(
315
- "Context is growing rapidly - consider context pruning strategies"
316
- );
317
- }
318
- }
319
- return { patterns, insights };
320
- }
321
- /**
322
- * Analyze context flow
323
- */
324
- async analyzeContextFlow(session) {
325
- return {
326
- avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce(
327
- (sum, size) => sum + size,
328
- 0
329
- ) / session.performance.contextSizes.length : 0,
330
- maxContextSize: Math.max(...session.performance.contextSizes),
331
- contextGrowthRate: this.calculateGrowthRate(
332
- session.performance.contextSizes
333
- ),
334
- efficiency: session.performance.contextEfficiency
335
- };
336
- }
337
- /**
338
- * Analyze performance metrics
339
- */
340
- async analyzePerformance(session) {
341
- return {
342
- memoryEfficiency: this.calculateMemoryEfficiency(
343
- session.performance.memoryUsage
344
- ),
345
- iterationEfficiency: session.performance.averageIterationTime,
346
- resourceUtilization: {
347
- cpu: "N/A",
348
- // Would need CPU monitoring
349
- memory: session.performance.peakMemory,
350
- context: session.performance.contextEfficiency
351
- }
352
- };
353
- }
354
- /**
355
- * Generate visualization HTML
356
- */
357
- async generateVisualization(session) {
358
- const htmlContent = await this.generateVisualizationHTML(session);
359
- const vizPath = path.join(
360
- ".ralph-debug",
361
- `visualization-${session.loopId}.html`
362
- );
363
- await fs.mkdir(path.dirname(vizPath), { recursive: true });
364
- await fs.writeFile(vizPath, htmlContent);
365
- return {
366
- id: `viz-${session.loopId}`,
367
- type: "interactive_timeline",
368
- htmlPath: vizPath,
369
- data: {
370
- iterations: session.iterations,
371
- performance: session.performance,
372
- contextFlow: session.contextFlow
373
- },
374
- metadata: {
375
- generatedAt: Date.now(),
376
- format: "html",
377
- interactive: true
378
- }
379
- };
380
- }
381
- /**
382
- * Generate recommendations
383
- */
384
- async generateRecommendations(session) {
385
- const recommendations = [];
386
- if (session.performance.averageIterationTime > 3e4) {
387
- recommendations.push(
388
- "Consider breaking down complex tasks into smaller iterations"
389
- );
390
- }
391
- if (session.performance.contextEfficiency < 0.7) {
392
- recommendations.push(
393
- "Optimize context management - consider using context budgeting"
394
- );
395
- }
396
- const successRate = session.iterations.filter((i) => i.success).length / Math.max(1, session.iterations.length);
397
- if (successRate < 0.5) {
398
- recommendations.push(
399
- "Low success rate detected - review task criteria and approach"
400
- );
401
- }
402
- if (session.performance.peakMemory > 500 * 1024 * 1024) {
403
- recommendations.push(
404
- "High memory usage detected - investigate memory leaks"
405
- );
406
- }
407
- return recommendations;
408
- }
409
- /**
410
- * Export report in specified format
411
- */
412
- async exportReport(report) {
413
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
414
- const filename = `ralph-debug-${report.loopId}-${timestamp}`;
415
- let content;
416
- let extension;
417
- switch (this.config.exportFormat) {
418
- case "json":
419
- content = JSON.stringify(report, null, 2);
420
- extension = "json";
421
- break;
422
- case "markdown":
423
- content = this.generateMarkdownReport(report);
424
- extension = "md";
425
- break;
426
- case "html":
427
- default:
428
- content = this.generateHTMLReport(report);
429
- extension = "html";
430
- break;
431
- }
432
- const exportPath = path.join(".ralph-debug", `${filename}.${extension}`);
433
- await fs.mkdir(path.dirname(exportPath), { recursive: true });
434
- await fs.writeFile(exportPath, content);
435
- return exportPath;
436
- }
437
- // Helper methods
438
- determineIterationPhase(_ralphDir) {
439
- return "working";
440
- }
441
- async calculateContextSize(ralphDir) {
442
- try {
443
- const feedbackPath = path.join(ralphDir, "feedback.txt");
444
- const feedback = await fs.readFile(feedbackPath, "utf8");
445
- return feedback.length;
446
- } catch {
447
- return 0;
448
- }
449
- }
450
- captureStackTrace() {
451
- const stack = new Error().stack || "";
452
- return stack.split("\n").slice(1, 6).join("\n");
453
- }
454
- findConsecutiveFailures(iterations) {
455
- const failures = [];
456
- let currentStreak = 0;
457
- for (const iteration of iterations) {
458
- if (!iteration.success) {
459
- currentStreak++;
460
- } else {
461
- if (currentStreak > 0) {
462
- failures.push(currentStreak);
463
- }
464
- currentStreak = 0;
465
- }
466
- }
467
- if (currentStreak > 0) {
468
- failures.push(currentStreak);
469
- }
470
- return failures;
471
- }
472
- calculateGrowthRate(sizes) {
473
- if (sizes.length < 2) return 0;
474
- const first = sizes[0];
475
- const last = sizes[sizes.length - 1];
476
- return first > 0 ? (last - first) / first : 0;
477
- }
478
- calculateMemoryEfficiency(memoryUsage) {
479
- if (memoryUsage.length < 2) return 1;
480
- const min = Math.min(...memoryUsage);
481
- const max = Math.max(...memoryUsage);
482
- return max > 0 ? min / max : 1;
483
- }
484
- generateTimelineHTML(timeline) {
485
- return `
486
- <!DOCTYPE html>
487
- <html>
488
- <head>
489
- <title>${timeline.title}</title>
490
- <script src="https://d3js.org/d3.v7.min.js"></script>
491
- <style>
492
- body { font-family: Arial, sans-serif; margin: 20px; }
493
- .timeline { margin: 20px 0; }
494
- .iteration { margin: 10px 0; padding: 10px; border-left: 4px solid #ccc; }
495
- .success { border-left-color: #4CAF50; }
496
- .failure { border-left-color: #F44336; }
497
- </style>
498
- </head>
499
- <body>
500
- <h1>${timeline.title}</h1>
501
- <div class="timeline">
502
- ${timeline.iterations.map(
503
- (iter) => `
504
- <div class="iteration ${iter.success ? "success" : "failure"}">
505
- <h3>Iteration ${iter.iteration}</h3>
506
- <p>Duration: ${iter.duration}ms</p>
507
- <p>Changes: ${iter.changes} | Errors: ${iter.errors}</p>
508
- <p>Context Size: ${iter.contextSize}</p>
509
- </div>
510
- `
511
- ).join("")}
512
- </div>
513
- </body>
514
- </html>
515
- `;
516
- }
517
- generateVisualizationHTML(session) {
518
- return `
519
- <!DOCTYPE html>
520
- <html>
521
- <head>
522
- <title>Ralph Loop Visualization - ${session.loopId}</title>
523
- <script src="https://d3js.org/d3.v7.min.js"></script>
524
- <style>
525
- body { font-family: Arial, sans-serif; margin: 20px; }
526
- .chart { margin: 20px 0; }
527
- .metric { display: inline-block; margin: 10px; padding: 10px; border: 1px solid #ccc; }
528
- </style>
529
- </head>
530
- <body>
531
- <h1>Ralph Loop Debug Visualization</h1>
532
- <div id="metrics">
533
- <div class="metric">
534
- <h3>Iterations</h3>
535
- <p>${session.iterations.length}</p>
536
- </div>
537
- <div class="metric">
538
- <h3>Avg Time</h3>
539
- <p>${Math.round(session.performance.averageIterationTime)}ms</p>
540
- </div>
541
- <div class="metric">
542
- <h3>Context Efficiency</h3>
543
- <p>${Math.round(session.performance.contextEfficiency * 100)}%</p>
544
- </div>
545
- </div>
546
- <div id="timeline" class="chart"></div>
547
- <script>
548
- // D3.js visualization code would go here
549
- console.log('Visualization data:', ${JSON.stringify(session)});
550
- </script>
551
- </body>
552
- </html>
553
- `;
554
- }
555
- generateMarkdownReport(report) {
556
- return `
557
- # Ralph Loop Debug Report
558
-
559
- **Loop ID:** ${report.loopId}
560
- **Generated:** ${new Date(report.generatedAt).toLocaleString()}
561
-
562
- ## Summary
563
- - **Total Iterations:** ${report.summary.totalIterations}
564
- - **Success Rate:** ${Math.round(report.summary.successRate * 100)}%
565
- - **Total Duration:** ${report.summary.totalDuration}ms
566
- - **Average Iteration Time:** ${Math.round(report.summary.averageIterationTime)}ms
567
-
568
- ## Performance Analysis
569
- - **Peak Memory:** ${Math.round(report.performanceAnalysis.resourceUtilization.memory / 1024 / 1024)}MB
570
- - **Context Efficiency:** ${Math.round(report.performanceAnalysis.resourceUtilization.context * 100)}%
571
-
572
- ## Recommendations
573
- ${report.recommendations.map((r) => `- ${r}`).join("\n")}
574
- `;
575
- }
576
- generateHTMLReport(report) {
577
- return `
578
- <!DOCTYPE html>
579
- <html>
580
- <head>
581
- <title>Ralph Debug Report - ${report.loopId}</title>
582
- <style>
583
- body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
584
- .summary { background: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0; }
585
- .metric { display: inline-block; margin: 10px; padding: 15px; background: white; border-radius: 4px; }
586
- .recommendations { background: #e3f2fd; padding: 15px; border-radius: 4px; }
587
- </style>
588
- </head>
589
- <body>
590
- <h1>Ralph Loop Debug Report</h1>
591
- <div class="summary">
592
- <h2>Executive Summary</h2>
593
- <div class="metric">
594
- <h3>${report.summary.totalIterations}</h3>
595
- <p>Total Iterations</p>
596
- </div>
597
- <div class="metric">
598
- <h3>${Math.round(report.summary.successRate * 100)}%</h3>
599
- <p>Success Rate</p>
600
- </div>
601
- <div class="metric">
602
- <h3>${Math.round(report.summary.averageIterationTime)}ms</h3>
603
- <p>Avg Iteration Time</p>
604
- </div>
605
- </div>
606
-
607
- <div class="recommendations">
608
- <h2>Recommendations</h2>
609
- <ul>
610
- ${report.recommendations.map((r) => `<li>${r}</li>`).join("")}
611
- </ul>
612
- </div>
613
- </body>
614
- </html>
615
- `;
616
- }
617
- /**
618
- * Stop debug session and cleanup
619
- */
620
- async stopDebugSession(loopId) {
621
- const session = this.activeSessions.get(loopId);
622
- if (!session) return;
623
- if (session.monitoringInterval) {
624
- clearInterval(session.monitoringInterval);
625
- }
626
- await this.generateDebugReport(loopId);
627
- this.activeSessions.delete(loopId);
628
- logger.info("Debug session stopped", { loopId });
629
- }
630
- }
631
- const ralphDebugger = new RalphDebugger();
632
- export {
633
- RalphDebugger,
634
- ralphDebugger
635
- };