@steno-ai/engine 0.1.0 → 0.1.2
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.
- package/README.md +122 -0
- package/dist/extraction/llm-extractor.d.ts.map +1 -1
- package/dist/extraction/llm-extractor.js +5 -3
- package/dist/extraction/llm-extractor.js.map +1 -1
- package/dist/extraction/prompts.d.ts +2 -2
- package/dist/extraction/prompts.d.ts.map +1 -1
- package/dist/extraction/prompts.js +7 -1
- package/dist/extraction/prompts.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/cache.js +2 -0
- package/src/adapters/embedding.js +2 -0
- package/src/adapters/llm.js +2 -0
- package/src/adapters/perplexity-embedding.js +78 -0
- package/src/adapters/storage.js +2 -0
- package/src/config.d.ts +211 -1
- package/src/config.d.ts.map +1 -1
- package/src/config.js +92 -0
- package/src/config.js.map +1 -1
- package/src/extraction/contradiction.js +23 -0
- package/src/extraction/dedup.js +93 -0
- package/src/extraction/dedup.js.map +1 -1
- package/src/extraction/entity-extractor.d.ts.map +1 -1
- package/src/extraction/entity-extractor.js +145 -0
- package/src/extraction/entity-extractor.js.map +1 -1
- package/src/extraction/hasher.js +8 -0
- package/src/extraction/heuristic.js +282 -0
- package/src/extraction/llm-extractor.d.ts +3 -1
- package/src/extraction/llm-extractor.d.ts.map +1 -1
- package/src/extraction/llm-extractor.js +238 -0
- package/src/extraction/llm-extractor.js.map +1 -1
- package/src/extraction/llm-extractor.ts +7 -5
- package/src/extraction/pipeline.d.ts +3 -0
- package/src/extraction/pipeline.d.ts.map +1 -1
- package/src/extraction/pipeline.js +398 -0
- package/src/extraction/pipeline.js.map +1 -1
- package/src/extraction/prompts.d.ts +28 -0
- package/src/extraction/prompts.d.ts.map +1 -0
- package/src/extraction/prompts.js +196 -0
- package/src/extraction/prompts.js.map +1 -1
- package/src/extraction/prompts.ts +7 -1
- package/src/extraction/sliding-window.js +84 -0
- package/src/extraction/sliding-window.js.map +1 -1
- package/src/extraction/types.d.ts +12 -0
- package/src/extraction/types.d.ts.map +1 -1
- package/src/extraction/types.js +2 -0
- package/src/feedback/tracker.js +90 -0
- package/src/models/api-key.d.ts +2 -2
- package/src/models/api-key.js +21 -0
- package/src/models/edge.d.ts +6 -6
- package/src/models/edge.js +29 -0
- package/src/models/entity.d.ts +2 -2
- package/src/models/entity.js +22 -0
- package/src/models/extraction.d.ts +6 -6
- package/src/models/extraction.js +40 -0
- package/src/models/fact-entity.js +14 -0
- package/src/models/fact.d.ts +191 -0
- package/src/models/fact.d.ts.map +1 -0
- package/src/models/fact.js +72 -0
- package/src/models/fact.js.map +1 -0
- package/src/models/index.js +13 -0
- package/src/models/memory-access.d.ts +4 -4
- package/src/models/memory-access.js +33 -0
- package/src/models/session.js +23 -0
- package/src/models/tenant.d.ts +248 -14
- package/src/models/tenant.d.ts.map +1 -1
- package/src/models/tenant.js +23 -0
- package/src/models/trigger.d.ts +5 -5
- package/src/models/trigger.js +41 -0
- package/src/models/usage-record.js +14 -0
- package/src/models/webhook.d.ts +1 -1
- package/src/models/webhook.js +25 -0
- package/src/retrieval/compound-search.d.ts.map +1 -1
- package/src/retrieval/compound-search.js +87 -0
- package/src/retrieval/compound-search.js.map +1 -1
- package/src/retrieval/contradiction-surfacer.js +64 -0
- package/src/retrieval/embedding-cache.js +56 -0
- package/src/retrieval/fusion.d.ts +1 -0
- package/src/retrieval/fusion.d.ts.map +1 -1
- package/src/retrieval/fusion.js +87 -0
- package/src/retrieval/fusion.js.map +1 -1
- package/src/retrieval/graph-traversal.d.ts +2 -1
- package/src/retrieval/graph-traversal.d.ts.map +1 -1
- package/src/retrieval/graph-traversal.js +208 -0
- package/src/retrieval/graph-traversal.js.map +1 -1
- package/src/retrieval/query-expansion.js +76 -0
- package/src/retrieval/reranker.js +47 -0
- package/src/retrieval/salience-scorer.js +41 -0
- package/src/retrieval/search.d.ts.map +1 -1
- package/src/retrieval/search.js +228 -0
- package/src/retrieval/search.js.map +1 -1
- package/src/retrieval/temporal-scorer.d.ts +18 -0
- package/src/retrieval/temporal-scorer.d.ts.map +1 -0
- package/src/retrieval/temporal-scorer.js +106 -0
- package/src/retrieval/temporal-scorer.js.map +1 -0
- package/src/retrieval/trigger-matcher.d.ts.map +1 -1
- package/src/retrieval/trigger-matcher.js +134 -0
- package/src/retrieval/trigger-matcher.js.map +1 -1
- package/src/retrieval/types.d.ts +4 -0
- package/src/retrieval/types.d.ts.map +1 -1
- package/src/retrieval/types.js +9 -0
- package/src/retrieval/types.js.map +1 -1
- package/src/retrieval/vector-search.d.ts.map +1 -1
- package/src/retrieval/vector-search.js +24 -0
- package/src/retrieval/vector-search.js.map +1 -1
- package/src/salience/decay.js +15 -0
- package/src/scratchpad/scratchpad.js +107 -0
- package/src/sessions/manager.d.ts +11 -0
- package/src/sessions/manager.d.ts.map +1 -0
- package/src/sessions/manager.js +63 -0
- package/src/sessions/manager.js.map +1 -0
package/src/retrieval/types.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"
|
|
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,
|
|
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":"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"}
|