@stackmemoryai/stackmemory 1.2.1 → 1.2.4

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 (100) hide show
  1. package/dist/src/cli/codex-sm.js +6 -8
  2. package/dist/src/cli/commands/config.js +0 -81
  3. package/dist/src/cli/commands/context-rehydrate.js +133 -47
  4. package/dist/src/cli/commands/db.js +35 -8
  5. package/dist/src/cli/commands/handoff.js +1 -1
  6. package/dist/src/cli/commands/linear.js +9 -0
  7. package/dist/src/cli/commands/ralph.js +2 -2
  8. package/dist/src/cli/commands/setup.js +2 -2
  9. package/dist/src/cli/commands/signup.js +3 -1
  10. package/dist/src/cli/commands/skills.js +123 -1
  11. package/dist/src/cli/commands/storage-tier.js +26 -8
  12. package/dist/src/cli/index.js +1 -57
  13. package/dist/src/core/config/feature-flags.js +0 -4
  14. package/dist/src/core/context/dual-stack-manager.js +10 -3
  15. package/dist/src/core/context/frame-database.js +32 -0
  16. package/dist/src/core/context/frame-handoff-manager.js +2 -2
  17. package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
  18. package/dist/src/core/context/index.js +2 -2
  19. package/dist/src/core/database/sqlite-adapter.js +161 -1
  20. package/dist/src/core/digest/frame-digest-integration.js +1 -1
  21. package/dist/src/core/digest/index.js +1 -1
  22. package/dist/src/core/execution/parallel-executor.js +5 -1
  23. package/dist/src/core/projects/project-isolation.js +18 -4
  24. package/dist/src/core/security/index.js +2 -0
  25. package/dist/src/core/security/input-sanitizer.js +23 -0
  26. package/dist/src/core/utils/update-checker.js +10 -6
  27. package/dist/src/daemon/daemon-config.js +2 -1
  28. package/dist/src/daemon/services/auto-save-service.js +121 -0
  29. package/dist/src/daemon/services/maintenance-service.js +76 -1
  30. package/dist/src/features/sweep/prompt-builder.js +2 -2
  31. package/dist/src/hooks/graphiti-hooks.js +149 -0
  32. package/dist/src/hooks/session-summary.js +30 -0
  33. package/dist/src/integrations/graphiti/linear-graphiti-bridge.js +115 -0
  34. package/dist/src/integrations/greptile/client.js +101 -0
  35. package/dist/src/integrations/greptile/config.js +14 -0
  36. package/dist/src/integrations/greptile/index.js +11 -0
  37. package/dist/src/integrations/greptile/types.js +4 -0
  38. package/dist/src/integrations/linear/config.js +3 -1
  39. package/dist/src/integrations/linear/sync.js +18 -5
  40. package/dist/src/integrations/linear/webhook.js +16 -0
  41. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
  42. package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
  43. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +456 -0
  44. package/dist/src/integrations/mcp/handlers/index.js +55 -1
  45. package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
  46. package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
  47. package/dist/src/integrations/mcp/handlers/trace-handlers.js +25 -9
  48. package/dist/src/integrations/mcp/index.js +2 -2
  49. package/dist/src/integrations/mcp/refactored-server.js +31 -10
  50. package/dist/src/integrations/mcp/server.js +27 -0
  51. package/dist/src/integrations/mcp/tool-definitions.js +215 -1
  52. package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
  53. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
  54. package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
  55. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
  56. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
  57. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
  58. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
  59. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
  60. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
  61. package/dist/src/skills/claude-skills.js +46 -103
  62. package/dist/src/skills/parallel-agent-skill.js +514 -0
  63. package/dist/src/utils/hook-installer.js +8 -0
  64. package/package.json +5 -5
  65. package/scripts/gepa/.before-optimize.md +140 -159
  66. package/scripts/gepa/config.json +7 -1
  67. package/scripts/gepa/evals/fixtures/api-endpoint.ts +31 -0
  68. package/scripts/gepa/evals/fixtures/brittle-integration.ts +38 -0
  69. package/scripts/gepa/evals/fixtures/fts5-triggers.sql +23 -0
  70. package/scripts/gepa/evals/fixtures/leaky-service.ts +70 -0
  71. package/scripts/gepa/evals/fixtures/mcp-dispatch-stub.ts +39 -0
  72. package/scripts/gepa/evals/fixtures/pr-diff.txt +24 -0
  73. package/scripts/gepa/evals/fixtures/unsafe-webhook.ts +34 -0
  74. package/scripts/gepa/evals/fixtures/unwrapped-db-op.ts +42 -0
  75. package/scripts/gepa/evals/stackmemory-tasks.jsonl +8 -0
  76. package/scripts/gepa/generations/gen-000/baseline.md +172 -159
  77. package/scripts/gepa/generations/gen-001/baseline.md +172 -159
  78. package/scripts/gepa/generations/gen-001/variant-a.md +156 -146
  79. package/scripts/gepa/generations/gen-001/variant-b.md +199 -170
  80. package/scripts/gepa/generations/gen-001/variant-c.md +127 -46
  81. package/scripts/gepa/generations/gen-001/variant-d.md +160 -107
  82. package/scripts/gepa/hooks/reflect.js +44 -5
  83. package/scripts/gepa/optimize.js +281 -39
  84. package/scripts/gepa/results/eval-1-baseline.json +187 -10
  85. package/scripts/gepa/results/eval-1-variant-a.json +188 -11
  86. package/scripts/gepa/results/eval-1-variant-b.json +188 -11
  87. package/scripts/gepa/results/eval-1-variant-c.json +168 -11
  88. package/scripts/gepa/results/eval-1-variant-d.json +169 -12
  89. package/scripts/gepa/state.json +18 -18
  90. package/scripts/install-claude-hooks-auto.js +8 -0
  91. package/templates/claude-hooks/cord-trace.js +225 -0
  92. package/dist/src/core/config/storage-config.js +0 -114
  93. package/dist/src/core/storage/chromadb-adapter.js +0 -379
  94. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
  95. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
  96. package/dist/src/skills/repo-ingestion-skill.js +0 -631
  97. package/templates/claude-hooks/chromadb-wrapper +0 -21
  98. /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
  99. /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
  100. /package/dist/src/core/session/{enhanced-handoff.js → handoff.js} +0 -0
