@yugenlab/vaayu 0.1.10 → 0.1.12

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 (53) hide show
  1. package/chunks/{agentic-tool-loop-2FZK72JO.js → agentic-tool-loop-NQESOBLC.js} +2 -2
  2. package/chunks/akasha-5C5Q6NMP.js +12 -0
  3. package/chunks/{chunk-JGI4SDWS.js → chunk-26K6DS6N.js} +7 -5
  4. package/chunks/chunk-5E3ZS5SW.js +529 -0
  5. package/chunks/{chunk-VJHNE47S.js → chunk-ARZCIITZ.js} +104 -94
  6. package/chunks/{chunk-PRXQW76U.js → chunk-EG37M4QL.js} +17 -6
  7. package/chunks/{chunk-HIYHTWFW.js → chunk-FEDPZOZ5.js} +572 -441
  8. package/chunks/{chunk-O4KV7TFP.js → chunk-GWYC7R2L.js} +38 -20
  9. package/chunks/chunk-H46F2Y6R.js +134 -0
  10. package/chunks/{chunk-M7THR63C.js → chunk-HXHDP2PZ.js} +78 -65
  11. package/chunks/chunk-KVQH4LE7.js +396 -0
  12. package/chunks/{chunk-TND3MU4Z.js → chunk-LJCT7UYP.js} +86 -68
  13. package/chunks/{chunk-OT4G2L46.js → chunk-M2RLX5LU.js} +229 -163
  14. package/chunks/{chunk-IGKYKEKT.js → chunk-NAQKA54E.js} +8 -2
  15. package/chunks/{chunk-77725AR7.js → chunk-PZ4AQ22L.js} +151 -57
  16. package/chunks/{chunk-C76USAC5.js → chunk-QFGAB4XD.js} +13 -5
  17. package/chunks/{chunk-MJ74G5RB.js → chunk-R273KC7J.js} +276 -3
  18. package/chunks/{chunk-JAWZ7ANC.js → chunk-RVKTGKFD.js} +12 -8
  19. package/chunks/{chunk-AGK3A7R7.js → chunk-TSOQ2CT3.js} +1430 -1173
  20. package/chunks/{chunk-YJRXLRTE.js → chunk-VEZ2DI2M.js} +24 -12
  21. package/chunks/{chunk-N22M7D4P.js → chunk-XP3NIH5F.js} +91 -98
  22. package/chunks/{chunk-6556EKOB.js → chunk-Y6IZH6FT.js} +42 -26
  23. package/chunks/{chunk-AS3DJFY3.js → chunk-YRTGGYJU.js} +45 -41
  24. package/chunks/{consolidation-indexer-VKQ6DNU3.js → consolidation-indexer-KPXORCJ4.js} +9 -9
  25. package/chunks/database-BX3LVYXS.js +11 -0
  26. package/chunks/{day-consolidation-BH3QU2SZ.js → day-consolidation-CR3TJFAL.js} +5 -5
  27. package/chunks/{src-Y3TGMINC.js → dist-ESCM3CP5.js} +31 -21
  28. package/chunks/graphrag-73XA7LBX.js +14 -0
  29. package/chunks/hierarchical-temporal-search-GHKVKNZ6.js +8 -0
  30. package/chunks/hybrid-search-OD756RDV.js +20 -0
  31. package/chunks/{memory-store-A6WOWLWC.js → memory-store-4GCBR2DZ.js} +4 -4
  32. package/chunks/periodic-consolidation-IINCHP6L.js +11 -0
  33. package/chunks/postgres-YLCUNVPQ.js +8 -0
  34. package/chunks/recall-64RROTUC.js +21 -0
  35. package/chunks/search-JVCDNTAJ.js +19 -0
  36. package/chunks/{session-store-3BRPGC6P.js → session-store-3EDQZEDS.js} +12 -6
  37. package/chunks/{sqlite-DHUQGPR5.js → sqlite-4N7YH2KK.js} +3 -3
  38. package/chunks/{src-6GVZTUH6.js → src-OPSDZEFI.js} +2 -2
  39. package/chunks/{suncalc-NOHGYHDU.js → suncalc-RM7URNUR.js} +2 -2
  40. package/chunks/{tree-RSHKDTCR.js → tree-FIUVGJ5J.js} +2 -2
  41. package/chunks/{vasana-engine-MU25OQ23.js → vasana-engine-W4PYWT5H.js} +5 -5
  42. package/gateway.js +38859 -30650
  43. package/package.json +1 -1
  44. package/pair-cli.js +2 -2
  45. package/chunks/chunk-U62ABYKD.js +0 -123
  46. package/chunks/chunk-UZ6OIVEC.js +0 -198
  47. package/chunks/graphrag-D7OXWAWD.js +0 -14
  48. package/chunks/hierarchical-temporal-search-PVHVA3NZ.js +0 -8
  49. package/chunks/hybrid-search-G2NAJKJ7.js +0 -20
  50. package/chunks/periodic-consolidation-LMYMNS4Q.js +0 -11
  51. package/chunks/postgres-WLH3D5HG.js +0 -8
  52. package/chunks/recall-ZNL4DJ2L.js +0 -21
  53. package/chunks/search-35JMSGUT.js +0 -19
@@ -1,21 +1,23 @@
1
1
  import {
2
- initAgentSchema
3
- } from "./chunk-YJRXLRTE.js";
2
+ initAgentSchema,
3
+ init_schema
4
+ } from "./chunk-VEZ2DI2M.js";
4
5
  import {
5
- DatabaseManager
6
- } from "./chunk-U62ABYKD.js";
6
+ DatabaseManager,
7
+ init_database
8
+ } from "./chunk-H46F2Y6R.js";
7
9
  import {
8
10
  SessionError,
9
- getChitraguptaHome
10
- } from "./chunk-UZ6OIVEC.js";
11
-
12
- // ../chitragupta/packages/smriti/src/session-store.ts
13
- import fs from "fs";
14
- import { renameSync as nodeRenameSync } from "node:fs";
15
- import path from "path";
16
- import crypto from "crypto";
11
+ getChitraguptaHome,
12
+ init_dist
13
+ } from "./chunk-KVQH4LE7.js";
14
+ import {
15
+ __esm,
16
+ __export,
17
+ __toCommonJS
18
+ } from "./chunk-NAQKA54E.js";
17
19
 
