@steno-ai/engine 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/adapters/storage.d.ts +1 -0
  2. package/dist/adapters/storage.d.ts.map +1 -1
  3. package/dist/extraction/llm-extractor.d.ts.map +1 -1
  4. package/dist/extraction/llm-extractor.js +5 -3
  5. package/dist/extraction/llm-extractor.js.map +1 -1
  6. package/dist/extraction/pipeline.d.ts.map +1 -1
  7. package/dist/extraction/pipeline.js +5 -1
  8. package/dist/extraction/pipeline.js.map +1 -1
  9. package/dist/extraction/prompts.d.ts +2 -2
  10. package/dist/extraction/prompts.d.ts.map +1 -1
  11. package/dist/extraction/prompts.js +12 -3
  12. package/dist/extraction/prompts.js.map +1 -1
  13. package/package.json +6 -2
  14. package/src/adapters/cache.js +2 -0
  15. package/src/adapters/embedding.js +2 -0
  16. package/src/adapters/llm.js +2 -0
  17. package/src/adapters/perplexity-embedding.js +78 -0
  18. package/src/adapters/storage.js +2 -0
  19. package/src/adapters/storage.ts +1 -0
  20. package/src/config.d.ts +211 -1
  21. package/src/config.d.ts.map +1 -1
  22. package/src/config.js +92 -0
  23. package/src/config.js.map +1 -1
  24. package/src/extraction/contradiction.js +23 -0
  25. package/src/extraction/dedup.js +93 -0
  26. package/src/extraction/dedup.js.map +1 -1
  27. package/src/extraction/entity-extractor.d.ts.map +1 -1
  28. package/src/extraction/entity-extractor.js +145 -0
  29. package/src/extraction/entity-extractor.js.map +1 -1
  30. package/src/extraction/hasher.js +8 -0
  31. package/src/extraction/heuristic.js +282 -0
  32. package/src/extraction/llm-extractor.d.ts +3 -1
  33. package/src/extraction/llm-extractor.d.ts.map +1 -1
  34. package/src/extraction/llm-extractor.js +238 -0
  35. package/src/extraction/llm-extractor.js.map +1 -1
  36. package/src/extraction/llm-extractor.ts +7 -5
  37. package/src/extraction/pipeline.d.ts +3 -0
  38. package/src/extraction/pipeline.d.ts.map +1 -1
  39. package/src/extraction/pipeline.js +398 -0
  40. package/src/extraction/pipeline.js.map +1 -1
  41. package/src/extraction/pipeline.ts +6 -1
  42. package/src/extraction/prompts.d.ts +28 -0
  43. package/src/extraction/prompts.d.ts.map +1 -0
  44. package/src/extraction/prompts.js +196 -0
  45. package/src/extraction/prompts.js.map +1 -1
  46. package/src/extraction/prompts.ts +12 -3
  47. package/src/extraction/sliding-window.js +84 -0
  48. package/src/extraction/sliding-window.js.map +1 -1
  49. package/src/extraction/types.d.ts +12 -0
  50. package/src/extraction/types.d.ts.map +1 -1
  51. package/src/extraction/types.js +2 -0
  52. package/src/feedback/tracker.js +90 -0
  53. package/src/models/api-key.d.ts +2 -2
  54. package/src/models/api-key.js +21 -0
  55. package/src/models/edge.d.ts +6 -6
  56. package/src/models/edge.js +29 -0
  57. package/src/models/entity.d.ts +2 -2
  58. package/src/models/entity.js +22 -0
  59. package/src/models/extraction.d.ts +6 -6
  60. package/src/models/extraction.js +40 -0
  61. package/src/models/fact-entity.js +14 -0
  62. package/src/models/fact.d.ts +191 -0
  63. package/src/models/fact.d.ts.map +1 -0
  64. package/src/models/fact.js +72 -0
  65. package/src/models/fact.js.map +1 -0
  66. package/src/models/index.js +13 -0
  67. package/src/models/memory-access.d.ts +4 -4
  68. package/src/models/memory-access.js +33 -0
  69. package/src/models/session.js +23 -0
  70. package/src/models/tenant.d.ts +248 -14
  71. package/src/models/tenant.d.ts.map +1 -1
  72. package/src/models/tenant.js +23 -0
  73. package/src/models/trigger.d.ts +5 -5
  74. package/src/models/trigger.js +41 -0
  75. package/src/models/usage-record.js +14 -0
  76. package/src/models/webhook.d.ts +1 -1
  77. package/src/models/webhook.js +25 -0
  78. package/src/retrieval/compound-search.d.ts.map +1 -1
  79. package/src/retrieval/compound-search.js +87 -0
  80. package/src/retrieval/compound-search.js.map +1 -1
  81. package/src/retrieval/contradiction-surfacer.js +64 -0
  82. package/src/retrieval/embedding-cache.js +56 -0
  83. package/src/retrieval/fusion.d.ts +1 -0
  84. package/src/retrieval/fusion.d.ts.map +1 -1
  85. package/src/retrieval/fusion.js +87 -0
  86. package/src/retrieval/fusion.js.map +1 -1
  87. package/src/retrieval/graph-traversal.d.ts +2 -1
  88. package/src/retrieval/graph-traversal.d.ts.map +1 -1
  89. package/src/retrieval/graph-traversal.js +208 -0
  90. package/src/retrieval/graph-traversal.js.map +1 -1
  91. package/src/retrieval/query-expansion.js +76 -0
  92. package/src/retrieval/reranker.js +47 -0
  93. package/src/retrieval/salience-scorer.js +41 -0
  94. package/src/retrieval/search.d.ts.map +1 -1
  95. package/src/retrieval/search.js +228 -0
  96. package/src/retrieval/search.js.map +1 -1
  97. package/src/retrieval/temporal-scorer.d.ts +18 -0
  98. package/src/retrieval/temporal-scorer.d.ts.map +1 -0
  99. package/src/retrieval/temporal-scorer.js +106 -0
  100. package/src/retrieval/temporal-scorer.js.map +1 -0
  101. package/src/retrieval/trigger-matcher.d.ts.map +1 -1
  102. package/src/retrieval/trigger-matcher.js +134 -0
  103. package/src/retrieval/trigger-matcher.js.map +1 -1
  104. package/src/retrieval/types.d.ts +4 -0
  105. package/src/retrieval/types.d.ts.map +1 -1
  106. package/src/retrieval/types.js +9 -0
  107. package/src/retrieval/types.js.map +1 -1
  108. package/src/retrieval/vector-search.d.ts.map +1 -1
  109. package/src/retrieval/vector-search.js +24 -0
  110. package/src/retrieval/vector-search.js.map +1 -1
  111. package/src/salience/decay.js +15 -0
  112. package/src/scratchpad/scratchpad.js +107 -0
  113. package/src/sessions/manager.d.ts +11 -0
  114. package/src/sessions/manager.d.ts.map +1 -0
  115. package/src/sessions/manager.js +63 -0
  116. package/src/sessions/manager.js.map +1 -0