@@ -0,0 +1,211 @@
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 TeamHandlers {
7
+ constructor(deps) {
8
+ this.deps = deps;
9
+ }
10
+ /**
11
+ * Get context from other agents working on the same project.
12
+ * Returns recent frames and shared anchors from other sessions.
13
+ */
14
+ async handleTeamContextGet(args) {
15
+ try {
16
+ const limit = args.limit ?? 10;
17
+ const types = args.types;
18
+ const since = args.since;
19
+ const projectId = this.getProjectId();
20
+ const runId = this.getRunId();
21
+ const frames = await this.deps.dbAdapter.getRecentFramesExcludingRun(
22
+ projectId,
23
+ runId,
24
+ { limit, types, since }
25
+ );
26
+ const sharedAnchors = await this.deps.dbAdapter.getSharedAnchors(
27
+ projectId,
28
+ { limit, since }
29
+ );
30
+ if (frames.length === 0 && sharedAnchors.length === 0) {
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: "No context from other agents found in this project."
36
+ }
37
+ ]
38
+ };
39
+ }
40
+ const frameSummaries = frames.map((f) => ({
41
+ frame_id: f.frame_id,
42
+ run_id: f.run_id,
43
+ name: f.name,
44
+ type: f.type,
45
+ state: f.state,
46
+ created_at: f.created_at,
47
+ digest_text: f.digest_text || null,
48
+ anchors: f.anchors.map((a) => ({
49
+ type: a.type,
50
+ text: a.text,
51
+ priority: a.priority
52
+ }))
53
+ }));
54
+ const sharedSummaries = sharedAnchors.map((a) => ({
55
+ type: a.type,
56
+ text: a.text,
57
+ priority: a.priority,
58
+ frame_name: a.frame_name,
59
+ run_id: a.run_id,
60
+ shared_by: a.metadata?.sharedBy
61
+ }));
62
+ const text = `Team Context (${frames.length} frames, ${sharedAnchors.length} shared anchors):
63
+
64
+ ` + frameSummaries.map(
65
+ (f) => `[${f.run_id?.slice(0, 8)}] ${f.name} (${f.type}, ${f.state})` + (f.digest_text ? `
66
+ ${f.digest_text}` : "") + (f.anchors.length > 0 ? "\n Anchors: " + f.anchors.map((a) => `${a.type}: ${a.text}`).join("; ") : "")
67
+ ).join("\n") + (sharedSummaries.length > 0 ? "\n\nShared Anchors:\n" + sharedSummaries.map((a) => ` [${a.type}] ${a.text} (priority: ${a.priority})`).join("\n") : "");
68
+ return {
69
+ content: [{ type: "text", text }],
70
+ metadata: { frames: frameSummaries, sharedAnchors: sharedSummaries }
71
+ };
72
+ } catch (error) {
73
+ logger.error(
74
+ "Error getting team context",
75
+ error instanceof Error ? error : new Error(String(error))
76
+ );
77
+ throw error;
78
+ }
79
+ }
80
+ /**
81
+ * Share a piece of context with other agents.
82
+ * Creates a high-priority anchor tagged with shared=true.
83
+ */
84
+ async handleTeamContextShare(args) {
85
+ try {
86
+ const { content, type = "FACT", priority = 8 } = args;
87
+ if (!content) {
88
+ throw new Error("content is required");
89
+ }
90
+ const validTypes = [
91
+ "FACT",
92
+ "DECISION",
93
+ "CONSTRAINT",
94
+ "INTERFACE_CONTRACT",
95
+ "TODO",
96
+ "RISK"
97
+ ];
98
+ if (!validTypes.includes(type)) {
99
+ throw new Error(
100
+ `Invalid type. Must be one of: ${validTypes.join(", ")}`
101
+ );
102
+ }
103
+ let frameId = this.deps.frameManager.getCurrentFrameId();
104
+ if (!frameId) {
105
+ frameId = this.deps.frameManager.createFrame({
106
+ type: "tool_scope",
107
+ name: "team_context_share"
108
+ });
109
+ }
110
+ const runId = this.getRunId();
111
+ this.deps.frameManager.addAnchor(type, content, priority, {
112
+ shared: true,
113
+ sharedBy: runId,
114
+ sharedAt: Date.now()
115
+ });
116
+ logger.info("Shared team context", { type, priority });
117
+ return {
118
+ content: [
119
+ {
120
+ type: "text",
121
+ text: `Shared ${type}: ${content}`
122
+ }
123
+ ]
124
+ };
125
+ } catch (error) {
126
+ logger.error(
127
+ "Error sharing team context",
128
+ error instanceof Error ? error : new Error(String(error))
129
+ );
130
+ throw error;
131
+ }
132
+ }
133
+ /**
134
+ * Search across all agents' context in the project.
135
+ * Uses FTS5 search without run_id filtering.
136
+ */
137
+ async handleTeamSearch(args) {
138
+ try {
139
+ const { query, limit = 20, include_events = false } = args;
140
+ if (!query) {
141
+ throw new Error("query is required");
142
+ }
143
+ const projectId = this.getProjectId();
144
+ const results = await this.deps.dbAdapter.search({
145
+ query,
146
+ projectId,
147
+ limit
148
+ });
149
+ if (results.length === 0) {
150
+ return {
151
+ content: [
152
+ {
153
+ type: "text",
154
+ text: `No results found for "${query}" across team sessions.`
155
+ }
156
+ ]
157
+ };
158
+ }
159
+ const frameResults = results.map((f) => ({
160
+ frame_id: f.frame_id,
161
+ run_id: f.run_id,
162
+ name: f.name,
163
+ type: f.type,
164
+ state: f.state,
165
+ score: f.score,
166
+ digest_text: f.digest_text || null,
167
+ created_at: f.created_at,
168
+ events: []
169
+ }));
170
+ if (include_events) {
171
+ for (const fr of frameResults) {
172
+ const events = await this.deps.dbAdapter.getFrameEvents(fr.frame_id, {
173
+ limit: 5
174
+ });
175
+ fr.events = events.map((e) => ({
176
+ event_type: e.event_type,
177
+ payload: e.payload,
178
+ ts: e.ts
179
+ }));
180
+ }
181
+ }
182
+ const text = `Team Search: ${results.length} results for "${query}":
183
+
184
+ ` + frameResults.map(
185
+ (f) => `[${f.run_id?.slice(0, 8)}] ${f.name} (score: ${f.score?.toFixed(3)})` + (f.digest_text ? `
186
+ ${f.digest_text}` : "")
187
+ ).join("\n");
188
+ return {
189
+ content: [{ type: "text", text }],
190
+ metadata: { results: frameResults, total: results.length }
191
+ };
192
+ } catch (error) {
193
+ logger.error(
194
+ "Error in team search",
195
+ error instanceof Error ? error : new Error(String(error))
196
+ );
197
+ throw error;
198
+ }
199
+ }
200
+ /** Extract projectId from the dbAdapter (protected field on DatabaseAdapter) */
201
+ getProjectId() {
202
+ return this.deps.dbAdapter.projectId;
203
+ }
204
+ /** Extract current runId from frameManager (private field) */
205
+ getRunId() {
206
+ return this.deps.frameManager.currentRunId;
207
+ }
208
+ }
209
+ export {
210
+ TeamHandlers
211
+ };
@@ -73,7 +73,10 @@ ${summaryText}`
73
73
  }
74
74
  return result;
75
75
  } catch (error) {
76
- logger.error("Error getting traces", error instanceof Error ? error : new Error(String(error)));
76
+ logger.error(
77
+ "Error getting traces",
78
+ error instanceof Error ? error : new Error(String(error))
79
+ );
77
80
  throw error;
78
81
  }
79
82
  }
@@ -129,9 +132,7 @@ ${summaryText}`
129
132
  }
