@kybernesis/brain-core 0.1.0

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 (129) hide show
  1. package/dist/claude-call.d.ts +37 -0
  2. package/dist/claude-call.d.ts.map +1 -0
  3. package/dist/claude-call.js +55 -0
  4. package/dist/claude-call.js.map +1 -0
  5. package/dist/entity-graph.d.ts +79 -0
  6. package/dist/entity-graph.d.ts.map +1 -0
  7. package/dist/entity-graph.js +611 -0
  8. package/dist/entity-graph.js.map +1 -0
  9. package/dist/fact-contradiction.d.ts +25 -0
  10. package/dist/fact-contradiction.d.ts.map +1 -0
  11. package/dist/fact-contradiction.js +109 -0
  12. package/dist/fact-contradiction.js.map +1 -0
  13. package/dist/fact-extractor.d.ts +26 -0
  14. package/dist/fact-extractor.d.ts.map +1 -0
  15. package/dist/fact-extractor.js +98 -0
  16. package/dist/fact-extractor.js.map +1 -0
  17. package/dist/fact-retrieval.d.ts +51 -0
  18. package/dist/fact-retrieval.d.ts.map +1 -0
  19. package/dist/fact-retrieval.js +401 -0
  20. package/dist/fact-retrieval.js.map +1 -0
  21. package/dist/fact-store.d.ts +26 -0
  22. package/dist/fact-store.d.ts.map +1 -0
  23. package/dist/fact-store.js +181 -0
  24. package/dist/fact-store.js.map +1 -0
  25. package/dist/fact-temporal.d.ts +20 -0
  26. package/dist/fact-temporal.d.ts.map +1 -0
  27. package/dist/fact-temporal.js +79 -0
  28. package/dist/fact-temporal.js.map +1 -0
  29. package/dist/fts-sanitizer.d.ts +32 -0
  30. package/dist/fts-sanitizer.d.ts.map +1 -0
  31. package/dist/fts-sanitizer.js +61 -0
  32. package/dist/fts-sanitizer.js.map +1 -0
  33. package/dist/hybrid-search.d.ts +44 -0
  34. package/dist/hybrid-search.d.ts.map +1 -0
  35. package/dist/hybrid-search.js +410 -0
  36. package/dist/hybrid-search.js.map +1 -0
  37. package/dist/index.d.ts +33 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +19 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/ops.d.ts +28 -0
  42. package/dist/ops.d.ts.map +1 -0
  43. package/dist/ops.js +307 -0
  44. package/dist/ops.js.map +1 -0
  45. package/dist/queue.d.ts +13 -0
  46. package/dist/queue.d.ts.map +1 -0
  47. package/dist/queue.js +28 -0
  48. package/dist/queue.js.map +1 -0
  49. package/dist/relationship-extractor.d.ts +38 -0
  50. package/dist/relationship-extractor.d.ts.map +1 -0
  51. package/dist/relationship-extractor.js +119 -0
  52. package/dist/relationship-extractor.js.map +1 -0
  53. package/dist/sleep/config.d.ts +47 -0
  54. package/dist/sleep/config.d.ts.map +1 -0
  55. package/dist/sleep/config.js +46 -0
  56. package/dist/sleep/config.js.map +1 -0
  57. package/dist/sleep/db.d.ts +16 -0
  58. package/dist/sleep/db.d.ts.map +1 -0
  59. package/dist/sleep/db.js +114 -0
  60. package/dist/sleep/db.js.map +1 -0
  61. package/dist/sleep/index.d.ts +69 -0
  62. package/dist/sleep/index.d.ts.map +1 -0
  63. package/dist/sleep/index.js +99 -0
  64. package/dist/sleep/index.js.map +1 -0
  65. package/dist/sleep/steps/consolidate.d.ts +19 -0
  66. package/dist/sleep/steps/consolidate.d.ts.map +1 -0
  67. package/dist/sleep/steps/consolidate.js +74 -0
  68. package/dist/sleep/steps/consolidate.js.map +1 -0
  69. package/dist/sleep/steps/decay.d.ts +19 -0
  70. package/dist/sleep/steps/decay.d.ts.map +1 -0
  71. package/dist/sleep/steps/decay.js +121 -0
  72. package/dist/sleep/steps/decay.js.map +1 -0
  73. package/dist/sleep/steps/entity-hygiene.d.ts +29 -0
  74. package/dist/sleep/steps/entity-hygiene.d.ts.map +1 -0
  75. package/dist/sleep/steps/entity-hygiene.js +452 -0
  76. package/dist/sleep/steps/entity-hygiene.js.map +1 -0
  77. package/dist/sleep/steps/link.d.ts +20 -0
  78. package/dist/sleep/steps/link.d.ts.map +1 -0
  79. package/dist/sleep/steps/link.js +216 -0
  80. package/dist/sleep/steps/link.js.map +1 -0
  81. package/dist/sleep/steps/observe.d.ts +17 -0
  82. package/dist/sleep/steps/observe.d.ts.map +1 -0
  83. package/dist/sleep/steps/observe.js +192 -0
  84. package/dist/sleep/steps/observe.js.map +1 -0
  85. package/dist/sleep/steps/profile.d.ts +15 -0
  86. package/dist/sleep/steps/profile.d.ts.map +1 -0
  87. package/dist/sleep/steps/profile.js +26 -0
  88. package/dist/sleep/steps/profile.js.map +1 -0
  89. package/dist/sleep/steps/reasoning.d.ts +19 -0
  90. package/dist/sleep/steps/reasoning.d.ts.map +1 -0
  91. package/dist/sleep/steps/reasoning.js +173 -0
  92. package/dist/sleep/steps/reasoning.js.map +1 -0
  93. package/dist/sleep/steps/summarize.d.ts +21 -0
  94. package/dist/sleep/steps/summarize.d.ts.map +1 -0
  95. package/dist/sleep/steps/summarize.js +206 -0
  96. package/dist/sleep/steps/summarize.js.map +1 -0
  97. package/dist/sleep/steps/tag.d.ts +16 -0
  98. package/dist/sleep/steps/tag.d.ts.map +1 -0
  99. package/dist/sleep/steps/tag.js +84 -0
  100. package/dist/sleep/steps/tag.js.map +1 -0
  101. package/dist/sleep/steps/tier.d.ts +18 -0
  102. package/dist/sleep/steps/tier.d.ts.map +1 -0
  103. package/dist/sleep/steps/tier.js +112 -0
  104. package/dist/sleep/steps/tier.js.map +1 -0
  105. package/dist/sleep/utils/checkpoint.d.ts +11 -0
  106. package/dist/sleep/utils/checkpoint.d.ts.map +1 -0
  107. package/dist/sleep/utils/checkpoint.js +26 -0
  108. package/dist/sleep/utils/checkpoint.js.map +1 -0
  109. package/dist/sleep/utils/jaccard.d.ts +7 -0
  110. package/dist/sleep/utils/jaccard.d.ts.map +1 -0
  111. package/dist/sleep/utils/jaccard.js +19 -0
  112. package/dist/sleep/utils/jaccard.js.map +1 -0
  113. package/dist/store-conversation.d.ts +29 -0
  114. package/dist/store-conversation.d.ts.map +1 -0
  115. package/dist/store-conversation.js +227 -0
  116. package/dist/store-conversation.js.map +1 -0
  117. package/dist/timeline.d.ts +50 -0
  118. package/dist/timeline.d.ts.map +1 -0
  119. package/dist/timeline.js +389 -0
  120. package/dist/timeline.js.map +1 -0
  121. package/dist/user-profile.d.ts +30 -0
  122. package/dist/user-profile.d.ts.map +1 -0
  123. package/dist/user-profile.js +147 -0
  124. package/dist/user-profile.js.map +1 -0
  125. package/dist/vectors.d.ts +56 -0
  126. package/dist/vectors.d.ts.map +1 -0
  127. package/dist/vectors.js +132 -0
  128. package/dist/vectors.js.map +1 -0
  129. package/package.json +53 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Fact contradiction detection — port of KAD's fact-contradiction.ts.