package/src/config.d.ts CHANGED
@@ -1,5 +1,124 @@
1
1
  import { z } from 'zod';
2
2
  export declare const unitFloat: z.ZodNumber;
3
+ export declare const EntityFieldSchema: z.ZodObject<{
4
+ name: z.ZodString;
5
+ type: z.ZodEnum<["string", "number", "boolean", "date"]>;
6
+ description: z.ZodString;
7
+ required: z.ZodDefault<z.ZodBoolean>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ name: string;
10
+ type: "string" | "number" | "boolean" | "date";
11
+ description: string;
12
+ required: boolean;
13
+ }, {
14
+ name: string;
15
+ type: "string" | "number" | "boolean" | "date";
16
+ description: string;
17
+ required?: boolean | undefined;
18
+ }>;
19
+ export type EntityField = z.infer<typeof EntityFieldSchema>;
20
+ export declare const DomainEntityTypeSchema: z.ZodObject<{
21
+ name: z.ZodString;
22
+ description: z.ZodString;
23
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
24
+ name: z.ZodString;
25
+ type: z.ZodEnum<["string", "number", "boolean", "date"]>;
26
+ description: z.ZodString;
27
+ required: z.ZodDefault<z.ZodBoolean>;
28
+ }, "strip", z.ZodTypeAny, {
29
+ name: string;
30
+ type: "string" | "number" | "boolean" | "date";
31
+ description: string;
32
+ required: boolean;
33
+ }, {
34
+ name: string;
35
+ type: "string" | "number" | "boolean" | "date";
36
+ description: string;
37
+ required?: boolean | undefined;
38
+ }>, "many">>;
39
+ }, "strip", z.ZodTypeAny, {
40
+ name: string;
41
+ description: string;
42
+ fields: {
43
+ name: string;
44
+ type: "string" | "number" | "boolean" | "date";
45
+ description: string;
46
+ required: boolean;
47
+ }[];
48
+ }, {
49
+ name: string;
50
+ description: string;
51
+ fields?: {
52
+ name: string;
53
+ type: "string" | "number" | "boolean" | "date";
54
+ description: string;
55
+ required?: boolean | undefined;
56
+ }[] | undefined;
57
+ }>;
58
+ export type DomainEntityType = z.infer<typeof DomainEntityTypeSchema>;
59
+ export declare const DomainSchemaSchema: z.ZodObject<{
60
+ entityTypes: z.ZodDefault<z.ZodArray<z.ZodObject<{
61
+ name: z.ZodString;
62
+ description: z.ZodString;
63
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
64
+ name: z.ZodString;
65
+ type: z.ZodEnum<["string", "number", "boolean", "date"]>;
66
+ description: z.ZodString;
67
+ required: z.ZodDefault<z.ZodBoolean>;
68
+ }, "strip", z.ZodTypeAny, {
69
+ name: string;
70
+ type: "string" | "number" | "boolean" | "date";
71
+ description: string;
72
+ required: boolean;
73
+ }, {
74
+ name: string;
75
+ type: "string" | "number" | "boolean" | "date";
76
+ description: string;
77
+ required?: boolean | undefined;
78
+ }>, "many">>;
79
+ }, "strip", z.ZodTypeAny, {
80
+ name: string;
81
+ description: string;
82
+ fields: {
83
+ name: string;
84
+ type: "string" | "number" | "boolean" | "date";
85
+ description: string;
86
+ required: boolean;
87
+ }[];
88
+ }, {
89
+ name: string;
90
+ description: string;
91
+ fields?: {
92
+ name: string;
93
+ type: "string" | "number" | "boolean" | "date";
94
+ description: string;
95
+ required?: boolean | undefined;
96
+ }[] | undefined;
97
+ }>, "many">>;
98
+ }, "strip", z.ZodTypeAny, {
99
+ entityTypes: {
100
+ name: string;
101
+ description: string;
102
+ fields: {
103
+ name: string;
104
+ type: "string" | "number" | "boolean" | "date";
105
+ description: string;
106
+ required: boolean;
107
+ }[];
108
+ }[];
109
+ }, {
110
+ entityTypes?: {
111
+ name: string;
112
+ description: string;
113
+ fields?: {
114
+ name: string;
115
+ type: "string" | "number" | "boolean" | "date";
116
+ description: string;
117
+ required?: boolean | undefined;
118
+ }[] | undefined;
119
+ }[] | undefined;
120
+ }>;
121
+ export type DomainSchema = z.infer<typeof DomainSchemaSchema>;
3
122
  export declare const StenoConfigSchema: z.ZodObject<{
4
123
  embeddingModel: z.ZodDefault<z.ZodString>;
5
124
  embeddingDim: z.ZodDefault<z.ZodNumber>;
@@ -12,18 +131,83 @@ export declare const StenoConfigSchema: z.ZodObject<{
12
131
  graph: z.ZodDefault<z.ZodNumber>;
13
132
  recency: z.ZodDefault<z.ZodNumber>;
14
133
  salience: z.ZodDefault<z.ZodNumber>;
134
+ temporal: z.ZodDefault<z.ZodNumber>;
15
135
  }, "strip", z.ZodTypeAny, {
16
136
  vector: number;
17
137
  keyword: number;
18
138
  graph: number;
19
139
  recency: number;
20
140
  salience: number;
141
+ temporal: number;
21
142
  }, {
22
143
  vector?: number | undefined;
23
144
  keyword?: number | undefined;
24
145
  graph?: number | undefined;
25
146
  recency?: number | undefined;
26
147
  salience?: number | undefined;
148
+ temporal?: number | undefined;
149
+ }>>;
150
+ domainSchema: z.ZodOptional<z.ZodObject<{
151
+ entityTypes: z.ZodDefault<z.ZodArray<z.ZodObject<{
152
+ name: z.ZodString;
153
+ description: z.ZodString;
154
+ fields: z.ZodDefault<z.ZodArray<z.ZodObject<{
155
+ name: z.ZodString;
156
+ type: z.ZodEnum<["string", "number", "boolean", "date"]>;
157
+ description: z.ZodString;
158
+ required: z.ZodDefault<z.ZodBoolean>;
159
+ }, "strip", z.ZodTypeAny, {
160
+ name: string;
161
+ type: "string" | "number" | "boolean" | "date";
162
+ description: string;
163
+ required: boolean;
164
+ }, {
165
+ name: string;
166
+ type: "string" | "number" | "boolean" | "date";
167
+ description: string;
168
+ required?: boolean | undefined;
169
+ }>, "many">>;
170
+ }, "strip", z.ZodTypeAny, {
171
+ name: string;
172
+ description: string;
173
+ fields: {
174
+ name: string;
175
+ type: "string" | "number" | "boolean" | "date";
176
+ description: string;
177
+ required: boolean;
178
+ }[];
179
+ }, {
180
+ name: string;
181
+ description: string;
182
+ fields?: {
183
+ name: string;
184
+ type: "string" | "number" | "boolean" | "date";
185
+ description: string;
186
+ required?: boolean | undefined;
187
+ }[] | undefined;
188
+ }>, "many">>;
189
+ }, "strip", z.ZodTypeAny, {
190
+ entityTypes: {
191
+ name: string;
192
+ description: string;
193
+ fields: {
194
+ name: string;
195
+ type: "string" | "number" | "boolean" | "date";
196
+ description: string;
197
+ required: boolean;
198
+ }[];
199
+ }[];
200
+ }, {
201
+ entityTypes?: {
202
+ name: string;
203
+ description: string;
204
+ fields?: {
205
+ name: string;
206
+ type: "string" | "number" | "boolean" | "date";
207
+ description: string;
208
+ required?: boolean | undefined;
209
+ }[] | undefined;
210
+ }[] | undefined;
27
211
  }>>;
28
212
  }, "strip", z.ZodTypeAny, {
29
213
  embeddingModel: string;
@@ -37,7 +221,20 @@ export declare const StenoConfigSchema: z.ZodObject<{
37
221
  graph: number;
38
222
  recency: number;
39
223
  salience: number;
224
+ temporal: number;
40
225
  };
226
+ domainSchema?: {
227
+ entityTypes: {
228
+ name: string;
229
+ description: string;
230
+ fields: {
231
+ name: string;
232
+ type: "string" | "number" | "boolean" | "date";
233
+ description: string;
234
+ required: boolean;
235
+ }[];
236
+ }[];
237
+ } | undefined;
41
238
  }, {
42
239
  embeddingModel?: string | undefined;
43
240
  embeddingDim?: number | undefined;
@@ -50,6 +247,19 @@ export declare const StenoConfigSchema: z.ZodObject<{
50
247
  graph?: number | undefined;
51
248
  recency?: number | undefined;
52
249
  salience?: number | undefined;
250
+ temporal?: number | undefined;
251
+ } | undefined;
252
+ domainSchema?: {
253
+ entityTypes?: {
254
+ name: string;
255
+ description: string;
256
+ fields?: {
257
+ name: string;
258
+ type: "string" | "number" | "boolean" | "date";
259
+ description: string;
260
+ required?: boolean | undefined;
261
+ }[] | undefined;
262
+ }[] | undefined;
53
263
  } | undefined;
54
264
  }>;