130
133
  if (include_recommendations && analysis.recommendations) {
131
134
  analysisText += "\n\nRecommendations:\n";
132
- analysisText += analysis.recommendations.map(
133
- (rec, i) => `${i + 1}. ${rec}`
134
- ).join("\n");
135
+ analysisText += analysis.recommendations.map((rec, i) => `${i + 1}. ${rec}`).join("\n");
135
136
  }
136
137
  return {
137
138
  content: [
@@ -147,7 +148,10 @@ ${summaryText}`
147
148
  }
148
149
  };
149
150
  } catch (error) {
150
- logger.error("Error analyzing traces", error instanceof Error ? error : new Error(String(error)));
151
+ logger.error(
152
+ "Error analyzing traces",
153
+ error instanceof Error ? error : new Error(String(error))
154
+ );
151
155
  throw error;
152
156
  }
153
157
  }
@@ -184,7 +188,10 @@ Navigated to: ${url}`
184
188
  }
185
189
  };
186
190
  } catch (error) {
187
- logger.error("Error starting browser debug session", error instanceof Error ? error : new Error(String(error)));
191
+ logger.error(
192
+ "Error starting browser debug session",
193
+ error instanceof Error ? error : new Error(String(error))
194
+ );
188
195
  throw error;
189
196
  }
