claude-memory-layer 1.0.24 → 1.0.25

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 (40) hide show
  1. package/.claude/settings.local.json +15 -1
  2. package/dist/cli/index.js +152 -969
  3. package/dist/cli/index.js.map +4 -4
  4. package/dist/core/index.js +31 -66
  5. package/dist/core/index.js.map +3 -3
  6. package/dist/hooks/post-tool-use.js +181 -967
  7. package/dist/hooks/post-tool-use.js.map +4 -4
  8. package/dist/hooks/semantic-daemon.js +148 -965
  9. package/dist/hooks/semantic-daemon.js.map +4 -4
  10. package/dist/hooks/session-end.js +148 -965
  11. package/dist/hooks/session-end.js.map +4 -4
  12. package/dist/hooks/session-start.js +150 -965
  13. package/dist/hooks/session-start.js.map +4 -4
  14. package/dist/hooks/stop.js +156 -965
  15. package/dist/hooks/stop.js.map +4 -4
  16. package/dist/hooks/user-prompt-submit.js +150 -967
  17. package/dist/hooks/user-prompt-submit.js.map +4 -4
  18. package/dist/server/api/index.js +148 -965
  19. package/dist/server/api/index.js.map +4 -4
  20. package/dist/server/index.js +148 -965
  21. package/dist/server/index.js.map +4 -4
  22. package/dist/services/memory-service.js +148 -965
  23. package/dist/services/memory-service.js.map +4 -4
  24. package/memory/agent_response/uncategorized/2026-03-04.md +217 -1
  25. package/memory/session_summary/uncategorized/2026-03-04.md +20 -1
  26. package/memory/tool_observation/uncategorized/2026-03-04.md +237 -1
  27. package/memory/user_prompt/uncategorized/2026-03-04.md +185 -1
  28. package/package.json +1 -2
  29. package/specs/memory-utilization-improvements/context.md +145 -0
  30. package/specs/memory-utilization-improvements/plan.md +361 -0
  31. package/specs/memory-utilization-improvements/spec.md +308 -0
  32. package/specs/optional-duckdb/context.md +77 -0
  33. package/specs/optional-duckdb/plan.md +142 -0
  34. package/specs/optional-duckdb/spec.md +35 -0
  35. package/src/core/db-wrapper.ts +18 -73
  36. package/src/core/sqlite-event-store.ts +24 -0
  37. package/src/hooks/post-tool-use.ts +25 -0
  38. package/src/hooks/session-start.ts +4 -0
  39. package/src/hooks/stop.ts +14 -0
  40. package/src/services/memory-service.ts +62 -58
@@ -621,25 +621,7 @@ function parseEntityCanonicalKey(canonicalKey) {
621
621
  import { randomUUID } from "crypto";
622
622
 
623
623
  // src/core/db-wrapper.ts
624
- import duckdb from "duckdb";
625
- function convertBigInts(obj) {
626
- if (obj === null || obj === void 0)
627
- return obj;
628
- if (typeof obj === "bigint")
629
- return Number(obj);
630
- if (obj instanceof Date)
631
- return obj;
632
- if (Array.isArray(obj))
633
- return obj.map(convertBigInts);
634
- if (typeof obj === "object") {
635
- const result = {};
636
- for (const [key, value] of Object.entries(obj)) {
637
- result[key] = convertBigInts(value);
638
- }
639
- return result;
640
- }
641
- return obj;
642
- }
624
+ import BetterSqlite3 from "better-sqlite3";
643
625
  function toDate(value) {
644
626
  if (value instanceof Date)
645
627
  return value;
@@ -649,59 +631,19 @@ function toDate(value) {
649
631
  return new Date(value);
650
632
  return new Date(String(value));
651
633
  }
652
- function createDatabase(path2, options) {
653
- if (options?.readOnly) {
654
- return new duckdb.Database(path2, { access_mode: "READ_ONLY" });
655
- }
656
- return new duckdb.Database(path2);
634
+ function createDatabase(dbPath, options) {
635
+ return new BetterSqlite3(dbPath, { readonly: options?.readOnly });
657
636
  }
658
637
  function dbRun(db, sql, params = []) {
659
- return new Promise((resolve, reject) => {
660
- if (params.length === 0) {
661
- db.run(sql, (err) => {
662
- if (err)
663
- reject(err);
664
- else
665
- resolve();
666
- });
667
- } else {
668
- db.run(sql, ...params, (err) => {
669
- if (err)
670
- reject(err);
671
- else
672
- resolve();
673
- });
674
- }
675
- });
638
+ db.prepare(sql).run(...params);
639
+ return Promise.resolve();
676
640
  }
677
641
  function dbAll(db, sql, params = []) {
678
- return new Promise((resolve, reject) => {
679
- if (params.length === 0) {
680
- db.all(sql, (err, rows) => {
681
- if (err)
682
- reject(err);
683
- else
684
- resolve(convertBigInts(rows || []));
685
- });
686
- } else {
687
- db.all(sql, ...params, (err, rows) => {
688
- if (err)
689
- reject(err);
690
- else
691
- resolve(convertBigInts(rows || []));
692
- });
693
- }
694
- });
642
+ return Promise.resolve(db.prepare(sql).all(...params));
695
643
  }
696
644
  function dbClose(db) {
697
- return new Promise((resolve, reject) => {
698
- db.close((err) => {
699
- if (err)
700
- reject(err);
701
- else
702
- resolve();
703
- });
704
- });
645
+ db.close();
646
+ return Promise.resolve();
705
647
  }
706
648
 
707
649
  // src/core/event-store.ts
@@ -1903,6 +1845,29 @@ var SQLiteEventStore = class {
1903
1845
  };
1904
1846
  }
1905
1847
  }
1848
+ /**
1849
+ * Get session IDs that have events but no session_summary event.
1850
+ * Used to backfill summaries for sessions that ended without Stop hook.
1851
+ */
1852
+ async getSessionsWithoutSummary(currentSessionId, limit = 5) {
1853
+ await this.initialize();
1854
+ const rows = sqliteAll(
1855
+ this.db,
1856
+ `SELECT DISTINCT e.session_id
1857
+ FROM events e
1858
+ WHERE e.session_id != ?
1859
+ AND e.event_type != 'session_summary'
1860
+ AND e.session_id NOT IN (
1861
+ SELECT DISTINCT session_id FROM events WHERE event_type = 'session_summary'
1862
+ )
1863
+ GROUP BY e.session_id
1864
+ HAVING COUNT(*) >= 3
1865
+ ORDER BY MAX(e.timestamp) DESC
1866
+ LIMIT ?`,
1867
+ [currentSessionId, limit]
1868
+ );
1869
+ return rows.map((r) => r.session_id);
1870
+ }
1906
1871
  /**
1907
1872
  * Get events by session ID
1908
1873
  */