55
265
  export type StenoConfig = z.infer<typeof StenoConfigSchema>;
@@ -69,7 +279,7 @@ export declare const EXTRACTION_TIERS_USED: readonly ["heuristic", "cheap_llm",
69
279
  export type ExtractionTierUsed = (typeof EXTRACTION_TIERS_USED)[number];
70
280
  export declare const MODALITIES: readonly ["text", "image", "audio", "code", "document"];
71
281
  export type Modality = (typeof MODALITIES)[number];
72
- export declare const EDGE_TYPES: readonly ["associative", "causal", "temporal", "contradictory", "hierarchical"];
282
+ export declare const EDGE_TYPES: readonly ["associative", "causal", "temporal", "contradictory", "hierarchical", "updates", "extends", "derives"];
73
283
  export type EdgeType = (typeof EDGE_TYPES)[number];
74
284
  export declare const EXTRACTION_STATUSES: readonly ["queued", "processing", "completed", "failed", "deduped"];
75
285
  export type ExtractionStatus = (typeof EXTRACTION_STATUSES)[number];
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,SAAS,aAA2B,CAAC;AAGlD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAe5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,MAAM,+CAAgD,CAAC;AACpE,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAG5C,eAAO,MAAM,cAAc,oCAAqC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,UAAU,6CAA8C,CAAC;AACtE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD,eAAO,MAAM,sBAAsB,uDAAwD,CAAC;AAC5F,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,eAAO,MAAM,YAAY,+EAOf,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,gBAAgB,kDAAmD,CAAC;AACjF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,eAAO,MAAM,qBAAqB,gEAA+C,CAAC;AAClF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,eAAO,MAAM,UAAU,yDAA0D,CAAC;AAClF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,UAAU,iFAMb,CAAC;AACX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,mBAAmB,qEAMtB,CAAC;AACX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,WAAW,oFAQd,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,KAAK,iDAAkD,CAAC;AACrE,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C,eAAO,MAAM,cAAc,qCAAsC,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,eAAO,MAAM,cAAc,6GAMjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,YAAY,6CAA8C,CAAC;AACxE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"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"}
package/src/config.js ADDED
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ // Shared Zod helpers
3
+ export const unitFloat = z.number().min(0).max(1);
4
+ // ---------------------------------------------------------------------------
5
+ // Domain-scoped graph schemas — custom entity types with typed attributes
6
+ // ---------------------------------------------------------------------------
7
+ export const EntityFieldSchema = z.object({
8
+ name: z.string(),
9
+ type: z.enum(['string', 'number', 'boolean', 'date']),
10
+ description: z.string(),
11
+ required: z.boolean().default(false),
12
+ });
13
+ export const DomainEntityTypeSchema = z.object({
14
+ name: z.string(),
15
+ description: z.string(),
16
+ fields: z.array(EntityFieldSchema).default([]),
17
+ });
18
+ export const DomainSchemaSchema = z.object({
19
+ entityTypes: z.array(DomainEntityTypeSchema).default([]),
20
+ });
21
+ // Steno engine configuration schema
22
+ export const StenoConfigSchema = z.object({
23
+ embeddingModel: z.string().default('text-embedding-3-small'),
24
+ embeddingDim: z.number().int().positive().default(1536),
25
+ decayHalfLifeDays: z.number().positive().default(30),
26
+ decayNormalizationK: z.number().positive().default(50),
27
+ maxFactsPerScope: z.number().int().positive().default(10000),
28
+ retrievalWeights: z
29
+ .object({
30
+ vector: z.number().min(0).max(1).default(0.35),
31
+ keyword: z.number().min(0).max(1).default(0.15),
32
+ graph: z.number().min(0).max(1).default(0.2),
33
+ recency: z.number().min(0).max(1).default(0.15),
34
+ salience: z.number().min(0).max(1).default(0.15),
35
+ temporal: z.number().min(0).max(1).default(0.20),
36
+ })
37
+ .default({}),
38
+ domainSchema: DomainSchemaSchema.optional(),
39
+ });
40
+ export const SCOPES = ['user', 'agent', 'session', 'hive'];
41
+ // SESSION_SCOPES is a subset of SCOPES — sessions themselves cannot be scoped to another session
42
+ export const SESSION_SCOPES = ['user', 'agent', 'hive'];
43
+ export const OPERATIONS = ['create', 'update', 'invalidate'];
44
+ export const CONTRADICTION_STATUSES = ['none', 'active', 'resolved', 'superseded'];
45
+ export const SOURCE_TYPES = [
46
+ 'conversation',
47
+ 'document',
48
+ 'url',
49
+ 'raw_text',
50
+ 'api',
51
+ 'agent_self',
52
+ ];
53
+ export const EXTRACTION_TIERS = ['heuristic', 'cheap_llm', 'smart_llm'];
54
+ export const EXTRACTION_TIERS_USED = [...EXTRACTION_TIERS, 'multi_tier'];
55
+ export const MODALITIES = ['text', 'image', 'audio', 'code', 'document'];
56
+ export const EDGE_TYPES = [
57
+ 'associative',
58
+ 'causal',
59
+ 'temporal',
60
+ 'contradictory',
61
+ 'hierarchical',
62
+ 'updates', // new fact supersedes old one (knowledge chain)
63
+ 'extends', // new fact adds detail to old one
64
+ 'derives', // new fact is inferred from combining others
65
+ ];
66
+ export const EXTRACTION_STATUSES = [
67
+ 'queued',
68
+ 'processing',
69
+ 'completed',
70
+ 'failed',
71
+ 'deduped',
72
+ ];
73
+ export const INPUT_TYPES = [
74
+ 'conversation',
75
+ 'document',
76
+ 'url',
77
+ 'raw_text',
78
+ 'image',
79
+ 'audio',
80
+ 'code',
81
+ ];
82
+ export const PLANS = ['free', 'pro', 'scale', 'enterprise'];
83
+ export const API_KEY_SCOPES = ['read', 'write', 'admin'];
84
+ export const FEEDBACK_TYPES = [
85
+ 'implicit_positive',
86
+ 'implicit_negative',
87
+ 'explicit_positive',
88
+ 'explicit_negative',
89
+ 'correction',
90
+ ];
91
+ export const ENTITY_ROLES = ['subject', 'object', 'mentioned'];
92
+ //# sourceMappingURL=config.js.map
package/src/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAElD,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACrC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC/C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACzD,CAAC,CAAC;AAGH,oCAAoC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IAC5D,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACvD,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACpD,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACtD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5D,gBAAgB,EAAE,CAAC;SAChB,MAAM,CAAC;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAChD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;KACjD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACd,YAAY,EAAE,kBAAkB,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAGpE,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAGjE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAU,CAAC;AAGtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAU,CAAC;AAG5F,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,cAAc;IACd,UAAU;IACV,KAAK;IACL,UAAU;IACV,KAAK;IACL,YAAY;CACJ,CAAC;AAGX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAU,CAAC;AAGjF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,gBAAgB,EAAE,YAAY,CAAU,CAAC;AAGlF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAGlF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,aAAa;IACb,QAAQ;IACR,UAAU;IACV,eAAe;IACf,cAAc;IACd,SAAS,EAAK,gDAAgD;IAC9D,SAAS,EAAK,kCAAkC;IAChD,SAAS,EAAK,6CAA6C;CACnD,CAAC;AAGX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,SAAS;CACD,CAAC;AAGX,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,cAAc;IACd,UAAU;IACV,KAAK;IACL,UAAU;IACV,OAAO;IACP,OAAO;IACP,MAAM;CACE,CAAC;AAGX,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,YAAY;CACJ,CAAC;AAGX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Process extracted facts and annotate contradictions.
3
+ * Facts with operation='contradict' get contradictionStatus='active'
4
+ * and contradictsId set to the fact they contradict.
5
+ * All other facts get contradictionStatus='none'.
6
+ */
7
+ export function processContradictions(facts) {
8
+ return facts.map(fact => {
9
+ if (fact.operation === 'contradict' && fact.contradictsFactId) {
10
+ return {
11
+ fact,
12
+ contradictionStatus: 'active',
13
+ contradictsId: fact.contradictsFactId,
14
+ };
15
+ }
16
+ return {
17
+ fact,
18
+ contradictionStatus: 'none',
19
+ contradictsId: null,
20
+ };
21
+ });
22
+ }
23
+ //# sourceMappingURL=contradiction.js.map
@@ -0,0 +1,93 @@
1
+ export async function deduplicateFacts(config, facts, tenantId, scope, scopeId) {
2
+ const threshold = config.similarityThreshold ?? 0.55;
3
+ const result = [];
4
+ for (const fact of facts) {
5
+ // If LLM already decided and it's not 'add', trust it
6
+ if (fact.operation && fact.operation !== 'add') {
7
+ result.push(fact);
8
+ continue;
9
+ }
10
+ // Embed the fact
11
+ const embedding = await config.embedding.embed(fact.content);
12
+ // Search for similar existing facts
13
+ const matches = await config.storage.vectorSearch({
14
+ embedding,
15
+ tenantId,
16
+ scope,
17
+ scopeId,
18
+ limit: 5,
19
+ minSimilarity: threshold,
20
+ validOnly: true,
21
+ });
22
+ if (matches.length === 0) {
23
+ // No similar facts — this is new
24
+ result.push({ ...fact, operation: 'add' });
25
+ continue;
26
+ }
27
+ // Similar facts found — ask LLM to classify
28
+ const decision = await classifyWithLLM(config.llm, fact.content, matches.map(m => ({
29
+ id: m.fact.id,
30
+ lineageId: m.fact.lineageId ?? '',
31
+ content: m.fact.content,
32
+ similarity: m.similarity,
33
+ })));
34
+ result.push({ ...fact, ...decision });
35
+ }
36
+ return result;
37
+ }
38
+ async function classifyWithLLM(llm, candidateContent, existingMatches) {
39
+ const messages = [
40
+ {
41
+ role: 'system',
42
+ content: `You are a memory deduplication classifier. Compare a NEW fact against EXISTING facts.
43
+
44
+ RULES:
45
+ - "noop" if the new fact says the SAME thing as an existing fact (even with different wording). Be AGGRESSIVE about noop — "User's name is Caroline" and "User is called Caroline" are NOOP.
46
+ - "update" if the new fact adds detail or changes a value ("User likes cats" → "User loves cats and has 3")
47
+ - "contradict" if the new fact directly conflicts ("User likes cats" vs "User hates cats")
48
+ - "add" ONLY if genuinely new information not covered by ANY existing fact
49
+
50
+ Return JSON:
51
+ {"operation": "add|update|noop|contradict", "existing_lineage_id": "...", "contradicts_fact_id": "..."}
52
+
53
+ Return ONLY valid JSON.`,
54
+ },
55
+ {
56
+ role: 'user',
57
+ content: `NEW FACT: "${candidateContent}"
58
+
59
+ EXISTING FACTS:
60
+ ${existingMatches.map(m => `[id: ${m.id}, lineage_id: ${m.lineageId}, similarity: ${m.similarity.toFixed(3)}] ${m.content}`).join('\n')}
61
+
62
+ Classify the new fact.`,
63
+ },
64
+ ];
65
+ try {
66
+ const response = await llm.complete(messages, { temperature: 0, responseFormat: 'json' });
67
+ const parsed = JSON.parse(response.content);
68
+ const operation = isValidDedupOp(parsed.operation) ? parsed.operation : 'add';
69
+ // Map dedup operations to relational versioning types
70
+ const relationType = operation === 'update' ? 'updates'
71
+ : operation === 'contradict' ? 'updates'
72
+ : undefined;
73
+ // Find the best matching existing fact for the relation
74
+ const relatedFactId = (operation === 'update' || operation === 'contradict') && existingMatches.length > 0
75
+ ? existingMatches[0].id
76
+ : undefined;
77
+ return {
78
+ operation,
79
+ existingLineageId: typeof parsed.existing_lineage_id === 'string' ? parsed.existing_lineage_id : undefined,
80
+ contradictsFactId: typeof parsed.contradicts_fact_id === 'string' ? parsed.contradicts_fact_id : undefined,
81
+ relationType,
82
+ relatedFactId,
83
+ };
84
+ }
85
+ catch {
86
+ // If LLM fails, default to 'add' (safe — might create a duplicate, but won't lose data)
87
+ return { operation: 'add' };
88
+ }
89
+ }
90
+ function isValidDedupOp(op) {
91
+ return typeof op === 'string' && ['add', 'update', 'noop', 'contradict', 'invalidate'].includes(op);
92
+ }
93
+ //# sourceMappingURL=dedup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dedup.js","sourceRoot":"","sources":["dedup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dedup.js","sourceRoot":"","sources":["dedup.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"entity-extractor.d.ts","sourceRoot":"","sources":["entity-extractor.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,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,eAAe,EAAE,GAC1B,OAAO,CAAC;IAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CAuCxE;AAmCD,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,EAAE,EACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CA6CjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EAAE,EAC3B,KAAK,EAAE,aAAa,EAAE,GACrB,OAAO,CAAC,uBAAuB,CAAC,CAiBlC"}
1
+ {"version":3,"file":"entity-extractor.d.ts","sourceRoot":"","sources":["entity-extractor.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,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,eAAe,EAAE,GAC1B,OAAO,CAAC;IAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CAuCxE;AA8CD,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,EAAE,EACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CA6CjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EAAE,EAC3B,KAAK,EAAE,aAAa,EAAE,GACrB,OAAO,CAAC,uBAAuB,CAAC,CAiBlC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Create or find all entities in the database.
3
+ * Does NOT link entities to any fact or create edges.
4
+ * Returns a map of canonicalName → entity.id for use in subsequent operations.
5
+ */
6
+ export async function buildEntityIdMap(storage, embedding, tenantId, entities) {
7
+ const entityIdMap = new Map();
8
+ let entitiesCreated = 0;
9
+ // Deduplicate entities by canonical name within this batch
10
+ const uniqueEntities = new Map();
11
+ for (const entity of entities) {
12
+ if (!uniqueEntities.has(entity.canonicalName)) {
13
+ uniqueEntities.set(entity.canonicalName, entity);
14
+ }
15
+ }
16
+ // Create or find each entity
17
+ for (const entity of uniqueEntities.values()) {
18
+ const existing = await storage.findEntityByCanonicalName(tenantId, entity.canonicalName, entity.entityType);
19
+ if (existing) {
20
+ entityIdMap.set(entity.canonicalName, existing.id);
21
+ }
22
+ else {
23
+ const id = crypto.randomUUID();
24
+ const emb = await embedding.embed(entity.name);
25
+ await storage.createEntity({
26
+ ...entity,
27
+ id,
28
+ tenantId,
29
+ embedding: emb,
30
+ embeddingModel: embedding.model,
31
+ embeddingDim: embedding.dimensions,
32
+ });
33
+ entityIdMap.set(entity.canonicalName, id);
34
+ entitiesCreated++;
35
+ }
36
+ }
37
+ return { entityIdMap, entitiesCreated };
38
+ }
39
+ /**
40
+ * Create edges between already-persisted entities.
41
+ * Uses the entityIdMap built by buildEntityIdMap.
42
+ */
43
+ // Normalize relation names so "loves_deeply" and "loves" merge
44
+ const RELATION_SYNONYMS = {
45
+ loves_deeply: 'loves',
46
+ has_relationship: 'partner_of',
47
+ has_relationship_with: 'partner_of',
48
+ dating: 'partner_of',
49
+ in_relationship_with: 'partner_of',
50
+ romantic_partner: 'partner_of',
51
+ girlfriend_of: 'partner_of',
52
+ boyfriend_of: 'partner_of',
53
+ married_to: 'partner_of',
54
+ works_for: 'works_at',
55
+ employed_at: 'works_at',
56
+ employed_by: 'works_at',
57
+ resides_in: 'lives_in',
58
+ located_at: 'located_in',
59
+ friends_with: 'friend_of',
60
+ acquainted_with: 'knows',
61
+ knows_about: 'knows',
62
+ interested_in: 'prefers',
63
+ attracted_to: 'prefers',
64
+ likes: 'prefers',
65
+ replaces: 'updates',
66
+ supersedes: 'updates',
67
+ overrides: 'updates',
68
+ corrects: 'updates',
69
+ supplements: 'extends',
70
+ refines: 'extends',
71
+ elaborates: 'extends',
72
+ details: 'extends',
73
+ infers: 'derives',
74
+ implies: 'derives',
75
+ combines: 'derives',
76
+ };
77
+ function normalizeRelation(relation) {
78
+ const lower = relation.toLowerCase().trim();
79
+ return RELATION_SYNONYMS[lower] ?? lower;
80
+ }
81
+ export async function persistEdges(storage, tenantId, factId, edges, entityIdMap) {
82
+ // Deduplicate edges by (source, target, normalized_relation) within this batch
83
+ const seen = new Set();
84
+ const dedupedEdges = [];
85
+ for (const edge of edges) {
86
+ const normalizedRelation = normalizeRelation(edge.relation);
87
+ const key = `${edge.sourceName}|${normalizedRelation}|${edge.targetName}`;
88
+ if (!seen.has(key)) {
89
+ seen.add(key);
90
+ dedupedEdges.push({ ...edge, relation: normalizedRelation });
91
+ }
92
+ }
93
+ let edgesCreated = 0;
94
+ for (const edge of dedupedEdges) {
95
+ const sourceId = entityIdMap.get(edge.sourceName);
96
+ const targetId = entityIdMap.get(edge.targetName);
97
+ if (sourceId && targetId) {
98
+ try {
99
+ await storage.createEdge({
100
+ tenantId,
101
+ sourceId,
102
+ targetId,
103
+ relation: edge.relation,
104
+ edgeType: edge.edgeType,
105
+ confidence: edge.confidence,
106
+ weight: 1.0,
107
+ metadata: {},
108
+ factId,
109
+ id: crypto.randomUUID(),
110
+ });
111
+ edgesCreated++;
112
+ }
113
+ catch {
114
+ // Edge creation failed (e.g., duplicate) — continue
115
+ }
116
+ }
117
+ if (!sourceId || !targetId) {
118
+ console.warn(`[steno] Edge dropped: "${edge.sourceName}" → "${edge.relation}" → "${edge.targetName}" ` +
119
+ `(source=${sourceId ? 'found' : 'MISSING'}, target=${targetId ? 'found' : 'MISSING'}) ` +
120
+ `entityMap keys: [${[...entityIdMap.keys()].join(', ')}]`);
121
+ }
122
+ }
123
+ return edgesCreated;
124
+ }
125
+ /**
126
+ * Persist extracted entities and edges to the database.
127
+ * - Creates new entities if canonical name doesn't exist for this tenant
128
+ * - Reuses existing entities if canonical name matches
129
+ * - Links all entities to the fact via fact_entities junction
130
+ * - Creates edges between entities
131
+ *
132
+ * @deprecated Use buildEntityIdMap + persistEdges directly for better control.
133
+ * This function is kept for backward compatibility.
134
+ */
135
+ export async function persistEntitiesAndEdges(storage, embedding, tenantId, factId, entities, edges) {
136
+ const { entityIdMap, entitiesCreated } = await buildEntityIdMap(storage, embedding, tenantId, entities);
137
+ // Link all entities to this fact
138
+ for (const [canonicalName, entityId] of entityIdMap) {
139
+ void canonicalName; // used as key only
140
+ await storage.linkFactEntity(factId, entityId, 'mentioned');
141
+ }
142
+ const edgesCreated = await persistEdges(storage, tenantId, factId, edges, entityIdMap);
143
+ return { entitiesCreated, edgesCreated, entityIdMap };
144
+ }
145
+ //# sourceMappingURL=entity-extractor.js.map