18
- // ../chitragupta/packages/smriti/src/markdown-parser.ts
20
+ // ../chitragupta/packages/smriti/dist/markdown-parser.js
19
21
  function parseFrontmatter(yaml) {
20
22
  const result = {};
21
23
  const lines = yaml.split("\n");
@@ -23,7 +25,8 @@ function parseFrontmatter(yaml) {
23
25
  let currentArray = null;
24
26
  for (const line of lines) {
25
27
  const trimmed = line.trim();
26
- if (!trimmed || trimmed.startsWith("#")) continue;
28
+ if (!trimmed || trimmed.startsWith("#"))
29
+ continue;
27
30
  if (trimmed.startsWith("- ") && currentKey && currentArray !== null) {
28
31
  currentArray.push(trimmed.slice(2).trim());
29
32
  continue;
@@ -34,7 +37,8 @@ function parseFrontmatter(yaml) {
34
37
  currentKey = null;
35
38
  }
36
39
  const colonIdx = trimmed.indexOf(":");
37
- if (colonIdx === -1) continue;
40
+ if (colonIdx === -1)
41
+ continue;
38
42
  const key = trimmed.slice(0, colonIdx).trim();
39
43
  const rawValue = trimmed.slice(colonIdx + 1).trim();
40
44
  if (rawValue === "" || rawValue === void 0) {
@@ -59,9 +63,12 @@ function parseFrontmatter(yaml) {
59
63
  return result;
60
64
  }
61
65
  function parseScalar(value) {
62
- if (value === "null" || value === "~") return null;
63
- if (value === "true") return true;
64
- if (value === "false") return false;
66
+ if (value === "null" || value === "~")
67
+ return null;
68
+ if (value === "true")
69
+ return true;
70
+ if (value === "false")
71
+ return false;
65
72
  if (value.startsWith('"') && value.endsWith('"')) {
66
73
  return value.slice(1, -1).replace(/\\"/g, '"');
67
74
  }
@@ -69,7 +76,8 @@ function parseScalar(value) {
69
76
  return value.slice(1, -1);
70
77
  }
71
78
  const num = Number(value);
72
- if (!Number.isNaN(num) && value !== "") return num;
79
+ if (!Number.isNaN(num) && value !== "")
80
+ return num;
73
81
  return value;
74
82
  }
75
83
  function parseSessionMarkdown(content) {
@@ -103,7 +111,8 @@ function buildSessionMeta(raw) {
103
111
  };
104
112
  }
105
113
  function parseTurns(body) {
106
- if (!body) return [];
114
+ if (!body)
115
+ return [];
107
116
  body = stripFooter(body);
108
117
  const turnPattern = /^## Turn (\d+) — (user|assistant)(?:\s+\(([^)]*)\))?/gm;
109
118
  const turns = [];
@@ -129,8 +138,10 @@ function parseTurns(body) {
129
138
  const parts = m.meta.split(",").map((s) => s.trim());
130
139
  for (const part of parts) {
131
140
  const [k, v] = part.split(":").map((s) => s.trim());
132
- if (k === "agent") agent = v;
133
- if (k === "model") model = v;
141
+ if (k === "agent")
142
+ agent = v;
143
+ if (k === "model")
144
+ model = v;
134
145
  }
135
146
  }
136
147
  const { content, toolCalls } = parseContentAndToolCalls(rawContent);
@@ -140,9 +151,12 @@ function parseTurns(body) {
140
151
  role: m.role,
141
152
  content: unescapedContent
142
153
  };
143
- if (agent) turn.agent = agent;
144
- if (model) turn.model = model;
145
- if (toolCalls.length > 0) turn.toolCalls = toolCalls;
154
+ if (agent)
155
+ turn.agent = agent;
156
+ if (model)
157
+ turn.model = model;
158
+ if (toolCalls.length > 0)
159
+ turn.toolCalls = toolCalls;
146
160
  turns.push(turn);
147
161
  }
148
162
  return turns;
@@ -193,11 +207,18 @@ function parseToolCallSection(name, section) {
193
207
  }
194
208
  }
195
209
  const toolCall = { name, input, result };
196
- if (isError) toolCall.isError = true;
210
+ if (isError)
211
+ toolCall.isError = true;
197
212
  return toolCall;
198
213
  }
214
+ var init_markdown_parser = __esm({
215
+ "../chitragupta/packages/smriti/dist/markdown-parser.js"() {
216
+ "use strict";
217
+ init_dist();
218
+ }
219
+ });
199
220
 
200
- // ../chitragupta/packages/smriti/src/markdown-writer.ts
221
+ // ../chitragupta/packages/smriti/dist/markdown-writer.js
201
222
  function writeFrontmatter(meta) {
202
223
  const lines = [];
203
224
  lines.push("---");
@@ -247,8 +268,10 @@ function writeTurn(turn) {
247
268
  const lines = [];
248
269
  let heading = `## Turn ${turn.turnNumber} \u2014 ${turn.role}`;
249
270
  const metaParts = [];
250
- if (turn.agent) metaParts.push(`agent: ${turn.agent}`);
251
- if (turn.model) metaParts.push(`model: ${turn.model}`);
271
+ if (turn.agent)
272
+ metaParts.push(`agent: ${turn.agent}`);
273
+ if (turn.model)
274
+ metaParts.push(`model: ${turn.model}`);
252
275
  if (metaParts.length > 0) {
253
276
  heading += ` (${metaParts.join(", ")})`;
254
277
  }
@@ -287,143 +310,24 @@ function writeSessionMarkdown(session) {
287
310
  function writeTurnMarkdown(turn) {
288
311
  return writeTurn(turn);
289
312
  }
290
-
291
- // ../chitragupta/packages/smriti/src/session-store.ts
292
- function atomicRename(tmpPath, targetPath) {
293
- try {
294
- nodeRenameSync(tmpPath, targetPath);
295
- } catch {
296
- fs.writeFileSync(targetPath, fs.readFileSync(tmpPath, "utf-8"), "utf-8");
297
- try {
298
- fs.unlinkSync(tmpPath);
299
- } catch {
300
- }
301
- }
302
- }
303
- var SESSION_CACHE_MAX = 500;
304
- var SESSION_CACHE_MAX_BYTES = 25 * 1024 * 1024;
305
- var sessionCache = /* @__PURE__ */ new Map();
306
- var sessionCacheSizes = /* @__PURE__ */ new Map();
307
- var sessionCacheBytes = 0;
308
- function estimateSessionBytes(session) {
309
- let bytes = 200;
310
- for (const turn of session.turns) {
311
- bytes += Buffer.byteLength(turn.content, "utf-8") + 50;
312
- }
313
- return bytes;
314
- }
315
- function cacheKey(id, project) {
316
- return `${id}:${project}`;
317
- }
318
- function cacheGet(id, project) {
319
- const key = cacheKey(id, project);
320
- const entry = sessionCache.get(key);
321
- if (!entry) return void 0;
322
- const size = sessionCacheSizes.get(key) ?? 0;
323
- sessionCache.delete(key);
324
- sessionCacheSizes.delete(key);
325
- sessionCache.set(key, entry);
326
- sessionCacheSizes.set(key, size);
327
- return entry;
328
- }
329
- function cachePut(id, project, session) {
330
- const key = cacheKey(id, project);
331
- const existingSize = sessionCacheSizes.get(key) ?? 0;
332
- sessionCache.delete(key);
333
- sessionCacheSizes.delete(key);
334
- sessionCacheBytes -= existingSize;
335
- const newSize = estimateSessionBytes(session);
336
- while ((sessionCache.size >= SESSION_CACHE_MAX || sessionCacheBytes + newSize > SESSION_CACHE_MAX_BYTES) && sessionCache.size > 0) {
337
- const oldest = sessionCache.keys().next().value;
338
- if (oldest === void 0) break;
339
- const evictedSize = sessionCacheSizes.get(oldest) ?? 0;
340
- sessionCache.delete(oldest);
341
- sessionCacheSizes.delete(oldest);
342
- sessionCacheBytes -= evictedSize;
313
+ var init_markdown_writer = __esm({
314
+ "../chitragupta/packages/smriti/dist/markdown-writer.js"() {
315
+ "use strict";
343
316
  }
344
- sessionCache.set(key, session);
345
- sessionCacheSizes.set(key, newSize);
346
- sessionCacheBytes += newSize;
347
- }
348
- function cacheInvalidate(id, project) {
349
- const key = cacheKey(id, project);
350
- const size = sessionCacheSizes.get(key) ?? 0;
351
- sessionCache.delete(key);
352
- sessionCacheSizes.delete(key);
353
- sessionCacheBytes -= size;
354
- }
355
- function _resetSessionCache() {
356
- sessionCache.clear();
357
- sessionCacheSizes.clear();
358
- sessionCacheBytes = 0;
359
- }
317
+ });
318
+
319
+ // ../chitragupta/packages/smriti/dist/session-db.js
320
+ import path from "path";
321
+ import crypto from "crypto";
360
322
  function hashProject(project) {
361
323
  return crypto.createHash("sha256").update(project).digest("hex").slice(0, 12);
362
324
  }
363
- function generateSessionId(project) {
364
- const now = /* @__PURE__ */ new Date();
365
- const yyyy = now.getFullYear().toString();
366
- const mm = (now.getMonth() + 1).toString().padStart(2, "0");
367
- const dd = now.getDate().toString().padStart(2, "0");
368
- const dateStr = `${yyyy}-${mm}-${dd}`;
369
- const projHash = hashProject(project).slice(0, 8);
370
- const baseId = `session-${dateStr}-${projHash}`;
371
- const projectDir = getProjectSessionDir(project);
372
- const yearMonthDir = path.join(projectDir, yyyy, mm);
373
- fs.mkdirSync(yearMonthDir, { recursive: true });
374
- const basePath = path.join(yearMonthDir, `${baseId}.md`);
375
- if (!fs.existsSync(basePath)) {
376
- return {
377
- id: baseId,
378
- filePath: path.join("sessions", hashProject(project), yyyy, mm, `${baseId}.md`)
379
- };
380
- }
381
- let counter = 2;
382
- while (fs.existsSync(path.join(yearMonthDir, `${baseId}-${counter}.md`))) {
383
- counter++;
384
- }
385
- const id = `${baseId}-${counter}`;
386
- return {
387
- id,
388
- filePath: path.join("sessions", hashProject(project), yyyy, mm, `${id}.md`)
389
- };
390
- }
391
325
  function getSessionsRoot() {
392
326
  return path.join(getChitraguptaHome(), "sessions");
393
327
  }
394
328
  function getProjectSessionDir(project) {
395
329
  return path.join(getSessionsRoot(), hashProject(project));
396
330
  }
397
- function resolveSessionPath(id, project) {
398
- const projectDir = getProjectSessionDir(project);
399
- const dateMatch = id.match(/^session-(\d{4})-(\d{2})-\d{2}/);
400
- if (dateMatch) {
401
- const newPath = path.join(projectDir, dateMatch[1], dateMatch[2], `${id}.md`);
402
- if (fs.existsSync(newPath)) return newPath;
403
- }
404
- const oldPath = path.join(projectDir, `${id}.md`);
405
- if (fs.existsSync(oldPath)) return oldPath;
406
- if (dateMatch) {
407
- return path.join(projectDir, dateMatch[1], dateMatch[2], `${id}.md`);
408
- }
409
- return oldPath;
410
- }
411
- function patchFrontmatterUpdated(content, updatedIso) {
412
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
413
- if (!fmMatch) return content;
414
- const frontmatter = fmMatch[1];
415
- if (!/^updated:\s/m.test(frontmatter)) return content;
416
- const patchedFrontmatter = frontmatter.replace(
417
- /^updated:\s.*$/m,
418
- `updated: ${updatedIso}`
419
- );
420
- if (patchedFrontmatter === frontmatter) return content;
421
- return `---
422
- ${patchedFrontmatter}
423
- ---${content.slice(fmMatch[0].length)}`;
424
- }
425
- var _dbInitialized = false;
426
- var _dbInitError = null;
427
331
  function getAgentDb() {
428
332
  const dbm = DatabaseManager.instance();
429
333
  if (!_dbInitialized) {
@@ -517,7 +421,8 @@ function upsertSessionToDb(meta, filePath) {
517
421
  }
518
422
  }
519
423
  function isRecoverableSessionConstraintError(err) {
520
- if (!(err instanceof Error)) return false;
424
+ if (!(err instanceof Error))
425
+ return false;
521
426
  const lower = err.message.toLowerCase();
522
427
  return lower.includes("foreign key constraint failed") || lower.includes("constraint failed");
523
428
  }
@@ -528,43 +433,21 @@ function seedSessionRowForTurn(sessionId, project, filePath) {
528
433
  db.prepare(`
529
434
  INSERT OR IGNORE INTO sessions (id, project, title, created_at, updated_at, turn_count, file_path)
530
435
  VALUES (?, ?, ?, ?, ?, ?, ?)
531
- `).run(
532
- sessionId,
533
- project,
534
- "Recovered Session",
535
- now,
536
- now,
537
- 0,
538
- normalizedFilePath
539
- );
436
+ `).run(sessionId, project, "Recovered Session", now, now, 0, normalizedFilePath);
540
437
  }
541
438
  function insertTurnToDb(sessionId, turn, context) {
542
439
  try {
543
440
  const db = getAgentDb();
441
+ const now = Date.now();
544
442
  const writeTurn2 = db.transaction(() => {
545
- const now = Date.now();
546
443
  const result = db.prepare(`
547
444
  INSERT OR IGNORE INTO turns (session_id, turn_number, role, content, agent, model, tool_calls, created_at)
548
445
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
549
- `).run(
550
- sessionId,
551
- turn.turnNumber,
552
- turn.role,
553
- turn.content,
554
- turn.agent ?? null,
555
- turn.model ?? null,
556
- turn.toolCalls ? JSON.stringify(turn.toolCalls) : null,
557
- now
558
- );
446
+ `).run(sessionId, turn.turnNumber, turn.role, turn.content, turn.agent ?? null, turn.model ?? null, turn.toolCalls ? JSON.stringify(turn.toolCalls) : null, now);
559
447
  if (result.changes > 0) {
560
- db.prepare("INSERT OR IGNORE INTO turns_fts (rowid, content) VALUES (?, ?)").run(
561
- result.lastInsertRowid,
562
- turn.content
563
- );
448
+ db.prepare("INSERT OR IGNORE INTO turns_fts (rowid, content) VALUES (?, ?)").run(result.lastInsertRowid, turn.content);
564
449
  }
565
- db.prepare(
566
- "UPDATE sessions SET turn_count = turn_count + 1, updated_at = ? WHERE id = ?"
567
- ).run(now, sessionId);
450
+ db.prepare("UPDATE sessions SET turn_count = turn_count + 1, updated_at = ? WHERE id = ?").run(now, sessionId);
568
451
  });
569
452
  try {
570
453
  writeTurn2();
@@ -579,87 +462,155 @@ function insertTurnToDb(sessionId, turn, context) {
579
462
  }
580
463
  } catch (err) {
581
464
  const code = typeof err === "object" && err !== null && "code" in err ? String(err.code) : "unknown";
582
- process.stderr.write(
583
- `[chitragupta] turn insert failed for session ${sessionId} (turn=${turn.turnNumber}, role=${turn.role}, code=${code}): ${err instanceof Error ? err.message : err}
584
- `
585
- );
465
+ process.stderr.write(`[chitragupta] turn insert failed for session ${sessionId} (turn=${turn.turnNumber}, role=${turn.role}, code=${code}): ${err instanceof Error ? err.message : err}
466
+ `);
586
467
  }
587
468
  }
588
- function createSession(opts) {
589
- const now = (/* @__PURE__ */ new Date()).toISOString();
590
- const { id, filePath } = generateSessionId(opts.project);
591
- const meta = {
592
- id,
593
- title: opts.title ?? "New Session",
594
- created: now,
595
- updated: now,
596
- agent: opts.agent ?? "chitragupta",
597
- model: opts.model ?? "unknown",
598
- provider: opts.provider,
599
- project: opts.project,
600
- parent: opts.parentSessionId ?? null,
601
- branch: opts.branch ?? null,
602
- tags: opts.tags ?? [],
603
- totalCost: 0,
604
- totalTokens: 0,
605
- metadata: opts.metadata
606
- };
607
- if (opts.provider) {
608
- meta.metadata = { ...meta.metadata, provider: opts.provider };
469
+ function getMaxTurnNumber(sessionId) {
470
+ try {
471
+ const db = getAgentDb();
472
+ const row = db.prepare("SELECT MAX(turn_number) as max_turn FROM turns WHERE session_id = ?").get(sessionId);
473
+ return row?.max_turn ?? 0;
474
+ } catch {
475
+ return 0;
609
476
  }
610
- const session = { meta, turns: [] };
611
- saveSession(session);
612
- upsertSessionToDb(meta, filePath);
613
- return session;
614
477
  }
615
- function saveSession(session) {
616
- const filePath = resolveSessionPath(session.meta.id, session.meta.project);
617
- const dir = path.dirname(filePath);
618
- try {
619
- fs.mkdirSync(dir, { recursive: true });
620
- session.meta.updated = (/* @__PURE__ */ new Date()).toISOString();
621
- const markdown = writeSessionMarkdown(session);
622
- const tmpPath = `${filePath}.tmp.${process.pid}`;
623
- fs.writeFileSync(tmpPath, markdown, "utf-8");
624
- atomicRename(tmpPath, filePath);
625
- cachePut(session.meta.id, session.meta.project, session);
626
- } catch (err) {
627
- throw new SessionError(
628
- `Failed to save session ${session.meta.id} at ${filePath}: ${err.message}`
629
- );
478
+ var _dbInitialized, _dbInitError;
479
+ var init_session_db = __esm({
480
+ "../chitragupta/packages/smriti/dist/session-db.js"() {
481
+ "use strict";
482
+ init_dist();
483
+ init_database();
484
+ init_schema();
485
+ _dbInitialized = false;
486
+ _dbInitError = null;
487
+ }
488
+ });
489
+
490
+ // ../chitragupta/packages/smriti/dist/session-store-cache.js
491
+ function estimateSessionBytes(session) {
492
+ let bytes = 200;
493
+ for (const turn of session.turns) {
494
+ bytes += Buffer.byteLength(turn.content, "utf-8") + 50;
630
495
  }
496
+ return bytes;
631
497
  }
632
- function loadSession(id, project) {
633
- const cached = cacheGet(id, project);
634
- if (cached) return cached;
635
- const filePath = resolveSessionPath(id, project);
636
- if (!fs.existsSync(filePath)) {
637
- throw new SessionError(`Session not found: ${id} (project: ${project})`);
498
+ function cacheKey(id, project) {
499
+ return `${id}:${project}`;
500
+ }
501
+ function cacheGet(id, project) {
502
+ const key = cacheKey(id, project);
503
+ const entry = sessionCache.get(key);
504
+ if (!entry)
505
+ return void 0;
506
+ const size = sessionCacheSizes.get(key) ?? 0;
507
+ sessionCache.delete(key);
508
+ sessionCacheSizes.delete(key);
509
+ sessionCache.set(key, entry);
510
+ sessionCacheSizes.set(key, size);
511
+ return entry;
512
+ }
513
+ function cachePut(id, project, session) {
514
+ const key = cacheKey(id, project);
515
+ const existingSize = sessionCacheSizes.get(key) ?? 0;
516
+ sessionCache.delete(key);
517
+ sessionCacheSizes.delete(key);
518
+ sessionCacheBytes -= existingSize;
519
+ const newSize = estimateSessionBytes(session);
520
+ while ((sessionCache.size >= SESSION_CACHE_MAX || sessionCacheBytes + newSize > SESSION_CACHE_MAX_BYTES) && sessionCache.size > 0) {
521
+ const oldest = sessionCache.keys().next().value;
522
+ if (oldest === void 0)
523
+ break;
524
+ const evictedSize = sessionCacheSizes.get(oldest) ?? 0;
525
+ sessionCache.delete(oldest);
526
+ sessionCacheSizes.delete(oldest);
527
+ sessionCacheBytes -= evictedSize;
528
+ }
529
+ sessionCache.set(key, session);
530
+ sessionCacheSizes.set(key, newSize);
531
+ sessionCacheBytes += newSize;
532
+ }
533
+ function cacheInvalidate(id, project) {
534
+ const key = cacheKey(id, project);
535
+ const size = sessionCacheSizes.get(key) ?? 0;
536
+ sessionCache.delete(key);
537
+ sessionCacheSizes.delete(key);
538
+ sessionCacheBytes -= size;
539
+ }
540
+ function _resetSessionCache() {
541
+ sessionCache.clear();
542
+ sessionCacheSizes.clear();
543
+ sessionCacheBytes = 0;
544
+ }
545
+ var SESSION_CACHE_MAX, SESSION_CACHE_MAX_BYTES, sessionCache, sessionCacheSizes, sessionCacheBytes;
546
+ var init_session_store_cache = __esm({
547
+ "../chitragupta/packages/smriti/dist/session-store-cache.js"() {
548
+ "use strict";
549
+ SESSION_CACHE_MAX = 500;
550
+ SESSION_CACHE_MAX_BYTES = 25 * 1024 * 1024;
551
+ sessionCache = /* @__PURE__ */ new Map();
552
+ sessionCacheSizes = /* @__PURE__ */ new Map();
553
+ sessionCacheBytes = 0;
554
+ }
555
+ });
556
+
557
+ // ../chitragupta/packages/smriti/dist/session-queries.js
558
+ import fs from "fs";
559
+ import path2 from "path";
560
+ function listSessionsFromFilesystem(project) {
561
+ const sessionsRoot = getSessionsRoot();
562
+ if (!fs.existsSync(sessionsRoot))
563
+ return [];
564
+ const results = [];
565
+ if (project) {
566
+ const projectDir = getProjectSessionDir(project);
567
+ if (!fs.existsSync(projectDir))
568
+ return [];
569
+ results.push(...scanDirRecursive(projectDir));
570
+ } else {
571
+ const projectDirs = fs.readdirSync(sessionsRoot, { withFileTypes: true });
572
+ for (const entry of projectDirs) {
573
+ if (entry.isDirectory()) {
574
+ results.push(...scanDirRecursive(path2.join(sessionsRoot, entry.name)));
575
+ }
576
+ }
638
577
  }
578
+ results.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime());
579
+ return results;
580
+ }
581
+ function scanDirRecursive(dir) {
582
+ const metas = [];
639
583
  try {
640
- const content = fs.readFileSync(filePath, "utf-8");
641
- const session = parseSessionMarkdown(content);
642
- cachePut(id, project, session);
643
- return session;
584
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
585
+ for (const entry of entries) {
586
+ const fullPath = path2.join(dir, entry.name);
587
+ if (entry.isDirectory()) {
588
+ metas.push(...scanDirRecursive(fullPath));
589
+ } else if (entry.name.endsWith(".md")) {
590
+ try {
591
+ const content = fs.readFileSync(fullPath, "utf-8");
592
+ const session = parseSessionMarkdown(content);
593
+ metas.push(session.meta);
594
+ } catch (err) {
595
+ process.stderr.write(`[smriti:session-queries] skip unparseable file ${fullPath}: ${err instanceof Error ? err.message : String(err)}
596
+ `);
597
+ }
598
+ }
599
+ }
644
600
  } catch (err) {
645
- if (err instanceof SessionError) throw err;
646
- throw new SessionError(
647
- `Failed to load session ${id}: ${err.message}`
648
- );
601
+ process.stderr.write(`[smriti:session-queries] directory scan failed for ${dir}: ${err instanceof Error ? err.message : String(err)}
602
+ `);
649
603
  }
604
+ return metas;
650
605
  }
651
606
  function listSessions(project) {
652
607
  try {
653
608
  const db = getAgentDb();
654
609
  let rows;
655
610
  if (project) {
656
- rows = db.prepare(
657
- "SELECT * FROM sessions WHERE project = ? ORDER BY updated_at DESC"
658
- ).all(project);
611
+ rows = db.prepare("SELECT * FROM sessions WHERE project = ? ORDER BY updated_at DESC").all(project);
659
612
  } else {
660
- rows = db.prepare(
661
- "SELECT * FROM sessions ORDER BY updated_at DESC"
662
- ).all();
613
+ rows = db.prepare("SELECT * FROM sessions ORDER BY updated_at DESC").all();
663
614
  }
664
615
  if (rows.length > 0) {
665
616
  return rows.map(rowToSessionMeta);
@@ -684,18 +635,16 @@ function listSessionsByDateRange(startMs, endMs, project) {
684
635
  const db = getAgentDb();
685
636
  let rows;
686
637
  if (project) {
687
- rows = db.prepare(
688
- "SELECT * FROM sessions WHERE project = ? AND created_at >= ? AND created_at < ? ORDER BY created_at ASC"
689
- ).all(project, startMs, endMs);
638
+ rows = db.prepare("SELECT * FROM sessions WHERE project = ? AND created_at >= ? AND created_at < ? ORDER BY created_at ASC").all(project, startMs, endMs);
690
639
  } else {
691
- rows = db.prepare(
692
- "SELECT * FROM sessions WHERE created_at >= ? AND created_at < ? ORDER BY created_at ASC"
693
- ).all(startMs, endMs);
640
+ rows = db.prepare("SELECT * FROM sessions WHERE created_at >= ? AND created_at < ? ORDER BY created_at ASC").all(startMs, endMs);
694
641
  }
695
642
  if (rows.length > 0) {
696
643
  return rows.map(rowToSessionMeta);
697
644
  }
698
- } catch {
645
+ } catch (err) {
646
+ process.stderr.write(`[smriti:session-queries] listSessionsByDateRange SQLite failed: ${err instanceof Error ? err.message : String(err)}
647
+ `);
699
648
  }
700
649
  const allSessions = listSessionsFromFilesystem(project);
701
650
  return allSessions.filter((s) => {
@@ -708,20 +657,18 @@ function listSessionDates(project) {
708
657
  const db = getAgentDb();
709
658
  let rows;
710
659
  if (project) {
711
- rows = db.prepare(
712
- `SELECT DISTINCT date(created_at / 1000, 'unixepoch') as session_date
660
+ rows = db.prepare(`SELECT DISTINCT date(created_at / 1000, 'unixepoch') as session_date
713
661
  FROM sessions WHERE project = ?
714
- ORDER BY session_date DESC`
715
- ).all(project);
662
+ ORDER BY session_date DESC`).all(project);
716
663
  } else {
717
- rows = db.prepare(
718
- `SELECT DISTINCT date(created_at / 1000, 'unixepoch') as session_date
664
+ rows = db.prepare(`SELECT DISTINCT date(created_at / 1000, 'unixepoch') as session_date
719
665
  FROM sessions
720
- ORDER BY session_date DESC`
721
- ).all();
666
+ ORDER BY session_date DESC`).all();
722
667
  }
723
668
  return rows.map((r) => r.session_date).filter(Boolean);
724
- } catch {
669
+ } catch (err) {
670
+ process.stderr.write(`[smriti:session-queries] listSessionDates SQLite failed: ${err instanceof Error ? err.message : String(err)}
671
+ `);
725
672
  const allSessions = listSessionsFromFilesystem(project);
726
673
  const dates = /* @__PURE__ */ new Set();
727
674
  for (const s of allSessions) {
@@ -733,139 +680,25 @@ function listSessionDates(project) {
733
680
  function listSessionProjects() {
734
681
  try {
735
682
  const db = getAgentDb();
736
- const rows = db.prepare(
737
- `SELECT project, COUNT(*) as count, MAX(updated_at) as last_active
683
+ const rows = db.prepare(`SELECT project, COUNT(*) as count, MAX(updated_at) as last_active
738
684
  FROM sessions
739
685
  GROUP BY project
740
- ORDER BY last_active DESC`
741
- ).all();
686
+ ORDER BY last_active DESC`).all();
742
687
  return rows.map((r) => ({
743
688
  project: r.project,
744
689
  sessionCount: r.count,
745
690
  lastActive: new Date(r.last_active).toISOString()
746
691
  }));
747
- } catch {
692
+ } catch (err) {
693
+ process.stderr.write(`[smriti:session-queries] listSessionProjects SQLite failed: ${err instanceof Error ? err.message : String(err)}
694
+ `);
748
695
  return [];
749
696
  }
750
697
  }
751
- function listSessionsFromFilesystem(project) {
752
- const sessionsRoot = getSessionsRoot();
753
- if (!fs.existsSync(sessionsRoot)) return [];
754
- const results = [];
755
- if (project) {
756
- const projectDir = getProjectSessionDir(project);
757
- if (!fs.existsSync(projectDir)) return [];
758
- results.push(...scanDirRecursive(projectDir));
759
- } else {
760
- const projectDirs = fs.readdirSync(sessionsRoot, { withFileTypes: true });
761
- for (const entry of projectDirs) {
762
- if (entry.isDirectory()) {
763
- results.push(...scanDirRecursive(path.join(sessionsRoot, entry.name)));
764
- }
765
- }
766
- }
767
- results.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime());
768
- return results;
769
- }
770
- function scanDirRecursive(dir) {
771
- const metas = [];
772
- try {
773
- const entries = fs.readdirSync(dir, { withFileTypes: true });
774
- for (const entry of entries) {
775
- const fullPath = path.join(dir, entry.name);
776
- if (entry.isDirectory()) {
777
- metas.push(...scanDirRecursive(fullPath));
778
- } else if (entry.name.endsWith(".md")) {
779
- try {
780
- const content = fs.readFileSync(fullPath, "utf-8");
781
- const session = parseSessionMarkdown(content);
782
- metas.push(session.meta);
783
- } catch {
784
- }
785
- }
786
- }
787
- } catch {
788
- }
789
- return metas;
790
- }
791
- function deleteSession(id, project) {
792
- const filePath = resolveSessionPath(id, project);
793
- if (!fs.existsSync(filePath)) {
794
- throw new SessionError(`Session not found: ${id} (project: ${project})`);
795
- }
796
- fs.unlinkSync(filePath);
797
- cacheInvalidate(id, project);
798
- let dir = path.dirname(filePath);
799
- const sessionsRoot = getSessionsRoot();
800
- while (dir !== sessionsRoot && dir.length > sessionsRoot.length) {
801
- try {
802
- const remaining = fs.readdirSync(dir);
803
- if (remaining.length === 0) {
804
- fs.rmdirSync(dir);
805
- dir = path.dirname(dir);
806
- } else {
807
- break;
808
- }
809
- } catch {
810
- break;
811
- }
812
- }
813
- try {
814
- const db = getAgentDb();
815
- const turns = db.prepare("SELECT id FROM turns WHERE session_id = ?").all(id);
816
- for (const t of turns) {
817
- db.prepare("DELETE FROM turns_fts WHERE rowid = ?").run(t.id);
818
- }
819
- db.prepare("DELETE FROM turns WHERE session_id = ?").run(id);
820
- db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
821
- } catch {
822
- }
823
- }
824
- var sessionWriteQueues = /* @__PURE__ */ new Map();
825
- function addTurn(sessionId, project, turn) {
826
- const key = `${sessionId}:${project}`;
827
- const prev = sessionWriteQueues.get(key) ?? Promise.resolve();
828
- const next = prev.then(() => {
829
- const filePath = resolveSessionPath(sessionId, project);
830
- if (!fs.existsSync(filePath)) {
831
- throw new SessionError(`Session not found: ${sessionId} (project: ${project})`);
832
- }
833
- const fileContent = fs.readFileSync(filePath, "utf-8");
834
- if (!turn.turnNumber) {
835
- try {
836
- const session = parseSessionMarkdown(fileContent);
837
- turn.turnNumber = session.turns.length + 1;
838
- } catch {
839
- turn.turnNumber = getMaxTurnNumber(sessionId) + 1;
840
- }
841
- }
842
- const updatedIso = (/* @__PURE__ */ new Date()).toISOString();
843
- const patchedContent = patchFrontmatterUpdated(fileContent, updatedIso);
844
- if (patchedContent !== fileContent) {
845
- fs.writeFileSync(filePath, patchedContent, "utf-8");
846
- }
847
- const turnMd = writeTurnMarkdown(turn);
848
- fs.appendFileSync(filePath, `
849
- ${turnMd}
850
- `, "utf-8");
851
- cacheInvalidate(sessionId, project);
852
- insertTurnToDb(sessionId, turn, { project, filePath });
853
- }).catch((err) => {
854
- throw err;
855
- }).finally(() => {
856
- if (sessionWriteQueues.get(key) === next) {
857
- sessionWriteQueues.delete(key);
858
- }
859
- });
860
- sessionWriteQueues.set(key, next);
861
- return next;
862
- }
863
698
  function listTurnsWithTimestamps(sessionId, project) {
864
699
  try {
865
700
  const db = getAgentDb();
866
- const rows = db.prepare(
867
- "SELECT turn_number, role, content, agent, model, tool_calls, created_at FROM turns WHERE session_id = ? ORDER BY turn_number ASC"
868
- ).all(sessionId);
701
+ const rows = db.prepare("SELECT turn_number, role, content, agent, model, tool_calls, created_at FROM turns WHERE session_id = ? ORDER BY turn_number ASC").all(sessionId);
869
702
  if (rows.length > 0) {
870
703
  return rows.map((row) => ({
871
704
  turnNumber: row.turn_number,
@@ -877,17 +710,67 @@ function listTurnsWithTimestamps(sessionId, project) {
877
710
  createdAt: row.created_at
878
711
  }));
879
712
  }
880
- } catch {
713
+ } catch (err) {
714
+ process.stderr.write(`[smriti:session-queries] listTurnsWithTimestamps SQLite failed: ${err instanceof Error ? err.message : String(err)}
715
+ `);
881
716
  }
882
717
  try {
883
- const session = loadSession(sessionId, project);
718
+ const { loadSession: loadSession2 } = (init_session_store(), __toCommonJS(session_store_exports));
719
+ const session = loadSession2(sessionId, project);
884
720
  const baseTime = new Date(session.meta.created).getTime();
885
721
  return session.turns.map((turn, i) => ({
886
722
  ...turn,
887
723
  createdAt: baseTime + i * 1e3
888
724
  // 1-second spacing
889
725
  }));
890
- } catch {
726
+ } catch (err) {
727
+ process.stderr.write(`[smriti:session-queries] listTurnsWithTimestamps markdown fallback failed: ${err instanceof Error ? err.message : String(err)}
728
+ `);
729
+ return [];
730
+ }
731
+ }
732
+ function findSessionByMetadata(key, value, project) {
733
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
734
+ return void 0;
735
+ }
736
+ try {
737
+ const db = getAgentDb();
738
+ const sql = project ? "SELECT * FROM sessions WHERE project = ? AND json_extract(metadata, ?) = ? LIMIT 1" : "SELECT * FROM sessions WHERE json_extract(metadata, ?) = ? LIMIT 1";
739
+ const params = project ? [project, `$.${key}`, value] : [`$.${key}`, value];
740
+ const row = db.prepare(sql).get(...params);
741
+ return row ? rowToSessionMeta(row) : void 0;
742
+ } catch (err) {
743
+ process.stderr.write(`[smriti:session-queries] findSessionByMetadata failed: ${err instanceof Error ? err.message : String(err)}
744
+ `);
745
+ return void 0;
746
+ }
747
+ }
748
+ function getTurnsSince(sessionId, sinceTurnNumber) {
749
+ try {
750
+ const db = getAgentDb();
751
+ const rows = db.prepare("SELECT turn_number, role, content, agent, model, tool_calls FROM turns WHERE session_id = ? AND turn_number > ? ORDER BY turn_number ASC").all(sessionId, sinceTurnNumber);
752
+ return rows.map((row) => ({
753
+ turnNumber: row.turn_number,
754
+ role: row.role,
755
+ content: row.content,
756
+ agent: row.agent ?? void 0,
757
+ model: row.model ?? void 0,
758
+ toolCalls: row.tool_calls ? JSON.parse(row.tool_calls) : void 0
759
+ }));
760
+ } catch (err) {
761
+ process.stderr.write(`[smriti:session-queries] getTurnsSince SQLite failed: ${err instanceof Error ? err.message : String(err)}
762
+ `);
763
+ return [];
764
+ }
765
+ }
766
+ function getSessionsModifiedSince(project, sinceMs) {
767
+ try {
768
+ const db = getAgentDb();
769
+ const rows = db.prepare("SELECT * FROM sessions WHERE project = ? AND updated_at > ? ORDER BY updated_at ASC").all(project, sinceMs);
770
+ return rows.map(rowToSessionMeta);
771
+ } catch (err) {
772
+ process.stderr.write(`[smriti:session-queries] getSessionsModifiedSince SQLite failed: ${err instanceof Error ? err.message : String(err)}
773
+ `);
891
774
  return [];
892
775
  }
893
776
  }
@@ -912,43 +795,37 @@ function updateSessionMeta(sessionId, updates) {
912
795
  sets.push("tags = @tags");
913
796
  params.tags = JSON.stringify(updates.tags);
914
797
  }
915
- if (sets.length === 0) return;
798
+ if (sets.length === 0)
799
+ return;
916
800
  sets.push("updated_at = @updated_at");
917
801
  params.updated_at = Date.now();
918
802
  db.prepare(`UPDATE sessions SET ${sets.join(", ")} WHERE id = @id`).run(params);
919
- } catch {
920
- }
921
- }
922
- function getMaxTurnNumber(sessionId) {
923
- try {
924
- const db = getAgentDb();
925
- const row = db.prepare("SELECT MAX(turn_number) as max_turn FROM turns WHERE session_id = ?").get(sessionId);
926
- return row?.max_turn ?? 0;
927
- } catch {
928
- return 0;
803
+ } catch (err) {
804
+ process.stderr.write(`[smriti:session-queries] updateSessionMeta failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}
805
+ `);
929
806
  }
930
807
  }
931
- function findSessionByMetadata(key, value, project) {
932
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
933
- return void 0;
934
- }
935
- try {
936
- const db = getAgentDb();
937
- const sql = project ? "SELECT * FROM sessions WHERE project = ? AND json_extract(metadata, ?) = ? LIMIT 1" : "SELECT * FROM sessions WHERE json_extract(metadata, ?) = ? LIMIT 1";
938
- const params = project ? [project, `$.${key}`, value] : [`$.${key}`, value];
939
- const row = db.prepare(sql).get(...params);
940
- return row ? rowToSessionMeta(row) : void 0;
941
- } catch {
942
- return void 0;
808
+ var init_session_queries = __esm({
809
+ "../chitragupta/packages/smriti/dist/session-queries.js"() {
810
+ "use strict";
811
+ init_dist();
812
+ init_markdown_parser();
813
+ init_session_db();
814
+ init_session_db();
943
815
  }
944
- }
816
+ });
817
+
818
+ // ../chitragupta/packages/smriti/dist/session-store-migration.js
819
+ import fs2 from "fs";
820
+ import path3 from "path";
945
821
  function migrateExistingSessions(project) {
946
822
  const db = getAgentDb();
947
823
  const sessionsRoot = getSessionsRoot();
948
- if (!fs.existsSync(sessionsRoot)) return { migrated: 0, skipped: 0 };
824
+ if (!fs2.existsSync(sessionsRoot))
825
+ return { migrated: 0, skipped: 0 };
949
826
  let migrated = 0;
950
827
  let skipped = 0;
951
- const dirs = project ? [getProjectSessionDir(project)] : fs.readdirSync(sessionsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path.join(sessionsRoot, e.name));
828
+ const dirs = project ? [getProjectSessionDir(project)] : fs2.readdirSync(sessionsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path3.join(sessionsRoot, e.name));
952
829
  const insertSession = db.prepare(`
953
830
  INSERT OR IGNORE INTO sessions (id, project, title, created_at, updated_at, turn_count, model, agent, cost, tokens, tags, file_path, parent_id, branch, metadata)
954
831
  VALUES (@id, @project, @title, @created_at, @updated_at, @turn_count, @model, @agent, @cost, @tokens, @tags, @file_path, @parent_id, @branch, @metadata)
@@ -957,12 +834,10 @@ function migrateExistingSessions(project) {
957
834
  INSERT OR IGNORE INTO turns (session_id, turn_number, role, content, agent, model, tool_calls, created_at)
958
835
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
959
836
  `);
960
- const insertFts = db.prepare(
961
- "INSERT INTO turns_fts (rowid, content) VALUES (?, ?)"
962
- );
837
+ const insertFts = db.prepare("INSERT INTO turns_fts (rowid, content) VALUES (?, ?)");
963
838
  const migrateFile = (mdPath, relativePath) => {
964
839
  try {
965
- const content = fs.readFileSync(mdPath, "utf-8");
840
+ const content = fs2.readFileSync(mdPath, "utf-8");
966
841
  const session = parseSessionMarkdown(content);
967
842
  const existing = db.prepare("SELECT id FROM sessions WHERE id = ?").get(session.meta.id);
968
843
  if (existing) {
@@ -973,16 +848,7 @@ function migrateExistingSessions(project) {
973
848
  row.turn_count = session.turns.length;
974
849
  insertSession.run(row);
975
850
  for (const turn of session.turns) {
976
- const result = insertTurn.run(
977
- session.meta.id,
978
- turn.turnNumber,
979
- turn.role,
980
- turn.content,
981
- turn.agent ?? null,
982
- turn.model ?? null,
983
- turn.toolCalls ? JSON.stringify(turn.toolCalls) : null,
984
- new Date(session.meta.created).getTime()
985
- );
851
+ const result = insertTurn.run(session.meta.id, turn.turnNumber, turn.role, turn.content, turn.agent ?? null, turn.model ?? null, turn.toolCalls ? JSON.stringify(turn.toolCalls) : null, new Date(session.meta.created).getTime());
986
852
  if (result.changes > 0) {
987
853
  insertFts.run(result.lastInsertRowid, turn.content);
988
854
  }
@@ -994,7 +860,8 @@ function migrateExistingSessions(project) {
994
860
  };
995
861
  const runMigration = db.transaction(() => {
996
862
  for (const dir of dirs) {
997
- if (!fs.existsSync(dir)) continue;
863
+ if (!fs2.existsSync(dir))
864
+ continue;
998
865
  walkMdFiles(dir, sessionsRoot, migrateFile);
999
866
  }
1000
867
  });
@@ -1003,41 +870,305 @@ function migrateExistingSessions(project) {
1003
870
  }
1004
871
  function walkMdFiles(dir, sessionsRoot, callback) {
1005
872
  try {
1006
- const entries = fs.readdirSync(dir, { withFileTypes: true });
873
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
1007
874
  for (const entry of entries) {
1008
- const fullPath = path.join(dir, entry.name);
875
+ const fullPath = path3.join(dir, entry.name);
1009
876
  if (entry.isDirectory()) {
1010
877
  walkMdFiles(fullPath, sessionsRoot, callback);
1011
878
  } else if (entry.name.endsWith(".md")) {
1012
- const relativePath = path.relative(path.dirname(sessionsRoot), fullPath);
879
+ const relativePath = path3.relative(path3.dirname(sessionsRoot), fullPath);
1013
880
  callback(fullPath, relativePath);
1014
881
  }
1015
882
  }
1016
883
  } catch {
1017
884
  }
1018
885
  }
886
+ var init_session_store_migration = __esm({
887
+ "../chitragupta/packages/smriti/dist/session-store-migration.js"() {
888
+ "use strict";
889
+ init_markdown_parser();
890
+ init_session_db();
891
+ }
892
+ });
893
+
894
+ // ../chitragupta/packages/smriti/dist/session-store.js
895
+ var session_store_exports = {};
896
+ __export(session_store_exports, {
897
+ _getDbStatus: () => _getDbStatus,
898
+ _resetDbInit: () => _resetDbInit,
899
+ _resetSessionCache: () => _resetSessionCache,
900
+ addTurn: () => addTurn,
901
+ createSession: () => createSession,
902
+ deleteSession: () => deleteSession,
903
+ findSessionByMetadata: () => findSessionByMetadata,
904
+ getMaxTurnNumber: () => getMaxTurnNumber,
905
+ getSessionsModifiedSince: () => getSessionsModifiedSince,
906
+ getTurnsSince: () => getTurnsSince,
907
+ listSessionDates: () => listSessionDates,
908
+ listSessionProjects: () => listSessionProjects,
909
+ listSessions: () => listSessions,
910
+ listSessionsByDate: () => listSessionsByDate,
911
+ listSessionsByDateRange: () => listSessionsByDateRange,
912
+ listTurnsWithTimestamps: () => listTurnsWithTimestamps,
913
+ loadSession: () => loadSession,
914
+ migrateExistingSessions: () => migrateExistingSessions,
915
+ saveSession: () => saveSession,
916
+ updateSessionMeta: () => updateSessionMeta
917
+ });
918
+ import fs3 from "fs";
919
+ import { renameSync as nodeRenameSync } from "node:fs";
920
+ import path4 from "path";
921
+ function atomicRename(tmpPath, targetPath) {
922
+ try {
923
+ nodeRenameSync(tmpPath, targetPath);
924
+ } catch (err) {
925
+ if (!process.env.VITEST) {
926
+ process.stderr.write(`[smriti:session-store] atomic rename failed, using direct write: ${err instanceof Error ? err.message : String(err)}
927
+ `);
928
+ }
929
+ fs3.writeFileSync(targetPath, fs3.readFileSync(tmpPath, "utf-8"), "utf-8");
930
+ try {
931
+ fs3.unlinkSync(tmpPath);
932
+ } catch {
933
+ }
934
+ }
935
+ }
936
+ function generateSessionId(project) {
937
+ const now = /* @__PURE__ */ new Date();
938
+ const yyyy = now.getFullYear().toString();
939
+ const mm = (now.getMonth() + 1).toString().padStart(2, "0");
940
+ const dd = now.getDate().toString().padStart(2, "0");
941
+ const dateStr = `${yyyy}-${mm}-${dd}`;
942
+ const projHash = hashProject(project).slice(0, 8);
943
+ const baseId = `session-${dateStr}-${projHash}`;
944
+ const projectDir = getProjectSessionDir(project);
945
+ const yearMonthDir = path4.join(projectDir, yyyy, mm);
946
+ fs3.mkdirSync(yearMonthDir, { recursive: true });
947
+ const basePath = path4.join(yearMonthDir, `${baseId}.md`);
948
+ if (!fs3.existsSync(basePath)) {
949
+ return {
950
+ id: baseId,
951
+ filePath: path4.join("sessions", hashProject(project), yyyy, mm, `${baseId}.md`)
952
+ };
953
+ }
954
+ let counter = 2;
955
+ while (fs3.existsSync(path4.join(yearMonthDir, `${baseId}-${counter}.md`))) {
956
+ counter++;
957
+ }
958
+ const id = `${baseId}-${counter}`;
959
+ return {
960
+ id,
961
+ filePath: path4.join("sessions", hashProject(project), yyyy, mm, `${id}.md`)
962
+ };
963
+ }
964
+ function resolveSessionPath(id, project) {
965
+ const projectDir = getProjectSessionDir(project);
966
+ const dateMatch = id.match(/^session-(\d{4})-(\d{2})-\d{2}/);
967
+ if (dateMatch) {
968
+ const newPath = path4.join(projectDir, dateMatch[1], dateMatch[2], `${id}.md`);
969
+ if (fs3.existsSync(newPath))
970
+ return newPath;
971
+ }
972
+ const oldPath = path4.join(projectDir, `${id}.md`);
973
+ if (fs3.existsSync(oldPath))
974
+ return oldPath;
975
+ if (dateMatch) {
976
+ return path4.join(projectDir, dateMatch[1], dateMatch[2], `${id}.md`);
977
+ }
978
+ return oldPath;
979
+ }
980
+ function patchFrontmatterUpdated(content, updatedIso) {
981
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
982
+ if (!fmMatch)
983
+ return content;
984
+ const frontmatter = fmMatch[1];
985
+ if (!/^updated:\s/m.test(frontmatter))
986
+ return content;
987
+ const patchedFrontmatter = frontmatter.replace(/^updated:\s.*$/m, `updated: ${updatedIso}`);
988
+ if (patchedFrontmatter === frontmatter)
989
+ return content;
990
+ return `---
991
+ ${patchedFrontmatter}
992
+ ---${content.slice(fmMatch[0].length)}`;
993
+ }
994
+ function createSession(opts) {
995
+ const now = (/* @__PURE__ */ new Date()).toISOString();
996
+ const { id, filePath } = generateSessionId(opts.project);
997
+ const meta = {
998
+ id,
999
+ title: opts.title ?? "New Session",
1000
+ created: now,
1001
+ updated: now,
1002
+ agent: opts.agent ?? "chitragupta",
1003
+ model: opts.model ?? "unknown",
1004
+ provider: opts.provider,
1005
+ project: opts.project,
1006
+ parent: opts.parentSessionId ?? null,
1007
+ branch: opts.branch ?? null,
1008
+ tags: opts.tags ?? [],
1009
+ totalCost: 0,
1010
+ totalTokens: 0,
1011
+ metadata: opts.metadata
1012
+ };
1013
+ if (opts.provider) {
1014
+ meta.metadata = { ...meta.metadata, provider: opts.provider };
1015
+ }
1016
+ const session = { meta, turns: [] };
1017
+ saveSession(session);
1018
+ upsertSessionToDb(meta, filePath);
1019
+ return session;
1020
+ }
1021
+ function saveSession(session) {
1022
+ const filePath = resolveSessionPath(session.meta.id, session.meta.project);
1023
+ const dir = path4.dirname(filePath);
1024
+ try {
1025
+ fs3.mkdirSync(dir, { recursive: true });
1026
+ session.meta.updated = (/* @__PURE__ */ new Date()).toISOString();
1027
+ const markdown = writeSessionMarkdown(session);
1028
+ const tmpPath = `${filePath}.tmp.${process.pid}`;
1029
+ fs3.writeFileSync(tmpPath, markdown, "utf-8");
1030
+ atomicRename(tmpPath, filePath);
1031
+ cachePut(session.meta.id, session.meta.project, session);
1032
+ } catch (err) {
1033
+ throw new SessionError(`Failed to save session ${session.meta.id} at ${filePath}: ${err.message}`);
1034
+ }
1035
+ }
1036
+ function loadSession(id, project) {
1037
+ const cached = cacheGet(id, project);
1038
+ if (cached)
1039
+ return cached;
1040
+ const filePath = resolveSessionPath(id, project);
1041
+ if (!fs3.existsSync(filePath)) {
1042
+ throw new SessionError(`Session not found: ${id} (project: ${project})`);
1043
+ }
1044
+ try {
1045
+ const content = fs3.readFileSync(filePath, "utf-8");
1046
+ const session = parseSessionMarkdown(content);
1047
+ cachePut(id, project, session);
1048
+ return session;
1049
+ } catch (err) {
1050
+ if (err instanceof SessionError)
1051
+ throw err;
1052
+ throw new SessionError(`Failed to load session ${id}: ${err.message}`);
1053
+ }
1054
+ }
1055
+ function deleteSession(id, project) {
1056
+ const filePath = resolveSessionPath(id, project);
1057
+ if (!fs3.existsSync(filePath)) {
1058
+ throw new SessionError(`Session not found: ${id} (project: ${project})`);
1059
+ }
1060
+ fs3.unlinkSync(filePath);
1061
+ cacheInvalidate(id, project);
1062
+ let dir = path4.dirname(filePath);
1063
+ const sessionsRoot = getSessionsRoot();
1064
+ while (dir !== sessionsRoot && dir.length > sessionsRoot.length) {
1065
+ try {
1066
+ const remaining = fs3.readdirSync(dir);
1067
+ if (remaining.length === 0) {
1068
+ fs3.rmdirSync(dir);
1069
+ dir = path4.dirname(dir);
1070
+ } else {
1071
+ break;
1072
+ }
1073
+ } catch {
1074
+ break;
1075
+ }
1076
+ }
1077
+ try {
1078
+ const db = getAgentDb();
1079
+ const turns = db.prepare("SELECT id FROM turns WHERE session_id = ?").all(id);
1080
+ for (const t of turns) {
1081
+ db.prepare("DELETE FROM turns_fts WHERE rowid = ?").run(t.id);
1082
+ }
1083
+ db.prepare("DELETE FROM turns WHERE session_id = ?").run(id);
1084
+ db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
1085
+ } catch (err) {
1086
+ process.stderr.write(`[smriti:session-store] deleteSession SQLite cleanup failed for ${id}: ${err instanceof Error ? err.message : String(err)}
1087
+ `);
1088
+ }
1089
+ }
1090
+ function addTurn(sessionId, project, turn) {
1091
+ const key = `${sessionId}:${project}`;
1092
+ const prev = sessionWriteQueues.get(key) ?? Promise.resolve();
1093
+ const next = prev.then(() => {
1094
+ const filePath = resolveSessionPath(sessionId, project);
1095
+ if (!fs3.existsSync(filePath)) {
1096
+ throw new SessionError(`Session not found: ${sessionId} (project: ${project})`);
1097
+ }
1098
+ const fileContent = fs3.readFileSync(filePath, "utf-8");
1099
+ if (!turn.turnNumber) {
1100
+ try {
1101
+ const session = parseSessionMarkdown(fileContent);
1102
+ turn.turnNumber = session.turns.length + 1;
1103
+ } catch {
1104
+ turn.turnNumber = getMaxTurnNumber(sessionId) + 1;
1105
+ }
1106
+ }
1107
+ const updatedIso = (/* @__PURE__ */ new Date()).toISOString();
1108
+ const patchedContent = patchFrontmatterUpdated(fileContent, updatedIso);
1109
+ if (patchedContent !== fileContent) {
1110
+ fs3.writeFileSync(filePath, patchedContent, "utf-8");
1111
+ }
1112
+ const turnMd = writeTurnMarkdown(turn);
1113
+ fs3.appendFileSync(filePath, `
1114
+ ${turnMd}
1115
+ `, "utf-8");
1116
+ cacheInvalidate(sessionId, project);
1117
+ insertTurnToDb(sessionId, turn, { project, filePath });
1118
+ }).catch((err) => {
1119
+ throw err;
1120
+ }).finally(() => {
1121
+ if (sessionWriteQueues.get(key) === next) {
1122
+ sessionWriteQueues.delete(key);
1123
+ }
1124
+ });
1125
+ sessionWriteQueues.set(key, next);
1126
+ return next;
1127
+ }
1128
+ var sessionWriteQueues;
1129
+ var init_session_store = __esm({
1130
+ "../chitragupta/packages/smriti/dist/session-store.js"() {
1131
+ init_dist();
1132
+ init_markdown_parser();
1133
+ init_markdown_writer();
1134
+ init_session_db();
1135
+ init_session_store_cache();
1136
+ init_session_store_cache();
1137
+ init_session_db();
1138
+ init_session_queries();
1139
+ init_session_store_migration();
1140
+ sessionWriteQueues = /* @__PURE__ */ new Map();
1141
+ }
1142
+ });
1019
1143
 
1020
1144
  export {
1021
1145
  parseSessionMarkdown,
1146
+ init_markdown_parser,
1022
1147
  writeSessionMarkdown,
1023
1148
  writeTurnMarkdown,
1024
- _resetSessionCache,
1149
+ init_markdown_writer,
1150
+ getAgentDb,
1025
1151
  _resetDbInit,
1026
1152
  _getDbStatus,
1027
- createSession,
1028
- saveSession,
1029
- loadSession,
1153
+ getMaxTurnNumber,
1154
+ init_session_db,
1155
+ _resetSessionCache,
1030
1156
  listSessions,
1031
1157
  listSessionsByDate,
1032
1158
  listSessionsByDateRange,
1033
1159
  listSessionDates,
1034
1160
  listSessionProjects,
1035
- deleteSession,
1036
- addTurn,
1037
1161
  listTurnsWithTimestamps,
1038
- updateSessionMeta,
1039
- getMaxTurnNumber,
1040
1162
  findSessionByMetadata,
1041
- migrateExistingSessions
1163
+ getTurnsSince,
1164
+ getSessionsModifiedSince,
1165
+ updateSessionMeta,
1166
+ migrateExistingSessions,
1167
+ createSession,
1168
+ saveSession,
1169
+ loadSession,
1170
+ deleteSession,
1171
+ addTurn,
1172
+ init_session_store
1042
1173
  };
1043
- //# sourceMappingURL=chunk-HIYHTWFW.js.map
1174
+ //# sourceMappingURL=chunk-FEDPZOZ5.js.map