@steno-ai/engine 0.1.15 → 0.1.17
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/dist/adapters/storage.d.ts +29 -2
- package/dist/adapters/storage.d.ts.map +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/extraction/index.d.ts +2 -0
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +2 -0
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/pipeline.d.ts.map +1 -1
- package/dist/extraction/pipeline.js +48 -1
- package/dist/extraction/pipeline.js.map +1 -1
- package/dist/extraction/structured-cross-linker.d.ts +55 -0
- package/dist/extraction/structured-cross-linker.d.ts.map +1 -0
- package/dist/extraction/structured-cross-linker.js +195 -0
- package/dist/extraction/structured-cross-linker.js.map +1 -0
- package/dist/extraction/structured-extractor.d.ts +59 -0
- package/dist/extraction/structured-extractor.d.ts.map +1 -0
- package/dist/extraction/structured-extractor.js +389 -0
- package/dist/extraction/structured-extractor.js.map +1 -0
- package/dist/extraction/types.d.ts +3 -1
- package/dist/extraction/types.d.ts.map +1 -1
- package/dist/identity/index.d.ts +2 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +2 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/resolver.d.ts +31 -0
- package/dist/identity/resolver.d.ts.map +1 -0
- package/dist/identity/resolver.js +122 -0
- package/dist/identity/resolver.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/models/edge.d.ts +6 -6
- package/dist/models/entity.d.ts +32 -0
- package/dist/models/entity.d.ts.map +1 -1
- package/dist/models/entity.js +11 -0
- package/dist/models/entity.js.map +1 -1
- package/dist/models/extraction.d.ts +6 -6
- package/dist/models/fact.d.ts +6 -6
- package/dist/retrieval/graph-traversal.d.ts +4 -1
- package/dist/retrieval/graph-traversal.d.ts.map +1 -1
- package/dist/retrieval/graph-traversal.js +6 -3
- package/dist/retrieval/graph-traversal.js.map +1 -1
- package/dist/retrieval/search.d.ts.map +1 -1
- package/dist/retrieval/search.js +56 -3
- package/dist/retrieval/search.js.map +1 -1
- package/dist/retrieval/types.d.ts +1 -0
- package/dist/retrieval/types.d.ts.map +1 -1
- package/dist/retrieval/types.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/storage.ts +35 -2
- package/src/config.ts +9 -0
- package/src/extraction/index.ts +2 -0
- package/src/extraction/pipeline.ts +63 -1
- package/src/extraction/structured-cross-linker.ts +259 -0
- package/src/extraction/structured-extractor.ts +463 -0
- package/src/extraction/types.ts +3 -1
- package/src/identity/index.ts +1 -0
- package/src/identity/resolver.ts +149 -0
- package/src/index.ts +1 -0
- package/src/models/entity.ts +13 -0
- package/src/retrieval/graph-traversal.ts +7 -4
- package/src/retrieval/search.ts +58 -3
- package/src/retrieval/types.ts +1 -0
- package/src/adapters/cache.d.ts +0 -9
- package/src/adapters/cache.d.ts.map +0 -1
- package/src/adapters/cache.js +0 -2
- package/src/adapters/cache.js.map +0 -1
- package/src/adapters/embedding.d.ts +0 -7
- package/src/adapters/embedding.d.ts.map +0 -1
- package/src/adapters/embedding.js +0 -2
- package/src/adapters/embedding.js.map +0 -1
- package/src/adapters/llm.d.ts +0 -19
- package/src/adapters/llm.d.ts.map +0 -1
- package/src/adapters/llm.js +0 -2
- package/src/adapters/llm.js.map +0 -1
- package/src/adapters/perplexity-embedding.d.ts +0 -24
- package/src/adapters/perplexity-embedding.d.ts.map +0 -1
- package/src/adapters/perplexity-embedding.js +0 -78
- package/src/adapters/perplexity-embedding.js.map +0 -1
- package/src/adapters/storage.d.ts +0 -173
- package/src/adapters/storage.d.ts.map +0 -1
- package/src/adapters/storage.js +0 -2
- package/src/adapters/storage.js.map +0 -1
- package/src/config.d.ts +0 -296
- package/src/config.d.ts.map +0 -1
- package/src/config.js +0 -92
- package/src/config.js.map +0 -1
- package/src/extraction/contradiction.d.ts +0 -15
- package/src/extraction/contradiction.d.ts.map +0 -1
- package/src/extraction/contradiction.js +0 -23
- package/src/extraction/contradiction.js.map +0 -1
- package/src/extraction/cross-linker.d.ts +0 -23
- package/src/extraction/cross-linker.d.ts.map +0 -1
- package/src/extraction/cross-linker.js +0 -146
- package/src/extraction/cross-linker.js.map +0 -1
- package/src/extraction/dedup.d.ts +0 -12
- package/src/extraction/dedup.d.ts.map +0 -1
- package/src/extraction/dedup.js +0 -93
- package/src/extraction/dedup.js.map +0 -1
- package/src/extraction/entity-extractor.d.ts +0 -30
- package/src/extraction/entity-extractor.d.ts.map +0 -1
- package/src/extraction/entity-extractor.js +0 -145
- package/src/extraction/entity-extractor.js.map +0 -1
- package/src/extraction/hasher.d.ts +0 -5
- package/src/extraction/hasher.d.ts.map +0 -1
- package/src/extraction/hasher.js +0 -8
- package/src/extraction/hasher.js.map +0 -1
- package/src/extraction/heuristic.d.ts +0 -3
- package/src/extraction/heuristic.d.ts.map +0 -1
- package/src/extraction/heuristic.js +0 -282
- package/src/extraction/heuristic.js.map +0 -1
- package/src/extraction/llm-extractor.d.ts +0 -23
- package/src/extraction/llm-extractor.d.ts.map +0 -1
- package/src/extraction/llm-extractor.js +0 -240
- package/src/extraction/llm-extractor.js.map +0 -1
- package/src/extraction/pipeline.d.ts +0 -30
- package/src/extraction/pipeline.d.ts.map +0 -1
- package/src/extraction/pipeline.js +0 -413
- package/src/extraction/pipeline.js.map +0 -1
- package/src/extraction/prompts.d.ts +0 -28
- package/src/extraction/prompts.d.ts.map +0 -1
- package/src/extraction/prompts.js +0 -205
- package/src/extraction/prompts.js.map +0 -1
- package/src/extraction/sliding-window.d.ts +0 -41
- package/src/extraction/sliding-window.d.ts.map +0 -1
- package/src/extraction/sliding-window.js +0 -84
- package/src/extraction/sliding-window.js.map +0 -1
- package/src/extraction/types.d.ts +0 -80
- package/src/extraction/types.d.ts.map +0 -1
- package/src/extraction/types.js +0 -2
- package/src/extraction/types.js.map +0 -1
- package/src/feedback/tracker.d.ts +0 -25
- package/src/feedback/tracker.d.ts.map +0 -1
- package/src/feedback/tracker.js +0 -90
- package/src/feedback/tracker.js.map +0 -1
- package/src/models/api-key.d.ts +0 -54
- package/src/models/api-key.d.ts.map +0 -1
- package/src/models/api-key.js +0 -21
- package/src/models/api-key.js.map +0 -1
- package/src/models/edge.d.ts +0 -78
- package/src/models/edge.d.ts.map +0 -1
- package/src/models/edge.js +0 -29
- package/src/models/edge.js.map +0 -1
- package/src/models/entity.d.ts +0 -60
- package/src/models/entity.d.ts.map +0 -1
- package/src/models/entity.js +0 -22
- package/src/models/entity.js.map +0 -1
- package/src/models/extraction.d.ts +0 -111
- package/src/models/extraction.d.ts.map +0 -1
- package/src/models/extraction.js +0 -40
- package/src/models/extraction.js.map +0 -1
- package/src/models/fact-entity.d.ts +0 -33
- package/src/models/fact-entity.d.ts.map +0 -1
- package/src/models/fact-entity.js +0 -14
- package/src/models/fact-entity.js.map +0 -1
- package/src/models/fact.d.ts +0 -191
- package/src/models/fact.d.ts.map +0 -1
- package/src/models/fact.js +0 -72
- package/src/models/fact.js.map +0 -1
- package/src/models/index.d.ts +0 -13
- package/src/models/index.d.ts.map +0 -1
- package/src/models/index.js +0 -13
- package/src/models/index.js.map +0 -1
- package/src/models/memory-access.d.ts +0 -89
- package/src/models/memory-access.d.ts.map +0 -1
- package/src/models/memory-access.js +0 -33
- package/src/models/memory-access.js.map +0 -1
- package/src/models/session.d.ts +0 -60
- package/src/models/session.d.ts.map +0 -1
- package/src/models/session.js +0 -23
- package/src/models/session.js.map +0 -1
- package/src/models/tenant.d.ts +0 -448
- package/src/models/tenant.d.ts.map +0 -1
- package/src/models/tenant.js +0 -23
- package/src/models/tenant.js.map +0 -1
- package/src/models/trigger.d.ts +0 -87
- package/src/models/trigger.d.ts.map +0 -1
- package/src/models/trigger.js +0 -41
- package/src/models/trigger.js.map +0 -1
- package/src/models/usage-record.d.ts +0 -37
- package/src/models/usage-record.d.ts.map +0 -1
- package/src/models/usage-record.js +0 -14
- package/src/models/usage-record.js.map +0 -1
- package/src/models/webhook.d.ts +0 -50
- package/src/models/webhook.d.ts.map +0 -1
- package/src/models/webhook.js +0 -25
- package/src/models/webhook.js.map +0 -1
- package/src/retrieval/compound-search.d.ts +0 -13
- package/src/retrieval/compound-search.d.ts.map +0 -1
- package/src/retrieval/compound-search.js +0 -87
- package/src/retrieval/compound-search.js.map +0 -1
- package/src/retrieval/contradiction-surfacer.d.ts +0 -18
- package/src/retrieval/contradiction-surfacer.d.ts.map +0 -1
- package/src/retrieval/contradiction-surfacer.js +0 -64
- package/src/retrieval/contradiction-surfacer.js.map +0 -1
- package/src/retrieval/embedding-cache.d.ts +0 -17
- package/src/retrieval/embedding-cache.d.ts.map +0 -1
- package/src/retrieval/embedding-cache.js +0 -56
- package/src/retrieval/embedding-cache.js.map +0 -1
- package/src/retrieval/fusion.d.ts +0 -27
- package/src/retrieval/fusion.d.ts.map +0 -1
- package/src/retrieval/fusion.js +0 -87
- package/src/retrieval/fusion.js.map +0 -1
- package/src/retrieval/graph-traversal.d.ts +0 -29
- package/src/retrieval/graph-traversal.d.ts.map +0 -1
- package/src/retrieval/graph-traversal.js +0 -208
- package/src/retrieval/graph-traversal.js.map +0 -1
- package/src/retrieval/query-expansion.d.ts +0 -20
- package/src/retrieval/query-expansion.d.ts.map +0 -1
- package/src/retrieval/query-expansion.js +0 -76
- package/src/retrieval/query-expansion.js.map +0 -1
- package/src/retrieval/reranker.d.ts +0 -15
- package/src/retrieval/reranker.d.ts.map +0 -1
- package/src/retrieval/reranker.js +0 -47
- package/src/retrieval/reranker.js.map +0 -1
- package/src/retrieval/salience-scorer.d.ts +0 -15
- package/src/retrieval/salience-scorer.d.ts.map +0 -1
- package/src/retrieval/salience-scorer.js +0 -41
- package/src/retrieval/salience-scorer.js.map +0 -1
- package/src/retrieval/search.d.ts +0 -21
- package/src/retrieval/search.d.ts.map +0 -1
- package/src/retrieval/search.js +0 -228
- package/src/retrieval/search.js.map +0 -1
- package/src/retrieval/temporal-scorer.d.ts +0 -18
- package/src/retrieval/temporal-scorer.d.ts.map +0 -1
- package/src/retrieval/temporal-scorer.js +0 -106
- package/src/retrieval/temporal-scorer.js.map +0 -1
- package/src/retrieval/trigger-matcher.d.ts +0 -18
- package/src/retrieval/trigger-matcher.d.ts.map +0 -1
- package/src/retrieval/trigger-matcher.js +0 -134
- package/src/retrieval/trigger-matcher.js.map +0 -1
- package/src/retrieval/types.d.ts +0 -70
- package/src/retrieval/types.d.ts.map +0 -1
- package/src/retrieval/types.js +0 -9
- package/src/retrieval/types.js.map +0 -1
- package/src/retrieval/vector-search.d.ts +0 -5
- package/src/retrieval/vector-search.d.ts.map +0 -1
- package/src/retrieval/vector-search.js +0 -24
- package/src/retrieval/vector-search.js.map +0 -1
- package/src/salience/decay.d.ts +0 -9
- package/src/salience/decay.d.ts.map +0 -1
- package/src/salience/decay.js +0 -15
- package/src/salience/decay.js.map +0 -1
- package/src/scratchpad/scratchpad.d.ts +0 -23
- package/src/scratchpad/scratchpad.d.ts.map +0 -1
- package/src/scratchpad/scratchpad.js +0 -137
- package/src/scratchpad/scratchpad.js.map +0 -1
- package/src/sessions/manager.d.ts +0 -11
- package/src/sessions/manager.d.ts.map +0 -1
- package/src/sessions/manager.js +0 -63
- package/src/sessions/manager.js.map +0 -1
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
import { extractHeuristic } from './heuristic.js';
|
|
2
|
-
import { extractWithLLM, normalizeEntityName } from './llm-extractor.js';
|
|
3
|
-
import { deduplicateFacts } from './dedup.js';
|
|
4
|
-
import { processContradictions } from './contradiction.js';
|
|
5
|
-
import { buildEntityIdMap, persistEdges } from './entity-extractor.js';
|
|
6
|
-
import { linkRelatedFacts } from './cross-linker.js';
|
|
7
|
-
import { hashInput } from './hasher.js';
|
|
8
|
-
import { updateScratchpad } from '../scratchpad/scratchpad.js';
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
// Helpers
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
export function inputToText(input) {
|
|
13
|
-
if (typeof input.data === 'string')
|
|
14
|
-
return input.data;
|
|
15
|
-
if (typeof input.data === 'object' && input.data !== null) {
|
|
16
|
-
const data = input.data;
|
|
17
|
-
if (Array.isArray(data.messages)) {
|
|
18
|
-
return data.messages
|
|
19
|
-
.filter((m) => typeof m === 'object' && m !== null &&
|
|
20
|
-
typeof m.role === 'string' &&
|
|
21
|
-
typeof m.content === 'string')
|
|
22
|
-
.map(m => `${m.role}: ${m.content}`)
|
|
23
|
-
.join('\n');
|
|
24
|
-
}
|
|
25
|
-
return JSON.stringify(input.data);
|
|
26
|
-
}
|
|
27
|
-
return String(input.data);
|
|
28
|
-
}
|
|
29
|
-
export function mergeFacts(heuristic, llm) {
|
|
30
|
-
const llmContents = new Set(llm.map(f => f.content.toLowerCase()));
|
|
31
|
-
const unique = heuristic.filter(f => !llmContents.has(f.content.toLowerCase()));
|
|
32
|
-
return [...llm, ...unique];
|
|
33
|
-
}
|
|
34
|
-
export function mergeEntities(heuristic, llm) {
|
|
35
|
-
const seen = new Map();
|
|
36
|
-
for (const e of [...heuristic, ...llm]) {
|
|
37
|
-
const normalized = normalizeEntityName(e.canonicalName);
|
|
38
|
-
if (normalized.length === 0)
|
|
39
|
-
continue;
|
|
40
|
-
seen.set(normalized, { ...e, canonicalName: normalized });
|
|
41
|
-
}
|
|
42
|
-
return Array.from(seen.values());
|
|
43
|
-
}
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// Core extraction logic (shared between pipeline and queue worker)
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
async function executeExtraction(config, extractionId, input, startTime) {
|
|
48
|
-
const tier = config.extractionTier ?? 'auto';
|
|
49
|
-
const textContent = inputToText(input);
|
|
50
|
-
let totalTokensInput = 0;
|
|
51
|
-
let totalTokensOutput = 0;
|
|
52
|
-
const tiersUsed = [];
|
|
53
|
-
// Run heuristic extraction (always)
|
|
54
|
-
const heuristicResult = extractHeuristic(textContent);
|
|
55
|
-
tiersUsed.push('heuristic');
|
|
56
|
-
let mergedFacts = heuristicResult.facts;
|
|
57
|
-
let mergedEntities = heuristicResult.entities;
|
|
58
|
-
let mergedEdges = heuristicResult.edges;
|
|
59
|
-
// Run LLM extraction (unless heuristic_only)
|
|
60
|
-
if (tier !== 'heuristic_only') {
|
|
61
|
-
const llmToUse = tier === 'smart_only' ? (config.smartLLM ?? config.cheapLLM) : config.cheapLLM;
|
|
62
|
-
const llmTier = tier === 'smart_only' ? 'smart_llm' : 'cheap_llm';
|
|
63
|
-
// Fetch existing facts for the LLM to compare against (enables contradiction detection)
|
|
64
|
-
let existingFactsForLLM = input.existingFacts?.map(f => ({
|
|
65
|
-
lineageId: f.lineageId,
|
|
66
|
-
content: f.content,
|
|
67
|
-
}));
|
|
68
|
-
if (!existingFactsForLLM || existingFactsForLLM.length === 0) {
|
|
69
|
-
try {
|
|
70
|
-
const queryEmbedding = await config.embedding.embed(textContent.slice(0, 1000));
|
|
71
|
-
const similar = await config.storage.vectorSearch({
|
|
72
|
-
embedding: queryEmbedding,
|
|
73
|
-
tenantId: input.tenantId,
|
|
74
|
-
scope: input.scope,
|
|
75
|
-
scopeId: input.scopeId,
|
|
76
|
-
limit: 20,
|
|
77
|
-
minSimilarity: 0.3,
|
|
78
|
-
validOnly: true,
|
|
79
|
-
});
|
|
80
|
-
if (similar.length > 0) {
|
|
81
|
-
existingFactsForLLM = similar.map(s => ({
|
|
82
|
-
lineageId: s.fact.lineageId ?? s.fact.id,
|
|
83
|
-
content: s.fact.content,
|
|
84
|
-
}));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
// Non-fatal — extraction continues without existing facts
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const llmResult = await extractWithLLM({ llm: llmToUse, tier: llmTier, entityTypes: config.entityTypes, domainEntityTypes: config.domainEntityTypes }, textContent, existingFactsForLLM);
|
|
92
|
-
totalTokensInput += llmResult.tokensInput;
|
|
93
|
-
totalTokensOutput += llmResult.tokensOutput;
|
|
94
|
-
tiersUsed.push(llmTier);
|
|
95
|
-
// Escalate to smart LLM if confidence is low
|
|
96
|
-
let finalLLMResult = llmResult;
|
|
97
|
-
if (tier === 'auto' &&
|
|
98
|
-
llmResult.confidence < 0.6 &&
|
|
99
|
-
config.smartLLM) {
|
|
100
|
-
const smartResult = await extractWithLLM({ llm: config.smartLLM, tier: 'smart_llm', entityTypes: config.entityTypes, domainEntityTypes: config.domainEntityTypes }, textContent, existingFactsForLLM);
|
|
101
|
-
totalTokensInput += smartResult.tokensInput;
|
|
102
|
-
totalTokensOutput += smartResult.tokensOutput;
|
|
103
|
-
tiersUsed.push('smart_llm');
|
|
104
|
-
finalLLMResult = smartResult;
|
|
105
|
-
}
|
|
106
|
-
// Merge results: LLM takes priority
|
|
107
|
-
mergedFacts = mergeFacts(heuristicResult.facts, finalLLMResult.facts);
|
|
108
|
-
// Merge entities: dedup by canonicalName, LLM overwrites heuristic
|
|
109
|
-
mergedEntities = mergeEntities(heuristicResult.entities, finalLLMResult.entities);
|
|
110
|
-
mergedEdges = [...heuristicResult.edges, ...finalLLMResult.edges];
|
|
111
|
-
}
|
|
112
|
-
// Run deduplication against existing memories
|
|
113
|
-
const dedupedFacts = await deduplicateFacts({
|
|
114
|
-
storage: config.storage,
|
|
115
|
-
embedding: config.embedding,
|
|
116
|
-
llm: config.cheapLLM,
|
|
117
|
-
}, mergedFacts, input.tenantId, input.scope, input.scopeId);
|
|
118
|
-
// Process contradictions
|
|
119
|
-
const contradictionResults = processContradictions(dedupedFacts);
|
|
120
|
-
// Persist facts
|
|
121
|
-
let factsCreated = 0;
|
|
122
|
-
let factsUpdated = 0;
|
|
123
|
-
let factsInvalidated = 0;
|
|
124
|
-
let entitiesCreated = 0;
|
|
125
|
-
let edgesCreated = 0;
|
|
126
|
-
// Determine the final tier label
|
|
127
|
-
const uniqueTiers = [...new Set(tiersUsed)];
|
|
128
|
-
const tierUsed = uniqueTiers.length > 1 ? 'multi_tier' :
|
|
129
|
-
(uniqueTiers[0] === 'heuristic' ? 'heuristic' :
|
|
130
|
-
uniqueTiers[0] === 'cheap_llm' ? 'cheap_llm' : 'smart_llm');
|
|
131
|
-
// Ensure "User" entity exists — LLM creates edges like "user → shops_at → target"
|
|
132
|
-
// but never extracts "user" as an entity, so those edges get silently dropped.
|
|
133
|
-
if (!mergedEntities.some(e => e.canonicalName === 'user')) {
|
|
134
|
-
mergedEntities.push({
|
|
135
|
-
name: 'User',
|
|
136
|
-
entityType: 'person',
|
|
137
|
-
canonicalName: 'user',
|
|
138
|
-
properties: { scopeId: input.scopeId },
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
// Persist entities ONCE (before the fact loop) to build entityIdMap.
|
|
142
|
-
const { entityIdMap, entitiesCreated: newEntitiesCreated } = await buildEntityIdMap(config.storage, config.embedding, input.tenantId, mergedEntities);
|
|
143
|
-
entitiesCreated = newEntitiesCreated;
|
|
144
|
-
// Collect the first persisted factId to anchor edges (edges reference a fact).
|
|
145
|
-
let firstFactId;
|
|
146
|
-
// Track all created fact IDs for cross-linking
|
|
147
|
-
const createdFactIds = [];
|
|
148
|
-
// ── BATCH EMBED all extracted facts at once (1 API call instead of N) ──
|
|
149
|
-
const factsToEmbed = contradictionResults.filter(r => r.fact.operation !== 'noop');
|
|
150
|
-
const factTexts = factsToEmbed.map(r => r.fact.contextualContent ?? r.fact.content);
|
|
151
|
-
const factEmbeddings = factTexts.length > 0 ? await config.embedding.embedBatch(factTexts) : [];
|
|
152
|
-
let factEmbIdx = 0;
|
|
153
|
-
// Persist facts and link entities per-fact.
|
|
154
|
-
for (const { fact, contradictionStatus, contradictsId } of contradictionResults) {
|
|
155
|
-
// Skip noop facts
|
|
156
|
-
if (fact.operation === 'noop')
|
|
157
|
-
continue;
|
|
158
|
-
// Generate IDs
|
|
159
|
-
const factId = crypto.randomUUID();
|
|
160
|
-
if (!firstFactId)
|
|
161
|
-
firstFactId = factId;
|
|
162
|
-
let lineageId;
|
|
163
|
-
if (fact.operation === 'update' && fact.existingLineageId) {
|
|
164
|
-
// For updates, reuse existing lineage ID
|
|
165
|
-
lineageId = fact.existingLineageId;
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
lineageId = crypto.randomUUID();
|
|
169
|
-
}
|
|
170
|
-
// Use pre-computed batch embedding
|
|
171
|
-
const embedding = factEmbeddings[factEmbIdx++] ?? await config.embedding.embed(fact.content);
|
|
172
|
-
// Create fact in storage
|
|
173
|
-
await config.storage.createFact({
|
|
174
|
-
id: factId,
|
|
175
|
-
lineageId,
|
|
176
|
-
tenantId: input.tenantId,
|
|
177
|
-
scope: input.scope,
|
|
178
|
-
scopeId: input.scopeId,
|
|
179
|
-
sessionId: input.sessionId,
|
|
180
|
-
content: fact.content,
|
|
181
|
-
embeddingModel: config.embeddingModel,
|
|
182
|
-
embeddingDim: config.embeddingDim,
|
|
183
|
-
embedding,
|
|
184
|
-
importance: fact.importance,
|
|
185
|
-
confidence: fact.confidence,
|
|
186
|
-
operation: fact.operation === 'add' || fact.operation === undefined ? 'create' :
|
|
187
|
-
fact.operation === 'update' ? 'update' :
|
|
188
|
-
fact.operation === 'invalidate' ? 'invalidate' : 'create',
|
|
189
|
-
contradictionStatus,
|
|
190
|
-
contradictsId: contradictsId ?? undefined,
|
|
191
|
-
sourceType: fact.sourceType,
|
|
192
|
-
originalContent: fact.originalContent,
|
|
193
|
-
extractionId,
|
|
194
|
-
extractionTier: tierUsed === 'multi_tier' ? 'heuristic' : tierUsed,
|
|
195
|
-
modality: fact.modality,
|
|
196
|
-
tags: fact.tags,
|
|
197
|
-
metadata: {
|
|
198
|
-
...(fact.relationType && { relationType: fact.relationType }),
|
|
199
|
-
...(fact.relatedFactId && { relatedFactId: fact.relatedFactId }),
|
|
200
|
-
},
|
|
201
|
-
sourceChunk: fact.sourceChunk,
|
|
202
|
-
eventDate: fact.eventDate,
|
|
203
|
-
documentDate: fact.documentDate ?? new Date(), // Always set — when the conversation happened
|
|
204
|
-
});
|
|
205
|
-
// Track counts — Git-style append-only: NEVER invalidate old facts.
|
|
206
|
-
// Updates create new versions with same lineageId. Recency scoring
|
|
207
|
-
// naturally prefers newer versions. Old versions remain searchable
|
|
208
|
-
// for temporal reasoning ("what was my old X?").
|
|
209
|
-
createdFactIds.push(factId);
|
|
210
|
-
if (fact.operation === 'update') {
|
|
211
|
-
factsUpdated++;
|
|
212
|
-
}
|
|
213
|
-
else if (fact.operation === 'invalidate') {
|
|
214
|
-
factsInvalidated++;
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
factsCreated++;
|
|
218
|
-
}
|
|
219
|
-
// Link only the entities that THIS fact mentions.
|
|
220
|
-
// If the LLM provided entityCanonicalNames, use those for precise linking.
|
|
221
|
-
// Otherwise fall back to TEXT-MATCH: check if the entity name appears in the fact content.
|
|
222
|
-
// NEVER link all entities — that creates garbage links.
|
|
223
|
-
let relevantNames = fact.entityCanonicalNames;
|
|
224
|
-
if (!relevantNames || relevantNames.length === 0) {
|
|
225
|
-
const contentLower = fact.content.toLowerCase();
|
|
226
|
-
relevantNames = [];
|
|
227
|
-
for (const [canonicalName] of entityIdMap) {
|
|
228
|
-
if (canonicalName === 'user') {
|
|
229
|
-
if (contentLower.startsWith('user ') || contentLower.includes(' user ')) {
|
|
230
|
-
relevantNames.push(canonicalName);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
else if (canonicalName.length >= 3 && contentLower.includes(canonicalName)) {
|
|
234
|
-
relevantNames.push(canonicalName);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
for (const name of relevantNames) {
|
|
239
|
-
const entityId = entityIdMap.get(name);
|
|
240
|
-
if (entityId) {
|
|
241
|
-
await config.storage.linkFactEntity(factId, entityId, 'mentioned');
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
// Cross-link new facts to existing related facts via shared entities + keyword overlap
|
|
246
|
-
if (createdFactIds.length > 0) {
|
|
247
|
-
try {
|
|
248
|
-
const crossLinked = await linkRelatedFacts(config.storage, input.tenantId, createdFactIds, entityIdMap);
|
|
249
|
-
edgesCreated += crossLinked;
|
|
250
|
-
}
|
|
251
|
-
catch (err) {
|
|
252
|
-
console.error('[steno] Cross-linking failed:', err instanceof Error ? err.message : err);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// Create edges ONCE after all facts are persisted.
|
|
256
|
-
console.error(`[steno] Edge creation: ${mergedEdges.length} edges to persist, firstFactId=${firstFactId ? 'set' : 'MISSING'}`);
|
|
257
|
-
if (mergedEdges.length > 0) {
|
|
258
|
-
for (const e of mergedEdges.slice(0, 5)) {
|
|
259
|
-
console.error(`[steno] edge: "${e.sourceName}" → "${e.relation}" → "${e.targetName}"`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
if (firstFactId !== undefined && mergedEdges.length > 0) {
|
|
263
|
-
edgesCreated = await persistEdges(config.storage, input.tenantId, firstFactId, mergedEdges, entityIdMap);
|
|
264
|
-
}
|
|
265
|
-
const durationMs = Date.now() - startTime;
|
|
266
|
-
// Update extraction record to 'completed'
|
|
267
|
-
await config.storage.updateExtraction(input.tenantId, extractionId, {
|
|
268
|
-
status: 'completed',
|
|
269
|
-
tierUsed,
|
|
270
|
-
factsCreated,
|
|
271
|
-
factsUpdated,
|
|
272
|
-
factsInvalidated,
|
|
273
|
-
entitiesCreated,
|
|
274
|
-
edgesCreated,
|
|
275
|
-
costTokensInput: totalTokensInput,
|
|
276
|
-
costTokensOutput: totalTokensOutput,
|
|
277
|
-
durationMs,
|
|
278
|
-
completedAt: new Date(),
|
|
279
|
-
});
|
|
280
|
-
// Update scratchpad with newly extracted facts
|
|
281
|
-
try {
|
|
282
|
-
const factContents = contradictionResults
|
|
283
|
-
.filter(r => r.fact.operation !== 'noop')
|
|
284
|
-
.map(r => r.fact.content);
|
|
285
|
-
if (factContents.length > 0) {
|
|
286
|
-
await updateScratchpad(config.storage, config.cheapLLM, input.tenantId, input.scope, input.scopeId, factContents);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
// Scratchpad update failure should not break the pipeline
|
|
291
|
-
}
|
|
292
|
-
// Increment usage
|
|
293
|
-
await config.storage.incrementUsage(input.tenantId, totalTokensInput + totalTokensOutput, 0, 1, 0);
|
|
294
|
-
return {
|
|
295
|
-
extractionId,
|
|
296
|
-
factsCreated,
|
|
297
|
-
factsUpdated,
|
|
298
|
-
factsInvalidated,
|
|
299
|
-
entitiesCreated,
|
|
300
|
-
edgesCreated,
|
|
301
|
-
tier: tierUsed,
|
|
302
|
-
costTokensInput: totalTokensInput,
|
|
303
|
-
costTokensOutput: totalTokensOutput,
|
|
304
|
-
durationMs,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
// ---------------------------------------------------------------------------
|
|
308
|
-
// Main pipeline (synchronous — creates its own extraction record)
|
|
309
|
-
// ---------------------------------------------------------------------------
|
|
310
|
-
export async function runExtractionPipeline(config, input) {
|
|
311
|
-
const startTime = Date.now();
|
|
312
|
-
// 1. Hash input for dedup
|
|
313
|
-
const inputHash = await hashInput({ type: input.inputType, data: input.data });
|
|
314
|
-
// 2. Check if already processed
|
|
315
|
-
const existing = await config.storage.getExtractionByHash(input.tenantId, inputHash);
|
|
316
|
-
if (existing && existing.status === 'completed') {
|
|
317
|
-
return {
|
|
318
|
-
extractionId: existing.id,
|
|
319
|
-
factsCreated: existing.factsCreated,
|
|
320
|
-
factsUpdated: existing.factsUpdated,
|
|
321
|
-
factsInvalidated: existing.factsInvalidated,
|
|
322
|
-
entitiesCreated: existing.entitiesCreated,
|
|
323
|
-
edgesCreated: existing.edgesCreated,
|
|
324
|
-
tier: existing.tierUsed ?? 'heuristic',
|
|
325
|
-
costTokensInput: existing.costTokensInput,
|
|
326
|
-
costTokensOutput: existing.costTokensOutput,
|
|
327
|
-
durationMs: existing.durationMs ?? 0,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
// If a previous extraction with the same hash failed, delete it so we can retry
|
|
331
|
-
if (existing && existing.status === 'failed') {
|
|
332
|
-
await config.storage.deleteExtraction(input.tenantId, existing.id);
|
|
333
|
-
}
|
|
334
|
-
// 3. Create extraction record with status='queued'
|
|
335
|
-
// Handle race condition: concurrent workers may try to create the same hash simultaneously
|
|
336
|
-
const extractionId = crypto.randomUUID();
|
|
337
|
-
const textContent = inputToText(input);
|
|
338
|
-
try {
|
|
339
|
-
await config.storage.createExtraction({
|
|
340
|
-
id: extractionId,
|
|
341
|
-
tenantId: input.tenantId,
|
|
342
|
-
inputType: input.inputType,
|
|
343
|
-
inputData: textContent,
|
|
344
|
-
inputHash,
|
|
345
|
-
inputSize: textContent.length,
|
|
346
|
-
scope: input.scope,
|
|
347
|
-
scopeId: input.scopeId,
|
|
348
|
-
sessionId: input.sessionId,
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
catch (createErr) {
|
|
352
|
-
// Log the actual error so it's not silently swallowed
|
|
353
|
-
console.error(`[steno] createExtraction failed:`, createErr instanceof Error ? createErr.message : createErr);
|
|
354
|
-
// Duplicate hash — another worker beat us. Return their result.
|
|
355
|
-
const raceWinner = await config.storage.getExtractionByHash(input.tenantId, inputHash);
|
|
356
|
-
if (raceWinner) {
|
|
357
|
-
return {
|
|
358
|
-
extractionId: raceWinner.id,
|
|
359
|
-
factsCreated: raceWinner.factsCreated,
|
|
360
|
-
factsUpdated: raceWinner.factsUpdated,
|
|
361
|
-
factsInvalidated: raceWinner.factsInvalidated,
|
|
362
|
-
entitiesCreated: raceWinner.entitiesCreated,
|
|
363
|
-
edgesCreated: raceWinner.edgesCreated,
|
|
364
|
-
tier: raceWinner.tierUsed ?? 'heuristic',
|
|
365
|
-
costTokensInput: raceWinner.costTokensInput,
|
|
366
|
-
costTokensOutput: raceWinner.costTokensOutput,
|
|
367
|
-
durationMs: raceWinner.durationMs ?? 0,
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
throw new Error('Extraction race condition: duplicate hash but no existing record found');
|
|
371
|
-
}
|
|
372
|
-
// 4. Update status to 'processing'
|
|
373
|
-
await config.storage.updateExtraction(input.tenantId, extractionId, {
|
|
374
|
-
status: 'processing',
|
|
375
|
-
});
|
|
376
|
-
try {
|
|
377
|
-
return await executeExtraction(config, extractionId, input, startTime);
|
|
378
|
-
}
|
|
379
|
-
catch (err) {
|
|
380
|
-
await config.storage.updateExtraction(input.tenantId, extractionId, {
|
|
381
|
-
status: 'failed',
|
|
382
|
-
error: err instanceof Error ? err.message : String(err),
|
|
383
|
-
});
|
|
384
|
-
throw err;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
// ---------------------------------------------------------------------------
|
|
388
|
-
// Queue worker entry — processes a pre-created extraction record
|
|
389
|
-
// ---------------------------------------------------------------------------
|
|
390
|
-
/**
|
|
391
|
-
* Run extraction for a pre-created extraction record (from queue).
|
|
392
|
-
* Unlike runExtractionPipeline, this does NOT create the extraction record
|
|
393
|
-
* or perform hash-based dedup — both were already handled by the API route.
|
|
394
|
-
* It updates the existing record through the pipeline lifecycle.
|
|
395
|
-
*/
|
|
396
|
-
export async function runExtractionFromQueue(config, extractionId, input) {
|
|
397
|
-
const startTime = Date.now();
|
|
398
|
-
// Update status to 'processing'
|
|
399
|
-
await config.storage.updateExtraction(input.tenantId, extractionId, {
|
|
400
|
-
status: 'processing',
|
|
401
|
-
});
|
|
402
|
-
try {
|
|
403
|
-
return await executeExtraction(config, extractionId, input, startTime);
|
|
404
|
-
}
|
|
405
|
-
catch (err) {
|
|
406
|
-
await config.storage.updateExtraction(input.tenantId, extractionId, {
|
|
407
|
-
status: 'failed',
|
|
408
|
-
error: err instanceof Error ? err.message : String(err),
|
|
409
|
-
});
|
|
410
|
-
throw err;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
//# sourceMappingURL=pipeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["pipeline.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAgB/D,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,UAAU,WAAW,CAAC,KAAsB;IAChD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC;IACtD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,IAA+B,CAAC;QACnD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,OAAQ,IAAI,CAAC,QAAsB;iBAChC,MAAM,CAAC,CAAC,CAAC,EAA0C,EAAE,CACpD,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;gBACnC,OAAQ,CAA6B,CAAC,IAAI,KAAK,QAAQ;gBACvD,OAAQ,CAA6B,CAAC,OAAO,KAAK,QAAQ,CAC3D;iBACA,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;iBACnC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,SAA0B,EAC1B,GAAoB;IAEpB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAA4B,EAC5B,GAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,mBAAmB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QACxD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACtC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,8EAA8E;AAC9E,mEAAmE;AACnE,8EAA8E;AAE9E,KAAK,UAAU,iBAAiB,CAC9B,MAAsB,EACtB,YAAoB,EACpB,KAAsB,EACtB,SAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC;IAC7C,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,oCAAoC;IACpC,MAAM,eAAe,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACtD,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5B,IAAI,WAAW,GAAoB,eAAe,CAAC,KAAK,CAAC;IACzD,IAAI,cAAc,GAAsB,eAAe,CAAC,QAAQ,CAAC;IACjE,IAAI,WAAW,GAAoB,eAAe,CAAC,KAAK,CAAC;IAEzD,6CAA6C;IAC7C,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChG,MAAM,OAAO,GAAG,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;QAElE,wFAAwF;QACxF,IAAI,mBAAmB,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvD,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC,CAAC;QAEJ,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBAChF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;oBAChD,SAAS,EAAE,cAAc;oBACzB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,KAAK,EAAE,EAAE;oBACT,aAAa,EAAE,GAAG;oBAClB,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;gBACH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBACtC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;wBACxC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;qBACxB,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,0DAA0D;YAC5D,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,cAAc,CACpC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,EAC9G,WAAW,EACX,mBAAmB,CACpB,CAAC;QAEF,gBAAgB,IAAI,SAAS,CAAC,WAAW,CAAC;QAC1C,iBAAiB,IAAI,SAAS,CAAC,YAAY,CAAC;QAC5C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExB,6CAA6C;QAC7C,IAAI,cAAc,GAAG,SAAS,CAAC;QAC/B,IACE,IAAI,KAAK,MAAM;YACf,SAAS,CAAC,UAAU,GAAG,GAAG;YAC1B,MAAM,CAAC,QAAQ,EACf,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,cAAc,CACtC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,EACzH,WAAW,EACX,mBAAmB,CACpB,CAAC;YACF,gBAAgB,IAAI,WAAW,CAAC,WAAW,CAAC;YAC5C,iBAAiB,IAAI,WAAW,CAAC,YAAY,CAAC;YAC9C,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC5B,cAAc,GAAG,WAAW,CAAC;QAC/B,CAAC;QAED,oCAAoC;QACpC,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;QAEtE,mEAAmE;QACnE,cAAc,GAAG,aAAa,CAAC,eAAe,CAAC,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClF,WAAW,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC;IAED,8CAA8C;IAC9C,MAAM,YAAY,GAAG,MAAM,gBAAgB,CACzC;QACE,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,EAAE,MAAM,CAAC,QAAQ;KACrB,EACD,WAAW,EACX,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,CACd,CAAC;IAEF,yBAAyB;IACzB,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAEjE,gBAAgB;IAChB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,iCAAiC;IACjC,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAA2B,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC9E,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAC7C,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAEhE,kFAAkF;IAClF,+EAA+E;IAC/E,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,MAAM,CAAC,EAAE,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC;YAClB,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,QAAQ;YACpB,aAAa,EAAE,MAAM;YACrB,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SACvC,CAAC,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,GAAG,MAAM,gBAAgB,CACjF,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,SAAS,EAChB,KAAK,CAAC,QAAQ,EACd,cAAc,CACf,CAAC;IACF,eAAe,GAAG,kBAAkB,CAAC;IAErC,+EAA+E;IAC/E,IAAI,WAA+B,CAAC;IAEpC,+CAA+C;IAC/C,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,0EAA0E;IAC1E,MAAM,YAAY,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,4CAA4C;IAC5C,KAAK,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,aAAa,EAAE,IAAI,oBAAoB,EAAE,CAAC;QAChF,kBAAkB;QAClB,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM;YAAE,SAAS;QAExC,eAAe;QACf,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW;YAAE,WAAW,GAAG,MAAM,CAAC;QAEvC,IAAI,SAAiB,CAAC;QAEtB,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1D,yCAAyC;YACzC,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,CAAC;QAED,mCAAmC;QACnC,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,EAAE,CAAC,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE7F,yBAAyB;QACzB,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAC9B,EAAE,EAAE,MAAM;YACV,SAAS;YACT,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,SAAS;YACT,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC9E,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;oBACtC,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ;YAC7D,mBAAmB;YACnB,aAAa,EAAE,aAAa,IAAI,SAAS;YACzC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,YAAY;YACZ,cAAc,EAAE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;YAClE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE;gBACR,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC7D,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC;aACjE;YACD,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,EAAE,8CAA8C;SAC9F,CAAC,CAAC;QAEH,oEAAoE;QACpE,mEAAmE;QACnE,mEAAmE;QACnE,iDAAiD;QACjD,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE5B,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAChC,YAAY,EAAE,CAAC;QACjB,CAAC;aAAM,IAAI,IAAI,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;YAC3C,gBAAgB,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,YAAY,EAAE,CAAC;QACjB,CAAC;QAED,kDAAkD;QAClD,2EAA2E;QAC3E,2FAA2F;QAC3F,wDAAwD;QACxD,IAAI,aAAa,GAAG,IAAI,CAAC,oBAAoB,CAAC;QAC9C,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAChD,aAAa,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC1C,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;oBAC7B,IAAI,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACxE,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC;qBAAM,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC7E,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,uFAAuF;IACvF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;YACxG,YAAY,IAAI,WAAW,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,OAAO,CAAC,KAAK,CAAC,0BAA0B,WAAW,CAAC,MAAM,kCAAkC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/H,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,UAAU,QAAQ,CAAC,CAAC,QAAQ,QAAQ,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IACD,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,YAAY,GAAG,MAAM,YAAY,CAC/B,MAAM,CAAC,OAAO,EACd,KAAK,CAAC,QAAQ,EACd,WAAW,EACX,WAAW,EACX,WAAW,CACZ,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE1C,0CAA0C;IAC1C,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE;QAClE,MAAM,EAAE,WAAW;QACnB,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,eAAe;QACf,YAAY;QACZ,eAAe,EAAE,gBAAgB;QACjC,gBAAgB,EAAE,iBAAiB;QACnC,UAAU;QACV,WAAW,EAAE,IAAI,IAAI,EAAE;KACxB,CAAC,CAAC;IAEH,+CAA+C;IAC/C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,oBAAoB;aACtC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,gBAAgB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACpH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;IAED,kBAAkB;IAClB,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CACjC,KAAK,CAAC,QAAQ,EACd,gBAAgB,GAAG,iBAAiB,EACpC,CAAC,EACD,CAAC,EACD,CAAC,CACF,CAAC;IAEF,OAAO;QACL,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,eAAe;QACf,YAAY;QACZ,IAAI,EAAE,QAAQ;QACd,eAAe,EAAE,gBAAgB;QACjC,gBAAgB,EAAE,iBAAiB;QACnC,UAAU;KACX,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,kEAAkE;AAClE,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAsB,EACtB,KAAsB;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,0BAA0B;IAC1B,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAE/E,gCAAgC;IAChC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACrF,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAChD,OAAO;YACL,YAAY,EAAE,QAAQ,CAAC,EAAE;YACzB,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,WAAW;YACtC,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,gFAAgF;IAChF,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,mDAAmD;IACnD,8FAA8F;IAC9F,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACzC,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC;YACpC,EAAE,EAAE,YAAY;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,WAAW;YACtB,SAAS;YACT,SAAS,EAAE,WAAW,CAAC,MAAM;YAC7B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,SAAS,EAAE,CAAC;QACnB,sDAAsD;QACtD,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC9G,gEAAgE;QAChE,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACvF,IAAI,UAAU,EAAE,CAAC;YACf,OAAO;gBACL,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;gBAC7C,eAAe,EAAE,UAAU,CAAC,eAAe;gBAC3C,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,IAAI,EAAE,UAAU,CAAC,QAAQ,IAAI,WAAW;gBACxC,eAAe,EAAE,UAAU,CAAC,eAAe;gBAC3C,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;gBAC7C,UAAU,EAAE,UAAU,CAAC,UAAU,IAAI,CAAC;aACvC,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE;QAClE,MAAM,EAAE,YAAY;KACrB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE;YAClE,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAC;QACH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,iEAAiE;AACjE,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAsB,EACtB,YAAoB,EACpB,KAAsB;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,gCAAgC;IAChC,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE;QAClE,MAAM,EAAE,YAAY;KACrB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE;YAClE,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAC;QACH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { LLMMessage } from '../adapters/llm.js';
|
|
2
|
-
import type { DomainEntityType } from '../config.js';
|
|
3
|
-
export declare const FACT_EXTRACTION_PROMPT = "You are a memory extraction engine. Extract facts from text for a personal AI memory system.\n\n## WHO IS \"USER\"?\n\nMessages labeled \"user\" are from THE PERSON whose memories we are storing.\nMessages labeled \"assistant\" or any other role are from OTHER people.\n\nCRITICAL: Focus on facts FROM \"user\" messages, but ALSO extract notable facts about other people mentioned in the conversation. If the assistant/conversation partner shares personal information (e.g., \"I painted a sunrise last year\", \"I realized self-care is important\"), store it as \"User's conversation partner [Name] painted a sunrise in [year]\".\n\nFor identity/trait facts, state them DIRECTLY:\n- \"User is a transgender woman\" (not just \"User went to a transgender conference\")\n- \"User works at Brightwell Capital\" (not just \"User had a busy day at work\")\n- \"User is researching adoption agencies\" (not just \"User attended a meeting about adoption\")\n\n## RULES\n\n1. Extract SELF-CONTAINED atomic facts. Each fact must be understandable on its own, without the original conversation.\n\n2. **DATES ARE CRITICAL** \u2014 Resolve ALL temporal references to exact dates:\n - \"yesterday\" \u2192 \"on 7 May 2023\"\n - \"last week\" \u2192 \"around 1 May 2023\"\n - \"recently\" \u2192 \"in early May 2023\"\n - Look for date context like \"[This conversation took place on 8 May, 2023]\" and resolve ALL relative dates from it.\n - EVERY event/activity fact MUST include WHEN it happened if the date can be inferred.\n - BAD: \"User went to an LGBTQ support group\"\n - GOOD: \"User went to an LGBTQ support group on 7 May 2023\"\n\n3. Resolve ALL other references:\n - Pronouns \u2192 names: \"she said\" \u2192 \"Casey said\"\n - Places \u2192 full names: \"there\" \u2192 \"at Brightwell Capital\"\n\n4. Be SPECIFIC, not vague:\n BAD: \"User had issues at work\"\n GOOD: \"User's team at Brightwell Capital rambles too much in meetings\"\n\n5. Extract ALL facts, even minor ones. You cannot predict what will be asked later.\n\n6. Write all facts in third person using \"User\" (e.g., \"User prefers dark mode\").\n\n7. For conversation partners: ALSO extract their facts with their name.\n - If Melanie says \"I painted a sunrise last year\" \u2192 \"Melanie painted a sunrise in 2022\"\n - If Melanie says \"I ran a charity race\" \u2192 \"Melanie ran a charity race\"\n\n8. For EVERY fact, include \"ed\" (event date) if the fact describes something that happened at a specific time.\n - \"User went to the gym on May 7\" \u2192 ed: \"2023-05-07\"\n - \"User prefers dark mode\" \u2192 ed: null (timeless preference)\n - If only a month is mentioned (e.g., \"in March 2026\") and today IS in that month, use TODAY's date from the header.\n - If only a month is mentioned and it's a PAST month, use the 15th as midpoint.\n Set \"dd\" (document date) to today's date from the header for ALL facts \u2014 this is when the conversation happened.\n\n9. PATTERN DETECTION: If the text reveals a recurring behavior, preference, routine, or coping strategy, extract it as a pattern fact with higher importance (0.7-0.9).\n - \"I always procrastinate on Mondays\" \u2192 {\"t\": \"User tends to procrastinate on Mondays\", \"i\": 0.8, \"ed\": null, \"dd\": \"...\", \"p\": true}\n - \"Coffee helps me focus\" \u2192 {\"t\": \"User finds that coffee helps with focus\", \"i\": 0.7, \"ed\": null, \"dd\": \"...\", \"p\": true}\n Patterns are behavioral insights \u2014 routines, coping strategies, energy patterns, recurring struggles.\n Mark patterns with \"p\": true in the output. Regular facts use \"p\": false.\n\n## OUTPUT\n\nReturn ONLY a JSON object:\n{\"facts\": [{\"t\": \"fact text here\", \"i\": 0.7, \"ed\": \"2023-05-07\", \"dd\": \"2023-05-08\", \"p\": false}, {\"t\": \"another fact\", \"i\": 0.3, \"ed\": null, \"dd\": \"2023-05-08\", \"p\": false}]}\n\n- ed (eventDate): ISO date string of WHEN the event occurred, or null if not temporal\n- dd (documentDate): ISO date string of when the conversation took place, from context header\n\nScore importance (i) from 0.0 to 1.0:\n- 0.9-1.0: Identity, health conditions, allergies, life events (birth, marriage, death)\n- 0.7-0.8: Relationships, employment, education, strong preferences, plans\n- 0.4-0.6: Activities, opinions, moderate preferences, daily events\n- 0.1-0.3: Casual mentions, weather, trivial observations\n\nNothing else. No explanation, no markdown.";
|
|
4
|
-
export declare const GRAPH_EXTRACTION_PROMPT = "You are a knowledge graph builder. Given a list of facts about a person, extract entities and relationships.\n\n## ENTITIES\n\nExtract only IMPORTANT named entities \u2014 proper nouns and specific things worth remembering. Aim for 3-8 entities total, not 40.\n\nDO extract: People (Casey, Jamie), Organizations (Brightwell Capital), Places (Harbor Point), Products/Projects (LifePath, AirPods Max), Named activities (Catan, D&D)\nDO NOT extract: Generic nouns (team, boss, meeting, work, food, gym), abstract concepts (motivation, stress), common objects (pizza, chair, phone)\n\n## RELATIONSHIPS\n\nExtract relationships between entities. Be SMART \u2014 infer from context:\n- \"User works at Google\" \u2192 user works_at google\n- \"User loves Casey, plans to propose\" \u2192 user partner_of casey\n- \"User's friend Jamie came over\" \u2192 user friend_of jamie\n\nUse snake_case relation names: works_at, partner_of, friend_of, lives_in, uses, studies, prefers, etc.\n\n## OUTPUT\n\nReturn ONLY a JSON object:\n{\n \"entities\": [\n {\"name\": \"Casey\", \"entity_type\": \"person\"},\n {\"name\": \"Brightwell Capital\", \"entity_type\": \"organization\"}\n ],\n \"edges\": [\n {\"source\": \"user\", \"target\": \"casey\", \"relation\": \"partner_of\"},\n {\"source\": \"user\", \"target\": \"brightwell capital\", \"relation\": \"works_at\"}\n ]\n}\n\nentity_type must be one of: {ENTITY_TYPES}.\nEntity names must be clean: no punctuation, no articles, no sentence fragments.\nReturn ONLY valid JSON.";
|
|
5
|
-
export declare const DEFAULT_ENTITY_TYPES: string[];
|
|
6
|
-
export declare const DEDUP_PROMPT = "You are a memory deduplication engine. Given NEW facts and EXISTING facts in a memory store, classify each new fact.\n\nFor each new fact, decide:\n- ADD: entirely new information, not covered by existing facts\n- UPDATE: replaces or refines an existing fact (provide the index). The new fact SUPERSEDES the old one.\n- EXTEND: adds new detail to an existing fact WITHOUT contradicting it (provide the index)\n- NOOP: already covered by an existing fact \u2014 skip it\n- CONTRADICT: conflicts with an existing fact (provide the index)\n\nReturn a JSON array:\n[\n {\"fact\": \"...\", \"operation\": \"ADD\"},\n {\"fact\": \"...\", \"operation\": \"UPDATE\", \"existing_index\": 3},\n {\"fact\": \"...\", \"operation\": \"EXTEND\", \"existing_index\": 5},\n {\"fact\": \"...\", \"operation\": \"NOOP\"},\n {\"fact\": \"...\", \"operation\": \"CONTRADICT\", \"existing_index\": 7}\n]\n\nBe conservative: prefer NOOP over ADD if the information is substantially similar.\nPrefer EXTEND over UPDATE when the new fact adds detail without changing the core meaning.";
|
|
7
|
-
export interface ExistingFact {
|
|
8
|
-
lineage_id: string;
|
|
9
|
-
content: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Build the fact extraction prompt (Pass 1).
|
|
13
|
-
* Simple: extract facts as strings.
|
|
14
|
-
*/
|
|
15
|
-
export declare function buildFactExtractionPrompt(input: string): LLMMessage[];
|
|
16
|
-
/**
|
|
17
|
-
* Build the graph extraction prompt (Pass 2).
|
|
18
|
-
* Takes extracted facts and produces entities + edges.
|
|
19
|
-
*/
|
|
20
|
-
export declare function buildGraphExtractionPrompt(facts: string[], entityTypes?: string[], domainEntityTypes?: DomainEntityType[]): LLMMessage[];
|
|
21
|
-
/**
|
|
22
|
-
* Build the dedup prompt.
|
|
23
|
-
* Compares new facts against existing facts.
|
|
24
|
-
*/
|
|
25
|
-
export declare function buildDedupPrompt(newFacts: string[], existingFacts: ExistingFact[]): LLMMessage[];
|
|
26
|
-
export declare const EXTRACTION_SYSTEM_PROMPT = "You are a memory extraction engine. Extract facts from text for a personal AI memory system.\n\n## WHO IS \"USER\"?\n\nMessages labeled \"user\" are from THE PERSON whose memories we are storing.\nMessages labeled \"assistant\" or any other role are from OTHER people.\n\nCRITICAL: Focus on facts FROM \"user\" messages, but ALSO extract notable facts about other people mentioned in the conversation. If the assistant/conversation partner shares personal information (e.g., \"I painted a sunrise last year\", \"I realized self-care is important\"), store it as \"User's conversation partner [Name] painted a sunrise in [year]\".\n\nFor identity/trait facts, state them DIRECTLY:\n- \"User is a transgender woman\" (not just \"User went to a transgender conference\")\n- \"User works at Brightwell Capital\" (not just \"User had a busy day at work\")\n- \"User is researching adoption agencies\" (not just \"User attended a meeting about adoption\")\n\n## RULES\n\n1. Extract SELF-CONTAINED atomic facts. Each fact must be understandable on its own, without the original conversation.\n\n2. **DATES ARE CRITICAL** \u2014 Resolve ALL temporal references to exact dates:\n - \"yesterday\" \u2192 \"on 7 May 2023\"\n - \"last week\" \u2192 \"around 1 May 2023\"\n - \"recently\" \u2192 \"in early May 2023\"\n - Look for date context like \"[This conversation took place on 8 May, 2023]\" and resolve ALL relative dates from it.\n - EVERY event/activity fact MUST include WHEN it happened if the date can be inferred.\n - BAD: \"User went to an LGBTQ support group\"\n - GOOD: \"User went to an LGBTQ support group on 7 May 2023\"\n\n3. Resolve ALL other references:\n - Pronouns \u2192 names: \"she said\" \u2192 \"Casey said\"\n - Places \u2192 full names: \"there\" \u2192 \"at Brightwell Capital\"\n\n4. Be SPECIFIC, not vague:\n BAD: \"User had issues at work\"\n GOOD: \"User's team at Brightwell Capital rambles too much in meetings\"\n\n5. Extract ALL facts, even minor ones. You cannot predict what will be asked later.\n\n6. Write all facts in third person using \"User\" (e.g., \"User prefers dark mode\").\n\n7. For conversation partners: ALSO extract their facts with their name.\n - If Melanie says \"I painted a sunrise last year\" \u2192 \"Melanie painted a sunrise in 2022\"\n - If Melanie says \"I ran a charity race\" \u2192 \"Melanie ran a charity race\"\n\n8. For EVERY fact, include \"ed\" (event date) if the fact describes something that happened at a specific time.\n - \"User went to the gym on May 7\" \u2192 ed: \"2023-05-07\"\n - \"User prefers dark mode\" \u2192 ed: null (timeless preference)\n - If only a month is mentioned (e.g., \"in March 2026\") and today IS in that month, use TODAY's date from the header.\n - If only a month is mentioned and it's a PAST month, use the 15th as midpoint.\n Set \"dd\" (document date) to today's date from the header for ALL facts \u2014 this is when the conversation happened.\n\n9. PATTERN DETECTION: If the text reveals a recurring behavior, preference, routine, or coping strategy, extract it as a pattern fact with higher importance (0.7-0.9).\n - \"I always procrastinate on Mondays\" \u2192 {\"t\": \"User tends to procrastinate on Mondays\", \"i\": 0.8, \"ed\": null, \"dd\": \"...\", \"p\": true}\n - \"Coffee helps me focus\" \u2192 {\"t\": \"User finds that coffee helps with focus\", \"i\": 0.7, \"ed\": null, \"dd\": \"...\", \"p\": true}\n Patterns are behavioral insights \u2014 routines, coping strategies, energy patterns, recurring struggles.\n Mark patterns with \"p\": true in the output. Regular facts use \"p\": false.\n\n## OUTPUT\n\nReturn ONLY a JSON object:\n{\"facts\": [{\"t\": \"fact text here\", \"i\": 0.7, \"ed\": \"2023-05-07\", \"dd\": \"2023-05-08\", \"p\": false}, {\"t\": \"another fact\", \"i\": 0.3, \"ed\": null, \"dd\": \"2023-05-08\", \"p\": false}]}\n\n- ed (eventDate): ISO date string of WHEN the event occurred, or null if not temporal\n- dd (documentDate): ISO date string of when the conversation took place, from context header\n\nScore importance (i) from 0.0 to 1.0:\n- 0.9-1.0: Identity, health conditions, allergies, life events (birth, marriage, death)\n- 0.7-0.8: Relationships, employment, education, strong preferences, plans\n- 0.4-0.6: Activities, opinions, moderate preferences, daily events\n- 0.1-0.3: Casual mentions, weather, trivial observations\n\nNothing else. No explanation, no markdown.";
|
|
27
|
-
export declare function buildExtractionPrompt(input: string, existingFacts?: ExistingFact[]): LLMMessage[];
|
|
28
|
-
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,eAAO,MAAM,sBAAsB,y3IAsEQ,CAAC;AAM5C,eAAO,MAAM,uBAAuB,6/CAkCZ,CAAC;AAEzB,eAAO,MAAM,oBAAoB,UAA2E,CAAC;AAM7G,eAAO,MAAM,YAAY,8iCAmBkE,CAAC;AAM5F,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAMrE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,GACrC,UAAU,EAAE,CA4Bd;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,UAAU,EAAE,CAOhG;AAMD,eAAO,MAAM,wBAAwB,y3IAAyB,CAAC;AAE/D,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,YAAY,EAAE,GAC7B,UAAU,EAAE,CAcd"}
|