@steno-ai/engine 0.1.1 → 0.1.3

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 (116) hide show
  1. package/dist/adapters/storage.d.ts +1 -0
  2. package/dist/adapters/storage.d.ts.map +1 -1
  3. package/dist/extraction/llm-extractor.d.ts.map +1 -1
  4. package/dist/extraction/llm-extractor.js +5 -3
  5. package/dist/extraction/llm-extractor.js.map +1 -1
  6. package/dist/extraction/pipeline.d.ts.map +1 -1
  7. package/dist/extraction/pipeline.js +5 -1
  8. package/dist/extraction/pipeline.js.map +1 -1
  9. package/dist/extraction/prompts.d.ts +2 -2
  10. package/dist/extraction/prompts.d.ts.map +1 -1
  11. package/dist/extraction/prompts.js +12 -3
  12. package/dist/extraction/prompts.js.map +1 -1
  13. package/package.json +6 -2
  14. package/src/adapters/cache.js +2 -0
  15. package/src/adapters/embedding.js +2 -0
  16. package/src/adapters/llm.js +2 -0
  17. package/src/adapters/perplexity-embedding.js +78 -0
  18. package/src/adapters/storage.js +2 -0
  19. package/src/adapters/storage.ts +1 -0
  20. package/src/config.d.ts +211 -1
  21. package/src/config.d.ts.map +1 -1
  22. package/src/config.js +92 -0
  23. package/src/config.js.map +1 -1
  24. package/src/extraction/contradiction.js +23 -0
  25. package/src/extraction/dedup.js +93 -0
  26. package/src/extraction/dedup.js.map +1 -1
  27. package/src/extraction/entity-extractor.d.ts.map +1 -1
  28. package/src/extraction/entity-extractor.js +145 -0
  29. package/src/extraction/entity-extractor.js.map +1 -1
  30. package/src/extraction/hasher.js +8 -0
  31. package/src/extraction/heuristic.js +282 -0
  32. package/src/extraction/llm-extractor.d.ts +3 -1
  33. package/src/extraction/llm-extractor.d.ts.map +1 -1
  34. package/src/extraction/llm-extractor.js +238 -0
  35. package/src/extraction/llm-extractor.js.map +1 -1
  36. package/src/extraction/llm-extractor.ts +7 -5
  37. package/src/extraction/pipeline.d.ts +3 -0
  38. package/src/extraction/pipeline.d.ts.map +1 -1
  39. package/src/extraction/pipeline.js +398 -0
  40. package/src/extraction/pipeline.js.map +1 -1
  41. package/src/extraction/pipeline.ts +6 -1
  42. package/src/extraction/prompts.d.ts +28 -0
  43. package/src/extraction/prompts.d.ts.map +1 -0
  44. package/src/extraction/prompts.js +196 -0
  45. package/src/extraction/prompts.js.map +1 -1
  46. package/src/extraction/prompts.ts +12 -3
  47. package/src/extraction/sliding-window.js +84 -0
  48. package/src/extraction/sliding-window.js.map +1 -1
  49. package/src/extraction/types.d.ts +12 -0
  50. package/src/extraction/types.d.ts.map +1 -1
  51. package/src/extraction/types.js +2 -0
  52. package/src/feedback/tracker.js +90 -0
  53. package/src/models/api-key.d.ts +2 -2
  54. package/src/models/api-key.js +21 -0
  55. package/src/models/edge.d.ts +6 -6
  56. package/src/models/edge.js +29 -0
  57. package/src/models/entity.d.ts +2 -2
  58. package/src/models/entity.js +22 -0
  59. package/src/models/extraction.d.ts +6 -6
  60. package/src/models/extraction.js +40 -0
  61. package/src/models/fact-entity.js +14 -0
  62. package/src/models/fact.d.ts +191 -0
  63. package/src/models/fact.d.ts.map +1 -0
  64. package/src/models/fact.js +72 -0
  65. package/src/models/fact.js.map +1 -0
  66. package/src/models/index.js +13 -0
  67. package/src/models/memory-access.d.ts +4 -4
  68. package/src/models/memory-access.js +33 -0
  69. package/src/models/session.js +23 -0
  70. package/src/models/tenant.d.ts +248 -14
  71. package/src/models/tenant.d.ts.map +1 -1
  72. package/src/models/tenant.js +23 -0
  73. package/src/models/trigger.d.ts +5 -5
  74. package/src/models/trigger.js +41 -0
  75. package/src/models/usage-record.js +14 -0
  76. package/src/models/webhook.d.ts +1 -1
  77. package/src/models/webhook.js +25 -0
  78. package/src/retrieval/compound-search.d.ts.map +1 -1
  79. package/src/retrieval/compound-search.js +87 -0
  80. package/src/retrieval/compound-search.js.map +1 -1
  81. package/src/retrieval/contradiction-surfacer.js +64 -0
  82. package/src/retrieval/embedding-cache.js +56 -0
  83. package/src/retrieval/fusion.d.ts +1 -0
  84. package/src/retrieval/fusion.d.ts.map +1 -1
  85. package/src/retrieval/fusion.js +87 -0
  86. package/src/retrieval/fusion.js.map +1 -1
  87. package/src/retrieval/graph-traversal.d.ts +2 -1
  88. package/src/retrieval/graph-traversal.d.ts.map +1 -1
  89. package/src/retrieval/graph-traversal.js +208 -0
  90. package/src/retrieval/graph-traversal.js.map +1 -1
  91. package/src/retrieval/query-expansion.js +76 -0
  92. package/src/retrieval/reranker.js +47 -0
  93. package/src/retrieval/salience-scorer.js +41 -0
  94. package/src/retrieval/search.d.ts.map +1 -1
  95. package/src/retrieval/search.js +228 -0
  96. package/src/retrieval/search.js.map +1 -1
  97. package/src/retrieval/temporal-scorer.d.ts +18 -0
  98. package/src/retrieval/temporal-scorer.d.ts.map +1 -0
  99. package/src/retrieval/temporal-scorer.js +106 -0
  100. package/src/retrieval/temporal-scorer.js.map +1 -0
  101. package/src/retrieval/trigger-matcher.d.ts.map +1 -1
  102. package/src/retrieval/trigger-matcher.js +134 -0
  103. package/src/retrieval/trigger-matcher.js.map +1 -1
  104. package/src/retrieval/types.d.ts +4 -0
  105. package/src/retrieval/types.d.ts.map +1 -1
  106. package/src/retrieval/types.js +9 -0
  107. package/src/retrieval/types.js.map +1 -1
  108. package/src/retrieval/vector-search.d.ts.map +1 -1
  109. package/src/retrieval/vector-search.js +24 -0
  110. package/src/retrieval/vector-search.js.map +1 -1
  111. package/src/salience/decay.js +15 -0
  112. package/src/scratchpad/scratchpad.js +107 -0
  113. package/src/sessions/manager.d.ts +11 -0
  114. package/src/sessions/manager.d.ts.map +1 -0
  115. package/src/sessions/manager.js +63 -0
  116. package/src/sessions/manager.js.map +1 -0
