@stackmemoryai/stackmemory 1.2.2 → 1.2.6

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 (77) hide show
  1. package/README.md +10 -6
  2. package/dist/src/cli/claude-sm.js +33 -4
  3. package/dist/src/cli/codex-sm-danger.js +4 -1
  4. package/dist/src/cli/codex-sm.js +6 -8
  5. package/dist/src/cli/commands/config.js +0 -81
  6. package/dist/src/cli/commands/context-rehydrate.js +133 -47
  7. package/dist/src/cli/commands/db.js +35 -8
  8. package/dist/src/cli/commands/handoff.js +1 -1
  9. package/dist/src/cli/commands/linear.js +9 -0
  10. package/dist/src/cli/commands/ralph.js +2 -2
  11. package/dist/src/cli/commands/setup.js +2 -2
  12. package/dist/src/cli/commands/signup.js +3 -1
  13. package/dist/src/cli/commands/skills.js +108 -1
  14. package/dist/src/cli/commands/storage-tier.js +26 -8
  15. package/dist/src/cli/index.js +1 -57
  16. package/dist/src/core/config/feature-flags.js +0 -4
  17. package/dist/src/core/context/dual-stack-manager.js +10 -3
  18. package/dist/src/core/context/frame-database.js +32 -0
  19. package/dist/src/core/context/frame-handoff-manager.js +2 -2
  20. package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
  21. package/dist/src/core/context/index.js +2 -2
  22. package/dist/src/core/database/sqlite-adapter.js +161 -1
  23. package/dist/src/core/digest/frame-digest-integration.js +1 -1
  24. package/dist/src/core/digest/index.js +1 -1
  25. package/dist/src/core/execution/parallel-executor.js +5 -1
  26. package/dist/src/core/projects/project-isolation.js +18 -4
  27. package/dist/src/core/security/index.js +2 -0
  28. package/dist/src/core/security/input-sanitizer.js +23 -0
  29. package/dist/src/core/utils/update-checker.js +10 -6
  30. package/dist/src/daemon/daemon-config.js +2 -1
  31. package/dist/src/daemon/services/auto-save-service.js +121 -0
  32. package/dist/src/daemon/services/maintenance-service.js +76 -1
  33. package/dist/src/features/sweep/prompt-builder.js +2 -2
  34. package/dist/src/hooks/daemon.js +0 -8
  35. package/dist/src/integrations/linear/config.js +3 -1
  36. package/dist/src/integrations/linear/sync.js +18 -5
  37. package/dist/src/integrations/linear/webhook.js +0 -16
  38. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
  39. package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
  40. package/dist/src/integrations/mcp/handlers/index.js +55 -9
  41. package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
  42. package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
  43. package/dist/src/integrations/mcp/handlers/trace-handlers.js +28 -9
  44. package/dist/src/integrations/mcp/index.js +2 -2
  45. package/dist/src/integrations/mcp/refactored-server.js +31 -10
  46. package/dist/src/integrations/mcp/server.js +0 -130
  47. package/dist/src/integrations/mcp/tool-definitions.js +196 -67
  48. package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
  49. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
  50. package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
  51. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
  52. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
  53. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
  54. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
  55. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
  56. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
  57. package/dist/src/skills/claude-skills.js +37 -103
  58. package/dist/src/skills/theory-skill.js +191 -0
  59. package/dist/src/utils/hook-installer.js +16 -0
  60. package/package.json +6 -6
  61. package/scripts/install-claude-hooks-auto.js +8 -0
  62. package/templates/claude-hooks/cord-trace.js +225 -0
  63. package/templates/claude-hooks/theory-capture.js +100 -0
  64. package/dist/src/core/config/storage-config.js +0 -114
  65. package/dist/src/core/storage/chromadb-adapter.js +0 -379
  66. package/dist/src/hooks/graphiti-hooks.js +0 -253
  67. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
  68. package/dist/src/integrations/graphiti/client.js +0 -115
  69. package/dist/src/integrations/graphiti/config.js +0 -17
  70. package/dist/src/integrations/graphiti/linear-graphiti-bridge.js +0 -115
  71. package/dist/src/integrations/graphiti/types.js +0 -4
  72. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
  73. package/dist/src/skills/repo-ingestion-skill.js +0 -631
  74. package/templates/claude-hooks/chromadb-wrapper +0 -21
  75. /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
  76. /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
  77. /package/dist/src/core/session/{enhanced-handoff.js → handoff.js} +0 -0
