@triedotdev/mcp 1.0.121 → 1.0.123

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 (47) hide show
  1. package/dist/chat-store-HFOOWZYN.js +15 -0
  2. package/dist/{chunk-Y52SNUW5.js → chunk-4YJ6KLGI.js} +19 -4
  3. package/dist/{chunk-Y52SNUW5.js.map → chunk-4YJ6KLGI.js.map} +1 -1
  4. package/dist/{chunk-PPZYVTUO.js → chunk-6LD7OPJL.js} +5 -5
  5. package/dist/{chunk-5TQ7J7UI.js → chunk-B46FDUKR.js} +8 -8
  6. package/dist/{chunk-GPLRFTMB.js → chunk-CKT2A33R.js} +5 -6
  7. package/dist/chunk-CKT2A33R.js.map +1 -0
  8. package/dist/chunk-DFPVUMVE.js +347 -0
  9. package/dist/chunk-DFPVUMVE.js.map +1 -0
  10. package/dist/{chunk-FNW7Z7ZS.js → chunk-F4ZIAHTZ.js} +3 -3
  11. package/dist/{chunk-PRFHN2X6.js → chunk-K5EXATBF.js} +2 -2
  12. package/dist/{chunk-7BY2KVIN.js → chunk-QIS2VDJL.js} +680 -319
  13. package/dist/chunk-QIS2VDJL.js.map +1 -0
  14. package/dist/{chunk-IQBHPTV7.js → chunk-TRIJC5MW.js} +4 -4
  15. package/dist/{chunk-4BGAVEO6.js → chunk-UHMMANC2.js} +77 -338
  16. package/dist/chunk-UHMMANC2.js.map +1 -0
  17. package/dist/chunk-WS6OA7H6.js +266 -0
  18. package/dist/chunk-WS6OA7H6.js.map +1 -0
  19. package/dist/cli/main.js +6 -5
  20. package/dist/cli/main.js.map +1 -1
  21. package/dist/cli/yolo-daemon.js +12 -10
  22. package/dist/cli/yolo-daemon.js.map +1 -1
  23. package/dist/{goal-manager-JKTNFJQE.js → goal-manager-RREOIX6U.js} +6 -5
  24. package/dist/{goal-validator-RD6QBQJB.js → goal-validator-XYA364W3.js} +3 -2
  25. package/dist/{goal-validator-RD6QBQJB.js.map → goal-validator-XYA364W3.js.map} +1 -1
  26. package/dist/{guardian-agent-ITZIDNQD.js → guardian-agent-PTC6G37Q.js} +9 -8
  27. package/dist/{hypothesis-PEVD2IJR.js → hypothesis-WWDONGPU.js} +6 -5
  28. package/dist/hypothesis-WWDONGPU.js.map +1 -0
  29. package/dist/index.js +16 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/insight-store-F5KDBY5Y.js +22 -0
  32. package/dist/insight-store-F5KDBY5Y.js.map +1 -0
  33. package/dist/{terminal-spawn-2GU5KLPS.js → terminal-spawn-P5M5PHAV.js} +28 -6
  34. package/dist/terminal-spawn-P5M5PHAV.js.map +1 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-4BGAVEO6.js.map +0 -1
  37. package/dist/chunk-7BY2KVIN.js.map +0 -1
  38. package/dist/chunk-GPLRFTMB.js.map +0 -1
  39. package/dist/terminal-spawn-2GU5KLPS.js.map +0 -1
  40. /package/dist/{goal-manager-JKTNFJQE.js.map → chat-store-HFOOWZYN.js.map} +0 -0
  41. /package/dist/{chunk-PPZYVTUO.js.map → chunk-6LD7OPJL.js.map} +0 -0
  42. /package/dist/{chunk-5TQ7J7UI.js.map → chunk-B46FDUKR.js.map} +0 -0
  43. /package/dist/{chunk-FNW7Z7ZS.js.map → chunk-F4ZIAHTZ.js.map} +0 -0
  44. /package/dist/{chunk-PRFHN2X6.js.map → chunk-K5EXATBF.js.map} +0 -0
  45. /package/dist/{chunk-IQBHPTV7.js.map → chunk-TRIJC5MW.js.map} +0 -0
  46. /package/dist/{guardian-agent-ITZIDNQD.js.map → goal-manager-RREOIX6U.js.map} +0 -0
  47. /package/dist/{hypothesis-PEVD2IJR.js.map → guardian-agent-PTC6G37Q.js.map} +0 -0