190
197
  }
@@ -218,7 +225,10 @@ Navigated to: ${url}`
218
225
  }
219
226
  };
220
227
  } catch (error) {
221
- logger.error("Error taking screenshot", error instanceof Error ? error : new Error(String(error)));
228
+ logger.error(
229
+ "Error taking screenshot",
230
+ error instanceof Error ? error : new Error(String(error))
231
+ );
222
232
  throw error;
223
233
  }
224
234
  }
@@ -251,7 +261,10 @@ Result: ${JSON.stringify(result, null, 2)}`
251
261
  }
252
262
  };
253
263
  } catch (error) {
254
- logger.error("Error executing script", error instanceof Error ? error : new Error(String(error)));
264
+ logger.error(
265
+ "Error executing script",
266
+ error instanceof Error ? error : new Error(String(error))
267
+ );
255
268
  throw error;
256
269
  }
257
270
  }
@@ -279,7 +292,10 @@ Result: ${JSON.stringify(result, null, 2)}`
279
292
  }
280
293
  };
281
294
  } catch (error) {
282
- logger.error("Error stopping browser debug session", error instanceof Error ? error : new Error(String(error)));
295
+ logger.error(
296
+ "Error stopping browser debug session",
297
+ error instanceof Error ? error : new Error(String(error))
298
+ );
283
299
  throw error;
284
300
  }
285
301
  }
@@ -2,7 +2,7 @@ import { fileURLToPath as __fileURLToPath } from 'url';
2
2
  import { dirname as __pathDirname } from 'path';
3
3
  const __filename = __fileURLToPath(import.meta.url);
4
4
  const __dirname = __pathDirname(__filename);
5
- import { RefactoredStackMemoryMCP } from "./refactored-server.js";
5
+ import { StackMemoryMCP } from "./refactored-server.js";
6
6
  import { MCPHandlerFactory } from "./handlers/index.js";
7
7
  import { ContextHandlers } from "./handlers/context-handlers.js";
8
8
  import { TaskHandlers } from "./handlers/task-handlers.js";
@@ -16,7 +16,7 @@ export {
16
16
  LinearHandlers,
17
17
  MCPHandlerFactory,
18
18
  MCPToolDefinitions,
19
- RefactoredStackMemoryMCP as StackMemoryMCP,
19
+ StackMemoryMCP,
20
20
  TaskHandlers,
21
21
  TraceHandlers
22
22
  };
@@ -11,13 +11,14 @@ import { existsSync, mkdirSync } from "fs";
11
11
  import { join, dirname } from "path";
12
12
  import { execSync } from "child_process";
13
13
  import { v4 as uuidv4 } from "uuid";
14
- import { RefactoredFrameManager } from "../../core/context/refactored-frame-manager.js";
14
+ import { FrameManager } from "../../core/context/frame-manager.js";
15
15
  import { LinearTaskManager } from "../../features/tasks/linear-task-manager.js";
16
16
  import { LinearAuthManager } from "../linear/auth.js";
17
17
  import { LinearSyncEngine, DEFAULT_SYNC_CONFIG } from "../linear/sync.js";
18
18
  import { BrowserMCPIntegration } from "../../features/browser/browser-mcp.js";
19
19
  import { TraceDetector } from "../../core/trace/trace-detector.js";
20
20
  import { LLMContextRetrieval } from "../../core/retrieval/index.js";
21
+ import { SQLiteAdapter } from "../../core/database/sqlite-adapter.js";
21
22
  import { ConfigManager } from "../../core/config/config-manager.js";
22
23
  import { logger } from "../../core/monitoring/logger.js";
23
24
  import { MCPHandlerFactory } from "./handlers/index.js";
@@ -34,7 +35,7 @@ function getEnv(key, defaultValue) {
34
35
  function getOptionalEnv(key) {
35
36
  return process.env[key];
36
37
  }
37
- class RefactoredStackMemoryMCP {
38
+ class StackMemoryMCP {
38
39
  server;
39
40
  db;
40
41
  projectRoot;
@@ -47,6 +48,7 @@ class RefactoredStackMemoryMCP {
47
48
  browserMCP;
48
49
  traceDetector;
49
50
  contextRetrieval;
51
+ dbAdapter;
50
52
  configManager;
51
53
  toolScoringMiddleware;
52
54
  // Handler factory
@@ -70,6 +72,7 @@ class RefactoredStackMemoryMCP {
70
72
  }
71
73
  const dbPath = join(dbDir, "context.db");
72
74
  this.db = new Database(dbPath);
75
+ this.dbAdapter = new SQLiteAdapter(this.projectId, { dbPath });
73
76
  logger.info("Database initialized", { dbPath });
74
77
  }
75
78
  /**
@@ -78,7 +81,7 @@ class RefactoredStackMemoryMCP {
78
81
  initializeComponents(config) {
79
82
  const configPath = join(this.projectRoot, ".stackmemory", "config.yaml");
80
83
  this.configManager = new ConfigManager(configPath);
81
- this.frameManager = new RefactoredFrameManager(this.db, this.projectId);
84
+ this.frameManager = new FrameManager(this.db, this.projectId);
82
85
  this.taskStore = new LinearTaskManager(this.projectRoot, this.db);
83
86
  this.linearAuthManager = new LinearAuthManager(this.projectRoot);
84
87
  this.linearSync = new LinearSyncEngine(
@@ -140,7 +143,8 @@ class RefactoredStackMemoryMCP {
140
143
  linearAuthManager: this.linearAuthManager,
141
144
  linearSync: this.linearSync,
142
145
  traceDetector: this.traceDetector,
143
- browserMCP: this.browserMCP
146
+ browserMCP: this.browserMCP,
147
+ dbAdapter: this.dbAdapter
144
148
  };
145
149
  this.handlerFactory = new MCPHandlerFactory(dependencies);
146
150
  this.toolDefinitions = new MCPToolDefinitions();
@@ -275,6 +279,8 @@ class RefactoredStackMemoryMCP {
275
279
  */
276
280
  async start() {
277
281
  try {
282
+ await this.dbAdapter.connect();
283
+ await this.dbAdapter.initializeSchema();
278
284
  await this.frameManager.initialize();
279
285
  const transport = new StdioServerTransport();
280
286
  await this.server.connect(transport);
@@ -285,7 +291,10 @@ class RefactoredStackMemoryMCP {
285
291
  });
286
292
  this.setupCleanup();
287
293
  } catch (error) {
288
- logger.error("Failed to start MCP server", error instanceof Error ? error : new Error(String(error)));
294
+ logger.error(
295
+ "Failed to start MCP server",
296
+ error instanceof Error ? error : new Error(String(error))
297
+ );
289
298
  throw error;
290
299
  }
291
300
  }
@@ -299,19 +308,28 @@ class RefactoredStackMemoryMCP {
299
308
  if (this.browserMCP) {
300
309
  await this.browserMCP.cleanup();
301
310
  }
311
+ if (this.dbAdapter) {
312
+ await this.dbAdapter.disconnect();
313
+ }
302
314
  if (this.db) {
303
315
  this.db.close();
304
316
  }
305
317
  logger.info("MCP server shutdown complete");
306
318
  } catch (error) {
307
- logger.error("Error during cleanup", error instanceof Error ? error : new Error(String(error)));
319
+ logger.error(
320
+ "Error during cleanup",
321
+ error instanceof Error ? error : new Error(String(error))
322
+ );
308
323
  }
309
324
  process.exit(0);
310
325
  };
311
326
  process.on("SIGINT", cleanup);
312
327
  process.on("SIGTERM", cleanup);
313
328
  process.on("uncaughtException", (error) => {
314
- logger.error("Uncaught exception", error instanceof Error ? error : new Error(String(error)));
329
+ logger.error(
330
+ "Uncaught exception",
331
+ error instanceof Error ? error : new Error(String(error))
332
+ );
315
333
  cleanup();
316
334
  });
317
335
  }
@@ -355,10 +373,13 @@ async function main() {
355
373
  enableTracing: process.env["DISABLE_TRACING"] !== "true",
356
374
  enableBrowser: process.env["DISABLE_BROWSER"] !== "true"
357
375
  };
358
- const server = new RefactoredStackMemoryMCP(config);
376
+ const server = new StackMemoryMCP(config);
359
377
  await server.start();
360
378
  } catch (error) {
361
- logger.error("Failed to start server", error instanceof Error ? error : new Error(String(error)));
379
+ logger.error(
380
+ "Failed to start server",
381
+ error instanceof Error ? error : new Error(String(error))
382
+ );
362
383
  process.exit(1);
363
384
  }
364
385
  }
@@ -369,5 +390,5 @@ if (import.meta.url === `file://${process.argv[1]}`) {
369
390
  });