@@ -1,379 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { v4 as uuidv4 } from "uuid";
6
- import { Logger } from "../monitoring/logger.js";
7
- let chromadbModule = null;
8
- async function getChromaDB() {
9
- if (!chromadbModule) {
10
- try {
11
- chromadbModule = await import("chromadb");
12
- } catch {
13
- throw new Error(
14
- "chromadb is not installed. Install it with: npm install chromadb"
15
- );
16
- }
17
- }
18
- return chromadbModule;
19
- }
20
- class ChromaDBAdapter {
21
- client = null;
22
- collection = null;
23
- logger;
24
- config;
25
- userId;
26
- teamId;
27
- constructor(config, userId, teamId) {
28
- this.config = config;
29
- this.userId = userId;
30
- this.teamId = teamId;
31
- this.logger = new Logger("ChromaDBAdapter");
32
- }
33
- /**
34
- * Factory method to create and initialize the adapter
35
- */
36
- static async create(config, userId, teamId) {
37
- const adapter = new ChromaDBAdapter(config, userId, teamId);
38
- await adapter.initClient();
39
- return adapter;
40
- }
41
- async initClient() {
42
- const chromadb = await getChromaDB();
43
- this.client = new chromadb.CloudClient({
44
- apiKey: this.config.apiKey,
45
- tenant: this.config.tenant,
46
- database: this.config.database
47
- });
48
- }
49
- async initialize() {
50
- try {
51
- if (!this.client) {
52
- await this.initClient();
53
- }
54
- const collectionName = this.config.collectionName || "stackmemory_contexts";
55
- this.collection = await this.client.getOrCreateCollection({
56
- name: collectionName,
57
- metadata: {
58
- description: "StackMemory context storage",
59
- version: "1.0.0",
60
- created_at: (/* @__PURE__ */ new Date()).toISOString()
61
- }
62
- });
63
- this.logger.info(`ChromaDB collection '${collectionName}' initialized`);
64
- } catch (error) {
65
- this.logger.error("Failed to initialize ChromaDB collection", error);
66
- throw error;
67
- }
68
- }
69
- /**
70
- * Store a frame in ChromaDB
71
- */
72
- async storeFrame(frame) {
73
- if (!this.collection) {
74
- throw new Error("ChromaDB not initialized");
75
- }
76
- try {
77
- const frameMetadata = {
78
- user_id: this.userId,
79
- frame_id: frame.frameId,
80
- session_id: frame.sessionId || "unknown",
81
- project_name: frame.projectName || "default",
82
- timestamp: frame.timestamp,
83
- type: "frame",
84
- score: frame.score,
85
- tags: frame.tags || []
86
- };
87
- if (this.teamId) {
88
- frameMetadata.team_id = this.teamId;
89
- }
90
- const document = {
91
- id: `frame_${frame.frameId}_${this.userId}`,
92
- document: this.frameToDocument(frame),
93
- metadata: frameMetadata
94
- };
95
- await this.collection.add({
96
- ids: [document.id],
97
- documents: [document.document],
98
- metadatas: [document.metadata]
99
- });
100
- this.logger.debug(
101
- `Stored frame ${frame.frameId} for user ${this.userId}`
102
- );
103
- } catch (error) {
104
- this.logger.error(`Failed to store frame ${frame.frameId}`, error);
105
- throw error;
106
- }
107
- }
108
- /**
109
- * Store a decision or observation
110
- */
111
- async storeContext(type, content, metadata) {
112
- if (!this.collection) {
113
- throw new Error("ChromaDB not initialized");
114
- }
115
- try {
116
- const contextId = `${type}_${uuidv4()}_${this.userId}`;
117
- const documentMetadata = {
118
- user_id: this.userId,
119
- frame_id: metadata?.frame_id || "none",
120
- session_id: metadata?.session_id || "unknown",
121
- project_name: metadata?.project_name || "default",
122
- timestamp: Date.now(),
123
- type,
124
- ...metadata
125
- };
126
- if (this.teamId) {
127
- documentMetadata.team_id = this.teamId;
128
- }
129
- const document = {
130
- id: contextId,
131
- document: content,
132
- metadata: documentMetadata
133
- };
134
- await this.collection.add({
135
- ids: [document.id],
136
- documents: [document.document],
137
- metadatas: [document.metadata]
138
- });
139
- this.logger.debug(`Stored ${type} for user ${this.userId}`);
140
- } catch (error) {
141
- this.logger.error(`Failed to store ${type}`, error);
142
- throw error;
143
- }
144
- }
145
- /**
146
- * Query contexts by semantic similarity
147
- */
148
- async queryContexts(query, limit = 10, filters) {
149
- if (!this.collection) {
150
- throw new Error("ChromaDB not initialized");
151
- }
152
- try {
153
- const whereClause = {
154
- user_id: this.userId
155
- };
156
- if (this.teamId) {
157
- whereClause["$or"] = [
158
- { team_id: this.teamId },
159
- { user_id: this.userId }
160
- ];
161
- }
162
- if (filters?.type && filters.type.length > 0) {
163
- whereClause.type = { $in: filters.type };
164
- }
165
- if (filters?.projectName) {
166
- whereClause.project_name = filters.projectName;
167
- }
168
- if (filters?.sessionId) {
169
- whereClause.session_id = filters.sessionId;
170
- }
171
- if (filters?.startTime || filters?.endTime) {
172
- whereClause.timestamp = {};
173
- if (filters.startTime) {
174
- whereClause.timestamp.$gte = filters.startTime;
175
- }
176
- if (filters.endTime) {
177
- whereClause.timestamp.$lte = filters.endTime;
178
- }
179
- }
180
- const results = await this.collection.query({
181
- queryTexts: [query],
182
- nResults: limit,
183
- where: whereClause,
184
- include: ["documents", "metadatas", "distances"]
185
- });
186
- const contexts = [];
187
- if (results.documents && results.documents[0]) {
188
- for (let i = 0; i < results.documents[0].length; i++) {
189
- contexts.push({
190
- content: results.documents[0][i] || "",
191
- metadata: results.metadatas?.[0]?.[i] || {},
192
- distance: results.distances?.[0]?.[i] || 0
193
- });
194
- }
195
- }
196
- this.logger.debug(`Found ${contexts.length} contexts for query`);
197
- return contexts;
198
- } catch (error) {
199
- this.logger.error("Failed to query contexts", error);
200
- throw error;
201
- }
202
- }
203
- /**
204
- * Get user's recent contexts
205
- */
206
- async getRecentContexts(limit = 20, type) {
207
- if (!this.collection) {
208
- throw new Error("ChromaDB not initialized");
209
- }
210
- try {
211
- const whereClause = {
212
- user_id: this.userId
213
- };
214
- if (type) {
215
- whereClause.type = type;
216
- }
217
- const results = await this.collection.get({
218
- where: whereClause,
219
- include: ["documents", "metadatas"]
220
- });
221
- const contexts = [];
222
- if (results.documents) {
223
- const indexed = results.documents.map((doc, i) => ({
224
- content: doc || "",
225
- metadata: results.metadatas?.[i] || {}
226
- }));
227
- indexed.sort(
228
- (a, b) => (b.metadata.timestamp || 0) - (a.metadata.timestamp || 0)
229
- );
230
- contexts.push(...indexed.slice(0, limit));
231
- }
232
- return contexts;
233
- } catch (error) {
234
- this.logger.error("Failed to get recent contexts", error);
235
- throw error;
236
- }
237
- }
238
- /**
239
- * Delete old contexts (retention policy)
240
- */
241
- async deleteOldContexts(olderThanDays = 30) {
242
- if (!this.collection) {
243
- throw new Error("ChromaDB not initialized");
244
- }
245
- try {
246
- const cutoffTime = Date.now() - olderThanDays * 24 * 60 * 60 * 1e3;
247
- const results = await this.collection.get({
248
- where: {
249
- user_id: this.userId,
250
- timestamp: { $lt: cutoffTime }
251
- },
252
- include: ["ids"]
253
- });
254
- if (!results.ids || results.ids.length === 0) {
255
- return 0;
256
- }
257
- await this.collection.delete({
258
- ids: results.ids
259
- });
260
- this.logger.info(`Deleted ${results.ids.length} old contexts`);
261
- return results.ids.length;
262
- } catch (error) {
263
- this.logger.error("Failed to delete old contexts", error);
264
- throw error;
265
- }
266
- }
267
- /**
268
- * Get team contexts (if user is part of a team)
269
- */
270
- async getTeamContexts(limit = 20) {
271
- if (!this.collection || !this.teamId) {
272
- return [];
273
- }
274
- try {
275
- const results = await this.collection.get({
276
- where: {
277
- team_id: this.teamId
278
- },
279
- include: ["documents", "metadatas"],
280
- limit
281
- });
282
- const contexts = [];
283
- if (results.documents) {
284
- for (let i = 0; i < results.documents.length; i++) {
285
- contexts.push({
286
- content: results.documents[i] || "",
287
- metadata: results.metadatas?.[i] || {}
288
- });
289
- }
290
- }
291
- return contexts;
292
- } catch (error) {
293
- this.logger.error("Failed to get team contexts", error);
294
- return [];
295
- }
296
- }
297
- /**
298
- * Convert frame to searchable document
299
- */
300
- frameToDocument(frame) {
301
- const parts = [
302
- `Frame: ${frame.title}`,
303
- `Type: ${frame.type}`,
304
- `Status: ${frame.status}`
305
- ];
306
- if (frame.description) {
307
- parts.push(`Description: ${frame.description}`);
308
- }
309
- if (frame.inputs && frame.inputs.length > 0) {
310
- parts.push(`Inputs: ${frame.inputs.join(", ")}`);
311
- }
312
- if (frame.outputs && frame.outputs.length > 0) {
313
- parts.push(`Outputs: ${frame.outputs.join(", ")}`);
314
- }
315
- if (frame.tags && frame.tags.length > 0) {
316
- parts.push(`Tags: ${frame.tags.join(", ")}`);
317
- }
318
- if (frame.digest_json) {
319
- try {
320
- const digest = JSON.parse(frame.digest_json);
321
- if (digest.summary) {
322
- parts.push(`Summary: ${digest.summary}`);
323
- }
324
- if (digest.keyDecisions) {
325
- parts.push(`Decisions: ${digest.keyDecisions.join(". ")}`);
326
- }
327
- } catch {
328
- }
329
- }
330
- return parts.join("\n");
331
- }
332
- /**
333
- * Update team ID for a user
334
- */
335
- async updateTeamId(newTeamId) {
336
- this.teamId = newTeamId;
337
- this.logger.info(`Updated team ID to ${newTeamId} for user ${this.userId}`);
338
- }
339
- /**
340
- * Get storage statistics
341
- */
342
- async getStats() {
343
- if (!this.collection) {
344
- throw new Error("ChromaDB not initialized");
345
- }
346
- try {
347
- const userResults = await this.collection.get({
348
- where: { user_id: this.userId },
349
- include: ["metadatas"]
350
- });
351
- const stats = {
352
- totalDocuments: 0,
353
- userDocuments: userResults.ids?.length || 0,
354
- documentsByType: {}
355
- };
356
- if (userResults.metadatas) {
357
- for (const metadata of userResults.metadatas) {
358
- const type = metadata?.type || "unknown";
359
- stats.documentsByType[type] = (stats.documentsByType[type] || 0) + 1;
360
- }
361
- }
362
- if (this.teamId) {
363
- const teamResults = await this.collection.get({
364
- where: { team_id: this.teamId },
365
- include: ["ids"]
366
- });
367
- stats.teamDocuments = teamResults.ids?.length || 0;
368
- }
369
- stats.totalDocuments = stats.userDocuments + (stats.teamDocuments || 0);
370
- return stats;
371
- } catch (error) {
372
- this.logger.error("Failed to get stats", error);
373
- throw error;
374
- }
375
- }
376
- }
377
- export {
378
- ChromaDBAdapter
379
- };
@@ -1,253 +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 { GraphitiClient } from "../integrations/graphiti/client.js";
7
- import { DEFAULT_GRAPHITI_CONFIG } from "../integrations/graphiti/config.js";
8
- class GraphitiHooks {
9
- client;
10
- config;
11
- constructor(config = {}) {
12
- this.config = { ...DEFAULT_GRAPHITI_CONFIG, ...config };
13
- this.client = new GraphitiClient(this.config);
14
- }
15
- register(emitter) {
16
- if (!this.config.enabled) {
17
- logger.debug("Graphiti hooks disabled");
18
- return;
19
- }
20
- emitter.registerHandler("session_start", this.onSessionStart.bind(this));
21
- emitter.registerHandler("file_change", this.onFileChange.bind(this));
22
- emitter.registerHandler("session_end", this.onSessionEnd.bind(this));
23
- emitter.registerHandler("input_idle", this.onInputIdle.bind(this));
24
- emitter.registerHandler("context_switch", this.onContextSwitch.bind(this));
25
- emitter.registerHandler("prompt_submit", this.onPromptSubmit.bind(this));
26
- emitter.registerHandler("tool_use", this.onToolUse.bind(this));
27
- emitter.registerHandler(
28
- "suggestion_ready",
29
- this.onSuggestionReady.bind(this)
30
- );
31
- emitter.registerHandler("agent_start", this.onAgentStart.bind(this));
32
- emitter.registerHandler("agent_complete", this.onAgentComplete.bind(this));
33
- emitter.registerHandler("agent_error", this.onAgentError.bind(this));
34
- logger.info("Graphiti hooks registered", {
35
- endpoint: this.config.endpoint,
36
- backend: this.config.backend,
37
- maxHops: this.config.maxHops
38
- });
39
- }
40
- async onSessionStart(event) {
41
- try {
42
- const status = await this.client.getStatus();
43
- if (!status.connected) {
44
- logger.warn("Graphiti not available - operating in degraded mode");
45
- return;
46
- }
47
- const episode = {
48
- type: "session_start",
49
- content: event.data || {},
50
- timestamp: Date.now(),
51
- source: "stackmemory",
52
- metadata: { severity: "info" }
53
- };
54
- await this.client.upsertEpisode(episode);
55
- } catch (error) {
56
- logger.debug("Graphiti session_start failed", {
57
- error: error instanceof Error ? error.message : String(error)
58
- });
59
- }
60
- }
61
- async onFileChange(event) {
62
- const fileEvent = event;
63
- try {
64
- const episode = {
65
- type: "file_change",
66
- content: {
67
- path: fileEvent.data.path,
68
- changeType: fileEvent.data.changeType,
69
- size: typeof fileEvent.data.content === "string" ? fileEvent.data.content.length : void 0
70
- },
71
- timestamp: Date.now(),
72
- source: "stackmemory"
73
- };
74
- await this.client.upsertEpisode(episode);
75
- } catch (error) {
76
- logger.debug("Graphiti file_change episode failed", {
77
- error: error instanceof Error ? error.message : String(error)
78
- });
79
- }
80
- }
81
- async onSessionEnd(event) {
82
- try {
83
- const episode = {
84
- type: "session_end",
85
- content: event.data || {},
86
- timestamp: Date.now(),
87
- source: "stackmemory"
88
- };
89
- await this.client.upsertEpisode(episode);
90
- } catch (error) {
91
- logger.debug("Graphiti session_end failed", {
92
- error: error instanceof Error ? error.message : String(error)
93
- });
94
- }
95
- }
96
- async onInputIdle(event) {
97
- const idle = event;
98
- try {
99
- const episode = {
100
- type: "input_idle",
101
- content: {
102
- idleDuration: idle.data.idleDuration,
103
- lastInput: idle.data.lastInput
104
- },
105
- timestamp: Date.now(),
106
- source: "stackmemory"
107
- };
108
- await this.client.upsertEpisode(episode);
109
- } catch (error) {
110
- logger.debug("Graphiti input_idle episode failed", {
111
- error: error instanceof Error ? error.message : String(error)
112
- });
113
- }
114
- }
115
- async onContextSwitch(event) {
116
- const ctx = event;
117
- try {
118
- const episode = {
119
- type: "context_switch",
120
- content: {
121
- fromBranch: ctx.data.fromBranch,
122
- toBranch: ctx.data.toBranch,
123
- fromProject: ctx.data.fromProject,
124
- toProject: ctx.data.toProject
125
- },
126
- timestamp: Date.now(),
127
- source: "stackmemory"
128
- };
129
- await this.client.upsertEpisode(episode);
130
- } catch (error) {
131
- logger.debug("Graphiti context_switch episode failed", {
132
- error: error instanceof Error ? error.message : String(error)
133
- });
134
- }
135
- }
136
- async onPromptSubmit(event) {
137
- try {
138
- const episode = {
139
- type: "prompt_submit",
140
- content: event.data || {},
141
- timestamp: Date.now(),
142
- source: "stackmemory"
143
- };
144
- await this.client.upsertEpisode(episode);
145
- } catch (error) {
146
- logger.debug("Graphiti prompt_submit episode failed", {
147
- error: error instanceof Error ? error.message : String(error)
148
- });
149
- }
150
- }
151
- async onToolUse(event) {
152
- try {
153
- const episode = {
154
- type: "tool_use",
155
- content: event.data || {},
156
- timestamp: Date.now(),
157
- source: "stackmemory"
158
- };
159
- await this.client.upsertEpisode(episode);
160
- } catch (error) {
161
- logger.debug("Graphiti tool_use episode failed", {
162
- error: error instanceof Error ? error.message : String(error)
163
- });
164
- }
165
- }
166
- async onSuggestionReady(event) {
167
- const suggestion = event;
168
- try {
169
- const episode = {
170
- type: "suggestion_ready",
171
- content: {
172
- source: suggestion.data.source,
173
- confidence: suggestion.data.confidence,
174
- preview: suggestion.data.preview
175
- },
176
- timestamp: Date.now(),
177
- source: "stackmemory"
178
- };
179
- await this.client.upsertEpisode(episode);
180
- } catch (error) {
181
- logger.debug("Graphiti suggestion_ready episode failed", {
182
- error: error instanceof Error ? error.message : String(error)
183
- });
184
- }
185
- }
186
- async onAgentStart(event) {
187
- const e = event;
188
- try {
189
- const episode = {
190
- type: "agent_start",
191
- content: { agentType: e.data.agentType, task: e.data.task },
192
- timestamp: Date.now(),
193
- source: "stackmemory"
194
- };
195
- await this.client.upsertEpisode(episode);
196
- } catch (error) {
197
- logger.debug("Graphiti agent_start episode failed", {
198
- error: error instanceof Error ? error.message : String(error)
199
- });
200
- }
201
- }
202
- async onAgentComplete(event) {
203
- const e = event;
204
- try {
205
- const episode = {
206
- type: "agent_complete",
207
- content: { ...e.data },
208
- timestamp: Date.now(),
209
- source: "stackmemory"
210
- };
211
- await this.client.upsertEpisode(episode);
212
- } catch (error) {
213
- logger.debug("Graphiti agent_complete episode failed", {
214
- error: error instanceof Error ? error.message : String(error)
215
- });
216
- }
217
- }
218
- async onAgentError(event) {
219
- const e = event;
220
- try {
221
- const episode = {
222
- type: "agent_error",
223
- content: { agentType: e.data.agentType, error: e.data.error },
224
- timestamp: Date.now(),
225
- source: "stackmemory"
226
- };
227
- await this.client.upsertEpisode(episode);
228
- } catch (error) {
229
- logger.debug("Graphiti agent_error episode failed", {
230
- error: error instanceof Error ? error.message : String(error)
231
- });
232
- }
233
- }
234
- // Expose a simple temporal query helper for future MCP tooling
235
- async buildTemporalContext(query = {}) {
236
- const now = Date.now();
237
- const q = {
238
- query: query.query || void 0,
239
- entityTypes: query.entityTypes || void 0,
240
- relationTypes: query.relationTypes || void 0,
241
- validFrom: query.validFrom ?? now - 1e3 * 60 * 60 * 24 * 30,
242
- // 30d default
243
- validTo: query.validTo ?? now,
244
- maxHops: query.maxHops ?? this.config.maxHops,
245
- k: query.k ?? 20,
246
- rerank: query.rerank ?? true
247
- };
248
- return this.client.queryTemporal(q);
249
- }
250
- }
251
- export {
252
- GraphitiHooks
253
- };