@@ -12,6 +12,7 @@ export interface SearchOptions {
12
12
  asOf?: Date;
13
13
  };
14
14
  weights?: FusionWeights;
15
+ tokenBudget?: number;
15
16
  }
16
17
  /** Configurable fusion weights (should sum to 1.0 — normalized if not) */
17
18
  export interface FusionWeights {
@@ -20,6 +21,7 @@ export interface FusionWeights {
20
21
  graph: number;
21
22
  recency: number;
22
23
  salience: number;
24
+ temporal: number;
23
25
  }
24
26
  /** A single search result with all signal scores */
25
27
  export interface SearchResult {
@@ -31,6 +33,7 @@ export interface SearchResult {
31
33
  graphScore: number;
32
34
  recencyScore: number;
33
35
  salienceScore: number;
36
+ temporalScore: number;
34
37
  };
35
38
  triggeredBy?: string;
36
39
  contradiction?: {
@@ -59,6 +62,7 @@ export interface Candidate {
59
62
  graphScore: number;
60
63
  recencyScore: number;
61
64
  salienceScore: number;
65
+ temporalScore: number;
62
66
  source: 'vector' | 'keyword' | 'graph' | 'trigger';
63
67
  triggeredBy?: string;
64
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE7D,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE;QACf,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE;QACd,WAAW,EAAE,IAAI,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE;QACN,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,EAAE,IAAI,EAAE,CAAC;KACf,CAAC;IACF,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;CAClB;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAMpC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE7D,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE;QACf,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE;QACd,WAAW,EAAE,IAAI,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE;QACN,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,EAAE,IAAI,EAAE,CAAC;KACf,CAAC;IACF,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;CAClB;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAOpC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export const DEFAULT_FUSION_WEIGHTS = {
2
+ vector: 0.30,
3
+ keyword: 0.15,
4
+ graph: 0.15,
5
+ recency: 0.10,
6
+ salience: 0.10,
7
+ temporal: 0.20,
8
+ };
9
+ //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAsEA,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;CACf,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AA0EA,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;CACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["vector-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,SAAS,EAAE,CAAC,CAuBtB"}
1
+ {"version":3,"file":"vector-search.d.ts","sourceRoot":"","sources":["vector-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,SAAS,EAAE,CAAC,CAwBtB"}
@@ -0,0 +1,24 @@
1
+ export async function vectorSearch(storage, embedding, query, tenantId, scope, scopeId, limit, asOf) {
2
+ const queryEmbedding = await embedding.embed(query);
3
+ const results = await storage.vectorSearch({
4
+ embedding: queryEmbedding,
5
+ tenantId,
6
+ scope,
7
+ scopeId,
8
+ limit,
9
+ minSimilarity: 0.0,
10
+ validOnly: true,
11
+ asOf,
12
+ });
13
+ return results.map((r) => ({
14
+ fact: r.fact,
15
+ vectorScore: r.similarity,
16
+ keywordScore: 0,
17
+ graphScore: 0,
18
+ recencyScore: 0,
19
+ salienceScore: 0,
20
+ temporalScore: 0,
21
+ source: 'vector',
22
+ }));
23
+ }
24
+ //# sourceMappingURL=vector-search.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vector-search.js","sourceRoot":"","sources":["vector-search.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAuB,EACvB,SAA2B,EAC3B,KAAa,EACb,QAAgB,EAChB,KAAa,EACb,OAAe,EACf,KAAa,EACb,IAAW;IAEX,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC;QACzC,SAAS,EAAE,cAAc;QACzB,QAAQ;QACR,KAAK;QACL,OAAO;QACP,KAAK;QACL,aAAa,EAAE,GAAG;QAClB,SAAS,EAAE,IAAI;QACf,IAAI;KACL,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,UAAU;QACzB,YAAY,EAAE,CAAC;QACf,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,MAAM,EAAE,QAAiB;KAC1B,CAAC,CAAC,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"vector-search.js","sourceRoot":"","sources":["vector-search.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAuB,EACvB,SAA2B,EAC3B,KAAa,EACb,QAAgB,EAChB,KAAa,EACb,OAAe,EACf,KAAa,EACb,IAAW;IAEX,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC;QACzC,SAAS,EAAE,cAAc;QACzB,QAAQ;QACR,KAAK;QACL,OAAO;QACP,KAAK;QACL,aAAa,EAAE,GAAG;QAClB,SAAS,EAAE,IAAI;QACf,IAAI;KACL,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,UAAU;QACzB,YAAY,EAAE,CAAC;QACf,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,CAAC;QAChB,MAAM,EAAE,QAAiB;KAC1B,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,15 @@
1
+ export function calculateDecayScore(input) {
2
+ const { importance, frequency, lastAccessed, halfLifeDays, normalizationK } = input;
3
+ if (lastAccessed === null)
4
+ return 0;
5
+ // Recency factor: exponential decay using Ebbinghaus forgetting curve
6
+ const daysSinceAccess = (Date.now() - lastAccessed.getTime()) / (1000 * 60 * 60 * 24);
7
+ const lambda = Math.LN2 / halfLifeDays;
8
+ const recencyFactor = Math.exp(-lambda * daysSinceAccess);
9
+ // Frequency factor: logarithmic scaling with fixed normalization constant K
10
+ const frequencyFactor = Math.min(1.0, Math.log(1 + frequency) / Math.log(1 + normalizationK));
11
+ // Final score: clamped to [0, 1]
12
+ const score = importance * recencyFactor * frequencyFactor;
13
+ return Math.max(0, Math.min(1, score));
14
+ }
15
+ //# sourceMappingURL=decay.js.map
@@ -0,0 +1,107 @@
1
+ const SCRATCHPAD_MAX_CHARS = 5000;
2
+ const SCRATCHPAD_COMPRESSED_CHARS = 2500;
3
+ /**
4
+ * Get or create a scratchpad for a scope.
5
+ * The scratchpad is stored as a special fact with tag 'scratchpad'.
6
+ */
7
+ export async function getScratchpad(storage, tenantId, scope, scopeId) {
8
+ const facts = await storage.getFactsByScope(tenantId, scope, scopeId, { limit: 100 });
9
+ const scratchpadFact = facts.data.find(f => f.tags?.includes('scratchpad'));
10
+ return scratchpadFact?.content ?? '';
11
+ }
12
+ /**
13
+ * Update the scratchpad after an extraction.
14
+ * Appends new facts to the existing scratchpad, compresses if too long.
15
+ */
16
+ export async function updateScratchpad(storage, llm, tenantId, scope, scopeId, newFacts) {
17
+ if (newFacts.length === 0)
18
+ return;
19
+ // Get existing scratchpad
20
+ const existing = await getScratchpad(storage, tenantId, scope, scopeId);
21
+ // Append new facts
22
+ const newSection = newFacts.join('\n');
23
+ let updated = existing ? `${existing}\n\n--- New information ---\n${newSection}` : newSection;
24
+ // Compress if too long
25
+ if (updated.length > SCRATCHPAD_MAX_CHARS) {
26
+ updated = await compressScratchpad(llm, updated);
27
+ }
28
+ // Find existing scratchpad fact and invalidate it
29
+ const facts = await storage.getFactsByScope(tenantId, scope, scopeId, { limit: 200 });
30
+ const existingScratchpad = facts.data.find(f => f.tags?.includes('scratchpad'));
31
+ if (existingScratchpad) {
32
+ await storage.invalidateFact(tenantId, existingScratchpad.id);
33
+ }
34
+ // Create new scratchpad fact (no embedding needed — it's retrieved by tag, not vector search)
35
+ const id = crypto.randomUUID();
36
+ await storage.createFact({
37
+ id,
38
+ lineageId: existingScratchpad?.lineageId ?? crypto.randomUUID(),
39
+ tenantId,
40
+ scope,
41
+ scopeId,
42
+ content: updated,
43
+ embeddingModel: 'none',
44
+ embeddingDim: 1,
45
+ importance: 1.0,
46
+ confidence: 1.0,
47
+ operation: existingScratchpad ? 'update' : 'create',
48
+ sourceType: 'api',
49
+ modality: 'text',
50
+ tags: ['scratchpad'],
51
+ metadata: { type: 'scratchpad', updatedAt: new Date().toISOString() },
52
+ contradictionStatus: 'none',
53
+ });
54
+ }
55
+ /**
56
+ * Compress the scratchpad using an LLM.
57
+ * Preserves the most important information while reducing size.
58
+ */
59
+ export async function compressScratchpad(llm, content) {
60
+ const response = await llm.complete([
61
+ {
62
+ role: 'system',
63
+ content: `Compress the following user profile/scratchpad into a concise summary of ~${SCRATCHPAD_COMPRESSED_CHARS} characters.
64
+
65
+ Preserve:
66
+ - Names of people and their relationships
67
+ - Key facts (job, location, health, allergies)
68
+ - Strong preferences and personality traits
69
+ - Important events with dates
70
+ - Goals and future plans
71
+ - Contradictions or changes in opinion
72
+
73
+ Remove:
74
+ - Duplicate information
75
+ - Trivial details
76
+ - Repetitive emotional expressions
77
+
78
+ Output ONLY the compressed summary, no explanation.`
79
+ },
80
+ { role: 'user', content }
81
+ ], { temperature: 0 });
82
+ return response.content;
83
+ }
84
+ /**
85
+ * Get filtered scratchpad content relevant to a query.
86
+ */
87
+ export async function getRelevantScratchpad(storage, llm, tenantId, scope, scopeId, query) {
88
+ const scratchpad = await getScratchpad(storage, tenantId, scope, scopeId);
89
+ if (!scratchpad || scratchpad.length < 50)
90
+ return '';
91
+ // If scratchpad is short, return all of it
92
+ if (scratchpad.length < 1000)
93
+ return scratchpad;
94
+ // Filter scratchpad for relevant content
95
+ const response = await llm.complete([
96
+ {
97
+ role: 'system',
98
+ content: 'Extract ONLY the parts of this user profile that are relevant to answering the given question. Return the relevant excerpts. If nothing is relevant, return empty string.'
99
+ },
100
+ {
101
+ role: 'user',
102
+ content: `Profile:\n${scratchpad}\n\nQuestion: ${query}`
103
+ }
104
+ ], { temperature: 0 });
105
+ return response.content;
106
+ }
107
+ //# sourceMappingURL=scratchpad.js.map
@@ -0,0 +1,11 @@
1
+ import type { StorageAdapter } from '../adapters/storage.js';
2
+ import type { LLMAdapter } from '../adapters/llm.js';
3
+ import type { Session } from '../models/session.js';
4
+ import type { SessionScope } from '../config.js';
5
+ /**
6
+ * Find an active (not ended) session for the given scope, or create a new one.
7
+ */
8
+ export declare function getOrCreateActiveSession(storage: StorageAdapter, tenantId: string, scope: SessionScope, scopeId: string): Promise<Session>;
9
+ export declare function startSession(storage: StorageAdapter, tenantId: string, scope: SessionScope, scopeId: string, metadata?: Record<string, unknown>): Promise<Session>;
10
+ export declare function endSession(storage: StorageAdapter, llm: LLMAdapter, tenantId: string, sessionId: string): Promise<Session>;
11
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,OAAO,CAAC,CASlB;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CA0ClB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Find an active (not ended) session for the given scope, or create a new one.
3
+ */
4
+ export async function getOrCreateActiveSession(storage, tenantId, scope, scopeId) {
5
+ // Fetch a few recent sessions — the active one (if any) is likely the most recent,
6
+ // but we check a small batch in case the latest was already ended.
7
+ const sessions = await storage.getSessionsByScope(tenantId, scope, scopeId, { limit: 5 });
8
+ const active = sessions.data.find(s => !s.endedAt);
9
+ if (active)
10
+ return active;
11
+ return startSession(storage, tenantId, scope, scopeId);
12
+ }
13
+ export async function startSession(storage, tenantId, scope, scopeId, metadata) {
14
+ const id = crypto.randomUUID();
15
+ return storage.createSession({
16
+ id,
17
+ tenantId,
18
+ scope,
19
+ scopeId,
20
+ metadata: metadata ?? {},
21
+ });
22
+ }
23
+ export async function endSession(storage, llm, tenantId, sessionId) {
24
+ // 1. Get session
25
+ const session = await storage.getSession(tenantId, sessionId);
26
+ if (!session)
27
+ throw new Error(`Session ${sessionId} not found`);
28
+ if (session.endedAt)
29
+ throw new Error(`Session ${sessionId} already ended`);
30
+ // 2. Get facts created during this session
31
+ const facts = await storage.getFactsByScope(tenantId, session.scope, session.scopeId, { limit: 100 });
32
+ const sessionFacts = facts.data.filter(f => f.sessionId === sessionId);
33
+ // 3. Generate summary if there are facts
34
+ let summary;
35
+ let topics;
36
+ if (sessionFacts.length > 0) {
37
+ const factContents = sessionFacts.map(f => f.content).join('\n');
38
+ const response = await llm.complete([
39
+ {
40
+ role: 'system',
41
+ content: 'Summarize the following facts from a conversation session in 2-3 sentences. Also extract the main topics (as a JSON array of strings). Return JSON: {"summary": "...", "topics": ["..."]}',
42
+ },
43
+ {
44
+ role: 'user',
45
+ content: factContents,
46
+ },
47
+ ], { temperature: 0, responseFormat: 'json' });
48
+ try {
49
+ const parsed = JSON.parse(response.content);
50
+ summary = typeof parsed.summary === 'string' ? parsed.summary : undefined;
51
+ topics = Array.isArray(parsed.topics)
52
+ ? parsed.topics.filter((t) => typeof t === 'string')
53
+ : undefined;
54
+ }
55
+ catch {
56
+ // If JSON parse fails, use raw content as summary
57
+ summary = response.content;
58
+ }
59
+ }
60
+ // 4. End the session
61
+ return storage.endSession(tenantId, sessionId, summary, topics);
62
+ }
63
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["manager.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAuB,EACvB,QAAgB,EAChB,KAAmB,EACnB,OAAe;IAEf,mFAAmF;IACnF,mEAAmE;IACnE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,OAAO,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAuB,EACvB,QAAgB,EAChB,KAAmB,EACnB,OAAe,EACf,QAAkC;IAElC,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAC/B,OAAO,OAAO,CAAC,aAAa,CAAC;QAC3B,EAAE;QACF,QAAQ;QACR,KAAK;QACL,OAAO;QACP,QAAQ,EAAE,QAAQ,IAAI,EAAE;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAuB,EACvB,GAAe,EACf,QAAgB,EAChB,SAAiB;IAEjB,iBAAiB;IACjB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,YAAY,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,gBAAgB,CAAC,CAAC;IAE3E,2CAA2C;IAC3C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACtG,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAEvE,yCAAyC;IACzC,IAAI,OAA2B,CAAC;IAChC,IAAI,MAA4B,CAAC;IAEjC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC;YAClC;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,2LAA2L;aACrM;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,YAAY;aACtB;SACF,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;QAE/C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5C,OAAO,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1E,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;gBACnC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;gBAC1E,CAAC,CAAC,SAAS,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;YAClD,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,OAAO,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClE,CAAC"}