370
391
  }
371
392
  export {
372
- RefactoredStackMemoryMCP
393
+ StackMemoryMCP
373
394
  };
@@ -30,6 +30,7 @@ import { TraceDetector } from "../../core/trace/trace-detector.js";
30
30
  import { LLMContextRetrieval } from "../../core/retrieval/index.js";
31
31
  import { DiscoveryHandlers } from "./handlers/discovery-handlers.js";
32
32
  import { DiffMemHandlers } from "./handlers/diffmem-handlers.js";
33
+ import { GreptileHandlers } from "./handlers/greptile-handlers.js";
33
34
  import { GraphitiClient } from "../graphiti/client.js";
34
35
  import { fuzzyEdit } from "../../utils/fuzzy-edit.js";
35
36
  import { v4 as uuidv4 } from "uuid";
@@ -64,6 +65,7 @@ class LocalStackMemoryMCP {
64
65
  contextRetrieval;
65
66
  discoveryHandlers;
66
67
  diffMemHandlers;
68
+ greptileHandlers;
67
69
  providerHandlers = null;
68
70
  graphitiClient = null;
69
71
  pendingPlans = /* @__PURE__ */ new Map();
@@ -138,6 +140,7 @@ class LocalStackMemoryMCP {
138
140
  projectRoot: this.projectRoot
139
141
  });