@@ -0,0 +1,347 @@
1
+ import {
2
+ atomicWriteJSON
3
+ } from "./chunk-43X6JBEM.js";
4
+ import {
5
+ getTrieDirectory
6
+ } from "./chunk-45Y5TLQZ.js";
7
+
8
+ // src/cli/dashboard/chat-store.ts
9
+ import { mkdir, readFile, unlink } from "fs/promises";
10
+ import { existsSync } from "fs";
11
+ import { join } from "path";
12
+ import { z } from "zod";
13
+ var ChatMessageSchema = z.object({
14
+ role: z.enum(["user", "assistant"]),
15
+ content: z.string(),
16
+ timestamp: z.number(),
17
+ toolCalls: z.array(z.object({
18
+ id: z.string(),
19
+ name: z.string(),
20
+ input: z.record(z.any())
21
+ })).optional(),
22
+ pendingFix: z.object({
23
+ id: z.string(),
24
+ file: z.string(),
25
+ goal: z.string(),
26
+ violation: z.string(),
27
+ suggestedFix: z.string().optional()
28
+ }).optional()
29
+ });
30
+ var ChatSessionSchema = z.object({
31
+ id: z.string(),
32
+ title: z.string(),
33
+ messages: z.array(ChatMessageSchema),
34
+ createdAt: z.number(),
35
+ updatedAt: z.number(),
36
+ archived: z.boolean()
37
+ });
38
+ var ChatStoreIndexSchema = z.object({
39
+ version: z.literal(1),
40
+ sessions: z.array(z.object({
41
+ id: z.string(),
42
+ title: z.string(),
43
+ createdAt: z.number(),
44
+ updatedAt: z.number(),
45
+ archived: z.boolean(),
46
+ messageCount: z.number()
47
+ })),
48
+ lastUpdated: z.string()
49
+ });
50
+ var ChatStore = class {
51
+ projectPath;
52
+ index = null;
53
+ constructor(projectPath) {
54
+ this.projectPath = projectPath;
55
+ }
56
+ /**
57
+ * Get the chats directory path
58
+ */
59
+ getChatsDir() {
60
+ return join(getTrieDirectory(this.projectPath), "memory", "chats");
61
+ }
62
+ /**
63
+ * Get the index file path
64
+ */
65
+ getIndexPath() {
66
+ return join(this.getChatsDir(), "index.json");
67
+ }
68
+ /**
69
+ * Get the path for a specific session file
70
+ */
71
+ getSessionPath(sessionId) {
72
+ return join(this.getChatsDir(), `${sessionId}.json`);
73
+ }
74
+ /**
75
+ * Load the index file
76
+ */
77
+ async loadIndex() {
78
+ if (this.index) {
79
+ return this.index;
80
+ }
81
+ const indexPath = this.getIndexPath();
82
+ if (existsSync(indexPath)) {
83
+ try {
84
+ const content = await readFile(indexPath, "utf-8");
85
+ const parsed = JSON.parse(content);
86
+ const result = ChatStoreIndexSchema.safeParse(parsed);
87
+ if (result.success) {
88
+ this.index = result.data;
89
+ return this.index;
90
+ }
91
+ } catch (error) {
92
+ console.error("Failed to load chat index:", error);
93
+ }
94
+ }
95
+ this.index = {
96
+ version: 1,
97
+ sessions: [],
98
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
99
+ };
100
+ return this.index;
101
+ }
102
+ /**
103
+ * Save the index file
104
+ */
105
+ async saveIndex() {
106
+ if (!this.index) return;
107
+ const indexPath = this.getIndexPath();
108
+ const chatsDir = this.getChatsDir();
109
+ await mkdir(chatsDir, { recursive: true });
110
+ this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
111
+ await atomicWriteJSON(indexPath, this.index);
112
+ }
113
+ /**
114
+ * Generate a unique session ID
115
+ */
116
+ generateSessionId() {
117
+ return `chat-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
118
+ }
119
+ /**
120
+ * Generate a default title from the first user message
121
+ */
122
+ generateTitle(messages) {
123
+ const firstUser = messages.find((m) => m.role === "user");
124
+ if (firstUser) {
125
+ const text = firstUser.content.trim();
126
+ const maxLen = 50;
127
+ if (text.length > maxLen) {
128
+ return text.slice(0, maxLen) + "...";
129
+ }
130
+ return text;
131
+ }
132
+ return "New Chat";
133
+ }
134
+ /**
135
+ * Save a chat session
136
+ */
137
+ async saveSession(messages, sessionId, title) {
138
+ await this.loadIndex();
139
+ const id = sessionId || this.generateSessionId();
140
+ const now = Date.now();
141
+ let createdAt = now;
142
+ if (sessionId) {
143
+ const existing = this.index.sessions.find((s) => s.id === sessionId);
144
+ if (existing) {
145
+ createdAt = existing.createdAt;
146
+ }
147
+ }
148
+ const session = {
149
+ id,
150
+ title: title || this.generateTitle(messages),
151
+ messages,
152
+ createdAt,
153
+ updatedAt: now,
154
+ archived: false
155
+ };
156
+ const result = ChatSessionSchema.safeParse(session);
157
+ if (!result.success) {
158
+ throw new Error(`Invalid chat session: ${result.error.message}`);
159
+ }
160
+ const sessionPath = this.getSessionPath(id);
161
+ await mkdir(this.getChatsDir(), { recursive: true });
162
+ await atomicWriteJSON(sessionPath, session);
163
+ const existingIndex = this.index.sessions.findIndex((s) => s.id === id);
164
+ const indexEntry = {
165
+ id,
166
+ title: session.title,
167
+ createdAt: session.createdAt,
168
+ updatedAt: session.updatedAt,
169
+ archived: session.archived,
170
+ messageCount: messages.length
171
+ };
172
+ if (existingIndex >= 0) {
173
+ this.index.sessions[existingIndex] = indexEntry;
174
+ } else {
175
+ this.index.sessions.unshift(indexEntry);
176
+ }
177
+ await this.saveIndex();
178
+ return id;
179
+ }
180
+ /**
181
+ * Load a chat session
182
+ */
183
+ async loadSession(sessionId) {
184
+ const sessionPath = this.getSessionPath(sessionId);
185
+ if (!existsSync(sessionPath)) {
186
+ return null;
187
+ }
188
+ try {
189
+ const content = await readFile(sessionPath, "utf-8");
190
+ const parsed = JSON.parse(content);
191
+ const result = ChatSessionSchema.safeParse(parsed);
192
+ if (result.success) {
193
+ return result.data;
194
+ }
195
+ console.error("Invalid chat session:", result.error.message);
196
+ return null;
197
+ } catch (error) {
198
+ console.error("Failed to load chat session:", error);
199
+ return null;
200
+ }
201
+ }
202
+ /**
203
+ * List all chat sessions
204
+ */
205
+ async listSessions(includeArchived = false) {
206
+ await this.loadIndex();
207
+ let sessions = this.index.sessions;
208
+ if (!includeArchived) {
209
+ sessions = sessions.filter((s) => !s.archived);
210
+ }
211
+ return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
212
+ }
213
+ /**
214
+ * Delete a chat session
215
+ */
216
+ async deleteSession(sessionId) {
217
+ await this.loadIndex();
218
+ const sessionPath = this.getSessionPath(sessionId);
219
+ if (!existsSync(sessionPath)) {
220
+ return false;
221
+ }
222
+ try {
223
+ await unlink(sessionPath);
224
+ this.index.sessions = this.index.sessions.filter((s) => s.id !== sessionId);
225
+ await this.saveIndex();
226
+ return true;
227
+ } catch (error) {
228
+ console.error("Failed to delete chat session:", error);
229
+ return false;
230
+ }
231
+ }
232
+ /**
233
+ * Rename a chat session
234
+ */
235
+ async renameSession(sessionId, newTitle) {
236
+ await this.loadIndex();
237
+ const session = await this.loadSession(sessionId);
238
+ if (!session) {
239
+ return false;
240
+ }
241
+ session.title = newTitle;
242
+ session.updatedAt = Date.now();
243
+ const sessionPath = this.getSessionPath(sessionId);
244
+ await atomicWriteJSON(sessionPath, session);
245
+ const indexEntry = this.index.sessions.find((s) => s.id === sessionId);
246
+ if (indexEntry) {
247
+ indexEntry.title = newTitle;
248
+ indexEntry.updatedAt = session.updatedAt;
249
+ await this.saveIndex();
250
+ }
251
+ return true;
252
+ }
253
+ /**
254
+ * Archive a chat session
255
+ */
256
+ async archiveSession(sessionId) {
257
+ await this.loadIndex();
258
+ const session = await this.loadSession(sessionId);
259
+ if (!session) {
260
+ return false;
261
+ }
262
+ session.archived = true;
263
+ session.updatedAt = Date.now();
264
+ const sessionPath = this.getSessionPath(sessionId);
265
+ await atomicWriteJSON(sessionPath, session);
266
+ const indexEntry = this.index.sessions.find((s) => s.id === sessionId);
267
+ if (indexEntry) {
268
+ indexEntry.archived = true;
269
+ indexEntry.updatedAt = session.updatedAt;
270
+ await this.saveIndex();
271
+ }
272
+ return true;
273
+ }
274
+ /**
275
+ * Unarchive a chat session
276
+ */
277
+ async unarchiveSession(sessionId) {
278
+ await this.loadIndex();
279
+ const session = await this.loadSession(sessionId);
280
+ if (!session) {
281
+ return false;
282
+ }
283
+ session.archived = false;
284
+ session.updatedAt = Date.now();
285
+ const sessionPath = this.getSessionPath(sessionId);
286
+ await atomicWriteJSON(sessionPath, session);
287
+ const indexEntry = this.index.sessions.find((s) => s.id === sessionId);
288
+ if (indexEntry) {
289
+ indexEntry.archived = false;
290
+ indexEntry.updatedAt = session.updatedAt;
291
+ await this.saveIndex();
292
+ }
293
+ return true;
294
+ }
295
+ /**
296
+ * Export a chat session as JSON
297
+ */
298
+ async exportSession(sessionId) {
299
+ const session = await this.loadSession(sessionId);
300
+ if (!session) {
301
+ return null;
302
+ }
303
+ return JSON.stringify(session, null, 2);
304
+ }
305
+ /**
306
+ * Get statistics about chat sessions
307
+ */
308
+ async getStats() {
309
+ await this.loadIndex();
310
+ const total = this.index.sessions.length;
311
+ const archived = this.index.sessions.filter((s) => s.archived).length;
312
+ const active = total - archived;
313
+ const totalMessages = this.index.sessions.reduce((sum, s) => sum + s.messageCount, 0);
314
+ return { total, active, archived, totalMessages };
315
+ }
316
+ /**
317
+ * Prune old sessions (older than N days)
318
+ */
319
+ async pruneOldSessions(daysToKeep = 90) {
320
+ await this.loadIndex();
321
+ const cutoff = Date.now() - daysToKeep * 24 * 60 * 60 * 1e3;
322
+ const toDelete = this.index.sessions.filter((s) => s.updatedAt < cutoff);
323
+ for (const session of toDelete) {
324
+ await this.deleteSession(session.id);
325
+ }
326
+ return toDelete.length;
327
+ }
328
+ };
329
+ var chatStores = /* @__PURE__ */ new Map();
330
+ function getChatStore(projectPath) {
331
+ let store = chatStores.get(projectPath);
332
+ if (!store) {
333
+ store = new ChatStore(projectPath);
334
+ chatStores.set(projectPath, store);
335
+ }
336
+ return store;
337
+ }
338
+ function clearChatStores() {
339
+ chatStores.clear();
340
+ }
341
+
342
+ export {
343
+ ChatStore,
344
+ getChatStore,
345
+ clearChatStores
346
+ };
347
+ //# sourceMappingURL=chunk-DFPVUMVE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/dashboard/chat-store.ts"],"sourcesContent":["/**\n * Chat Store - Persistent storage for chat history\n * \n * Features:\n * - Save and load chat sessions\n * - List all chat sessions\n * - Archive management (rename, delete, export)\n * - Atomic writes with backup rotation\n * - Zod validation for data integrity\n * \n * Persists to: .trie/memory/chats/\n */\n\nimport { mkdir, readFile, unlink } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getTrieDirectory } from '../../utils/workspace.js';\nimport { z } from 'zod';\nimport { atomicWriteJSON } from '../../utils/atomic-write.js';\nimport type { ChatMessage } from './types.js';\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\nconst ChatMessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n timestamp: z.number(),\n toolCalls: z.array(z.object({\n id: z.string(),\n name: z.string(),\n input: z.record(z.any()),\n })).optional(),\n pendingFix: z.object({\n id: z.string(),\n file: z.string(),\n goal: z.string(),\n violation: z.string(),\n suggestedFix: z.string().optional(),\n }).optional(),\n});\n\nconst ChatSessionSchema = z.object({\n id: z.string(),\n title: z.string(),\n messages: z.array(ChatMessageSchema),\n createdAt: z.number(),\n updatedAt: z.number(),\n archived: z.boolean(),\n});\n\nexport type ChatSession = z.infer<typeof ChatSessionSchema>;\n\nconst ChatStoreIndexSchema = z.object({\n version: z.literal(1),\n sessions: z.array(z.object({\n id: z.string(),\n title: z.string(),\n createdAt: z.number(),\n updatedAt: z.number(),\n archived: z.boolean(),\n messageCount: z.number(),\n })),\n lastUpdated: z.string(),\n});\n\ntype ChatStoreIndex = z.infer<typeof ChatStoreIndexSchema>;\n\n// ============================================================================\n// ChatStore Class\n// ============================================================================\n\nexport class ChatStore {\n private projectPath: string;\n private index: ChatStoreIndex | null = null;\n \n constructor(projectPath: string) {\n this.projectPath = projectPath;\n }\n \n /**\n * Get the chats directory path\n */\n private getChatsDir(): string {\n return join(getTrieDirectory(this.projectPath), 'memory', 'chats');\n }\n \n /**\n * Get the index file path\n */\n private getIndexPath(): string {\n return join(this.getChatsDir(), 'index.json');\n }\n \n /**\n * Get the path for a specific session file\n */\n private getSessionPath(sessionId: string): string {\n return join(this.getChatsDir(), `${sessionId}.json`);\n }\n \n /**\n * Load the index file\n */\n private async loadIndex(): Promise<ChatStoreIndex> {\n if (this.index) {\n return this.index;\n }\n \n const indexPath = this.getIndexPath();\n \n if (existsSync(indexPath)) {\n try {\n const content = await readFile(indexPath, 'utf-8');\n const parsed = JSON.parse(content);\n const result = ChatStoreIndexSchema.safeParse(parsed);\n \n if (result.success) {\n this.index = result.data;\n return this.index;\n }\n } catch (error) {\n console.error('Failed to load chat index:', error);\n }\n }\n \n // Create empty index\n this.index = {\n version: 1,\n sessions: [],\n lastUpdated: new Date().toISOString(),\n };\n \n return this.index;\n }\n \n /**\n * Save the index file\n */\n private async saveIndex(): Promise<void> {\n if (!this.index) return;\n \n const indexPath = this.getIndexPath();\n const chatsDir = this.getChatsDir();\n \n // Ensure directory exists\n await mkdir(chatsDir, { recursive: true });\n \n // Update timestamp\n this.index.lastUpdated = new Date().toISOString();\n \n // Atomic write\n await atomicWriteJSON(indexPath, this.index);\n }\n \n /**\n * Generate a unique session ID\n */\n private generateSessionId(): string {\n return `chat-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n }\n \n /**\n * Generate a default title from the first user message\n */\n private generateTitle(messages: ChatMessage[]): string {\n const firstUser = messages.find(m => m.role === 'user');\n if (firstUser) {\n const text = firstUser.content.trim();\n const maxLen = 50;\n if (text.length > maxLen) {\n return text.slice(0, maxLen) + '...';\n }\n return text;\n }\n return 'New Chat';\n }\n \n /**\n * Save a chat session\n */\n async saveSession(messages: ChatMessage[], sessionId?: string, title?: string): Promise<string> {\n await this.loadIndex();\n \n const id = sessionId || this.generateSessionId();\n const now = Date.now();\n \n // Load existing session if updating\n let createdAt = now;\n if (sessionId) {\n const existing = this.index!.sessions.find(s => s.id === sessionId);\n if (existing) {\n createdAt = existing.createdAt;\n }\n }\n \n const session: ChatSession = {\n id,\n title: title || this.generateTitle(messages),\n messages,\n createdAt,\n updatedAt: now,\n archived: false,\n };\n \n // Validate\n const result = ChatSessionSchema.safeParse(session);\n if (!result.success) {\n throw new Error(`Invalid chat session: ${result.error.message}`);\n }\n \n // Save session file\n const sessionPath = this.getSessionPath(id);\n await mkdir(this.getChatsDir(), { recursive: true });\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const existingIndex = this.index!.sessions.findIndex(s => s.id === id);\n const indexEntry = {\n id,\n title: session.title,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt,\n archived: session.archived,\n messageCount: messages.length,\n };\n \n if (existingIndex >= 0) {\n this.index!.sessions[existingIndex] = indexEntry;\n } else {\n this.index!.sessions.unshift(indexEntry);\n }\n \n await this.saveIndex();\n \n return id;\n }\n \n /**\n * Load a chat session\n */\n async loadSession(sessionId: string): Promise<ChatSession | null> {\n const sessionPath = this.getSessionPath(sessionId);\n \n if (!existsSync(sessionPath)) {\n return null;\n }\n \n try {\n const content = await readFile(sessionPath, 'utf-8');\n const parsed = JSON.parse(content);\n const result = ChatSessionSchema.safeParse(parsed);\n \n if (result.success) {\n return result.data;\n }\n \n console.error('Invalid chat session:', result.error.message);\n return null;\n } catch (error) {\n console.error('Failed to load chat session:', error);\n return null;\n }\n }\n \n /**\n * List all chat sessions\n */\n async listSessions(includeArchived: boolean = false): Promise<ChatStoreIndex['sessions']> {\n await this.loadIndex();\n \n let sessions = this.index!.sessions;\n \n if (!includeArchived) {\n sessions = sessions.filter(s => !s.archived);\n }\n \n // Sort by most recent first\n return sessions.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n \n /**\n * Delete a chat session\n */\n async deleteSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const sessionPath = this.getSessionPath(sessionId);\n \n if (!existsSync(sessionPath)) {\n return false;\n }\n \n try {\n await unlink(sessionPath);\n \n // Remove from index\n this.index!.sessions = this.index!.sessions.filter(s => s.id !== sessionId);\n await this.saveIndex();\n \n return true;\n } catch (error) {\n console.error('Failed to delete chat session:', error);\n return false;\n }\n }\n \n /**\n * Rename a chat session\n */\n async renameSession(sessionId: string, newTitle: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.title = newTitle;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.title = newTitle;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Archive a chat session\n */\n async archiveSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.archived = true;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.archived = true;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Unarchive a chat session\n */\n async unarchiveSession(sessionId: string): Promise<boolean> {\n await this.loadIndex();\n \n const session = await this.loadSession(sessionId);\n if (!session) {\n return false;\n }\n \n session.archived = false;\n session.updatedAt = Date.now();\n \n // Save updated session\n const sessionPath = this.getSessionPath(sessionId);\n await atomicWriteJSON(sessionPath, session);\n \n // Update index\n const indexEntry = this.index!.sessions.find(s => s.id === sessionId);\n if (indexEntry) {\n indexEntry.archived = false;\n indexEntry.updatedAt = session.updatedAt;\n await this.saveIndex();\n }\n \n return true;\n }\n \n /**\n * Export a chat session as JSON\n */\n async exportSession(sessionId: string): Promise<string | null> {\n const session = await this.loadSession(sessionId);\n if (!session) {\n return null;\n }\n \n return JSON.stringify(session, null, 2);\n }\n \n /**\n * Get statistics about chat sessions\n */\n async getStats(): Promise<{\n total: number;\n active: number;\n archived: number;\n totalMessages: number;\n }> {\n await this.loadIndex();\n \n const total = this.index!.sessions.length;\n const archived = this.index!.sessions.filter(s => s.archived).length;\n const active = total - archived;\n const totalMessages = this.index!.sessions.reduce((sum, s) => sum + s.messageCount, 0);\n \n return { total, active, archived, totalMessages };\n }\n \n /**\n * Prune old sessions (older than N days)\n */\n async pruneOldSessions(daysToKeep: number = 90): Promise<number> {\n await this.loadIndex();\n \n const cutoff = Date.now() - (daysToKeep * 24 * 60 * 60 * 1000);\n const toDelete = this.index!.sessions.filter(s => s.updatedAt < cutoff);\n \n for (const session of toDelete) {\n await this.deleteSession(session.id);\n }\n \n return toDelete.length;\n }\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst chatStores: Map<string, ChatStore> = new Map();\n\n/**\n * Get the ChatStore for a project (singleton per project)\n */\nexport function getChatStore(projectPath: string): ChatStore {\n let store = chatStores.get(projectPath);\n if (!store) {\n store = new ChatStore(projectPath);\n chatStores.set(projectPath, store);\n }\n return store;\n}\n\n/**\n * Clear all ChatStore instances (for testing)\n */\nexport function clearChatStores(): void {\n chatStores.clear();\n}\n"],"mappings":"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","names":[]}
@@ -3,12 +3,12 @@ import {
3
3
  } from "./chunk-WRGSH5RT.js";
4
4
  import {
5
5
  searchIssues
6
- } from "./chunk-PRFHN2X6.js";
6
+ } from "./chunk-K5EXATBF.js";
7
7
  import {
8
8
  BackupManager,
9
9
  GlobalPatternsIndexSchema,
10
10
  safeParseAndValidate
11
- } from "./chunk-4BGAVEO6.js";
11
+ } from "./chunk-WS6OA7H6.js";
12
12
  import {
13
13
  scanForVulnerabilities
14
14
  } from "./chunk-F4NJ4CBP.js";
@@ -801,4 +801,4 @@ export {
801
801
  getStorage,
802
802
  GotchaPredictor
803
803
  };
804
- //# sourceMappingURL=chunk-FNW7Z7ZS.js.map
804
+ //# sourceMappingURL=chunk-F4ZIAHTZ.js.map
@@ -3,7 +3,7 @@ import {
3
3
  CompactedSummariesIndexSchema,
4
4
  IssueIndexSchema,
5
5
  safeParseAndValidate
6
- } from "./chunk-4BGAVEO6.js";
6
+ } from "./chunk-WS6OA7H6.js";
7
7
  import {
8
8
  appendIssuesToLedger
9
9
  } from "./chunk-7Q6I2CB4.js";
@@ -769,4 +769,4 @@ export {
769
769
  purgeIssues,
770
770
  getDailyLogs
771
771
  };
772
- //# sourceMappingURL=chunk-PRFHN2X6.js.map
772
+ //# sourceMappingURL=chunk-K5EXATBF.js.map