3
+ *
4
+ * When new facts are stored, checks if they contradict existing facts
5
+ * for the same entities. Uses Claude Haiku for semantic comparison.
6
+ */
7
+ import type { TenantContext } from '@kybernesis/brain-contracts';
8
+ export interface ContradictionResult {
9
+ contradictions: Array<{
10
+ oldFactId: number;
11
+ relationship: 'updates' | 'extends';
12
+ rationale: string;
13
+ }>;
14
+ checked: number;
15
+ }
16
+ /**
17
+ * Detect contradictions between a new fact and existing facts for the same
18
+ * entities. Returns which existing facts are updated or extended by the new one.
19
+ */
20
+ export declare function detectContradictions(t: TenantContext, newFact: {
21
+ content: string;
22
+ entities: string[];
23
+ category: string;
24
+ }): Promise<ContradictionResult>;
25
+ //# sourceMappingURL=fact-contradiction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-contradiction.d.ts","sourceRoot":"","sources":["../src/fact-contradiction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKjE,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,KAAK,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;QACpC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAsBD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,CAAC,EAAE,aAAa,EAChB,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjE,OAAO,CAAC,mBAAmB,CAAC,CAmF9B"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Fact contradiction detection — port of KAD's fact-contradiction.ts.
3
+ *
4
+ * When new facts are stored, checks if they contradict existing facts
5
+ * for the same entities. Uses Claude Haiku for semantic comparison.
6
+ */
7
+ import { getFactsForEntity } from './fact-store.js';
8
+ import { callClaude } from './claude-call.js';
9
+ const RELATED_CATEGORIES = {
10
+ biographical: new Set(['biographical']),
11
+ preference: new Set(['preference']),
12
+ event: new Set(['event', 'temporal']),
13
+ relationship: new Set(['relationship']),
14
+ temporal: new Set(['event', 'temporal']),
15
+ opinion: new Set(['opinion']),
16
+ plan: new Set(['plan']),
17
+ general: new Set([
18
+ 'biographical', 'preference', 'event', 'relationship',
19
+ 'temporal', 'opinion', 'plan', 'general',
20
+ ]),
21
+ };
22
+ function areCategoriesRelated(a, b) {
23
+ const related = RELATED_CATEGORIES[a];
24
+ if (!related)
25
+ return true;
26
+ return related.has(b);
27
+ }
28
+ /**
29
+ * Detect contradictions between a new fact and existing facts for the same
30
+ * entities. Returns which existing facts are updated or extended by the new one.
31
+ */
32
+ export async function detectContradictions(t, newFact) {
33
+ if (!newFact.entities || newFact.entities.length === 0) {
34
+ return { contradictions: [], checked: 0 };
35
+ }
36
+ const candidateMap = new Map();
37
+ for (const entity of newFact.entities) {
38
+ try {
39
+ const facts = await getFactsForEntity(t, entity, { latestOnly: true, limit: 20 });
40
+ for (const fact of facts)
41
+ candidateMap.set(fact.id, fact);
42
+ }
43
+ catch (err) {
44
+ console.warn(`[brain-core/fact-contradiction] fetch failed for "${entity}"`, { err: String(err) });
45
+ }
46
+ }
47
+ const candidates = Array.from(candidateMap.values()).filter((f) => areCategoriesRelated(newFact.category, f.category));
48
+ if (candidates.length === 0)
49
+ return { contradictions: [], checked: 0 };
50
+ const toCheck = candidates.slice(0, 10);
51
+ try {
52
+ const existingList = toCheck
53
+ .map((f, i) => `${i + 1}. "${f.content}" (id=${f.id})`)
54
+ .join('\n');
55
+ const prompt = `Given a NEW fact and a list of EXISTING facts about the same person/entity, determine if the new fact contradicts (updates/replaces) any existing fact.
56
+
57
+ NEW FACT: "${newFact.content}"
58
+
59
+ EXISTING FACTS:
60
+ ${existingList}
61
+
62
+ For each existing fact, determine:
63
+ - "updates" — the new fact replaces this (e.g., "favorite color is green" updates "favorite color is blue")
64
+ - "extends" — the new fact adds detail without contradicting (e.g., "lives in Brooklyn" extends "lives in NYC")
65
+ - "none" — no relationship
66
+
67
+ Return JSON array:
68
+ [{"id": 42, "relationship": "updates", "rationale": "favorite color changed"}]
69
+
70
+ Only include facts with "updates" or "extends" relationship. Return [] if no relationships found.`;
71
+ const response = await callClaude(prompt, { maxTokens: 512 });
72
+ if (!response)
73
+ return { contradictions: [], checked: toCheck.length };
74
+ const jsonMatch = response.match(/\[[\s\S]*?\]/);
75
+ if (!jsonMatch)
76
+ return { contradictions: [], checked: toCheck.length };
77
+ let parsed;
78
+ try {
79
+ parsed = JSON.parse(jsonMatch[0]);
80
+ if (!Array.isArray(parsed))
81
+ return { contradictions: [], checked: toCheck.length };
82
+ }
83
+ catch {
84
+ return { contradictions: [], checked: toCheck.length };
85
+ }
86
+ const validIds = new Set(toCheck.map((f) => f.id));
87
+ const contradictions = parsed
88
+ .filter((item) => {
89
+ if (!item || typeof item !== 'object')
90
+ return false;
91
+ const o = item;
92
+ return (typeof o['id'] === 'number' &&
93
+ validIds.has(o['id']) &&
94
+ (o['relationship'] === 'updates' || o['relationship'] === 'extends') &&
95
+ typeof o['rationale'] === 'string');
96
+ })
97
+ .map((item) => ({
98
+ oldFactId: item.id,
99
+ relationship: item.relationship,
100
+ rationale: item.rationale,
101
+ }));
102
+ return { contradictions, checked: toCheck.length };
103
+ }
104
+ catch (err) {
105
+ console.warn('[brain-core/fact-contradiction] detection failed', { err: String(err) });
106
+ return { contradictions: [], checked: toCheck.length };
107
+ }
108
+ }
109
+ //# sourceMappingURL=fact-contradiction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-contradiction.js","sourceRoot":"","sources":["../src/fact-contradiction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Real-time fact extraction — port of KAD's fact-extractor.ts.
3
+ *
4
+ * Lightweight inline extraction that runs after a conversation is stored.
5
+ * Haiku-backed, capped at 3 facts per call to keep latency low.
6
+ */
7
+ import type { TenantContext } from '@kybernesis/brain-contracts';
8
+ /**
9
+ * Extract facts from a conversation in real-time (best-effort).
10
+ * Called after entity graph storage in storeConversation().
11
+ * Never throws — all errors are caught and logged.
12
+ */
13
+ export declare function extractFactsRealtime(t: TenantContext, conversationId: string, text: string, options?: {
14
+ entities?: string[];
15
+ sourcePath?: string;
16
+ timestamp?: string;
17
+ sourceType?: string;
18
+ arpMetadata?: {
19
+ project_id?: string;
20
+ tags?: string[];
21
+ classification?: 'public' | 'internal' | 'confidential' | 'pii';
22
+ connection_id?: string;
23
+ source_did?: string;
24
+ };
25
+ }): Promise<number>;
26
+ //# sourceMappingURL=fact-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-extractor.d.ts","sourceRoot":"","sources":["../src/fact-extractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AA0BjE;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,CAAC,EAAE,aAAa,EAChB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,cAAc,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,KAAK,CAAC;QAChE,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACE,GACL,OAAO,CAAC,MAAM,CAAC,CAgFjB"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Real-time fact extraction — port of KAD's fact-extractor.ts.
3
+ *
4
+ * Lightweight inline extraction that runs after a conversation is stored.
5
+ * Haiku-backed, capped at 3 facts per call to keep latency low.
6
+ */
7
+ import { SOURCE_CONFIDENCE } from '@kybernesis/brain-contracts';
8
+ import { storeFact, ensureFactsTable } from './fact-store.js';
9
+ import { detectTemporalExpiry } from './fact-temporal.js';
10
+ import { callClaude } from './claude-call.js';
11
+ const VALID_CATEGORIES = new Set([
12
+ 'biographical', 'preference', 'event', 'relationship',
13
+ 'temporal', 'opinion', 'plan', 'general',
14
+ ]);
15
+ const REALTIME_FACT_PROMPT = `Extract 1-3 concrete facts about specific people, companies, or projects from this conversation. Only clear, verifiable facts — skip vague observations, greetings, and meta-commentary.
16
+
17
+ Each fact object has:
18
+ - "content": The fact statement (8-25 words, include names not pronouns)
19
+ - "category": One of: biographical, preference, event, relationship, temporal, opinion, plan, general
20
+ - "confidence": 0.5-0.9 (how confident you are)
21
+ - "entities": Array of person/entity names
22
+
23
+ Return a JSON array, or [] if no concrete facts.
24
+
25
+ Conversation:
26
+ `;
27
+ /**
28
+ * Extract facts from a conversation in real-time (best-effort).
29
+ * Called after entity graph storage in storeConversation().
30
+ * Never throws — all errors are caught and logged.
31
+ */
32
+ export async function extractFactsRealtime(t, conversationId, text, options = {}) {
33
+ const { entities = [], sourcePath = `realtime://${conversationId}`, timestamp = new Date().toISOString(), sourceType = 'chat', arpMetadata, } = options;
34
+ // Guard: skip short conversations or those with no entities
35
+ if (text.length < 50 || entities.length === 0)
36
+ return 0;
37
+ await ensureFactsTable(t);
38
+ let factsCreated = 0;
39
+ try {
40
+ const content = text.slice(0, 2000);
41
+ const response = await callClaude(REALTIME_FACT_PROMPT + content, { maxTokens: 256 });
42
+ if (!response)
43
+ return 0;
44
+ const jsonMatch = response.match(/\[[\s\S]*\]/);
45
+ if (!jsonMatch)
46
+ return 0;
47
+ let rawFacts;
48
+ try {
49
+ const parsed = JSON.parse(jsonMatch[0]);
50
+ if (!Array.isArray(parsed))
51
+ return 0;
52
+ rawFacts = parsed;
53
+ }
54
+ catch (err) {
55
+ console.warn('[brain-core/fact-extractor] JSON parse failed', { err: String(err) });
56
+ return 0;
57
+ }
58
+ const parentId = sourcePath.replace('channel://', '');
59
+ const maxConfidence = SOURCE_CONFIDENCE[sourceType] ?? 0.85;
60
+ for (const [i, fact] of rawFacts.slice(0, 3).entries()) {
61
+ if (!fact.content || fact.content.length < 10 || fact.content.length > 200)
62
+ continue;
63
+ if (!fact.entities || fact.entities.length === 0)
64
+ continue;
65
+ const category = VALID_CATEGORIES.has(fact.category) ? fact.category : 'general';
66
+ const confidence = Math.min(fact.confidence || 0.6, maxConfidence, 0.60);
67
+ const temporal = detectTemporalExpiry(fact.content, timestamp);
68
+ const factInput = {
69
+ content: fact.content,
70
+ sourcePath: `realtime://${parentId}/${i}`,
71
+ sourceConversationId: parentId,
72
+ entities: fact.entities,
73
+ timestamp,
74
+ confidence,
75
+ category: category,
76
+ sourceType: 'ai-extraction',
77
+ ...(temporal.expires_at ? { expiresAt: temporal.expires_at } : {}),
78
+ ...(arpMetadata?.project_id ? { projectId: arpMetadata.project_id } : {}),
79
+ tags: arpMetadata?.tags ?? [],
80
+ ...(arpMetadata?.classification ? { classification: arpMetadata.classification } : {}),
81
+ ...(arpMetadata?.connection_id ? { connectionId: arpMetadata.connection_id } : {}),
82
+ ...(arpMetadata?.source_did ? { sourceDid: arpMetadata.source_did } : {}),
83
+ };
84
+ try {
85
+ await storeFact(t, factInput);
86
+ factsCreated++;
87
+ }
88
+ catch {
89
+ // Individual fact storage is best-effort
90
+ }
91
+ }
92
+ }
93
+ catch (err) {
94
+ console.warn('[brain-core/fact-extractor] extraction skipped', { error: String(err) });
95
+ }
96
+ return factsCreated;
97
+ }
98
+ //# sourceMappingURL=fact-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-extractor.js","sourceRoot":"","sources":["../src/fact-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Fact-first retrieval engine — port of KAD's fact-retrieval.ts.
3
+ *
4
+ * 4-layer retrieval:
5
+ * Layer 1: Direct FTS5 + semantic search on facts
6
+ * Layer 2: Entity expansion (1-3 hop BFS graph traversal)
7
+ * Layer 2.5: Scene expansion + bridge discovery
8
+ * Layer 3: Supporting context (source conversation segments)
9
+ * Layer 4: Context optimization (prune to token budget, deduplicate)
10
+ *
11
+ * Bug Fix #2 applied here: uses sanitizeFtsQuery for all FTS MATCH calls.
12
+ * Bug Fix #9 applied here: wordMatchRatio denominator is FTS-query token count.
13
+ */
14
+ import type { TenantContext } from '@kybernesis/brain-contracts';
15
+ export interface FactSearchOptions {
16
+ limit?: number;
17
+ tokenBudget?: number;
18
+ includeSupporting?: boolean;
19
+ maxSupportingPerFact?: number;
20
+ }
21
+ export interface FactSearchResult {
22
+ facts: Array<{
23
+ id: number;
24
+ content: string;
25
+ category: string;
26
+ confidence: number;
27
+ timestamp: string;
28
+ entities: string[];
29
+ score: number;
30
+ source: 'direct' | 'entity_expansion' | 'graph_expansion' | 'scene_expansion' | 'bridge';
31
+ }>;
32
+ supporting_context: Array<{
33
+ content: string;
34
+ source_path: string;
35
+ timestamp: string;
36
+ related_fact_id: number;
37
+ }>;
38
+ assembled_context: string;
39
+ token_estimate: number;
40
+ stats: {
41
+ direct_facts: number;
42
+ expanded_facts: number;
43
+ graph_expanded_facts: number;
44
+ scene_expanded_facts: number;
45
+ bridge_facts: number;
46
+ supporting_chunks: number;
47
+ pruned_items: number;
48
+ };
49
+ }
50
+ export declare function factFirstSearch(t: TenantContext, query: string, options?: FactSearchOptions): Promise<FactSearchResult>;
51
+ //# sourceMappingURL=fact-retrieval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fact-retrieval.d.ts","sourceRoot":"","sources":["../src/fact-retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAMjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,QAAQ,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,QAAQ,CAAC;KAC1F,CAAC,CAAC;IACH,kBAAkB,EAAE,KAAK,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAgUD,wBAAsB,eAAe,CACnC,CAAC,EAAE,aAAa,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CA4I3B"}