140
142
  this.diffMemHandlers = new DiffMemHandlers();
143
+ this.greptileHandlers = new GreptileHandlers();
141
144
  this.initProviderHandlers();
142
145
  if (process.env.GRAPHITI_ENDPOINT) {
143
146
  this.graphitiClient = new GraphitiClient({
@@ -1129,6 +1132,8 @@ ${summary}...`, 0.8);
1129
1132
  }
1130
1133
  }
1131
1134
  ] : [],
1135
+ // Greptile tools (only active when GREPTILE_API_KEY is set)
1136
+ ...process.env.GREPTILE_API_KEY ? this.greptileHandlers.getToolDefinitions() : [],
1132
1137
  // Provider tools (only active when STACKMEMORY_MULTI_PROVIDER=true)
1133
1138
  ...isFeatureEnabled("multiProvider") ? [
1134
1139
  {
@@ -1377,6 +1382,28 @@ ${summary}...`, 0.8);
1377
1382
  case "diffmem_status":
1378
1383
  result = await this.diffMemHandlers.handleStatus();
1379
1384
  break;
1385
+ // Greptile handlers
1386
+ case "greptile_pr_comments":
1387
+ result = await this.greptileHandlers.handleListPRComments(args);
1388
+ break;
1389
+ case "greptile_pr_details":
1390
+ result = await this.greptileHandlers.handleGetMergeRequest(args);
1391
+ break;
1392
+ case "greptile_list_prs":
1393
+ result = await this.greptileHandlers.handleListPullRequests(args);
1394
+ break;
1395
+ case "greptile_trigger_review":
1396
+ result = await this.greptileHandlers.handleTriggerCodeReview(args);
1397
+ break;
1398
+ case "greptile_search_patterns":
1399
+ result = await this.greptileHandlers.handleSearchPatterns(args);
1400
+ break;
1401
+ case "greptile_create_pattern":
1402
+ result = await this.greptileHandlers.handleCreatePattern(args);
1403
+ break;
1404
+ case "greptile_status":
1405
+ result = await this.greptileHandlers.handleStatus();
1406
+ break;
1380
1407
  case "sm_edit":
1381
1408
  result = await this.handleSmEdit(args);
1382
1409
  break;