claude-memory-layer 1.0.44 → 1.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli/index.js +801 -1421
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +1319 -1501
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +465 -756
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +454 -734
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +450 -726
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +451 -728
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +458 -742
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +494 -814
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +1397 -1615
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1587 -1655
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +484 -792
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +492 -808
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +450 -726
- package/dist/services/memory-service.js.map +2 -2
- package/package.json +15 -3
|
@@ -51,6 +51,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
51
51
|
this.options = options;
|
|
52
52
|
this.fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
53
53
|
}
|
|
54
|
+
options;
|
|
54
55
|
fileSystem;
|
|
55
56
|
getEmbeddingModelName() {
|
|
56
57
|
return this.options.getEmbeddingModelName();
|
|
@@ -85,8 +86,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
85
86
|
}
|
|
86
87
|
const worker = this.options.getVectorWorker();
|
|
87
88
|
const wasRunning = worker?.isRunning() || false;
|
|
88
|
-
if (wasRunning)
|
|
89
|
-
worker?.stop();
|
|
89
|
+
if (wasRunning) worker?.stop();
|
|
90
90
|
await this.options.vectorStore.clearAll();
|
|
91
91
|
await this.options.eventStore.clearEmbeddingOutbox();
|
|
92
92
|
const enqueued = await this.reenqueueAllEvents();
|
|
@@ -103,8 +103,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
103
103
|
2
|
|
104
104
|
)
|
|
105
105
|
);
|
|
106
|
-
if (wasRunning)
|
|
107
|
-
worker?.start();
|
|
106
|
+
if (wasRunning) worker?.start();
|
|
108
107
|
return {
|
|
109
108
|
changed: true,
|
|
110
109
|
previousModel,
|
|
@@ -129,15 +128,13 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
129
128
|
let enqueued = 0;
|
|
130
129
|
while (true) {
|
|
131
130
|
const page = await this.options.eventStore.getEventsPage(DEFAULT_PAGE_SIZE, offset);
|
|
132
|
-
if (page.length === 0)
|
|
133
|
-
break;
|
|
131
|
+
if (page.length === 0) break;
|
|
134
132
|
for (const event of page) {
|
|
135
133
|
await this.options.eventStore.enqueueForEmbedding(event.id, event.content);
|
|
136
134
|
enqueued += 1;
|
|
137
135
|
}
|
|
138
136
|
offset += page.length;
|
|
139
|
-
if (page.length < DEFAULT_PAGE_SIZE)
|
|
140
|
-
break;
|
|
137
|
+
if (page.length < DEFAULT_PAGE_SIZE) break;
|
|
141
138
|
}
|
|
142
139
|
return enqueued;
|
|
143
140
|
}
|
|
@@ -155,12 +152,9 @@ import { randomUUID } from "crypto";
|
|
|
155
152
|
// src/core/db-wrapper.ts
|
|
156
153
|
import BetterSqlite3 from "better-sqlite3";
|
|
157
154
|
function toDate(value) {
|
|
158
|
-
if (value instanceof Date)
|
|
159
|
-
|
|
160
|
-
if (typeof value === "
|
|
161
|
-
return new Date(value);
|
|
162
|
-
if (typeof value === "number")
|
|
163
|
-
return new Date(value);
|
|
155
|
+
if (value instanceof Date) return value;
|
|
156
|
+
if (typeof value === "string") return new Date(value);
|
|
157
|
+
if (typeof value === "number") return new Date(value);
|
|
164
158
|
return new Date(String(value));
|
|
165
159
|
}
|
|
166
160
|
function createDatabase(dbPath, options) {
|
|
@@ -184,6 +178,8 @@ var WorkingSetStore = class {
|
|
|
184
178
|
this.eventStore = eventStore;
|
|
185
179
|
this.config = config;
|
|
186
180
|
}
|
|
181
|
+
eventStore;
|
|
182
|
+
config;
|
|
187
183
|
get db() {
|
|
188
184
|
return this.eventStore.getDatabase();
|
|
189
185
|
}
|
|
@@ -269,8 +265,7 @@ var WorkingSetStore = class {
|
|
|
269
265
|
* Prune specific events from working set (after consolidation)
|
|
270
266
|
*/
|
|
271
267
|
async prune(eventIds) {
|
|
272
|
-
if (eventIds.length === 0)
|
|
273
|
-
return;
|
|
268
|
+
if (eventIds.length === 0) return;
|
|
274
269
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
275
270
|
await dbRun(
|
|
276
271
|
this.db,
|
|
@@ -340,8 +335,7 @@ var WorkingSetStore = class {
|
|
|
340
335
|
LIMIT ?`,
|
|
341
336
|
[maxEvents]
|
|
342
337
|
);
|
|
343
|
-
if (keepIds.length === 0)
|
|
344
|
-
return;
|
|
338
|
+
if (keepIds.length === 0) return;
|
|
345
339
|
const keepIdList = keepIds.map((r) => r.id);
|
|
346
340
|
const placeholders = keepIdList.map(() => "?").join(",");
|
|
347
341
|
await dbRun(
|
|
@@ -388,6 +382,7 @@ var ConsolidatedStore = class {
|
|
|
388
382
|
constructor(eventStore) {
|
|
389
383
|
this.eventStore = eventStore;
|
|
390
384
|
}
|
|
385
|
+
eventStore;
|
|
391
386
|
get db() {
|
|
392
387
|
return this.eventStore.getDatabase();
|
|
393
388
|
}
|
|
@@ -420,8 +415,7 @@ var ConsolidatedStore = class {
|
|
|
420
415
|
`SELECT * FROM consolidated_memories WHERE memory_id = ?`,
|
|
421
416
|
[memoryId]
|
|
422
417
|
);
|
|
423
|
-
if (rows.length === 0)
|
|
424
|
-
return null;
|
|
418
|
+
if (rows.length === 0) return null;
|
|
425
419
|
return this.rowToMemory(rows[0]);
|
|
426
420
|
}
|
|
427
421
|
/**
|
|
@@ -639,8 +633,7 @@ var ConsolidatedStore = class {
|
|
|
639
633
|
WHERE source_events LIKE ?`,
|
|
640
634
|
[`%"${eventId}"%`]
|
|
641
635
|
);
|
|
642
|
-
if ((result[0]?.count || 0) > 0)
|
|
643
|
-
return true;
|
|
636
|
+
if ((result[0]?.count || 0) > 0) return true;
|
|
644
637
|
}
|
|
645
638
|
return false;
|
|
646
639
|
}
|
|
@@ -654,8 +647,7 @@ var ConsolidatedStore = class {
|
|
|
654
647
|
ORDER BY created_at DESC
|
|
655
648
|
LIMIT 1`
|
|
656
649
|
);
|
|
657
|
-
if (result.length === 0)
|
|
658
|
-
return null;
|
|
650
|
+
if (result.length === 0) return null;
|
|
659
651
|
return new Date(result[0].created_at);
|
|
660
652
|
}
|
|
661
653
|
/**
|
|
@@ -685,6 +677,9 @@ var ConsolidationWorker = class {
|
|
|
685
677
|
this.consolidatedStore = consolidatedStore;
|
|
686
678
|
this.config = config;
|
|
687
679
|
}
|
|
680
|
+
workingSetStore;
|
|
681
|
+
consolidatedStore;
|
|
682
|
+
config;
|
|
688
683
|
running = false;
|
|
689
684
|
timeout = null;
|
|
690
685
|
lastActivity = /* @__PURE__ */ new Date();
|
|
@@ -692,8 +687,7 @@ var ConsolidationWorker = class {
|
|
|
692
687
|
* Start the consolidation worker
|
|
693
688
|
*/
|
|
694
689
|
start() {
|
|
695
|
-
if (this.running)
|
|
696
|
-
return;
|
|
690
|
+
if (this.running) return;
|
|
697
691
|
this.running = true;
|
|
698
692
|
this.scheduleNext();
|
|
699
693
|
}
|
|
@@ -736,8 +730,7 @@ var ConsolidationWorker = class {
|
|
|
736
730
|
* Schedule the next consolidation check
|
|
737
731
|
*/
|
|
738
732
|
scheduleNext() {
|
|
739
|
-
if (!this.running)
|
|
740
|
-
return;
|
|
733
|
+
if (!this.running) return;
|
|
741
734
|
this.timeout = setTimeout(
|
|
742
735
|
() => this.run(),
|
|
743
736
|
this.config.consolidation.triggerIntervalMs
|
|
@@ -747,8 +740,7 @@ var ConsolidationWorker = class {
|
|
|
747
740
|
* Run consolidation check
|
|
748
741
|
*/
|
|
749
742
|
async run() {
|
|
750
|
-
if (!this.running)
|
|
751
|
-
return;
|
|
743
|
+
if (!this.running) return;
|
|
752
744
|
try {
|
|
753
745
|
await this.checkAndConsolidate();
|
|
754
746
|
} catch (error) {
|
|
@@ -786,12 +778,10 @@ var ConsolidationWorker = class {
|
|
|
786
778
|
let consolidatedCount = 0;
|
|
787
779
|
const createdMemoryIds = [];
|
|
788
780
|
for (const group of groups) {
|
|
789
|
-
if (group.events.length < 3)
|
|
790
|
-
continue;
|
|
781
|
+
if (group.events.length < 3) continue;
|
|
791
782
|
const eventIds = group.events.map((e) => e.id);
|
|
792
783
|
const alreadyConsolidated = await this.consolidatedStore.isAlreadyConsolidated(eventIds);
|
|
793
|
-
if (alreadyConsolidated)
|
|
794
|
-
continue;
|
|
784
|
+
if (alreadyConsolidated) continue;
|
|
795
785
|
const summary = await this.summarize(group);
|
|
796
786
|
const memoryId = await this.consolidatedStore.create({
|
|
797
787
|
summary,
|
|
@@ -807,8 +797,7 @@ var ConsolidationWorker = class {
|
|
|
807
797
|
const consolidatedEventIds = groups.filter((g) => g.events.length >= 3).flatMap((g) => g.events.map((e) => e.id));
|
|
808
798
|
const oldEventIds = consolidatedEventIds.filter((id) => {
|
|
809
799
|
const event = workingSet.recentEvents.find((e) => e.id === id);
|
|
810
|
-
if (!event)
|
|
811
|
-
return false;
|
|
800
|
+
if (!event) return false;
|
|
812
801
|
const ageHours = (Date.now() - event.timestamp.getTime()) / (1e3 * 60 * 60);
|
|
813
802
|
return ageHours > this.config.workingSet.timeWindowHours / 2;
|
|
814
803
|
});
|
|
@@ -823,18 +812,13 @@ var ConsolidationWorker = class {
|
|
|
823
812
|
let promoted = 0;
|
|
824
813
|
for (const memoryId of memoryIds) {
|
|
825
814
|
const memory = await this.consolidatedStore.get(memoryId);
|
|
826
|
-
if (!memory)
|
|
827
|
-
|
|
828
|
-
if (memory.
|
|
829
|
-
continue;
|
|
830
|
-
if (memory.sourceEvents.length < 4)
|
|
831
|
-
continue;
|
|
815
|
+
if (!memory) continue;
|
|
816
|
+
if (memory.confidence < 0.55) continue;
|
|
817
|
+
if (memory.sourceEvents.length < 4) continue;
|
|
832
818
|
const exists = await this.consolidatedStore.hasRuleForSourceMemory(memoryId);
|
|
833
|
-
if (exists)
|
|
834
|
-
continue;
|
|
819
|
+
if (exists) continue;
|
|
835
820
|
const rule = this.buildRuleFromSummary(memory.summary, memory.topics);
|
|
836
|
-
if (!rule)
|
|
837
|
-
continue;
|
|
821
|
+
if (!rule) continue;
|
|
838
822
|
await this.consolidatedStore.createRule({
|
|
839
823
|
rule,
|
|
840
824
|
topics: memory.topics,
|
|
@@ -850,8 +834,7 @@ var ConsolidationWorker = class {
|
|
|
850
834
|
const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).filter((l) => !l.toLowerCase().startsWith("topics:"));
|
|
851
835
|
const bullet = lines.find((l) => l.startsWith("- "))?.replace(/^-\s*/, "");
|
|
852
836
|
const seed = bullet || lines[0];
|
|
853
|
-
if (!seed || seed.length < 8)
|
|
854
|
-
return null;
|
|
837
|
+
if (!seed || seed.length < 8) return null;
|
|
855
838
|
const topicPrefix = topics.length > 0 ? `[${topics.slice(0, 2).join(", ")}] ` : "";
|
|
856
839
|
return `${topicPrefix}${seed}`;
|
|
857
840
|
}
|
|
@@ -1012,8 +995,7 @@ var ConsolidationWorker = class {
|
|
|
1012
995
|
*/
|
|
1013
996
|
extractKeyPoint(content) {
|
|
1014
997
|
const sentences = content.split(/[.!?\n]+/).filter((s) => s.trim().length > 10);
|
|
1015
|
-
if (sentences.length === 0)
|
|
1016
|
-
return null;
|
|
998
|
+
if (sentences.length === 0) return null;
|
|
1017
999
|
const firstSentence = sentences[0].trim();
|
|
1018
1000
|
if (firstSentence.length > 100) {
|
|
1019
1001
|
return firstSentence.slice(0, 100) + "...";
|
|
@@ -1033,8 +1015,7 @@ var ConsolidationWorker = class {
|
|
|
1033
1015
|
* Calculate time proximity score
|
|
1034
1016
|
*/
|
|
1035
1017
|
calculateTimeProximity(events) {
|
|
1036
|
-
if (events.length < 2)
|
|
1037
|
-
return 1;
|
|
1018
|
+
if (events.length < 2) return 1;
|
|
1038
1019
|
const timestamps = events.map((e) => e.timestamp.getTime()).sort((a, b) => a - b);
|
|
1039
1020
|
const timeSpan = timestamps[timestamps.length - 1] - timestamps[0];
|
|
1040
1021
|
const avgGap = timeSpan / (events.length - 1);
|
|
@@ -1053,6 +1034,8 @@ var ContinuityManager = class {
|
|
|
1053
1034
|
this.eventStore = eventStore;
|
|
1054
1035
|
this.config = config;
|
|
1055
1036
|
}
|
|
1037
|
+
eventStore;
|
|
1038
|
+
config;
|
|
1056
1039
|
lastContext = null;
|
|
1057
1040
|
get db() {
|
|
1058
1041
|
return this.eventStore.getDatabase();
|
|
@@ -1172,8 +1155,7 @@ var ContinuityManager = class {
|
|
|
1172
1155
|
* Calculate overlap between two arrays
|
|
1173
1156
|
*/
|
|
1174
1157
|
calculateOverlap(a, b) {
|
|
1175
|
-
if (a.length === 0 || b.length === 0)
|
|
1176
|
-
return 0;
|
|
1158
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
1177
1159
|
const setA = new Set(a.map((s) => s.toLowerCase()));
|
|
1178
1160
|
const setB = new Set(b.map((s) => s.toLowerCase()));
|
|
1179
1161
|
const intersection = [...setA].filter((x) => setB.has(x));
|
|
@@ -1346,6 +1328,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1346
1328
|
this.options = options;
|
|
1347
1329
|
this.factories = options.factories ? { ...options.factories, randomUUID: options.factories.randomUUID ?? randomUUID4 } : defaultFactories;
|
|
1348
1330
|
}
|
|
1331
|
+
options;
|
|
1349
1332
|
factories;
|
|
1350
1333
|
workingSetStore = null;
|
|
1351
1334
|
consolidatedStore = null;
|
|
@@ -1360,8 +1343,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1360
1343
|
}
|
|
1361
1344
|
}
|
|
1362
1345
|
async initializeEndlessMode() {
|
|
1363
|
-
if (this.consolidationWorker)
|
|
1364
|
-
return;
|
|
1346
|
+
if (this.consolidationWorker) return;
|
|
1365
1347
|
const config = await this.getEndlessConfig();
|
|
1366
1348
|
const workingSetStore = this.factories.createWorkingSetStore(this.options.eventStore, config);
|
|
1367
1349
|
const consolidatedStore = this.factories.createConsolidatedStore(this.options.eventStore);
|
|
@@ -1393,8 +1375,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1393
1375
|
}
|
|
1394
1376
|
async setMode(mode) {
|
|
1395
1377
|
await this.options.initialize();
|
|
1396
|
-
if (mode === this.mode)
|
|
1397
|
-
return;
|
|
1378
|
+
if (mode === this.mode) return;
|
|
1398
1379
|
this.mode = mode;
|
|
1399
1380
|
await this.options.configStore.setEndlessConfig("mode", mode);
|
|
1400
1381
|
if (mode === "endless") {
|
|
@@ -1410,33 +1391,27 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1410
1391
|
return this.mode === "endless";
|
|
1411
1392
|
}
|
|
1412
1393
|
async addToWorkingSet(eventId, relevanceScore) {
|
|
1413
|
-
if (!this.workingSetStore)
|
|
1414
|
-
return;
|
|
1394
|
+
if (!this.workingSetStore) return;
|
|
1415
1395
|
await this.workingSetStore.add(eventId, relevanceScore);
|
|
1416
1396
|
}
|
|
1417
1397
|
async getWorkingSet() {
|
|
1418
|
-
if (!this.workingSetStore)
|
|
1419
|
-
return null;
|
|
1398
|
+
if (!this.workingSetStore) return null;
|
|
1420
1399
|
return this.workingSetStore.get();
|
|
1421
1400
|
}
|
|
1422
1401
|
async searchConsolidated(query, options) {
|
|
1423
|
-
if (!this.consolidatedStore)
|
|
1424
|
-
return [];
|
|
1402
|
+
if (!this.consolidatedStore) return [];
|
|
1425
1403
|
return this.consolidatedStore.search(query, options);
|
|
1426
1404
|
}
|
|
1427
1405
|
async getConsolidatedMemories(limit) {
|
|
1428
|
-
if (!this.consolidatedStore)
|
|
1429
|
-
return [];
|
|
1406
|
+
if (!this.consolidatedStore) return [];
|
|
1430
1407
|
return this.consolidatedStore.getAll({ limit });
|
|
1431
1408
|
}
|
|
1432
1409
|
async markMemoryAccessed(memoryId) {
|
|
1433
|
-
if (!this.consolidatedStore)
|
|
1434
|
-
return;
|
|
1410
|
+
if (!this.consolidatedStore) return;
|
|
1435
1411
|
await this.consolidatedStore.markAccessed(memoryId);
|
|
1436
1412
|
}
|
|
1437
1413
|
async calculateContinuity(content, metadata) {
|
|
1438
|
-
if (!this.continuityManager)
|
|
1439
|
-
return null;
|
|
1414
|
+
if (!this.continuityManager) return null;
|
|
1440
1415
|
const snapshot = this.continuityManager.createSnapshot(
|
|
1441
1416
|
this.factories.randomUUID(),
|
|
1442
1417
|
content,
|
|
@@ -1448,8 +1423,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1448
1423
|
this.consolidationWorker?.recordActivity();
|
|
1449
1424
|
}
|
|
1450
1425
|
async forceConsolidation() {
|
|
1451
|
-
if (!this.consolidationWorker)
|
|
1452
|
-
return 0;
|
|
1426
|
+
if (!this.consolidationWorker) return 0;
|
|
1453
1427
|
return this.consolidationWorker.forceRun();
|
|
1454
1428
|
}
|
|
1455
1429
|
async getEndlessModeStatus() {
|
|
@@ -1541,8 +1515,7 @@ var Embedder = class _Embedder {
|
|
|
1541
1515
|
* Initialize the embedding pipeline
|
|
1542
1516
|
*/
|
|
1543
1517
|
async initialize() {
|
|
1544
|
-
if (this.initialized)
|
|
1545
|
-
return;
|
|
1518
|
+
if (this.initialized) return;
|
|
1546
1519
|
const pipeline = await withSuppressedKnownTransformersWarnings(async () => {
|
|
1547
1520
|
try {
|
|
1548
1521
|
return await loadTransformersPipeline();
|
|
@@ -1659,8 +1632,7 @@ async function withSuppressedKnownTransformersWarnings(fn) {
|
|
|
1659
1632
|
originalConsoleWarn = console.warn;
|
|
1660
1633
|
console.warn = (...args) => {
|
|
1661
1634
|
const message = args.map(String).join(" ");
|
|
1662
|
-
if (isKnownBenignTransformersWarning(message))
|
|
1663
|
-
return;
|
|
1635
|
+
if (isKnownBenignTransformersWarning(message)) return;
|
|
1664
1636
|
(originalConsoleWarn ?? console.warn)(...args);
|
|
1665
1637
|
};
|
|
1666
1638
|
}
|
|
@@ -1942,8 +1914,7 @@ var GraduationPipeline = class {
|
|
|
1942
1914
|
const preferenceKeywords = ["prefer", "like", "want", "always", "never", "favorite"];
|
|
1943
1915
|
const preferences = [];
|
|
1944
1916
|
for (const event of events) {
|
|
1945
|
-
if (event.eventType !== "user_prompt")
|
|
1946
|
-
continue;
|
|
1917
|
+
if (event.eventType !== "user_prompt") continue;
|
|
1947
1918
|
const lowerContent = event.content.toLowerCase();
|
|
1948
1919
|
for (const keyword of preferenceKeywords) {
|
|
1949
1920
|
if (lowerContent.includes(keyword)) {
|
|
@@ -2109,11 +2080,9 @@ function sanitizeSegment(input, fallback) {
|
|
|
2109
2080
|
return v || fallback;
|
|
2110
2081
|
}
|
|
2111
2082
|
function getAtPath(obj, dotted) {
|
|
2112
|
-
if (!obj)
|
|
2113
|
-
return void 0;
|
|
2083
|
+
if (!obj) return void 0;
|
|
2114
2084
|
return dotted.split(".").reduce((acc, key) => {
|
|
2115
|
-
if (!acc || typeof acc !== "object")
|
|
2116
|
-
return void 0;
|
|
2085
|
+
if (!acc || typeof acc !== "object") return void 0;
|
|
2117
2086
|
return acc[key];
|
|
2118
2087
|
}, obj);
|
|
2119
2088
|
}
|
|
@@ -2133,6 +2102,7 @@ var MarkdownMirror = class {
|
|
|
2133
2102
|
constructor(rootDir) {
|
|
2134
2103
|
this.rootDir = rootDir;
|
|
2135
2104
|
}
|
|
2105
|
+
rootDir;
|
|
2136
2106
|
async append(event, eventId) {
|
|
2137
2107
|
const out = buildMirrorPath(this.rootDir, event);
|
|
2138
2108
|
fs2.mkdirSync(path2.dirname(out), { recursive: true });
|
|
@@ -2264,10 +2234,8 @@ function sqliteClose(db) {
|
|
|
2264
2234
|
db.close();
|
|
2265
2235
|
}
|
|
2266
2236
|
function toDateFromSQLite(value) {
|
|
2267
|
-
if (value instanceof Date)
|
|
2268
|
-
|
|
2269
|
-
if (typeof value === "number")
|
|
2270
|
-
return new Date(value);
|
|
2237
|
+
if (value instanceof Date) return value;
|
|
2238
|
+
if (typeof value === "number") return new Date(value);
|
|
2271
2239
|
if (typeof value === "string") {
|
|
2272
2240
|
const trimmed = value.trim();
|
|
2273
2241
|
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
|
|
@@ -2289,8 +2257,7 @@ var DEFAULT_CATEGORY = "uncategorized";
|
|
|
2289
2257
|
function sanitizeSegment2(input, fallback) {
|
|
2290
2258
|
const raw = String(input ?? "").trim().toLowerCase();
|
|
2291
2259
|
const safe = raw.normalize("NFKD").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2292
|
-
if (!safe || safe === "." || safe === "..")
|
|
2293
|
-
return fallback;
|
|
2260
|
+
if (!safe || safe === "." || safe === "..") return fallback;
|
|
2294
2261
|
return safe;
|
|
2295
2262
|
}
|
|
2296
2263
|
function getCategorySegments(metadata, eventType) {
|
|
@@ -2331,6 +2298,7 @@ var MarkdownMirror2 = class {
|
|
|
2331
2298
|
constructor(rootDir) {
|
|
2332
2299
|
this.rootDir = rootDir;
|
|
2333
2300
|
}
|
|
2301
|
+
rootDir;
|
|
2334
2302
|
async append(event) {
|
|
2335
2303
|
const outPath = buildMirrorPath2(this.rootDir, event);
|
|
2336
2304
|
await fs5.mkdir(path4.dirname(outPath), { recursive: true });
|
|
@@ -2353,6 +2321,7 @@ var VectorOutbox = class {
|
|
|
2353
2321
|
this.db = db;
|
|
2354
2322
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
2355
2323
|
}
|
|
2324
|
+
db;
|
|
2356
2325
|
config;
|
|
2357
2326
|
/**
|
|
2358
2327
|
* Enqueue item for vectorization (idempotent).
|
|
@@ -2449,8 +2418,7 @@ var VectorOutbox = class {
|
|
|
2449
2418
|
`SELECT retry_count FROM vector_outbox WHERE job_id = ?`,
|
|
2450
2419
|
[jobId]
|
|
2451
2420
|
);
|
|
2452
|
-
if (rows.length === 0)
|
|
2453
|
-
return;
|
|
2421
|
+
if (rows.length === 0) return;
|
|
2454
2422
|
const retryCount = rows[0].retry_count;
|
|
2455
2423
|
const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
|
|
2456
2424
|
await dbRun(
|
|
@@ -2470,8 +2438,7 @@ var VectorOutbox = class {
|
|
|
2470
2438
|
`SELECT * FROM vector_outbox WHERE job_id = ?`,
|
|
2471
2439
|
[jobId]
|
|
2472
2440
|
);
|
|
2473
|
-
if (rows.length === 0)
|
|
2474
|
-
return null;
|
|
2441
|
+
if (rows.length === 0) return null;
|
|
2475
2442
|
return this.rowToJob(rows[0]);
|
|
2476
2443
|
}
|
|
2477
2444
|
/**
|
|
@@ -2605,30 +2572,24 @@ function isRetrievalDebugLaneName(value) {
|
|
|
2605
2572
|
return typeof value === "string" && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);
|
|
2606
2573
|
}
|
|
2607
2574
|
function normalizeRetrievalDebugLanes(value, maxItems = 6) {
|
|
2608
|
-
if (!Array.isArray(value) || maxItems <= 0)
|
|
2609
|
-
return [];
|
|
2575
|
+
if (!Array.isArray(value) || maxItems <= 0) return [];
|
|
2610
2576
|
const normalized = [];
|
|
2611
2577
|
const seen = /* @__PURE__ */ new Set();
|
|
2612
2578
|
for (const item of value) {
|
|
2613
2579
|
const lane = normalizeRetrievalDebugLane(item);
|
|
2614
|
-
if (!lane)
|
|
2615
|
-
continue;
|
|
2580
|
+
if (!lane) continue;
|
|
2616
2581
|
const key = [lane.lane, lane.reason, lane.score ?? ""].join("\0");
|
|
2617
|
-
if (seen.has(key))
|
|
2618
|
-
continue;
|
|
2582
|
+
if (seen.has(key)) continue;
|
|
2619
2583
|
seen.add(key);
|
|
2620
2584
|
normalized.push(lane);
|
|
2621
|
-
if (normalized.length >= maxItems)
|
|
2622
|
-
break;
|
|
2585
|
+
if (normalized.length >= maxItems) break;
|
|
2623
2586
|
}
|
|
2624
2587
|
return normalized;
|
|
2625
2588
|
}
|
|
2626
2589
|
function normalizeRetrievalDebugLane(value) {
|
|
2627
|
-
if (!value || typeof value !== "object")
|
|
2628
|
-
return null;
|
|
2590
|
+
if (!value || typeof value !== "object") return null;
|
|
2629
2591
|
const raw = value;
|
|
2630
|
-
if (!isRetrievalDebugLaneName(raw.lane))
|
|
2631
|
-
return null;
|
|
2592
|
+
if (!isRetrievalDebugLaneName(raw.lane)) return null;
|
|
2632
2593
|
const reason = sanitizeRetrievalLaneReason(typeof raw.reason === "string" ? raw.reason : "") || "unspecified";
|
|
2633
2594
|
const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? Math.max(0, Math.min(1, raw.score)) : void 0;
|
|
2634
2595
|
return score === void 0 ? { lane: raw.lane, reason } : { lane: raw.lane, reason, score };
|
|
@@ -2651,27 +2612,21 @@ function normalizeRetrievalTraceDetails(details) {
|
|
|
2651
2612
|
eventId: detail.eventId,
|
|
2652
2613
|
score: detail.score
|
|
2653
2614
|
};
|
|
2654
|
-
if (detail.semanticScore !== void 0)
|
|
2655
|
-
|
|
2656
|
-
if (detail.
|
|
2657
|
-
|
|
2658
|
-
if (detail.recencyScore !== void 0)
|
|
2659
|
-
normalized.recencyScore = detail.recencyScore;
|
|
2660
|
-
if (lanes.length > 0)
|
|
2661
|
-
normalized.lanes = lanes;
|
|
2615
|
+
if (detail.semanticScore !== void 0) normalized.semanticScore = detail.semanticScore;
|
|
2616
|
+
if (detail.lexicalScore !== void 0) normalized.lexicalScore = detail.lexicalScore;
|
|
2617
|
+
if (detail.recencyScore !== void 0) normalized.recencyScore = detail.recencyScore;
|
|
2618
|
+
if (lanes.length > 0) normalized.lanes = lanes;
|
|
2662
2619
|
return normalized;
|
|
2663
2620
|
});
|
|
2664
2621
|
}
|
|
2665
2622
|
function parseRetrievalTraceDetails(value) {
|
|
2666
|
-
if (typeof value !== "string" || value.length === 0)
|
|
2667
|
-
return [];
|
|
2623
|
+
if (typeof value !== "string" || value.length === 0) return [];
|
|
2668
2624
|
const parsed = JSON.parse(value);
|
|
2669
2625
|
return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed) : [];
|
|
2670
2626
|
}
|
|
2671
2627
|
function normalizeQueryRewriteKind(value) {
|
|
2672
2628
|
const normalized = (value || "").trim().toLowerCase();
|
|
2673
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
2674
|
-
return normalized;
|
|
2629
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
2675
2630
|
return "none";
|
|
2676
2631
|
}
|
|
2677
2632
|
var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
|
|
@@ -2689,8 +2644,7 @@ function isRecord(value) {
|
|
|
2689
2644
|
function getNestedRecord(root, path11) {
|
|
2690
2645
|
let cursor = root;
|
|
2691
2646
|
for (const key of path11) {
|
|
2692
|
-
if (!isRecord(cursor))
|
|
2693
|
-
return void 0;
|
|
2647
|
+
if (!isRecord(cursor)) return void 0;
|
|
2694
2648
|
cursor = cursor[key];
|
|
2695
2649
|
}
|
|
2696
2650
|
return isRecord(cursor) ? cursor : void 0;
|
|
@@ -2698,8 +2652,7 @@ function getNestedRecord(root, path11) {
|
|
|
2698
2652
|
function getNestedString(root, path11) {
|
|
2699
2653
|
let cursor = root;
|
|
2700
2654
|
for (const key of path11) {
|
|
2701
|
-
if (!isRecord(cursor))
|
|
2702
|
-
return void 0;
|
|
2655
|
+
if (!isRecord(cursor)) return void 0;
|
|
2703
2656
|
cursor = cursor[key];
|
|
2704
2657
|
}
|
|
2705
2658
|
return typeof cursor === "string" && cursor.length > 0 ? cursor : void 0;
|
|
@@ -2715,8 +2668,7 @@ function metadataProjectPaths(metadata) {
|
|
|
2715
2668
|
];
|
|
2716
2669
|
const paths = [];
|
|
2717
2670
|
for (const value of candidates) {
|
|
2718
|
-
if (value && !paths.includes(value))
|
|
2719
|
-
paths.push(value);
|
|
2671
|
+
if (value && !paths.includes(value)) paths.push(value);
|
|
2720
2672
|
}
|
|
2721
2673
|
return paths;
|
|
2722
2674
|
}
|
|
@@ -2737,12 +2689,9 @@ function maybeQuarantinePredicate(options, column = "metadata") {
|
|
|
2737
2689
|
return options?.includeQuarantined ? "1=1" : notActiveQuarantinedSql(column);
|
|
2738
2690
|
}
|
|
2739
2691
|
function safeParseMetadataValue(value) {
|
|
2740
|
-
if (!value)
|
|
2741
|
-
|
|
2742
|
-
if (typeof value
|
|
2743
|
-
return isRecord(value) ? value : void 0;
|
|
2744
|
-
if (typeof value !== "string")
|
|
2745
|
-
return void 0;
|
|
2692
|
+
if (!value) return void 0;
|
|
2693
|
+
if (typeof value === "object") return isRecord(value) ? value : void 0;
|
|
2694
|
+
if (typeof value !== "string") return void 0;
|
|
2746
2695
|
try {
|
|
2747
2696
|
const parsed = JSON.parse(value);
|
|
2748
2697
|
return isRecord(parsed) ? parsed : void 0;
|
|
@@ -2751,16 +2700,14 @@ function safeParseMetadataValue(value) {
|
|
|
2751
2700
|
}
|
|
2752
2701
|
}
|
|
2753
2702
|
function isImportedOrLegacyScopedMetadata(metadata) {
|
|
2754
|
-
if (!metadata)
|
|
2755
|
-
return false;
|
|
2703
|
+
if (!metadata) return false;
|
|
2756
2704
|
return Boolean(
|
|
2757
2705
|
metadata.importedFrom || metadata.sourceSessionId || metadata.sourceSessionHash || metadata.hermesSource || metadata.projectPath || metadata.sourceProjectPath || metadata.source === "hermes" || metadata.source === "claude" || metadata.source === "codex"
|
|
2758
2706
|
);
|
|
2759
2707
|
}
|
|
2760
2708
|
function addMetadataTag(metadata, tag) {
|
|
2761
2709
|
const current = Array.isArray(metadata.tags) ? metadata.tags.filter((value) => typeof value === "string") : [];
|
|
2762
|
-
if (!current.includes(tag))
|
|
2763
|
-
metadata.tags = [...current, tag];
|
|
2710
|
+
if (!current.includes(tag)) metadata.tags = [...current, tag];
|
|
2764
2711
|
}
|
|
2765
2712
|
function buildRepairResult(projectHash, dryRun) {
|
|
2766
2713
|
return {
|
|
@@ -2778,8 +2725,7 @@ function normalizeRepoName(value) {
|
|
|
2778
2725
|
return value.replace(/\.git$/i, "").trim().toLowerCase();
|
|
2779
2726
|
}
|
|
2780
2727
|
function projectBasename(projectPath) {
|
|
2781
|
-
if (!projectPath)
|
|
2782
|
-
return void 0;
|
|
2728
|
+
if (!projectPath) return void 0;
|
|
2783
2729
|
const trimmed = projectPath.replace(/[\\/]+$/, "");
|
|
2784
2730
|
const basename2 = nodePath2.basename(trimmed);
|
|
2785
2731
|
return basename2 ? normalizeRepoName(basename2) : void 0;
|
|
@@ -2792,23 +2738,19 @@ function isProjectScopeRepairExplanation(content) {
|
|
|
2792
2738
|
}
|
|
2793
2739
|
function hasConflictingContentProjectHint(content, projectPath) {
|
|
2794
2740
|
const currentName = projectBasename(projectPath);
|
|
2795
|
-
if (!currentName)
|
|
2796
|
-
|
|
2797
|
-
if (isProjectScopeRepairExplanation(content))
|
|
2798
|
-
return false;
|
|
2741
|
+
if (!currentName) return false;
|
|
2742
|
+
if (isProjectScopeRepairExplanation(content)) return false;
|
|
2799
2743
|
const githubRepoPattern = /github\.com[:/]([^/\s`'"#)]+)\/([^/\s`'"#)]+)(?:\.git)?/gi;
|
|
2800
2744
|
let githubMatch;
|
|
2801
2745
|
while ((githubMatch = githubRepoPattern.exec(content)) !== null) {
|
|
2802
2746
|
const repo = normalizeRepoName(githubMatch[2] || "");
|
|
2803
|
-
if (repo && repo !== currentName)
|
|
2804
|
-
return true;
|
|
2747
|
+
if (repo && repo !== currentName) return true;
|
|
2805
2748
|
}
|
|
2806
2749
|
const workspacePathPattern = /\/workspace\/([^/\s`'"#)]+)/gi;
|
|
2807
2750
|
let workspaceMatch;
|
|
2808
2751
|
while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {
|
|
2809
2752
|
const repo = normalizeRepoName(workspaceMatch[1] || "");
|
|
2810
|
-
if (repo && repo !== currentName)
|
|
2811
|
-
return true;
|
|
2753
|
+
if (repo && repo !== currentName) return true;
|
|
2812
2754
|
}
|
|
2813
2755
|
return false;
|
|
2814
2756
|
}
|
|
@@ -2828,15 +2770,12 @@ var SQLiteEventStore = class {
|
|
|
2828
2770
|
this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);
|
|
2829
2771
|
}
|
|
2830
2772
|
createVectorOutbox(option) {
|
|
2831
|
-
if (this.readOnly || option === false)
|
|
2832
|
-
|
|
2833
|
-
if (option instanceof VectorOutbox)
|
|
2834
|
-
return option;
|
|
2773
|
+
if (this.readOnly || option === false) return null;
|
|
2774
|
+
if (option instanceof VectorOutbox) return option;
|
|
2835
2775
|
return new VectorOutbox(this.db, option ?? {});
|
|
2836
2776
|
}
|
|
2837
2777
|
enqueueVectorOutboxEventSync(eventId) {
|
|
2838
|
-
if (!this.vectorOutbox)
|
|
2839
|
-
return;
|
|
2778
|
+
if (!this.vectorOutbox) return;
|
|
2840
2779
|
this.vectorOutbox.enqueueSync("event", eventId);
|
|
2841
2780
|
}
|
|
2842
2781
|
async enqueueVectorOutboxEvent(eventId) {
|
|
@@ -2846,8 +2785,7 @@ var SQLiteEventStore = class {
|
|
|
2846
2785
|
* Initialize database schema
|
|
2847
2786
|
*/
|
|
2848
2787
|
async initialize() {
|
|
2849
|
-
if (this.initialized)
|
|
2850
|
-
return;
|
|
2788
|
+
if (this.initialized) return;
|
|
2851
2789
|
if (this.readOnly) {
|
|
2852
2790
|
this.initialized = true;
|
|
2853
2791
|
return;
|
|
@@ -3405,10 +3343,8 @@ var SQLiteEventStore = class {
|
|
|
3405
3343
|
try {
|
|
3406
3344
|
const edgeIndexes = sqliteAll(this.db, `PRAGMA index_list(memory_action_edges)`, []);
|
|
3407
3345
|
const hasSourceAwareUnique = edgeIndexes.some((index) => {
|
|
3408
|
-
if (Number(index.unique) !== 1)
|
|
3409
|
-
|
|
3410
|
-
if (!/^[A-Za-z0-9_]+$/.test(index.name))
|
|
3411
|
-
return false;
|
|
3346
|
+
if (Number(index.unique) !== 1) return false;
|
|
3347
|
+
if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;
|
|
3412
3348
|
const escapedName = index.name.replace(/"/g, '""');
|
|
3413
3349
|
const columns = sqliteAll(this.db, 'PRAGMA index_info("' + escapedName + '")', []).map((column) => column.name);
|
|
3414
3350
|
return columns.length === 5 && columns[0] === "src_action_id" && columns[1] === "rel_type" && columns[2] === "dst_type" && columns[3] === "dst_id" && columns[4] === "source";
|
|
@@ -3648,8 +3584,7 @@ var SQLiteEventStore = class {
|
|
|
3648
3584
|
`SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,
|
|
3649
3585
|
[id]
|
|
3650
3586
|
);
|
|
3651
|
-
if (!row)
|
|
3652
|
-
return null;
|
|
3587
|
+
if (!row) return null;
|
|
3653
3588
|
return this.rowToEvent(row);
|
|
3654
3589
|
}
|
|
3655
3590
|
/**
|
|
@@ -3687,10 +3622,8 @@ var SQLiteEventStore = class {
|
|
|
3687
3622
|
* NOTE: This bypasses the append() id generation to preserve stable IDs.
|
|
3688
3623
|
*/
|
|
3689
3624
|
async importEvents(events) {
|
|
3690
|
-
if (events.length === 0)
|
|
3691
|
-
|
|
3692
|
-
if (this.readOnly)
|
|
3693
|
-
return { inserted: 0, skipped: events.length };
|
|
3625
|
+
if (events.length === 0) return { inserted: 0, skipped: 0 };
|
|
3626
|
+
if (this.readOnly) return { inserted: 0, skipped: events.length };
|
|
3694
3627
|
await this.initialize();
|
|
3695
3628
|
const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);
|
|
3696
3629
|
const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);
|
|
@@ -3808,8 +3741,7 @@ var SQLiteEventStore = class {
|
|
|
3808
3741
|
`SELECT * FROM sessions WHERE id = ?`,
|
|
3809
3742
|
[id]
|
|
3810
3743
|
);
|
|
3811
|
-
if (!row)
|
|
3812
|
-
return null;
|
|
3744
|
+
if (!row) return null;
|
|
3813
3745
|
return {
|
|
3814
3746
|
id: row.id,
|
|
3815
3747
|
startedAt: toDateFromSQLite(row.started_at),
|
|
@@ -3864,8 +3796,7 @@ var SQLiteEventStore = class {
|
|
|
3864
3796
|
LIMIT ?`,
|
|
3865
3797
|
[limit]
|
|
3866
3798
|
);
|
|
3867
|
-
if (pending.length === 0)
|
|
3868
|
-
return [];
|
|
3799
|
+
if (pending.length === 0) return [];
|
|
3869
3800
|
const ids = pending.map((r) => r.id);
|
|
3870
3801
|
const placeholders = ids.map(() => "?").join(",");
|
|
3871
3802
|
sqliteRun(
|
|
@@ -3889,8 +3820,7 @@ var SQLiteEventStore = class {
|
|
|
3889
3820
|
* Mark outbox items as done
|
|
3890
3821
|
*/
|
|
3891
3822
|
async completeOutboxItems(ids) {
|
|
3892
|
-
if (ids.length === 0)
|
|
3893
|
-
return;
|
|
3823
|
+
if (ids.length === 0) return;
|
|
3894
3824
|
const placeholders = ids.map(() => "?").join(",");
|
|
3895
3825
|
sqliteRun(
|
|
3896
3826
|
this.db,
|
|
@@ -3929,8 +3859,7 @@ var SQLiteEventStore = class {
|
|
|
3929
3859
|
* Mark outbox items as failed
|
|
3930
3860
|
*/
|
|
3931
3861
|
async failOutboxItems(ids, error) {
|
|
3932
|
-
if (ids.length === 0)
|
|
3933
|
-
return;
|
|
3862
|
+
if (ids.length === 0) return;
|
|
3934
3863
|
const placeholders = ids.map(() => "?").join(",");
|
|
3935
3864
|
sqliteRun(
|
|
3936
3865
|
this.db,
|
|
@@ -4057,8 +3986,7 @@ var SQLiteEventStore = class {
|
|
|
4057
3986
|
[]
|
|
4058
3987
|
);
|
|
4059
3988
|
const sample = (entry) => {
|
|
4060
|
-
if (result.samples.length < 20)
|
|
4061
|
-
result.samples.push(entry);
|
|
3989
|
+
if (result.samples.length < 20) result.samples.push(entry);
|
|
4062
3990
|
};
|
|
4063
3991
|
for (const row of rows) {
|
|
4064
3992
|
result.scanned++;
|
|
@@ -4185,12 +4113,10 @@ var SQLiteEventStore = class {
|
|
|
4185
4113
|
`SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`
|
|
4186
4114
|
);
|
|
4187
4115
|
const processingAgeMs = (value) => {
|
|
4188
|
-
if (value === null || value === void 0)
|
|
4189
|
-
return null;
|
|
4116
|
+
if (value === null || value === void 0) return null;
|
|
4190
4117
|
const date = toDateFromSQLite(value);
|
|
4191
4118
|
const time = date.getTime();
|
|
4192
|
-
if (!Number.isFinite(time))
|
|
4193
|
-
return null;
|
|
4119
|
+
if (!Number.isFinite(time)) return null;
|
|
4194
4120
|
return Math.max(0, now.getTime() - time);
|
|
4195
4121
|
};
|
|
4196
4122
|
const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs) => {
|
|
@@ -4339,8 +4265,7 @@ var SQLiteEventStore = class {
|
|
|
4339
4265
|
`SELECT value FROM endless_config WHERE key = ?`,
|
|
4340
4266
|
[key]
|
|
4341
4267
|
);
|
|
4342
|
-
if (!row)
|
|
4343
|
-
return null;
|
|
4268
|
+
if (!row) return null;
|
|
4344
4269
|
return JSON.parse(row.value);
|
|
4345
4270
|
}
|
|
4346
4271
|
/**
|
|
@@ -4359,8 +4284,7 @@ var SQLiteEventStore = class {
|
|
|
4359
4284
|
* Increment access count for events
|
|
4360
4285
|
*/
|
|
4361
4286
|
async incrementAccessCount(eventIds) {
|
|
4362
|
-
if (eventIds.length === 0 || this.readOnly)
|
|
4363
|
-
return;
|
|
4287
|
+
if (eventIds.length === 0 || this.readOnly) return;
|
|
4364
4288
|
await this.initialize();
|
|
4365
4289
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4366
4290
|
const currentTime = toSQLiteTimestamp(/* @__PURE__ */ new Date());
|
|
@@ -4403,8 +4327,7 @@ var SQLiteEventStore = class {
|
|
|
4403
4327
|
* Record a memory retrieval for helpfulness tracking
|
|
4404
4328
|
*/
|
|
4405
4329
|
async recordRetrieval(eventId, sessionId, score, query) {
|
|
4406
|
-
if (this.readOnly)
|
|
4407
|
-
return;
|
|
4330
|
+
if (this.readOnly) return;
|
|
4408
4331
|
await this.initialize();
|
|
4409
4332
|
const id = randomUUID6();
|
|
4410
4333
|
sqliteRun(
|
|
@@ -4434,16 +4357,14 @@ var SQLiteEventStore = class {
|
|
|
4434
4357
|
* Called at session end - uses behavioral signals to compute score
|
|
4435
4358
|
*/
|
|
4436
4359
|
async evaluateSessionHelpfulness(sessionId) {
|
|
4437
|
-
if (this.readOnly)
|
|
4438
|
-
return;
|
|
4360
|
+
if (this.readOnly) return;
|
|
4439
4361
|
await this.initialize();
|
|
4440
4362
|
const retrievals = sqliteAll(
|
|
4441
4363
|
this.db,
|
|
4442
4364
|
`SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,
|
|
4443
4365
|
[sessionId]
|
|
4444
4366
|
);
|
|
4445
|
-
if (retrievals.length === 0)
|
|
4446
|
-
return;
|
|
4367
|
+
if (retrievals.length === 0) return;
|
|
4447
4368
|
const sessionEvents = sqliteAll(
|
|
4448
4369
|
this.db,
|
|
4449
4370
|
`SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
|
|
@@ -4456,8 +4377,7 @@ var SQLiteEventStore = class {
|
|
|
4456
4377
|
for (const t of toolEvents) {
|
|
4457
4378
|
try {
|
|
4458
4379
|
const content = JSON.parse(t.content);
|
|
4459
|
-
if (content.success !== false)
|
|
4460
|
-
toolSuccessCount++;
|
|
4380
|
+
if (content.success !== false) toolSuccessCount++;
|
|
4461
4381
|
} catch {
|
|
4462
4382
|
toolSuccessCount++;
|
|
4463
4383
|
}
|
|
@@ -4475,8 +4395,7 @@ var SQLiteEventStore = class {
|
|
|
4475
4395
|
const pWords = new Set(p.content.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
4476
4396
|
let overlap = 0;
|
|
4477
4397
|
for (const w of queryWords) {
|
|
4478
|
-
if (pWords.has(w))
|
|
4479
|
-
overlap++;
|
|
4398
|
+
if (pWords.has(w)) overlap++;
|
|
4480
4399
|
}
|
|
4481
4400
|
if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {
|
|
4482
4401
|
wasReasked = 1;
|
|
@@ -4658,8 +4577,7 @@ var SQLiteEventStore = class {
|
|
|
4658
4577
|
return this.db;
|
|
4659
4578
|
}
|
|
4660
4579
|
hasTableColumn(tableName, columnName2) {
|
|
4661
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName))
|
|
4662
|
-
return false;
|
|
4580
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;
|
|
4663
4581
|
try {
|
|
4664
4582
|
const rows = sqliteAll(this.db, `PRAGMA table_info("${tableName}")`, []);
|
|
4665
4583
|
return rows.some((row) => row.name === columnName2);
|
|
@@ -4726,8 +4644,7 @@ var SQLiteEventStore = class {
|
|
|
4726
4644
|
createdAt: toDateFromSQLite(row.created_at)
|
|
4727
4645
|
}));
|
|
4728
4646
|
} catch (err) {
|
|
4729
|
-
if (err?.message?.includes("no such table"))
|
|
4730
|
-
return [];
|
|
4647
|
+
if (err?.message?.includes("no such table")) return [];
|
|
4731
4648
|
throw err;
|
|
4732
4649
|
}
|
|
4733
4650
|
}
|
|
@@ -4900,8 +4817,7 @@ var SQLiteEventStore = class {
|
|
|
4900
4817
|
`SELECT id FROM events WHERE session_id = ?`,
|
|
4901
4818
|
[sessionId]
|
|
4902
4819
|
);
|
|
4903
|
-
if (events.length === 0)
|
|
4904
|
-
return 0;
|
|
4820
|
+
if (events.length === 0) return 0;
|
|
4905
4821
|
const eventIds = events.map((e) => e.id);
|
|
4906
4822
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4907
4823
|
const ftsTriggersDropped = [];
|
|
@@ -5113,8 +5029,7 @@ function sanitizeGovernanceAuditValue(value, key) {
|
|
|
5113
5029
|
return value;
|
|
5114
5030
|
}
|
|
5115
5031
|
function sanitizeAuditJson(value) {
|
|
5116
|
-
if (value === void 0)
|
|
5117
|
-
return void 0;
|
|
5032
|
+
if (value === void 0) return void 0;
|
|
5118
5033
|
return sanitizeGovernanceAuditValue(value);
|
|
5119
5034
|
}
|
|
5120
5035
|
function normalizeSourceEventIds(sourceEventIds) {
|
|
@@ -5163,12 +5078,10 @@ async function writeGovernanceAuditEntry(db, input) {
|
|
|
5163
5078
|
|
|
5164
5079
|
// src/core/operations/facet-repository.ts
|
|
5165
5080
|
function parseStringArray(value) {
|
|
5166
|
-
if (typeof value !== "string")
|
|
5167
|
-
return [];
|
|
5081
|
+
if (typeof value !== "string") return [];
|
|
5168
5082
|
try {
|
|
5169
5083
|
const parsed = JSON.parse(value);
|
|
5170
|
-
if (!Array.isArray(parsed))
|
|
5171
|
-
return [];
|
|
5084
|
+
if (!Array.isArray(parsed)) return [];
|
|
5172
5085
|
return parsed.filter((item) => typeof item === "string" && item.length > 0);
|
|
5173
5086
|
} catch {
|
|
5174
5087
|
return [];
|
|
@@ -5212,6 +5125,7 @@ var FacetRepository = class {
|
|
|
5212
5125
|
constructor(db) {
|
|
5213
5126
|
this.db = db;
|
|
5214
5127
|
}
|
|
5128
|
+
db;
|
|
5215
5129
|
async assign(input) {
|
|
5216
5130
|
const assignment = parseFacetAssignmentInput(input);
|
|
5217
5131
|
const existing = this.findByUniqueKey(assignment);
|
|
@@ -5516,19 +5430,14 @@ var RetentionFacetSchema = z5.object({
|
|
|
5516
5430
|
confidence: z5.number().min(0).max(1).default(1)
|
|
5517
5431
|
});
|
|
5518
5432
|
var DateLikeSchema = z5.preprocess((value) => {
|
|
5519
|
-
if (value instanceof Date)
|
|
5520
|
-
|
|
5521
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5522
|
-
return new Date(value);
|
|
5433
|
+
if (value instanceof Date) return value;
|
|
5434
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5523
5435
|
return value;
|
|
5524
5436
|
}, z5.date());
|
|
5525
5437
|
var NullableDateLikeSchema = z5.preprocess((value) => {
|
|
5526
|
-
if (value === null || value === void 0 || value === "")
|
|
5527
|
-
|
|
5528
|
-
if (value
|
|
5529
|
-
return value;
|
|
5530
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5531
|
-
return new Date(value);
|
|
5438
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
5439
|
+
if (value instanceof Date) return value;
|
|
5440
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5532
5441
|
return value;
|
|
5533
5442
|
}, z5.date().nullable());
|
|
5534
5443
|
var OptionalTrimmedStringSchema2 = z5.preprocess(
|
|
@@ -5557,10 +5466,8 @@ import { z as z6 } from "zod";
|
|
|
5557
5466
|
var RequiredTrimmedStringSchema = z6.string().trim().min(1);
|
|
5558
5467
|
var OptionalTrimmedStringSchema3 = z6.string().trim().min(1).optional();
|
|
5559
5468
|
var DateLikeSchema2 = z6.preprocess((value) => {
|
|
5560
|
-
if (value instanceof Date)
|
|
5561
|
-
|
|
5562
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5563
|
-
return new Date(value);
|
|
5469
|
+
if (value instanceof Date) return value;
|
|
5470
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5564
5471
|
return value;
|
|
5565
5472
|
}, z6.date());
|
|
5566
5473
|
var RetentionReasonSchema = z6.object({
|
|
@@ -5749,8 +5656,7 @@ var MemoryOperationsConfigSchema = z7.object({
|
|
|
5749
5656
|
}).default({});
|
|
5750
5657
|
var MemoryLessonNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5751
5658
|
var MemoryLessonStringArraySchema = z7.preprocess((value) => {
|
|
5752
|
-
if (!Array.isArray(value))
|
|
5753
|
-
return value;
|
|
5659
|
+
if (!Array.isArray(value)) return value;
|
|
5754
5660
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5755
5661
|
}, z7.array(MemoryLessonNonEmptyStringSchema)).default([]);
|
|
5756
5662
|
var MemoryLessonSchema = z7.object({
|
|
@@ -5795,14 +5701,12 @@ var ListMemoryLessonsInputSchema = z7.object({
|
|
|
5795
5701
|
});
|
|
5796
5702
|
var PerspectiveMemoryNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5797
5703
|
var PerspectiveMemoryOptionalStringSchema = z7.preprocess((value) => {
|
|
5798
|
-
if (typeof value !== "string")
|
|
5799
|
-
return value;
|
|
5704
|
+
if (typeof value !== "string") return value;
|
|
5800
5705
|
const normalized = value.trim();
|
|
5801
5706
|
return normalized.length > 0 ? normalized : void 0;
|
|
5802
5707
|
}, PerspectiveMemoryNonEmptyStringSchema.optional());
|
|
5803
5708
|
var PerspectiveMemoryStringArraySchema = z7.preprocess((value) => {
|
|
5804
|
-
if (!Array.isArray(value))
|
|
5805
|
-
return value;
|
|
5709
|
+
if (!Array.isArray(value)) return value;
|
|
5806
5710
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5807
5711
|
}, z7.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);
|
|
5808
5712
|
var ActorCardSensitivePattern = /(?:\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)\b\s*[:=])|(?:\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)=)|(?:^|\s)(?:\/[A-Za-z0-9._-][^\s`'\"]*)/i;
|
|
@@ -6460,6 +6364,7 @@ var GraphPathService = class {
|
|
|
6460
6364
|
constructor(db) {
|
|
6461
6365
|
this.db = db;
|
|
6462
6366
|
}
|
|
6367
|
+
db;
|
|
6463
6368
|
expand(input) {
|
|
6464
6369
|
const graph = this.loadGraph(input.direction ?? "both");
|
|
6465
6370
|
const effectiveMaxHops = normalizeMaxHops(input.maxHops);
|
|
@@ -6477,11 +6382,9 @@ var GraphPathService = class {
|
|
|
6477
6382
|
while (queue.length > 0) {
|
|
6478
6383
|
queue.sort((a, b) => a.totalCost - b.totalCost || a.hops - b.hops || a.key.localeCompare(b.key));
|
|
6479
6384
|
const current = queue.shift();
|
|
6480
|
-
if (current.hops >= effectiveMaxHops)
|
|
6481
|
-
continue;
|
|
6385
|
+
if (current.hops >= effectiveMaxHops) continue;
|
|
6482
6386
|
for (const edge of graph.adjacency.get(current.key) ?? []) {
|
|
6483
|
-
if (current.visited.has(edge.toKey))
|
|
6484
|
-
continue;
|
|
6387
|
+
if (current.visited.has(edge.toKey)) continue;
|
|
6485
6388
|
const nextHops = current.hops + 1;
|
|
6486
6389
|
const nextTotalCost = current.totalCost + edge.step.cost;
|
|
6487
6390
|
const nextSteps = [...current.steps, edge.step];
|
|
@@ -6561,17 +6464,13 @@ function addTraversal(adjacency, fromKey, edge) {
|
|
|
6561
6464
|
adjacency.set(fromKey, edges);
|
|
6562
6465
|
}
|
|
6563
6466
|
function normalizeMaxHops(maxHops) {
|
|
6564
|
-
if (maxHops === void 0)
|
|
6565
|
-
|
|
6566
|
-
if (!Number.isFinite(maxHops))
|
|
6567
|
-
return MAX_HOPS;
|
|
6467
|
+
if (maxHops === void 0) return 1;
|
|
6468
|
+
if (!Number.isFinite(maxHops)) return MAX_HOPS;
|
|
6568
6469
|
return Math.min(Math.max(0, Math.trunc(maxHops)), MAX_HOPS);
|
|
6569
6470
|
}
|
|
6570
6471
|
function normalizeMaxResults(maxResults) {
|
|
6571
|
-
if (maxResults === void 0)
|
|
6572
|
-
|
|
6573
|
-
if (!Number.isFinite(maxResults))
|
|
6574
|
-
return DEFAULT_MAX_RESULTS;
|
|
6472
|
+
if (maxResults === void 0) return DEFAULT_MAX_RESULTS;
|
|
6473
|
+
if (!Number.isFinite(maxResults)) return DEFAULT_MAX_RESULTS;
|
|
6575
6474
|
return Math.min(Math.max(0, Math.trunc(maxResults)), MAX_RESULTS);
|
|
6576
6475
|
}
|
|
6577
6476
|
function isBetterPath(totalCost, hops, signature, existing) {
|
|
@@ -6583,18 +6482,15 @@ function pathSignature(steps) {
|
|
|
6583
6482
|
function edgeWeight(metaJson) {
|
|
6584
6483
|
const meta = parseMeta(metaJson);
|
|
6585
6484
|
const raw = meta.weight;
|
|
6586
|
-
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
6587
|
-
return raw;
|
|
6485
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
6588
6486
|
if (typeof raw === "string") {
|
|
6589
6487
|
const parsed = Number(raw);
|
|
6590
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
6591
|
-
return parsed;
|
|
6488
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
6592
6489
|
}
|
|
6593
6490
|
return DEFAULT_WEIGHT;
|
|
6594
6491
|
}
|
|
6595
6492
|
function parseMeta(metaJson) {
|
|
6596
|
-
if (!metaJson)
|
|
6597
|
-
return {};
|
|
6493
|
+
if (!metaJson) return {};
|
|
6598
6494
|
try {
|
|
6599
6495
|
const parsed = JSON.parse(metaJson);
|
|
6600
6496
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -6607,8 +6503,7 @@ function nodeKey(node) {
|
|
|
6607
6503
|
}
|
|
6608
6504
|
function nodeFromKey(key) {
|
|
6609
6505
|
const index = key.indexOf(":");
|
|
6610
|
-
if (index === -1)
|
|
6611
|
-
return { type: "entity", id: key };
|
|
6506
|
+
if (index === -1) return { type: "entity", id: key };
|
|
6612
6507
|
return { type: key.slice(0, index), id: key.slice(index + 1) };
|
|
6613
6508
|
}
|
|
6614
6509
|
|
|
@@ -6664,6 +6559,7 @@ var QueryEntityExtractor = class {
|
|
|
6664
6559
|
constructor(db) {
|
|
6665
6560
|
this.db = db;
|
|
6666
6561
|
}
|
|
6562
|
+
db;
|
|
6667
6563
|
extract(query, options = {}) {
|
|
6668
6564
|
const maxCandidates = normalizeMaxCandidates(options.maxCandidates);
|
|
6669
6565
|
const candidates = [];
|
|
@@ -6685,8 +6581,7 @@ var QueryEntityExtractor = class {
|
|
|
6685
6581
|
let match;
|
|
6686
6582
|
while ((match = regex.exec(query)) !== null) {
|
|
6687
6583
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6688
|
-
if (!isUsefulCandidate(text))
|
|
6689
|
-
continue;
|
|
6584
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6690
6585
|
const start = match.index + 1;
|
|
6691
6586
|
const end = start + text.length;
|
|
6692
6587
|
ranges.push([match.index, match.index + match[0].length]);
|
|
@@ -6700,8 +6595,7 @@ var QueryEntityExtractor = class {
|
|
|
6700
6595
|
return ranges;
|
|
6701
6596
|
}
|
|
6702
6597
|
extractKnownAliases(query, candidates) {
|
|
6703
|
-
if (!this.db)
|
|
6704
|
-
return;
|
|
6598
|
+
if (!this.db) return;
|
|
6705
6599
|
const rows = sqliteAll(
|
|
6706
6600
|
this.db,
|
|
6707
6601
|
`SELECT
|
|
@@ -6725,11 +6619,9 @@ var QueryEntityExtractor = class {
|
|
|
6725
6619
|
]).filter(isUsefulCandidate);
|
|
6726
6620
|
for (const alias of aliasLabels) {
|
|
6727
6621
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6728
|
-
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias))
|
|
6729
|
-
continue;
|
|
6622
|
+
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias)) continue;
|
|
6730
6623
|
const aliasKey = `${row.entity_id}:${normalizedAlias}`;
|
|
6731
|
-
if (seenAliases.has(aliasKey))
|
|
6732
|
-
continue;
|
|
6624
|
+
if (seenAliases.has(aliasKey)) continue;
|
|
6733
6625
|
seenAliases.add(aliasKey);
|
|
6734
6626
|
const range = findRange(query, alias);
|
|
6735
6627
|
pushCandidate(candidates, {
|
|
@@ -6750,8 +6642,7 @@ var QueryEntityExtractor = class {
|
|
|
6750
6642
|
let match;
|
|
6751
6643
|
while ((match = regex.exec(query)) !== null) {
|
|
6752
6644
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6753
|
-
if (!isUsefulCandidate(text))
|
|
6754
|
-
continue;
|
|
6645
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6755
6646
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6756
6647
|
pushCandidate(candidates, {
|
|
6757
6648
|
text,
|
|
@@ -6766,8 +6657,7 @@ var QueryEntityExtractor = class {
|
|
|
6766
6657
|
let match;
|
|
6767
6658
|
while ((match = regex.exec(query)) !== null) {
|
|
6768
6659
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6769
|
-
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./"))
|
|
6770
|
-
continue;
|
|
6660
|
+
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./")) continue;
|
|
6771
6661
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6772
6662
|
pushCandidate(candidates, {
|
|
6773
6663
|
text,
|
|
@@ -6786,21 +6676,17 @@ var QueryEntityExtractor = class {
|
|
|
6786
6676
|
if (previous && query.slice(previous.end, token.start).match(/^\s+$/)) {
|
|
6787
6677
|
current.push(token);
|
|
6788
6678
|
} else {
|
|
6789
|
-
if (current.length > 0)
|
|
6790
|
-
groups.push(current);
|
|
6679
|
+
if (current.length > 0) groups.push(current);
|
|
6791
6680
|
current = [token];
|
|
6792
6681
|
}
|
|
6793
6682
|
}
|
|
6794
|
-
if (current.length > 0)
|
|
6795
|
-
groups.push(current);
|
|
6683
|
+
if (current.length > 0) groups.push(current);
|
|
6796
6684
|
for (const group of groups) {
|
|
6797
|
-
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text))
|
|
6798
|
-
continue;
|
|
6685
|
+
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text)) continue;
|
|
6799
6686
|
const start = group[0].start;
|
|
6800
6687
|
const end = group[group.length - 1].end;
|
|
6801
6688
|
const text = query.slice(start, end);
|
|
6802
|
-
if (!isUsefulCandidate(text))
|
|
6803
|
-
continue;
|
|
6689
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6804
6690
|
pushCandidate(candidates, {
|
|
6805
6691
|
text,
|
|
6806
6692
|
source: "capitalized_term",
|
|
@@ -6821,8 +6707,7 @@ function collectCapitalizedTokens(query) {
|
|
|
6821
6707
|
}
|
|
6822
6708
|
function pushCandidate(candidates, input) {
|
|
6823
6709
|
const text = cleanCandidateText(input.text);
|
|
6824
|
-
if (!isUsefulCandidate(text))
|
|
6825
|
-
return;
|
|
6710
|
+
if (!isUsefulCandidate(text)) return;
|
|
6826
6711
|
const source = input.source;
|
|
6827
6712
|
candidates.push({
|
|
6828
6713
|
...input,
|
|
@@ -6840,15 +6725,13 @@ function dedupeAndSort(candidates) {
|
|
|
6840
6725
|
for (const candidate of sorted) {
|
|
6841
6726
|
if (candidate.source === "entity_alias") {
|
|
6842
6727
|
const aliasKey = `alias:${candidate.entityId ?? ""}:${normalizeCandidate(candidate.matchedAlias ?? candidate.text)}`;
|
|
6843
|
-
if (seenAliasKeys.has(aliasKey))
|
|
6844
|
-
continue;
|
|
6728
|
+
if (seenAliasKeys.has(aliasKey)) continue;
|
|
6845
6729
|
seenAliasKeys.add(aliasKey);
|
|
6846
6730
|
seenNormalized.add(candidate.normalized);
|
|
6847
6731
|
result.push(candidate);
|
|
6848
6732
|
continue;
|
|
6849
6733
|
}
|
|
6850
|
-
if (seenNormalized.has(candidate.normalized))
|
|
6851
|
-
continue;
|
|
6734
|
+
if (seenNormalized.has(candidate.normalized)) continue;
|
|
6852
6735
|
seenNormalized.add(candidate.normalized);
|
|
6853
6736
|
result.push(candidate);
|
|
6854
6737
|
}
|
|
@@ -6858,8 +6741,7 @@ function compareCandidates(a, b) {
|
|
|
6858
6741
|
return a.priority - b.priority || a.start - b.start || a.end - b.end || compareStrings(a.text, b.text) || compareStrings(a.entityId ?? "", b.entityId ?? "") || compareStrings(a.matchedAlias ?? "", b.matchedAlias ?? "");
|
|
6859
6742
|
}
|
|
6860
6743
|
function compareStrings(a, b) {
|
|
6861
|
-
if (a === b)
|
|
6862
|
-
return 0;
|
|
6744
|
+
if (a === b) return 0;
|
|
6863
6745
|
return a < b ? -1 : 1;
|
|
6864
6746
|
}
|
|
6865
6747
|
function stripPriority(candidate) {
|
|
@@ -6867,10 +6749,8 @@ function stripPriority(candidate) {
|
|
|
6867
6749
|
return publicCandidate;
|
|
6868
6750
|
}
|
|
6869
6751
|
function normalizeMaxCandidates(maxCandidates) {
|
|
6870
|
-
if (maxCandidates === void 0)
|
|
6871
|
-
|
|
6872
|
-
if (!Number.isFinite(maxCandidates))
|
|
6873
|
-
return DEFAULT_MAX_CANDIDATES;
|
|
6752
|
+
if (maxCandidates === void 0) return DEFAULT_MAX_CANDIDATES;
|
|
6753
|
+
if (!Number.isFinite(maxCandidates)) return DEFAULT_MAX_CANDIDATES;
|
|
6874
6754
|
return Math.min(Math.max(0, Math.trunc(maxCandidates)), MAX_CANDIDATES);
|
|
6875
6755
|
}
|
|
6876
6756
|
function cleanCandidateText(text) {
|
|
@@ -6892,21 +6772,17 @@ function aliasLabelFromCanonicalKey(canonicalKey) {
|
|
|
6892
6772
|
function findRange(query, alias) {
|
|
6893
6773
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6894
6774
|
const directIndex = query.toLowerCase().indexOf(alias.toLowerCase());
|
|
6895
|
-
if (directIndex >= 0)
|
|
6896
|
-
return { start: directIndex, end: directIndex + alias.length };
|
|
6775
|
+
if (directIndex >= 0) return { start: directIndex, end: directIndex + alias.length };
|
|
6897
6776
|
const normalizedQuery = normalizeForContainment(query);
|
|
6898
6777
|
const normalizedIndex = normalizedQuery.indexOf(normalizedAlias);
|
|
6899
|
-
if (normalizedIndex < 0)
|
|
6900
|
-
return { start: 0, end: 0 };
|
|
6778
|
+
if (normalizedIndex < 0) return { start: 0, end: 0 };
|
|
6901
6779
|
const queryLower = query.toLowerCase();
|
|
6902
6780
|
const words = normalizedAlias.split(" ").filter(Boolean);
|
|
6903
|
-
if (words.length === 0)
|
|
6904
|
-
return { start: 0, end: 0 };
|
|
6781
|
+
if (words.length === 0) return { start: 0, end: 0 };
|
|
6905
6782
|
const first = queryLower.indexOf(words[0]);
|
|
6906
6783
|
const lastWord = words[words.length - 1];
|
|
6907
6784
|
const last = queryLower.indexOf(lastWord, first >= 0 ? first : 0);
|
|
6908
|
-
if (first >= 0 && last >= 0)
|
|
6909
|
-
return { start: first, end: last + lastWord.length };
|
|
6785
|
+
if (first >= 0 && last >= 0) return { start: first, end: last + lastWord.length };
|
|
6910
6786
|
return { start: normalizedIndex, end: normalizedIndex + normalizedAlias.length };
|
|
6911
6787
|
}
|
|
6912
6788
|
function isUsefulCandidate(text) {
|
|
@@ -6917,10 +6793,8 @@ function isInsideAnyRange(index, ranges) {
|
|
|
6917
6793
|
return ranges.some(([start, end]) => index >= start && index < end);
|
|
6918
6794
|
}
|
|
6919
6795
|
function isStrongSingleCapitalized(text) {
|
|
6920
|
-
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text))
|
|
6921
|
-
|
|
6922
|
-
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text))
|
|
6923
|
-
return true;
|
|
6796
|
+
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text)) return true;
|
|
6797
|
+
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text)) return true;
|
|
6924
6798
|
return text.length >= 4 && !SENTENCE_START_STOPWORDS.has(text);
|
|
6925
6799
|
}
|
|
6926
6800
|
function uniqueStrings(values) {
|
|
@@ -6928,8 +6802,7 @@ function uniqueStrings(values) {
|
|
|
6928
6802
|
const result = [];
|
|
6929
6803
|
for (const value of values) {
|
|
6930
6804
|
const key = normalizeForContainment(value);
|
|
6931
|
-
if (!key || seen.has(key))
|
|
6932
|
-
continue;
|
|
6805
|
+
if (!key || seen.has(key)) continue;
|
|
6933
6806
|
seen.add(key);
|
|
6934
6807
|
result.push(value);
|
|
6935
6808
|
}
|
|
@@ -6951,8 +6824,7 @@ var LessonCandidateInputSchema = z9.object({
|
|
|
6951
6824
|
import { z as z10 } from "zod";
|
|
6952
6825
|
var NonEmptyStringSchema5 = z10.string().transform((value) => value.trim()).pipe(z10.string().min(1));
|
|
6953
6826
|
var PromotionStringArraySchema = z10.preprocess((value) => {
|
|
6954
|
-
if (!Array.isArray(value))
|
|
6955
|
-
return value;
|
|
6827
|
+
if (!Array.isArray(value)) return value;
|
|
6956
6828
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
6957
6829
|
}, z10.array(NonEmptyStringSchema5).max(100));
|
|
6958
6830
|
var ReviewedLessonCandidateSchema = z10.object({
|
|
@@ -7000,8 +6872,7 @@ function projectHashFromStorage(projectHash) {
|
|
|
7000
6872
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7001
6873
|
}
|
|
7002
6874
|
function parseJsonRecord(value) {
|
|
7003
|
-
if (!value)
|
|
7004
|
-
return void 0;
|
|
6875
|
+
if (!value) return void 0;
|
|
7005
6876
|
try {
|
|
7006
6877
|
const parsed = JSON.parse(value);
|
|
7007
6878
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7013,8 +6884,7 @@ function sanitizeString(value) {
|
|
|
7013
6884
|
return String(sanitizeGovernanceAuditValue(value)).trim();
|
|
7014
6885
|
}
|
|
7015
6886
|
function sanitizeMetadata(metadata) {
|
|
7016
|
-
if (!metadata)
|
|
7017
|
-
return void 0;
|
|
6887
|
+
if (!metadata) return void 0;
|
|
7018
6888
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7019
6889
|
}
|
|
7020
6890
|
function slugActorPart(value) {
|
|
@@ -7022,8 +6892,7 @@ function slugActorPart(value) {
|
|
|
7022
6892
|
return slug.length > 0 ? slug : "unknown";
|
|
7023
6893
|
}
|
|
7024
6894
|
function stableActorId(input) {
|
|
7025
|
-
if (input.actorId)
|
|
7026
|
-
return sanitizeString(input.actorId);
|
|
6895
|
+
if (input.actorId) return sanitizeString(input.actorId);
|
|
7027
6896
|
const projectPart = input.projectHash ? `project:${slugActorPart(input.projectHash)}` : "global";
|
|
7028
6897
|
return [
|
|
7029
6898
|
"actor",
|
|
@@ -7046,12 +6915,10 @@ function rowToActor(row) {
|
|
|
7046
6915
|
});
|
|
7047
6916
|
}
|
|
7048
6917
|
function metadataString(metadata, keys) {
|
|
7049
|
-
if (!metadata)
|
|
7050
|
-
return void 0;
|
|
6918
|
+
if (!metadata) return void 0;
|
|
7051
6919
|
for (const key of keys) {
|
|
7052
6920
|
const value = metadata[key];
|
|
7053
|
-
if (typeof value === "string" && value.trim().length > 0)
|
|
7054
|
-
return value.trim();
|
|
6921
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
7055
6922
|
}
|
|
7056
6923
|
return void 0;
|
|
7057
6924
|
}
|
|
@@ -7101,6 +6968,7 @@ var ActorRepository = class {
|
|
|
7101
6968
|
constructor(db) {
|
|
7102
6969
|
this.db = db;
|
|
7103
6970
|
}
|
|
6971
|
+
db;
|
|
7104
6972
|
async upsert(input) {
|
|
7105
6973
|
const parsed = UpsertMemoryActorInputSchema.parse(input);
|
|
7106
6974
|
const actorId = stableActorId(parsed);
|
|
@@ -7154,8 +7022,7 @@ var ActorRepository = class {
|
|
|
7154
7022
|
}
|
|
7155
7023
|
require(actorId) {
|
|
7156
7024
|
const actor = this.get(actorId);
|
|
7157
|
-
if (!actor)
|
|
7158
|
-
throw new Error(`Memory actor not found: ${actorId}`);
|
|
7025
|
+
if (!actor) throw new Error(`Memory actor not found: ${actorId}`);
|
|
7159
7026
|
return actor;
|
|
7160
7027
|
}
|
|
7161
7028
|
async list(input = {}) {
|
|
@@ -7191,8 +7058,7 @@ function projectHashFromStorage2(projectHash) {
|
|
|
7191
7058
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7192
7059
|
}
|
|
7193
7060
|
function parseJsonRecord2(value) {
|
|
7194
|
-
if (!value)
|
|
7195
|
-
return void 0;
|
|
7061
|
+
if (!value) return void 0;
|
|
7196
7062
|
try {
|
|
7197
7063
|
const parsed = JSON.parse(value);
|
|
7198
7064
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7201,8 +7067,7 @@ function parseJsonRecord2(value) {
|
|
|
7201
7067
|
}
|
|
7202
7068
|
}
|
|
7203
7069
|
function sanitizeMetadata2(metadata) {
|
|
7204
|
-
if (!metadata)
|
|
7205
|
-
return void 0;
|
|
7070
|
+
if (!metadata) return void 0;
|
|
7206
7071
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7207
7072
|
}
|
|
7208
7073
|
function rowToSessionActor(row) {
|
|
@@ -7222,6 +7087,7 @@ var SessionActorRepository = class {
|
|
|
7222
7087
|
constructor(db) {
|
|
7223
7088
|
this.db = db;
|
|
7224
7089
|
}
|
|
7090
|
+
db;
|
|
7225
7091
|
async upsertMembership(input) {
|
|
7226
7092
|
const parsed = UpsertSessionActorInputSchema.parse(input);
|
|
7227
7093
|
const projectHash = projectHashToStorage3(parsed.projectHash);
|
|
@@ -7268,8 +7134,7 @@ var SessionActorRepository = class {
|
|
|
7268
7134
|
);
|
|
7269
7135
|
}
|
|
7270
7136
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7271
|
-
if (!saved)
|
|
7272
|
-
throw new Error("session actor membership was not saved");
|
|
7137
|
+
if (!saved) throw new Error("session actor membership was not saved");
|
|
7273
7138
|
return saved;
|
|
7274
7139
|
}
|
|
7275
7140
|
async listBySession(input) {
|
|
@@ -7305,8 +7170,7 @@ var SessionActorRepository = class {
|
|
|
7305
7170
|
]
|
|
7306
7171
|
);
|
|
7307
7172
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7308
|
-
if (!saved)
|
|
7309
|
-
throw new Error("session actor membership not found after update");
|
|
7173
|
+
if (!saved) throw new Error("session actor membership not found after update");
|
|
7310
7174
|
return saved;
|
|
7311
7175
|
}
|
|
7312
7176
|
get(projectHash, sessionId, actorId) {
|
|
@@ -7328,8 +7192,7 @@ function projectHashFromStorage3(projectHash) {
|
|
|
7328
7192
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7329
7193
|
}
|
|
7330
7194
|
function parseStringArray2(value) {
|
|
7331
|
-
if (!value)
|
|
7332
|
-
return [];
|
|
7195
|
+
if (!value) return [];
|
|
7333
7196
|
try {
|
|
7334
7197
|
const parsed = JSON.parse(value);
|
|
7335
7198
|
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
@@ -7338,8 +7201,7 @@ function parseStringArray2(value) {
|
|
|
7338
7201
|
}
|
|
7339
7202
|
}
|
|
7340
7203
|
function parseJsonRecord3(value) {
|
|
7341
|
-
if (!value)
|
|
7342
|
-
return void 0;
|
|
7204
|
+
if (!value) return void 0;
|
|
7343
7205
|
try {
|
|
7344
7206
|
const parsed = JSON.parse(value);
|
|
7345
7207
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7355,8 +7217,7 @@ function sanitizeStoredStringArray(values) {
|
|
|
7355
7217
|
return values.map(sanitizeStoredString).filter((value) => value.length > 0);
|
|
7356
7218
|
}
|
|
7357
7219
|
function sanitizeStoredRecord(value) {
|
|
7358
|
-
if (!value)
|
|
7359
|
-
return void 0;
|
|
7220
|
+
if (!value) return void 0;
|
|
7360
7221
|
return sanitizeGovernanceAuditValue(value);
|
|
7361
7222
|
}
|
|
7362
7223
|
function stableHash(value) {
|
|
@@ -7407,8 +7268,7 @@ function sanitizedObservationSnapshot(observation) {
|
|
|
7407
7268
|
});
|
|
7408
7269
|
}
|
|
7409
7270
|
function queryScore(observation, terms) {
|
|
7410
|
-
if (terms.length === 0)
|
|
7411
|
-
return 0;
|
|
7271
|
+
if (terms.length === 0) return 0;
|
|
7412
7272
|
const haystack = [observation.content, observation.level, observation.sessionId ?? ""].join(" ").toLowerCase();
|
|
7413
7273
|
return terms.reduce((score, term) => score + (haystack.includes(term) ? 1 : 0), 0);
|
|
7414
7274
|
}
|
|
@@ -7454,12 +7314,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7454
7314
|
this.vectorOutbox = options.vectorOutbox;
|
|
7455
7315
|
}
|
|
7456
7316
|
}
|
|
7317
|
+
db;
|
|
7457
7318
|
vectorOutbox = null;
|
|
7458
7319
|
vectorOutboxOption;
|
|
7459
7320
|
getVectorOutbox() {
|
|
7460
7321
|
const option = this.vectorOutboxOption;
|
|
7461
|
-
if (option === false)
|
|
7462
|
-
return null;
|
|
7322
|
+
if (option === false) return null;
|
|
7463
7323
|
if (option instanceof VectorOutbox) {
|
|
7464
7324
|
this.vectorOutbox = option;
|
|
7465
7325
|
return option;
|
|
@@ -7471,8 +7331,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7471
7331
|
}
|
|
7472
7332
|
enqueueObservationSync(observationId) {
|
|
7473
7333
|
const outbox = this.getVectorOutbox();
|
|
7474
|
-
if (!outbox)
|
|
7475
|
-
return;
|
|
7334
|
+
if (!outbox) return;
|
|
7476
7335
|
outbox.enqueueSync("perspective_observation", observationId);
|
|
7477
7336
|
}
|
|
7478
7337
|
async create(input) {
|
|
@@ -7534,14 +7393,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7534
7393
|
contentHash,
|
|
7535
7394
|
sourceHash
|
|
7536
7395
|
);
|
|
7537
|
-
if (!saved)
|
|
7538
|
-
throw new Error("perspective observation was not saved");
|
|
7396
|
+
if (!saved) throw new Error("perspective observation was not saved");
|
|
7539
7397
|
this.enqueueObservationSync(saved.observationId);
|
|
7540
7398
|
});
|
|
7541
7399
|
transaction();
|
|
7542
7400
|
const savedObservation = saved;
|
|
7543
|
-
if (!savedObservation)
|
|
7544
|
-
throw new Error("perspective observation was not saved");
|
|
7401
|
+
if (!savedObservation) throw new Error("perspective observation was not saved");
|
|
7545
7402
|
await this.writeCreateAudit({ ...parsed, observerActorId, observedActorId, sessionId, content, sourceEventIds, sourceObservationIds, createdBy, actor, metadata }, savedObservation);
|
|
7546
7403
|
return savedObservation;
|
|
7547
7404
|
}
|
|
@@ -7551,8 +7408,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7551
7408
|
const ftsQuery = buildObservationFtsQuery(parsed.query);
|
|
7552
7409
|
if (ftsQuery) {
|
|
7553
7410
|
const ftsResult = this.queryWithFts(parsed, ftsQuery);
|
|
7554
|
-
if (ftsResult)
|
|
7555
|
-
return ftsResult;
|
|
7411
|
+
if (ftsResult) return ftsResult;
|
|
7556
7412
|
}
|
|
7557
7413
|
}
|
|
7558
7414
|
return this.queryWithPrefetch(parsed);
|
|
@@ -7573,8 +7429,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7573
7429
|
);
|
|
7574
7430
|
return rows.map(rowToObservation);
|
|
7575
7431
|
} catch (error) {
|
|
7576
|
-
if (isFtsUnavailableError(error))
|
|
7577
|
-
return null;
|
|
7432
|
+
if (isFtsUnavailableError(error)) return null;
|
|
7578
7433
|
throw error;
|
|
7579
7434
|
}
|
|
7580
7435
|
}
|
|
@@ -7615,8 +7470,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7615
7470
|
const parsed = DeletePerspectiveObservationInputSchema.parse(input);
|
|
7616
7471
|
const projectHash = projectHashToStorage4(parsed.projectHash);
|
|
7617
7472
|
const before = this.get(projectHash, parsed.observationId);
|
|
7618
|
-
if (!before)
|
|
7619
|
-
throw new Error("perspective observation not found");
|
|
7473
|
+
if (!before) throw new Error("perspective observation not found");
|
|
7620
7474
|
const deletedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7621
7475
|
sqliteRun(
|
|
7622
7476
|
this.db,
|
|
@@ -7626,8 +7480,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7626
7480
|
[deletedAt, deletedAt, projectHash, parsed.observationId]
|
|
7627
7481
|
);
|
|
7628
7482
|
const after = this.get(projectHash, parsed.observationId);
|
|
7629
|
-
if (!after)
|
|
7630
|
-
throw new Error("perspective observation not found after delete");
|
|
7483
|
+
if (!after) throw new Error("perspective observation not found after delete");
|
|
7631
7484
|
await writeGovernanceAuditEntry(this.db, {
|
|
7632
7485
|
operation: "perspective_observation_delete",
|
|
7633
7486
|
actor: parsed.actor,
|
|
@@ -7683,11 +7536,9 @@ var DEFAULT_CONFIG3 = {
|
|
|
7683
7536
|
var MAX_OBSERVATION_CONTENT_CHARS = 600;
|
|
7684
7537
|
var RuleBasedPerspectiveObservationExtractor = class {
|
|
7685
7538
|
async extract(event) {
|
|
7686
|
-
if (!isSupportedSourceEvent(event))
|
|
7687
|
-
return [];
|
|
7539
|
+
if (!isSupportedSourceEvent(event)) return [];
|
|
7688
7540
|
const content = normalizeObservationContent(event.content);
|
|
7689
|
-
if (!content)
|
|
7690
|
-
return [];
|
|
7541
|
+
if (!content) return [];
|
|
7691
7542
|
return [{
|
|
7692
7543
|
content,
|
|
7693
7544
|
confidence: 0.6,
|
|
@@ -7758,8 +7609,7 @@ var PerspectiveDeriver = class {
|
|
|
7758
7609
|
for (const candidate of candidates) {
|
|
7759
7610
|
const observedActorId = candidate.observedActorId ?? sourceActor.actorId;
|
|
7760
7611
|
const observers = selectObservers(members, observedActorId, this.config.deriver.maxObserversPerSession);
|
|
7761
|
-
if (observers.length === 0)
|
|
7762
|
-
continue;
|
|
7612
|
+
if (observers.length === 0) continue;
|
|
7763
7613
|
for (const observerActorId of observers) {
|
|
7764
7614
|
await this.observations.create({
|
|
7765
7615
|
projectHash,
|
|
@@ -7812,28 +7662,22 @@ function normalizeConfig(config) {
|
|
|
7812
7662
|
};
|
|
7813
7663
|
}
|
|
7814
7664
|
function clampInteger(value, fallback, min, max) {
|
|
7815
|
-
if (!Number.isFinite(value))
|
|
7816
|
-
return fallback;
|
|
7665
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7817
7666
|
return Math.max(min, Math.min(max, Math.trunc(Number(value))));
|
|
7818
7667
|
}
|
|
7819
7668
|
function isSupportedSourceEvent(event) {
|
|
7820
7669
|
return event.eventType === "user_prompt" || event.eventType === "agent_response";
|
|
7821
7670
|
}
|
|
7822
7671
|
function roleForEvent(event) {
|
|
7823
|
-
if (event.eventType === "user_prompt")
|
|
7824
|
-
|
|
7825
|
-
if (event.eventType === "
|
|
7826
|
-
|
|
7827
|
-
if (event.eventType === "tool_observation")
|
|
7828
|
-
return "tool";
|
|
7829
|
-
if (event.eventType === "session_summary")
|
|
7830
|
-
return "system";
|
|
7672
|
+
if (event.eventType === "user_prompt") return "speaker";
|
|
7673
|
+
if (event.eventType === "agent_response") return "assistant";
|
|
7674
|
+
if (event.eventType === "tool_observation") return "tool";
|
|
7675
|
+
if (event.eventType === "session_summary") return "system";
|
|
7831
7676
|
return "unknown";
|
|
7832
7677
|
}
|
|
7833
7678
|
function normalizeCandidate2(candidate) {
|
|
7834
7679
|
const content = normalizeObservationContent(candidate.content);
|
|
7835
|
-
if (!content)
|
|
7836
|
-
return null;
|
|
7680
|
+
if (!content) return null;
|
|
7837
7681
|
return {
|
|
7838
7682
|
content,
|
|
7839
7683
|
confidence: clampNumber(candidate.confidence, 0.6, 0, 1),
|
|
@@ -7845,8 +7689,7 @@ function normalizeCandidate2(candidate) {
|
|
|
7845
7689
|
}
|
|
7846
7690
|
function normalizeObservationContent(content) {
|
|
7847
7691
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
7848
|
-
if (!normalized)
|
|
7849
|
-
return null;
|
|
7692
|
+
if (!normalized) return null;
|
|
7850
7693
|
return normalized.slice(0, MAX_OBSERVATION_CONTENT_CHARS);
|
|
7851
7694
|
}
|
|
7852
7695
|
function normalizeOptionalString2(value) {
|
|
@@ -7854,13 +7697,11 @@ function normalizeOptionalString2(value) {
|
|
|
7854
7697
|
return normalized.length > 0 ? normalized : void 0;
|
|
7855
7698
|
}
|
|
7856
7699
|
function clampNumber(value, fallback, min, max) {
|
|
7857
|
-
if (!Number.isFinite(value))
|
|
7858
|
-
return fallback;
|
|
7700
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7859
7701
|
return Math.max(min, Math.min(max, Number(value)));
|
|
7860
7702
|
}
|
|
7861
7703
|
function sanitizeCandidateMetadata(metadata) {
|
|
7862
|
-
if (!metadata)
|
|
7863
|
-
return void 0;
|
|
7704
|
+
if (!metadata) return void 0;
|
|
7864
7705
|
const result = {};
|
|
7865
7706
|
for (const [key, value] of Object.entries(metadata)) {
|
|
7866
7707
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -7873,12 +7714,9 @@ function selectObservers(members, observedActorId, maxObservers) {
|
|
|
7873
7714
|
const selected = [];
|
|
7874
7715
|
for (const member of members) {
|
|
7875
7716
|
const canObserve = member.actorId === observedActorId ? member.observeSelf : member.observeOthers;
|
|
7876
|
-
if (!canObserve)
|
|
7877
|
-
|
|
7878
|
-
if (
|
|
7879
|
-
selected.push(member.actorId);
|
|
7880
|
-
if (selected.length >= maxObservers)
|
|
7881
|
-
break;
|
|
7717
|
+
if (!canObserve) continue;
|
|
7718
|
+
if (!selected.includes(member.actorId)) selected.push(member.actorId);
|
|
7719
|
+
if (selected.length >= maxObservers) break;
|
|
7882
7720
|
}
|
|
7883
7721
|
return selected;
|
|
7884
7722
|
}
|
|
@@ -7897,6 +7735,7 @@ var VectorStore = class {
|
|
|
7897
7735
|
constructor(dbPath) {
|
|
7898
7736
|
this.dbPath = dbPath;
|
|
7899
7737
|
}
|
|
7738
|
+
dbPath;
|
|
7900
7739
|
db = null;
|
|
7901
7740
|
tableCache = /* @__PURE__ */ new Map();
|
|
7902
7741
|
defaultTableName = "conversations";
|
|
@@ -7908,8 +7747,7 @@ var VectorStore = class {
|
|
|
7908
7747
|
* conversations table.
|
|
7909
7748
|
*/
|
|
7910
7749
|
async initialize() {
|
|
7911
|
-
if (this.db)
|
|
7912
|
-
return;
|
|
7750
|
+
if (this.db) return;
|
|
7913
7751
|
this.db = await lancedb.connect(this.dbPath);
|
|
7914
7752
|
}
|
|
7915
7753
|
/**
|
|
@@ -7923,8 +7761,7 @@ var VectorStore = class {
|
|
|
7923
7761
|
* Add or update multiple vector records in batch, grouped by inferred table.
|
|
7924
7762
|
*/
|
|
7925
7763
|
async upsertBatch(records) {
|
|
7926
|
-
if (records.length === 0)
|
|
7927
|
-
return;
|
|
7764
|
+
if (records.length === 0) return;
|
|
7928
7765
|
await this.initialize();
|
|
7929
7766
|
if (!this.db) {
|
|
7930
7767
|
throw new Error("Database not initialized");
|
|
@@ -7979,8 +7816,7 @@ var VectorStore = class {
|
|
|
7979
7816
|
async delete(eventId) {
|
|
7980
7817
|
await this.initialize();
|
|
7981
7818
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
7982
|
-
if (!table)
|
|
7983
|
-
return;
|
|
7819
|
+
if (!table) return;
|
|
7984
7820
|
await table.delete(`eventId = ${toLanceSqlString(eventId)}`);
|
|
7985
7821
|
}
|
|
7986
7822
|
/**
|
|
@@ -7989,8 +7825,7 @@ var VectorStore = class {
|
|
|
7989
7825
|
async count() {
|
|
7990
7826
|
await this.initialize();
|
|
7991
7827
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
7992
|
-
if (!table)
|
|
7993
|
-
return 0;
|
|
7828
|
+
if (!table) return 0;
|
|
7994
7829
|
const result = await table.countRows();
|
|
7995
7830
|
return result;
|
|
7996
7831
|
}
|
|
@@ -7999,8 +7834,7 @@ var VectorStore = class {
|
|
|
7999
7834
|
*/
|
|
8000
7835
|
async clearAll() {
|
|
8001
7836
|
await this.initialize();
|
|
8002
|
-
if (!this.db)
|
|
8003
|
-
return;
|
|
7837
|
+
if (!this.db) return;
|
|
8004
7838
|
try {
|
|
8005
7839
|
if (typeof this.db.dropTable === "function") {
|
|
8006
7840
|
await this.db.dropTable(this.defaultTableName);
|
|
@@ -8017,8 +7851,7 @@ var VectorStore = class {
|
|
|
8017
7851
|
async exists(eventId) {
|
|
8018
7852
|
await this.initialize();
|
|
8019
7853
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8020
|
-
if (!table)
|
|
8021
|
-
return false;
|
|
7854
|
+
if (!table) return false;
|
|
8022
7855
|
const results = await table.search([]).where(`eventId = ${toLanceSqlString(eventId)}`).limit(1).toArray();
|
|
8023
7856
|
return results.length > 0;
|
|
8024
7857
|
}
|
|
@@ -8053,8 +7886,7 @@ var VectorStore = class {
|
|
|
8053
7886
|
throw new Error("Database not initialized");
|
|
8054
7887
|
}
|
|
8055
7888
|
const cached = this.tableCache.get(tableName);
|
|
8056
|
-
if (cached)
|
|
8057
|
-
return cached;
|
|
7889
|
+
if (cached) return cached;
|
|
8058
7890
|
const tableNames = await this.db.tableNames();
|
|
8059
7891
|
if (!tableNames.includes(tableName)) {
|
|
8060
7892
|
return null;
|
|
@@ -8133,12 +7965,9 @@ var IngestInterceptorRegistry = class {
|
|
|
8133
7965
|
}
|
|
8134
7966
|
};
|
|
8135
7967
|
function mergeHierarchicalMetadata(base, patch) {
|
|
8136
|
-
if (!base && !patch)
|
|
8137
|
-
|
|
8138
|
-
if (!base
|
|
8139
|
-
return patch;
|
|
8140
|
-
if (!patch)
|
|
8141
|
-
return base;
|
|
7968
|
+
if (!base && !patch) return void 0;
|
|
7969
|
+
if (!base) return patch;
|
|
7970
|
+
if (!patch) return base;
|
|
8142
7971
|
const result = { ...base };
|
|
8143
7972
|
for (const [key, value] of Object.entries(patch)) {
|
|
8144
7973
|
const current = result[key];
|
|
@@ -8168,33 +7997,26 @@ var VALID_TAG_NAMESPACES = new Set(Object.values(TAG_NAMESPACES));
|
|
|
8168
7997
|
function parseTag(tag) {
|
|
8169
7998
|
const value = (tag || "").trim();
|
|
8170
7999
|
const idx = value.indexOf(":");
|
|
8171
|
-
if (idx <= 0)
|
|
8172
|
-
return { value };
|
|
8000
|
+
if (idx <= 0) return { value };
|
|
8173
8001
|
const namespace = `${value.slice(0, idx)}:`;
|
|
8174
8002
|
const tagValue = value.slice(idx + 1);
|
|
8175
|
-
if (!tagValue)
|
|
8176
|
-
return { value };
|
|
8003
|
+
if (!tagValue) return { value };
|
|
8177
8004
|
return { namespace, value: tagValue };
|
|
8178
8005
|
}
|
|
8179
8006
|
function validateTag(tag) {
|
|
8180
8007
|
const normalized = (tag || "").trim();
|
|
8181
|
-
if (!normalized)
|
|
8182
|
-
return false;
|
|
8008
|
+
if (!normalized) return false;
|
|
8183
8009
|
const { namespace } = parseTag(normalized);
|
|
8184
|
-
if (!namespace)
|
|
8185
|
-
return true;
|
|
8010
|
+
if (!namespace) return true;
|
|
8186
8011
|
return VALID_TAG_NAMESPACES.has(namespace);
|
|
8187
8012
|
}
|
|
8188
8013
|
function normalizeTags(tags) {
|
|
8189
|
-
if (!Array.isArray(tags))
|
|
8190
|
-
return [];
|
|
8014
|
+
if (!Array.isArray(tags)) return [];
|
|
8191
8015
|
const dedup = /* @__PURE__ */ new Set();
|
|
8192
8016
|
for (const item of tags) {
|
|
8193
|
-
if (typeof item !== "string")
|
|
8194
|
-
continue;
|
|
8017
|
+
if (typeof item !== "string") continue;
|
|
8195
8018
|
const normalized = item.trim();
|
|
8196
|
-
if (!validateTag(normalized))
|
|
8197
|
-
continue;
|
|
8019
|
+
if (!validateTag(normalized)) continue;
|
|
8198
8020
|
dedup.add(normalized);
|
|
8199
8021
|
}
|
|
8200
8022
|
return [...dedup];
|
|
@@ -8211,10 +8033,8 @@ var SummaryDeriver = class {
|
|
|
8211
8033
|
* orchestration, while this class owns summary text and metadata decisions.
|
|
8212
8034
|
*/
|
|
8213
8035
|
deriveSessionSummary(events) {
|
|
8214
|
-
if (events.length < 3)
|
|
8215
|
-
|
|
8216
|
-
if (events.some((event) => event.eventType === "session_summary"))
|
|
8217
|
-
return null;
|
|
8036
|
+
if (events.length < 3) return null;
|
|
8037
|
+
if (events.some((event) => event.eventType === "session_summary")) return null;
|
|
8218
8038
|
const prompts = events.filter((event) => event.eventType === "user_prompt");
|
|
8219
8039
|
const toolObservations = events.filter((event) => event.eventType === "tool_observation");
|
|
8220
8040
|
const toolNames = Array.from(new Set(
|
|
@@ -8362,8 +8182,7 @@ var MemoryIngestService = class {
|
|
|
8362
8182
|
await this.initialize();
|
|
8363
8183
|
const events = await this.eventStore.getSessionEvents(sessionId);
|
|
8364
8184
|
const summary = this.summaryDeriver.deriveSessionSummary(events);
|
|
8365
|
-
if (!summary)
|
|
8366
|
-
return;
|
|
8185
|
+
if (!summary) return;
|
|
8367
8186
|
await this.storeSessionSummary(sessionId, summary.text, summary.metadata);
|
|
8368
8187
|
}
|
|
8369
8188
|
async storeToolObservation(sessionId, payload) {
|
|
@@ -8431,10 +8250,8 @@ var MemoryIngestService = class {
|
|
|
8431
8250
|
}
|
|
8432
8251
|
}
|
|
8433
8252
|
async runPerspectiveDeriver(input, eventId, operation) {
|
|
8434
|
-
if (!this.perspectiveDeriver)
|
|
8435
|
-
|
|
8436
|
-
if (operation !== "user_prompt" && operation !== "agent_response")
|
|
8437
|
-
return;
|
|
8253
|
+
if (!this.perspectiveDeriver) return;
|
|
8254
|
+
if (operation !== "user_prompt" && operation !== "agent_response") return;
|
|
8438
8255
|
const event = {
|
|
8439
8256
|
id: eventId,
|
|
8440
8257
|
eventType: input.eventType,
|
|
@@ -8504,11 +8321,13 @@ var MemoryQueryService = class {
|
|
|
8504
8321
|
this.queryStore = queryStore;
|
|
8505
8322
|
this.deps = deps;
|
|
8506
8323
|
}
|
|
8324
|
+
initialize;
|
|
8325
|
+
queryStore;
|
|
8326
|
+
deps;
|
|
8507
8327
|
async keywordSearch(query, options) {
|
|
8508
8328
|
await this.initialize();
|
|
8509
8329
|
const results = await this.queryStore.keywordSearch(query, options?.topK ?? 10);
|
|
8510
|
-
if (results.length === 0)
|
|
8511
|
-
return [];
|
|
8330
|
+
if (results.length === 0) return [];
|
|
8512
8331
|
const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
|
|
8513
8332
|
const minRank = Math.max(...results.map((r) => r.rank), -1e3);
|
|
8514
8333
|
const rankRange = maxRank - minRank || 1;
|
|
@@ -8603,6 +8422,18 @@ var COMMAND_ARTIFACT_PATTERNS = [
|
|
|
8603
8422
|
/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
|
|
8604
8423
|
/<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
|
|
8605
8424
|
];
|
|
8425
|
+
var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
8426
|
+
/<environment_context\b[\s\S]*<\/environment_context>/i,
|
|
8427
|
+
/<turn_aborted>/i,
|
|
8428
|
+
/^#\s*AGENTS\.md\s+instructions\b[\s\S]*<INSTRUCTIONS>/i,
|
|
8429
|
+
/^\s*(?:understood[,\s.]*)?(?:stopping|stopped|pausing|paused)\s+here\b[\s\S]{0,180}\blet\s+me\s+know\s+when\s+you(?:'d|\s+would)?\s+like\s+to\s+continue\b/i,
|
|
8430
|
+
/^\s*\[?CONTEXT\s+COMPACTION\s*[—-]\s*REFERENCE\s+ONLY\]?\b[\s\S]{0,600}\b(?:earlier\s+turns\s+were\s+compacted|handoff\s+from\s+a\s+previous\s+context\s+window|active\s+task)\b/i,
|
|
8431
|
+
/^\s*Summary\s+generation\s+was\s+unavailable\.\s*\d+\s+message\(s\)\s+were\s+removed\s+to\s+free\s+context\s+space\b/i,
|
|
8432
|
+
/^\s*---\s*END\s+OF\s+CONTEXT\s+SUMMARY\b/i,
|
|
8433
|
+
/^\s*\[Your\s+active\s+task\s+list\s+was\s+preserved\s+across\s+context\s+compression\]/i,
|
|
8434
|
+
/^➜\s+\S+\s+git:\([^)]*\)\s+/i,
|
|
8435
|
+
/^\$\s+\S+/i
|
|
8436
|
+
];
|
|
8606
8437
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
8607
8438
|
/^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
|
|
8608
8439
|
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
@@ -8614,7 +8445,7 @@ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
|
8614
8445
|
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
8615
8446
|
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
8616
8447
|
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
8617
|
-
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|
|
|
8448
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|status)\b/i,
|
|
8618
8449
|
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
8619
8450
|
];
|
|
8620
8451
|
var STALE_CONTENT_PATTERNS = [
|
|
@@ -8754,55 +8585,67 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8754
8585
|
]);
|
|
8755
8586
|
function isCommandArtifactQuery(query) {
|
|
8756
8587
|
const trimmed = query.trim();
|
|
8757
|
-
if (!trimmed)
|
|
8758
|
-
return false;
|
|
8588
|
+
if (!trimmed) return false;
|
|
8759
8589
|
const normalized = trimmed.toLowerCase();
|
|
8760
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8590
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8591
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8592
|
+
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8593
|
+
}
|
|
8594
|
+
function isCommandArtifactContent(content) {
|
|
8595
|
+
const trimmed = content.trim();
|
|
8596
|
+
if (!trimmed) return false;
|
|
8597
|
+
const normalized = trimmed.toLowerCase();
|
|
8598
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8599
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8764
8600
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8765
8601
|
}
|
|
8602
|
+
function isLowSignalContextContent(content) {
|
|
8603
|
+
const trimmed = content.trim();
|
|
8604
|
+
if (!trimmed) return true;
|
|
8605
|
+
if (isCommandArtifactContent(trimmed)) return true;
|
|
8606
|
+
if (LOW_SIGNAL_CONTEXT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
8607
|
+
return false;
|
|
8608
|
+
}
|
|
8766
8609
|
function isGenericContinuationQuery(query) {
|
|
8767
8610
|
const trimmed = query.trim();
|
|
8768
|
-
if (!trimmed)
|
|
8769
|
-
|
|
8770
|
-
if (
|
|
8771
|
-
return false;
|
|
8772
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8773
|
-
return false;
|
|
8611
|
+
if (!trimmed) return false;
|
|
8612
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8613
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8774
8614
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8775
|
-
if (tokens.length > 10)
|
|
8776
|
-
return false;
|
|
8615
|
+
if (tokens.length > 10) return false;
|
|
8777
8616
|
return !/[A-Za-z0-9_-]+\.[A-Za-z0-9]+/.test(trimmed) && !/(?:^|\s)(?:feat|fix|chore|refactor|docs)\/[A-Za-z0-9._-]+/.test(trimmed) && !/[A-Za-z]:?[\\/]|\/Users\/|\.\/|\.\.\//.test(trimmed);
|
|
8778
8617
|
}
|
|
8779
8618
|
function isShortRepairFollowUpQuery(query) {
|
|
8780
8619
|
const trimmed = query.trim();
|
|
8781
|
-
if (!trimmed)
|
|
8782
|
-
|
|
8783
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8784
|
-
return false;
|
|
8620
|
+
if (!trimmed) return false;
|
|
8621
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8785
8622
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8786
|
-
if (tokens.length > 8)
|
|
8787
|
-
return false;
|
|
8623
|
+
if (tokens.length > 8) return false;
|
|
8788
8624
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8789
8625
|
}
|
|
8626
|
+
function isLowConfidenceContextFallbackQuery(query) {
|
|
8627
|
+
const trimmed = query.trim();
|
|
8628
|
+
if (!trimmed) return false;
|
|
8629
|
+
if (isGenericContinuationQuery(trimmed) || isShortRepairFollowUpQuery(trimmed)) return true;
|
|
8630
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8631
|
+
if ((terms.has("compacted") || terms.has("compaction")) && terms.has("handoff")) return false;
|
|
8632
|
+
const hasContinuationRecall = /^(?:continue|resume)\b/i.test(trimmed) && (terms.has("work") || terms.has("step") || terms.has("task") || terms.has("last") || terms.has("completed"));
|
|
8633
|
+
const hasValidationGateRecall = terms.has("validation") && (terms.has("gate") || terms.has("check")) && (terms.has("run") || terms.has("before") || terms.has("commit") || terms.has("committing") || terms.has("change"));
|
|
8634
|
+
return hasContinuationRecall || hasValidationGateRecall;
|
|
8635
|
+
}
|
|
8790
8636
|
function isCurrentStateQuery(query) {
|
|
8791
8637
|
const trimmed = query.trim();
|
|
8792
|
-
if (!trimmed)
|
|
8793
|
-
return false;
|
|
8638
|
+
if (!trimmed) return false;
|
|
8794
8639
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8795
8640
|
}
|
|
8796
8641
|
function isStaleOrSupersededContent(content) {
|
|
8797
8642
|
const trimmed = content.trim();
|
|
8798
|
-
if (!trimmed)
|
|
8799
|
-
return false;
|
|
8643
|
+
if (!trimmed) return false;
|
|
8800
8644
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8801
8645
|
}
|
|
8802
8646
|
function buildRetrievalQualityQuery(query) {
|
|
8803
8647
|
const trimmed = query.trim();
|
|
8804
|
-
if (!trimmed)
|
|
8805
|
-
return query;
|
|
8648
|
+
if (!trimmed) return query;
|
|
8806
8649
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8807
8650
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8808
8651
|
}
|
|
@@ -8816,12 +8659,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
8816
8659
|
}
|
|
8817
8660
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
8818
8661
|
const trimmed = query.trim();
|
|
8819
|
-
if (!trimmed)
|
|
8820
|
-
return false;
|
|
8662
|
+
if (!trimmed) return false;
|
|
8821
8663
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8822
8664
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8823
|
-
if (!hasDecisionSignal)
|
|
8824
|
-
return false;
|
|
8665
|
+
if (!hasDecisionSignal) return false;
|
|
8825
8666
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
8826
8667
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
8827
8668
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -8834,16 +8675,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
8834
8675
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
8835
8676
|
const terms = matches.filter((term) => {
|
|
8836
8677
|
const lower = term.toLowerCase();
|
|
8837
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
8838
|
-
return false;
|
|
8678
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
8839
8679
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
8840
8680
|
});
|
|
8841
8681
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
8842
8682
|
}
|
|
8843
8683
|
function hasTechnicalTermOverlap(query, content) {
|
|
8844
8684
|
const terms = extractTechnicalQueryTerms(query);
|
|
8845
|
-
if (terms.length === 0)
|
|
8846
|
-
return true;
|
|
8685
|
+
if (terms.length === 0) return true;
|
|
8847
8686
|
const normalizedContent = content.toLowerCase();
|
|
8848
8687
|
return terms.some((term) => normalizedContent.includes(term));
|
|
8849
8688
|
}
|
|
@@ -8859,15 +8698,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
8859
8698
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
8860
8699
|
}
|
|
8861
8700
|
}
|
|
8862
|
-
if (queryTerms.length < 3)
|
|
8863
|
-
return true;
|
|
8701
|
+
if (queryTerms.length < 3) return true;
|
|
8864
8702
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
8865
8703
|
let hits = 0;
|
|
8866
8704
|
for (const term of queryTerms) {
|
|
8867
|
-
if (contentTerms.has(term))
|
|
8868
|
-
|
|
8869
|
-
if (hits >= requiredHits)
|
|
8870
|
-
return true;
|
|
8705
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8706
|
+
if (hits >= requiredHits) return true;
|
|
8871
8707
|
}
|
|
8872
8708
|
return false;
|
|
8873
8709
|
}
|
|
@@ -8877,17 +8713,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
8877
8713
|
function hasAnyTerm(terms, expectedTerms) {
|
|
8878
8714
|
let found = false;
|
|
8879
8715
|
expectedTerms.forEach((term) => {
|
|
8880
|
-
if (terms.has(term))
|
|
8881
|
-
found = true;
|
|
8716
|
+
if (terms.has(term)) found = true;
|
|
8882
8717
|
});
|
|
8883
8718
|
return found;
|
|
8884
8719
|
}
|
|
8885
8720
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
8886
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
8887
|
-
return false;
|
|
8721
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
8888
8722
|
const trimmed = query.trim();
|
|
8889
|
-
if (!trimmed)
|
|
8890
|
-
return false;
|
|
8723
|
+
if (!trimmed) return false;
|
|
8891
8724
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8892
8725
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8893
8726
|
}
|
|
@@ -8895,12 +8728,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
8895
8728
|
const seen = /* @__PURE__ */ new Set();
|
|
8896
8729
|
const terms = [];
|
|
8897
8730
|
for (const token of tokenizeQualityText(query)) {
|
|
8898
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
8899
|
-
|
|
8900
|
-
if (
|
|
8901
|
-
continue;
|
|
8902
|
-
if (seen.has(token))
|
|
8903
|
-
continue;
|
|
8731
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8732
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8733
|
+
if (seen.has(token)) continue;
|
|
8904
8734
|
seen.add(token);
|
|
8905
8735
|
terms.push(token);
|
|
8906
8736
|
}
|
|
@@ -8915,14 +8745,10 @@ function tokenizeQualityText(text) {
|
|
|
8915
8745
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^A-Za-z0-9가-힣\s_.:-]/g, " ").split(/\s+/).flatMap((token) => token.split(/(?=[._:-])|(?<=[._:-])/g)).map((token) => normalizeQualityToken(token.replace(/^[._:-]+|[._:-]+$/g, ""))).filter((token) => token.length >= 2);
|
|
8916
8746
|
}
|
|
8917
8747
|
function normalizeQualityToken(token) {
|
|
8918
|
-
if (token === "apis")
|
|
8919
|
-
|
|
8920
|
-
if (token
|
|
8921
|
-
|
|
8922
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
8923
|
-
return token;
|
|
8924
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
8925
|
-
return `${token.slice(0, -3)}y`;
|
|
8748
|
+
if (token === "apis") return "api";
|
|
8749
|
+
if (token === "ids") return "id";
|
|
8750
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8751
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
8926
8752
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
8927
8753
|
return token.slice(0, -1);
|
|
8928
8754
|
}
|
|
@@ -9074,7 +8900,14 @@ var Retriever = class {
|
|
|
9074
8900
|
};
|
|
9075
8901
|
fallbackTrace.push("fallback:summary");
|
|
9076
8902
|
}
|
|
9077
|
-
const
|
|
8903
|
+
const selectedResults = current.results.slice(0, opts.topK).filter((result) => {
|
|
8904
|
+
if (current.matchResult.confidence !== "none") return true;
|
|
8905
|
+
if (isLowConfidenceContextFallbackQuery(query)) {
|
|
8906
|
+
return (result.semanticScore ?? result.score) >= 0.5 || result.score >= 0.5;
|
|
8907
|
+
}
|
|
8908
|
+
return (result.semanticScore ?? result.score) >= 0.62 || result.score >= 0.62;
|
|
8909
|
+
});
|
|
8910
|
+
const memories = await this.enrichResults(selectedResults, opts, query);
|
|
9078
8911
|
const context = this.buildContext(memories, opts.maxTokens);
|
|
9079
8912
|
return {
|
|
9080
8913
|
memories,
|
|
@@ -9082,7 +8915,7 @@ var Retriever = class {
|
|
|
9082
8915
|
totalTokens: this.estimateTokens(context),
|
|
9083
8916
|
context,
|
|
9084
8917
|
fallbackTrace,
|
|
9085
|
-
selectedDebug:
|
|
8918
|
+
selectedDebug: selectedResults.map((r) => this.debugDetailForResult(r)),
|
|
9086
8919
|
candidateDebug: (current.candidateResults || []).slice(0, Math.max(opts.topK * 3, 20)).map((r) => this.debugDetailForResult(r)),
|
|
9087
8920
|
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
9088
8921
|
effectiveQueryText: current.effectiveQueryText,
|
|
@@ -9104,8 +8937,7 @@ var Retriever = class {
|
|
|
9104
8937
|
const sharedMemories = [];
|
|
9105
8938
|
for (const result of sharedVectorResults) {
|
|
9106
8939
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9107
|
-
if (!entry)
|
|
9108
|
-
continue;
|
|
8940
|
+
if (!entry) continue;
|
|
9109
8941
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9110
8942
|
sharedMemories.push(entry);
|
|
9111
8943
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9178,6 +9010,7 @@ var Retriever = class {
|
|
|
9178
9010
|
if (isCurrentStateQuery(options.query)) {
|
|
9179
9011
|
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
9180
9012
|
}
|
|
9013
|
+
filtered = filtered.filter((result) => !isLowSignalContextContent(result.content));
|
|
9181
9014
|
filtered = filtered.filter(
|
|
9182
9015
|
(result) => this.isGraphPathResult(result) || hasDiscriminativeTermOverlap(options.query, result.content)
|
|
9183
9016
|
);
|
|
@@ -9186,18 +9019,15 @@ var Retriever = class {
|
|
|
9186
9019
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9187
9020
|
);
|
|
9188
9021
|
}
|
|
9189
|
-
if (filtered.length <= 2)
|
|
9190
|
-
return filtered;
|
|
9022
|
+
if (filtered.length <= 2) return filtered;
|
|
9191
9023
|
const topScore = filtered[0].score;
|
|
9192
|
-
if (topScore < 0.8)
|
|
9193
|
-
return filtered;
|
|
9024
|
+
if (topScore < 0.8) return filtered;
|
|
9194
9025
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9195
9026
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9196
9027
|
}
|
|
9197
9028
|
mergeResults(primary, secondary, limit) {
|
|
9198
9029
|
const byId = /* @__PURE__ */ new Map();
|
|
9199
|
-
for (const row of primary)
|
|
9200
|
-
byId.set(row.eventId, row);
|
|
9030
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9201
9031
|
for (const row of secondary) {
|
|
9202
9032
|
const prev = byId.get(row.eventId);
|
|
9203
9033
|
if (!prev || row.score > prev.score) {
|
|
@@ -9208,23 +9038,19 @@ var Retriever = class {
|
|
|
9208
9038
|
}
|
|
9209
9039
|
async expandGraphHops(seeds, opts) {
|
|
9210
9040
|
const byId = /* @__PURE__ */ new Map();
|
|
9211
|
-
for (const s of seeds)
|
|
9212
|
-
byId.set(s.eventId, s);
|
|
9041
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9213
9042
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9214
9043
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9215
9044
|
const next = [];
|
|
9216
9045
|
for (const f of frontier) {
|
|
9217
9046
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9218
|
-
if (!ev)
|
|
9219
|
-
continue;
|
|
9047
|
+
if (!ev) continue;
|
|
9220
9048
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9221
9049
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9222
9050
|
for (const rid of relatedIds) {
|
|
9223
|
-
if (byId.has(rid))
|
|
9224
|
-
continue;
|
|
9051
|
+
if (byId.has(rid)) continue;
|
|
9225
9052
|
const target = await this.eventStore.getEvent(rid);
|
|
9226
|
-
if (!target)
|
|
9227
|
-
continue;
|
|
9053
|
+
if (!target) continue;
|
|
9228
9054
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9229
9055
|
const row = {
|
|
9230
9056
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9238,15 +9064,12 @@ var Retriever = class {
|
|
|
9238
9064
|
};
|
|
9239
9065
|
byId.set(row.eventId, row);
|
|
9240
9066
|
next.push({ row, hop });
|
|
9241
|
-
if (byId.size >= opts.limit)
|
|
9242
|
-
break;
|
|
9067
|
+
if (byId.size >= opts.limit) break;
|
|
9243
9068
|
}
|
|
9244
|
-
if (byId.size >= opts.limit)
|
|
9245
|
-
break;
|
|
9069
|
+
if (byId.size >= opts.limit) break;
|
|
9246
9070
|
}
|
|
9247
9071
|
frontier = next;
|
|
9248
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9249
|
-
break;
|
|
9072
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9250
9073
|
}
|
|
9251
9074
|
if (opts.queryGraphEnabled) {
|
|
9252
9075
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9254,8 +9077,7 @@ var Retriever = class {
|
|
|
9254
9077
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9255
9078
|
}
|
|
9256
9079
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9257
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9258
|
-
return;
|
|
9080
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9259
9081
|
try {
|
|
9260
9082
|
const db = this.eventStore.getDatabase();
|
|
9261
9083
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9264,8 +9086,7 @@ var Retriever = class {
|
|
|
9264
9086
|
});
|
|
9265
9087
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9266
9088
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9267
|
-
if (startNodes.length === 0)
|
|
9268
|
-
return;
|
|
9089
|
+
if (startNodes.length === 0) return;
|
|
9269
9090
|
const expansion = new GraphPathService(db).expand({
|
|
9270
9091
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9271
9092
|
maxHops: opts.maxHops,
|
|
@@ -9274,11 +9095,9 @@ var Retriever = class {
|
|
|
9274
9095
|
});
|
|
9275
9096
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9276
9097
|
for (const path11 of expansion.paths) {
|
|
9277
|
-
if (path11.target.type !== "event")
|
|
9278
|
-
continue;
|
|
9098
|
+
if (path11.target.type !== "event") continue;
|
|
9279
9099
|
const target = await this.eventStore.getEvent(path11.target.id);
|
|
9280
|
-
if (!target)
|
|
9281
|
-
continue;
|
|
9100
|
+
if (!target) continue;
|
|
9282
9101
|
const graphPath = toRetrievalGraphPathDebug(path11, titleByEntityId);
|
|
9283
9102
|
const score = graphPathScore(path11, opts.hopPenalty);
|
|
9284
9103
|
const existing = byId.get(target.id);
|
|
@@ -9304,17 +9123,14 @@ var Retriever = class {
|
|
|
9304
9123
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9305
9124
|
};
|
|
9306
9125
|
byId.set(row.eventId, row);
|
|
9307
|
-
if (byId.size >= opts.limit)
|
|
9308
|
-
break;
|
|
9126
|
+
if (byId.size >= opts.limit) break;
|
|
9309
9127
|
}
|
|
9310
9128
|
} catch {
|
|
9311
9129
|
}
|
|
9312
9130
|
}
|
|
9313
9131
|
shouldFallback(matchResult, results) {
|
|
9314
|
-
if (results.length === 0)
|
|
9315
|
-
|
|
9316
|
-
if (matchResult.confidence === "none")
|
|
9317
|
-
return true;
|
|
9132
|
+
if (results.length === 0) return true;
|
|
9133
|
+
if (matchResult.confidence === "none") return true;
|
|
9318
9134
|
return false;
|
|
9319
9135
|
}
|
|
9320
9136
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9419,29 +9235,21 @@ var Retriever = class {
|
|
|
9419
9235
|
(value) => typeof value === "string" && value.length > 0
|
|
9420
9236
|
)
|
|
9421
9237
|
);
|
|
9422
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9423
|
-
return results;
|
|
9238
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9424
9239
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9425
9240
|
const filtered = [];
|
|
9426
9241
|
for (const result of results) {
|
|
9427
|
-
if (scope?.sessionId && result.sessionId !== scope.sessionId)
|
|
9428
|
-
|
|
9429
|
-
if (scope?.
|
|
9430
|
-
continue;
|
|
9431
|
-
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType))
|
|
9432
|
-
continue;
|
|
9242
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9243
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9244
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9433
9245
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9434
|
-
if (!event)
|
|
9435
|
-
|
|
9436
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9437
|
-
continue;
|
|
9246
|
+
if (!event) continue;
|
|
9247
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9438
9248
|
if (normalizedIncludes.length > 0) {
|
|
9439
9249
|
const lc = event.content.toLowerCase();
|
|
9440
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9441
|
-
continue;
|
|
9250
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9442
9251
|
}
|
|
9443
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9444
|
-
continue;
|
|
9252
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9445
9253
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9446
9254
|
filtered.push({ result, projectHash });
|
|
9447
9255
|
}
|
|
@@ -9458,27 +9266,21 @@ var Retriever = class {
|
|
|
9458
9266
|
});
|
|
9459
9267
|
}
|
|
9460
9268
|
normalizeFacetFilters(facets) {
|
|
9461
|
-
if (!facets || facets.length === 0)
|
|
9462
|
-
return null;
|
|
9269
|
+
if (!facets || facets.length === 0) return null;
|
|
9463
9270
|
const normalized = [];
|
|
9464
9271
|
for (const facet of facets) {
|
|
9465
9272
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9466
9273
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9467
|
-
if (!parsedDimension.success || !value)
|
|
9468
|
-
return [];
|
|
9274
|
+
if (!parsedDimension.success || !value) return [];
|
|
9469
9275
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9470
9276
|
}
|
|
9471
9277
|
return normalized;
|
|
9472
9278
|
}
|
|
9473
9279
|
async applyFacetFilters(results, options) {
|
|
9474
|
-
if (options.facets === null)
|
|
9475
|
-
|
|
9476
|
-
if (options.
|
|
9477
|
-
|
|
9478
|
-
if (!options.projectHash)
|
|
9479
|
-
return [];
|
|
9480
|
-
if (!this.eventStore.getDatabase)
|
|
9481
|
-
return [];
|
|
9280
|
+
if (options.facets === null) return results;
|
|
9281
|
+
if (options.facets.length === 0) return [];
|
|
9282
|
+
if (!options.projectHash) return [];
|
|
9283
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9482
9284
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9483
9285
|
const filtered = [];
|
|
9484
9286
|
for (const result of results) {
|
|
@@ -9535,14 +9337,11 @@ var Retriever = class {
|
|
|
9535
9337
|
return (result.graphPaths || []).length > 0;
|
|
9536
9338
|
}
|
|
9537
9339
|
extractProjectHash(metadata) {
|
|
9538
|
-
if (!metadata || typeof metadata !== "object")
|
|
9539
|
-
return void 0;
|
|
9340
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9540
9341
|
const scope = metadata.scope;
|
|
9541
|
-
if (!scope || typeof scope !== "object")
|
|
9542
|
-
return void 0;
|
|
9342
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9543
9343
|
const project = scope.project;
|
|
9544
|
-
if (!project || typeof project !== "object")
|
|
9545
|
-
return void 0;
|
|
9344
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9546
9345
|
const hash = project.hash;
|
|
9547
9346
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9548
9347
|
}
|
|
@@ -9552,52 +9351,48 @@ var Retriever = class {
|
|
|
9552
9351
|
async retrieveRecent(limit = 100) {
|
|
9553
9352
|
return this.eventStore.getRecentEvents(limit);
|
|
9554
9353
|
}
|
|
9555
|
-
async enrichResults(results, options) {
|
|
9354
|
+
async enrichResults(results, options, query) {
|
|
9556
9355
|
const memories = [];
|
|
9557
9356
|
for (const result of results) {
|
|
9558
9357
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9559
|
-
if (!event)
|
|
9560
|
-
continue;
|
|
9358
|
+
if (!event) continue;
|
|
9561
9359
|
if (this.graduation) {
|
|
9562
9360
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9563
9361
|
}
|
|
9564
9362
|
let sessionContext;
|
|
9565
9363
|
if (options.includeSessionContext) {
|
|
9566
|
-
sessionContext = await this.getSessionContext(event.sessionId, event.id);
|
|
9364
|
+
sessionContext = await this.getSessionContext(event.sessionId, event.id, query);
|
|
9567
9365
|
}
|
|
9568
9366
|
memories.push({ event, score: result.score, sessionContext });
|
|
9569
9367
|
}
|
|
9570
9368
|
return memories;
|
|
9571
9369
|
}
|
|
9572
|
-
async getSessionContext(sessionId, eventId) {
|
|
9370
|
+
async getSessionContext(sessionId, eventId, query) {
|
|
9573
9371
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9574
9372
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9575
|
-
if (eventIndex === -1)
|
|
9576
|
-
return void 0;
|
|
9373
|
+
if (eventIndex === -1) return void 0;
|
|
9577
9374
|
const start = Math.max(0, eventIndex - 1);
|
|
9578
9375
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9579
9376
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9580
|
-
if (contextEvents.length <= 1)
|
|
9581
|
-
|
|
9582
|
-
|
|
9377
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9378
|
+
const suppressStaleState = isCurrentStateQuery(query);
|
|
9379
|
+
const contextLines = contextEvents.filter((e) => e.id !== eventId).filter((e) => !isLowSignalContextContent(e.content)).filter((e) => !(suppressStaleState && isStaleOrSupersededContent(e.content))).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`);
|
|
9380
|
+
return contextLines.length > 0 ? contextLines.join("\n") : void 0;
|
|
9583
9381
|
}
|
|
9584
9382
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9585
9383
|
let context = projectResult.context;
|
|
9586
|
-
if (sharedMemories.length === 0)
|
|
9587
|
-
return context;
|
|
9384
|
+
if (sharedMemories.length === 0) return context;
|
|
9588
9385
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9589
9386
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9590
9387
|
context += `### ${memory.title}
|
|
9591
9388
|
`;
|
|
9592
|
-
if (memory.symptoms.length > 0)
|
|
9593
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9389
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9594
9390
|
`;
|
|
9595
9391
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9596
9392
|
`;
|
|
9597
9393
|
context += `**Solution:** ${memory.solution}
|
|
9598
9394
|
`;
|
|
9599
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9600
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9395
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9601
9396
|
`;
|
|
9602
9397
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9603
9398
|
|
|
@@ -9611,13 +9406,11 @@ var Retriever = class {
|
|
|
9611
9406
|
for (const memory of memories) {
|
|
9612
9407
|
const memoryText = this.formatMemory(memory);
|
|
9613
9408
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9614
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9615
|
-
break;
|
|
9409
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9616
9410
|
parts.push(memoryText);
|
|
9617
9411
|
currentTokens += memoryTokens;
|
|
9618
9412
|
}
|
|
9619
|
-
if (parts.length === 0)
|
|
9620
|
-
return "";
|
|
9413
|
+
if (parts.length === 0) return "";
|
|
9621
9414
|
return `## Relevant Memories
|
|
9622
9415
|
|
|
9623
9416
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9627,19 +9420,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9627
9420
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9628
9421
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9629
9422
|
${event.content}`;
|
|
9630
|
-
if (sessionContext)
|
|
9631
|
-
text += `
|
|
9423
|
+
if (sessionContext) text += `
|
|
9632
9424
|
|
|
9633
9425
|
_Context:_ ${sessionContext}`;
|
|
9634
9426
|
return text;
|
|
9635
9427
|
}
|
|
9636
9428
|
matchesMetadataScope(metadata, expected) {
|
|
9637
|
-
if (!metadata)
|
|
9638
|
-
return false;
|
|
9429
|
+
if (!metadata) return false;
|
|
9639
9430
|
return Object.entries(expected).every(([path11, value]) => {
|
|
9640
9431
|
const actual = path11.split(".").reduce((acc, key) => {
|
|
9641
|
-
if (typeof acc !== "object" || acc === null)
|
|
9642
|
-
return void 0;
|
|
9432
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9643
9433
|
return acc[key];
|
|
9644
9434
|
}, metadata);
|
|
9645
9435
|
return actual === value;
|
|
@@ -9649,27 +9439,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9649
9439
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).map((token) => this.normalizeToken(token)).filter((t) => t.length >= 2).slice(0, 64);
|
|
9650
9440
|
}
|
|
9651
9441
|
normalizeToken(token) {
|
|
9652
|
-
if (token === "apis")
|
|
9653
|
-
|
|
9654
|
-
if (token === "
|
|
9655
|
-
|
|
9656
|
-
if (token === "does")
|
|
9657
|
-
return token;
|
|
9658
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9659
|
-
return `${token.slice(0, -3)}y`;
|
|
9442
|
+
if (token === "apis") return "api";
|
|
9443
|
+
if (token === "ids") return "id";
|
|
9444
|
+
if (token === "does") return token;
|
|
9445
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9660
9446
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9661
9447
|
return token.slice(0, -1);
|
|
9662
9448
|
}
|
|
9663
9449
|
return token;
|
|
9664
9450
|
}
|
|
9665
9451
|
keywordOverlap(a, b) {
|
|
9666
|
-
if (a.length === 0 || b.length === 0)
|
|
9667
|
-
return 0;
|
|
9452
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9668
9453
|
const bs = new Set(b);
|
|
9669
9454
|
let hit = 0;
|
|
9670
|
-
for (const t of a)
|
|
9671
|
-
if (bs.has(t))
|
|
9672
|
-
hit += 1;
|
|
9455
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9673
9456
|
return hit / a.length;
|
|
9674
9457
|
}
|
|
9675
9458
|
estimateTokens(text) {
|
|
@@ -9690,8 +9473,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9690
9473
|
const seen = /* @__PURE__ */ new Set();
|
|
9691
9474
|
const nodes = [];
|
|
9692
9475
|
for (const candidate of candidates) {
|
|
9693
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9694
|
-
continue;
|
|
9476
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9695
9477
|
seen.add(candidate.entityId);
|
|
9696
9478
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9697
9479
|
}
|
|
@@ -9715,16 +9497,14 @@ function graphPathScore(path11, hopPenalty) {
|
|
|
9715
9497
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path11.hops - 1));
|
|
9716
9498
|
}
|
|
9717
9499
|
function clampGraphHops(maxHops) {
|
|
9718
|
-
if (!Number.isFinite(maxHops))
|
|
9719
|
-
return 2;
|
|
9500
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9720
9501
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9721
9502
|
}
|
|
9722
9503
|
function mergeGraphPaths(existing, incoming) {
|
|
9723
9504
|
const byKey = /* @__PURE__ */ new Map();
|
|
9724
9505
|
for (const path11 of [...existing, ...incoming]) {
|
|
9725
9506
|
const key = [path11.startEntityId, path11.targetType, path11.targetId, path11.hops, ...path11.relationPath].join("\0");
|
|
9726
|
-
if (!byKey.has(key))
|
|
9727
|
-
byKey.set(key, path11);
|
|
9507
|
+
if (!byKey.has(key)) byKey.set(key, path11);
|
|
9728
9508
|
}
|
|
9729
9509
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9730
9510
|
}
|
|
@@ -9732,10 +9512,8 @@ function graphPathSignature(path11) {
|
|
|
9732
9512
|
return [path11.startEntityId, path11.targetType, path11.targetId, path11.hops, ...path11.relationPath].join("|");
|
|
9733
9513
|
}
|
|
9734
9514
|
function compareStable(a, b) {
|
|
9735
|
-
if (a < b)
|
|
9736
|
-
|
|
9737
|
-
if (a > b)
|
|
9738
|
-
return 1;
|
|
9515
|
+
if (a < b) return -1;
|
|
9516
|
+
if (a > b) return 1;
|
|
9739
9517
|
return 0;
|
|
9740
9518
|
}
|
|
9741
9519
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9747,6 +9525,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9747
9525
|
constructor(deps) {
|
|
9748
9526
|
this.deps = deps;
|
|
9749
9527
|
}
|
|
9528
|
+
deps;
|
|
9750
9529
|
async getRetrievalTraceStats() {
|
|
9751
9530
|
await this.deps.initialize();
|
|
9752
9531
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -9824,6 +9603,7 @@ var RetrievalDisclosureService = class {
|
|
|
9824
9603
|
constructor(deps) {
|
|
9825
9604
|
this.deps = deps;
|
|
9826
9605
|
}
|
|
9606
|
+
deps;
|
|
9827
9607
|
async search(query, options) {
|
|
9828
9608
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
9829
9609
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -9853,8 +9633,7 @@ var RetrievalDisclosureService = class {
|
|
|
9853
9633
|
return this.expandShared(parsedId.entryId);
|
|
9854
9634
|
}
|
|
9855
9635
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9856
|
-
if (!targetEvent)
|
|
9857
|
-
return null;
|
|
9636
|
+
if (!targetEvent) return null;
|
|
9858
9637
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
9859
9638
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
9860
9639
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -9878,8 +9657,7 @@ var RetrievalDisclosureService = class {
|
|
|
9878
9657
|
return this.sourceShared(parsedId.entryId);
|
|
9879
9658
|
}
|
|
9880
9659
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9881
|
-
if (!rawEvent)
|
|
9882
|
-
return null;
|
|
9660
|
+
if (!rawEvent) return null;
|
|
9883
9661
|
return {
|
|
9884
9662
|
...this.sourceReferenceForEvent(rawEvent),
|
|
9885
9663
|
rawEvents: [rawEvent],
|
|
@@ -9888,8 +9666,7 @@ var RetrievalDisclosureService = class {
|
|
|
9888
9666
|
}
|
|
9889
9667
|
async expandShared(entryId) {
|
|
9890
9668
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9891
|
-
if (!entry)
|
|
9892
|
-
return null;
|
|
9669
|
+
if (!entry) return null;
|
|
9893
9670
|
return {
|
|
9894
9671
|
target: this.sharedToEnvelope(entry),
|
|
9895
9672
|
surroundingFacts: [],
|
|
@@ -9900,8 +9677,7 @@ var RetrievalDisclosureService = class {
|
|
|
9900
9677
|
}
|
|
9901
9678
|
async sourceShared(entryId) {
|
|
9902
9679
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9903
|
-
if (!entry)
|
|
9904
|
-
return null;
|
|
9680
|
+
if (!entry) return null;
|
|
9905
9681
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
9906
9682
|
return {
|
|
9907
9683
|
...sourceReference,
|
|
@@ -9987,38 +9763,25 @@ var RetrievalDisclosureService = class {
|
|
|
9987
9763
|
const reasons = /* @__PURE__ */ new Set();
|
|
9988
9764
|
const usedVector = this.usedVector(result);
|
|
9989
9765
|
const usedKeyword = this.usedKeyword(result);
|
|
9990
|
-
if (usedVector && (debug?.semanticScore ?? 0) > 0)
|
|
9991
|
-
|
|
9992
|
-
if ((debug?.
|
|
9993
|
-
|
|
9994
|
-
if ((debug?.
|
|
9995
|
-
|
|
9996
|
-
if (
|
|
9997
|
-
|
|
9998
|
-
if (
|
|
9999
|
-
reasons.add("entity_overlap");
|
|
10000
|
-
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary"))
|
|
10001
|
-
reasons.add("summary_fallback");
|
|
10002
|
-
if (memory.sessionContext)
|
|
10003
|
-
reasons.add("continuity_link");
|
|
10004
|
-
if (memory.event.eventType === "tool_observation")
|
|
10005
|
-
reasons.add("tool_followup");
|
|
10006
|
-
if (reasons.size === 0)
|
|
10007
|
-
reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
9766
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9767
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9768
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9769
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9770
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9771
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9772
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9773
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9774
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10008
9775
|
return Array.from(reasons);
|
|
10009
9776
|
}
|
|
10010
9777
|
reasonsForContextEvent(event) {
|
|
10011
|
-
if (event.eventType === "tool_observation")
|
|
10012
|
-
|
|
10013
|
-
if (event.eventType === "session_summary")
|
|
10014
|
-
return ["summary_fallback"];
|
|
9778
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9779
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10015
9780
|
return ["continuity_link"];
|
|
10016
9781
|
}
|
|
10017
9782
|
resultTypeForEvent(event) {
|
|
10018
|
-
if (event.eventType === "session_summary")
|
|
10019
|
-
|
|
10020
|
-
if (event.eventType === "tool_observation")
|
|
10021
|
-
return "tool_evidence";
|
|
9783
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9784
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10022
9785
|
return "source";
|
|
10023
9786
|
}
|
|
10024
9787
|
sourceReferenceForEvent(event) {
|
|
@@ -10042,21 +9805,15 @@ var RetrievalDisclosureService = class {
|
|
|
10042
9805
|
}
|
|
10043
9806
|
sourceTypeForEvent(event) {
|
|
10044
9807
|
const metadata = event.metadata || {};
|
|
10045
|
-
if (event.eventType === "tool_observation")
|
|
10046
|
-
|
|
10047
|
-
if (typeof metadata.
|
|
10048
|
-
return "transcript";
|
|
10049
|
-
if (typeof metadata.importedFrom === "string")
|
|
10050
|
-
return "imported_history";
|
|
9808
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9809
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9810
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10051
9811
|
return "raw_event";
|
|
10052
9812
|
}
|
|
10053
9813
|
titleForEvent(event) {
|
|
10054
|
-
if (event.eventType === "session_summary")
|
|
10055
|
-
|
|
10056
|
-
if (event.eventType === "
|
|
10057
|
-
return "Tool evidence";
|
|
10058
|
-
if (event.eventType === "agent_response")
|
|
10059
|
-
return "Agent response";
|
|
9814
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9815
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9816
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10060
9817
|
return "User prompt";
|
|
10061
9818
|
}
|
|
10062
9819
|
usedVector(result) {
|
|
@@ -10082,8 +9839,7 @@ var RetrievalDisclosureService = class {
|
|
|
10082
9839
|
}
|
|
10083
9840
|
preview(content, maxLength) {
|
|
10084
9841
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10085
|
-
if (normalized.length <= maxLength)
|
|
10086
|
-
return normalized;
|
|
9842
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10087
9843
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10088
9844
|
}
|
|
10089
9845
|
};
|
|
@@ -10112,6 +9868,7 @@ var RetrievalOrchestrator = class {
|
|
|
10112
9868
|
this.deps = deps;
|
|
10113
9869
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10114
9870
|
}
|
|
9871
|
+
deps;
|
|
10115
9872
|
/**
|
|
10116
9873
|
* Retrieve relevant memories for a query.
|
|
10117
9874
|
*/
|
|
@@ -10193,8 +9950,7 @@ var RetrievalOrchestrator = class {
|
|
|
10193
9950
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10194
9951
|
*/
|
|
10195
9952
|
async incrementMemoryAccess(eventIds) {
|
|
10196
|
-
if (eventIds.length === 0)
|
|
10197
|
-
return;
|
|
9953
|
+
if (eventIds.length === 0) return;
|
|
10198
9954
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10199
9955
|
}
|
|
10200
9956
|
/**
|
|
@@ -10207,10 +9963,8 @@ var RetrievalOrchestrator = class {
|
|
|
10207
9963
|
resolveGraphHopOptions(callerOptions) {
|
|
10208
9964
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10209
9965
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10210
|
-
if (!callerOptions)
|
|
10211
|
-
|
|
10212
|
-
if (!graphExpansion)
|
|
10213
|
-
return callerOptions;
|
|
9966
|
+
if (!callerOptions) return durableOptions;
|
|
9967
|
+
if (!graphExpansion) return callerOptions;
|
|
10214
9968
|
if (graphExpansion.enabled !== true) {
|
|
10215
9969
|
return {
|
|
10216
9970
|
...callerOptions,
|
|
@@ -10270,12 +10024,10 @@ var RetrievalOrchestrator = class {
|
|
|
10270
10024
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10271
10025
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10272
10026
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10273
|
-
if (!allFinite)
|
|
10274
|
-
return void 0;
|
|
10027
|
+
if (!allFinite) return void 0;
|
|
10275
10028
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10276
10029
|
const total = semantic + lexical + recency;
|
|
10277
|
-
if (!nonNegative || total <= 0)
|
|
10278
|
-
return void 0;
|
|
10030
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10279
10031
|
return {
|
|
10280
10032
|
semantic: semantic / total,
|
|
10281
10033
|
lexical: lexical / total,
|
|
@@ -10284,17 +10036,14 @@ var RetrievalOrchestrator = class {
|
|
|
10284
10036
|
}
|
|
10285
10037
|
async getRerankWeights(adaptive) {
|
|
10286
10038
|
const configured = this.getConfiguredRerankWeights();
|
|
10287
|
-
if (configured)
|
|
10288
|
-
|
|
10289
|
-
if (adaptive)
|
|
10290
|
-
return this.getAdaptiveRerankWeights();
|
|
10039
|
+
if (configured) return configured;
|
|
10040
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10291
10041
|
return void 0;
|
|
10292
10042
|
}
|
|
10293
10043
|
async getAdaptiveRerankWeights() {
|
|
10294
10044
|
try {
|
|
10295
10045
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10296
|
-
if (stats.totalEvaluated < 20)
|
|
10297
|
-
return void 0;
|
|
10046
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10298
10047
|
let semantic = 0.7;
|
|
10299
10048
|
let lexical = 0.2;
|
|
10300
10049
|
let recency = 0.1;
|
|
@@ -10316,11 +10065,9 @@ var RetrievalOrchestrator = class {
|
|
|
10316
10065
|
}
|
|
10317
10066
|
}
|
|
10318
10067
|
async rewriteQueryIntent(query) {
|
|
10319
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10320
|
-
return null;
|
|
10068
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10321
10069
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10322
|
-
if (!apiUrl)
|
|
10323
|
-
return null;
|
|
10070
|
+
if (!apiUrl) return null;
|
|
10324
10071
|
const controller = new AbortController();
|
|
10325
10072
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10326
10073
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10346,11 +10093,9 @@ var RetrievalOrchestrator = class {
|
|
|
10346
10093
|
signal: controller.signal
|
|
10347
10094
|
});
|
|
10348
10095
|
const text = (await res.text()).trim();
|
|
10349
|
-
if (!text)
|
|
10350
|
-
return null;
|
|
10096
|
+
if (!text) return null;
|
|
10351
10097
|
const oneLine = text.replace(/^data:\s*/gm, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ").slice(0, 240);
|
|
10352
|
-
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase())
|
|
10353
|
-
return null;
|
|
10098
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10354
10099
|
return oneLine;
|
|
10355
10100
|
} catch {
|
|
10356
10101
|
return null;
|
|
@@ -10492,8 +10237,7 @@ function createMemoryEngineServices(options) {
|
|
|
10492
10237
|
};
|
|
10493
10238
|
}
|
|
10494
10239
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10495
|
-
if (options.readOnly)
|
|
10496
|
-
return false;
|
|
10240
|
+
if (options.readOnly) return false;
|
|
10497
10241
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10498
10242
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10499
10243
|
}
|
|
@@ -10527,6 +10271,9 @@ var GraduationWorker = class {
|
|
|
10527
10271
|
this.graduation = graduation;
|
|
10528
10272
|
this.config = config;
|
|
10529
10273
|
}
|
|
10274
|
+
eventStore;
|
|
10275
|
+
graduation;
|
|
10276
|
+
config;
|
|
10530
10277
|
running = false;
|
|
10531
10278
|
timeout = null;
|
|
10532
10279
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10534,8 +10281,7 @@ var GraduationWorker = class {
|
|
|
10534
10281
|
* Start the graduation worker
|
|
10535
10282
|
*/
|
|
10536
10283
|
start() {
|
|
10537
|
-
if (this.running)
|
|
10538
|
-
return;
|
|
10284
|
+
if (this.running) return;
|
|
10539
10285
|
this.running = true;
|
|
10540
10286
|
this.scheduleNext();
|
|
10541
10287
|
}
|
|
@@ -10565,8 +10311,7 @@ var GraduationWorker = class {
|
|
|
10565
10311
|
* Schedule the next graduation check
|
|
10566
10312
|
*/
|
|
10567
10313
|
scheduleNext() {
|
|
10568
|
-
if (!this.running)
|
|
10569
|
-
return;
|
|
10314
|
+
if (!this.running) return;
|
|
10570
10315
|
this.timeout = setTimeout(
|
|
10571
10316
|
() => this.run(),
|
|
10572
10317
|
this.config.evaluationIntervalMs
|
|
@@ -10576,8 +10321,7 @@ var GraduationWorker = class {
|
|
|
10576
10321
|
* Run graduation evaluation
|
|
10577
10322
|
*/
|
|
10578
10323
|
async run() {
|
|
10579
|
-
if (!this.running)
|
|
10580
|
-
return;
|
|
10324
|
+
if (!this.running) return;
|
|
10581
10325
|
try {
|
|
10582
10326
|
await this.runGraduation();
|
|
10583
10327
|
} catch (error) {
|
|
@@ -10641,10 +10385,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10641
10385
|
maxRetries: 3
|
|
10642
10386
|
};
|
|
10643
10387
|
function parseJsonArray(value) {
|
|
10644
|
-
if (Array.isArray(value))
|
|
10645
|
-
|
|
10646
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10647
|
-
return [];
|
|
10388
|
+
if (Array.isArray(value)) return value;
|
|
10389
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10648
10390
|
try {
|
|
10649
10391
|
const parsed = JSON.parse(value);
|
|
10650
10392
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10674,8 +10416,7 @@ var VectorWorker = class {
|
|
|
10674
10416
|
* Start the worker polling loop
|
|
10675
10417
|
*/
|
|
10676
10418
|
start() {
|
|
10677
|
-
if (this.running)
|
|
10678
|
-
return;
|
|
10419
|
+
if (this.running) return;
|
|
10679
10420
|
this.running = true;
|
|
10680
10421
|
this.stopping = false;
|
|
10681
10422
|
this.poll();
|
|
@@ -10751,8 +10492,7 @@ var VectorWorker = class {
|
|
|
10751
10492
|
* Poll for new items
|
|
10752
10493
|
*/
|
|
10753
10494
|
async poll() {
|
|
10754
|
-
if (!this.running || this.stopping)
|
|
10755
|
-
return;
|
|
10495
|
+
if (!this.running || this.stopping) return;
|
|
10756
10496
|
try {
|
|
10757
10497
|
await this.processBatch();
|
|
10758
10498
|
} catch (error) {
|
|
@@ -10797,6 +10537,7 @@ var DefaultContentProvider = class {
|
|
|
10797
10537
|
constructor(db) {
|
|
10798
10538
|
this.db = db;
|
|
10799
10539
|
}
|
|
10540
|
+
db;
|
|
10800
10541
|
async getContent(itemKind, itemId) {
|
|
10801
10542
|
switch (itemKind) {
|
|
10802
10543
|
case "entry":
|
|
@@ -10817,8 +10558,7 @@ var DefaultContentProvider = class {
|
|
|
10817
10558
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
10818
10559
|
[entryId]
|
|
10819
10560
|
);
|
|
10820
|
-
if (rows.length === 0)
|
|
10821
|
-
return null;
|
|
10561
|
+
if (rows.length === 0) return null;
|
|
10822
10562
|
const row = rows[0];
|
|
10823
10563
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
10824
10564
|
return {
|
|
@@ -10837,8 +10577,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10837
10577
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
10838
10578
|
[taskId]
|
|
10839
10579
|
);
|
|
10840
|
-
if (rows.length === 0)
|
|
10841
|
-
return null;
|
|
10580
|
+
if (rows.length === 0) return null;
|
|
10842
10581
|
const row = rows[0];
|
|
10843
10582
|
return {
|
|
10844
10583
|
content: row.search_text || row.title,
|
|
@@ -10854,8 +10593,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10854
10593
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
10855
10594
|
[eventId]
|
|
10856
10595
|
);
|
|
10857
|
-
if (rows.length === 0)
|
|
10858
|
-
return null;
|
|
10596
|
+
if (rows.length === 0) return null;
|
|
10859
10597
|
const row = rows[0];
|
|
10860
10598
|
return {
|
|
10861
10599
|
content: row.content,
|
|
@@ -10883,8 +10621,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10883
10621
|
}
|
|
10884
10622
|
throw error;
|
|
10885
10623
|
}
|
|
10886
|
-
if (rows.length === 0)
|
|
10887
|
-
return null;
|
|
10624
|
+
if (rows.length === 0) return null;
|
|
10888
10625
|
const row = rows[0];
|
|
10889
10626
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
10890
10627
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -10926,8 +10663,7 @@ var VectorWorkerV2 = class {
|
|
|
10926
10663
|
* Start the worker polling loop
|
|
10927
10664
|
*/
|
|
10928
10665
|
start() {
|
|
10929
|
-
if (this.running)
|
|
10930
|
-
return;
|
|
10666
|
+
if (this.running) return;
|
|
10931
10667
|
this.running = true;
|
|
10932
10668
|
this.stopping = false;
|
|
10933
10669
|
this.poll();
|
|
@@ -10997,8 +10733,7 @@ var VectorWorkerV2 = class {
|
|
|
10997
10733
|
* Poll for new jobs
|
|
10998
10734
|
*/
|
|
10999
10735
|
async poll() {
|
|
11000
|
-
if (!this.running || this.stopping)
|
|
11001
|
-
return;
|
|
10736
|
+
if (!this.running || this.stopping) return;
|
|
11002
10737
|
try {
|
|
11003
10738
|
await this.processBatch();
|
|
11004
10739
|
} catch (error) {
|
|
@@ -11065,8 +10800,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11065
10800
|
let graduationWorker = null;
|
|
11066
10801
|
return {
|
|
11067
10802
|
async initialize() {
|
|
11068
|
-
if (initialized)
|
|
11069
|
-
return;
|
|
10803
|
+
if (initialized) return;
|
|
11070
10804
|
await deps.sqliteStore.initialize();
|
|
11071
10805
|
if (deps.lightweightMode) {
|
|
11072
10806
|
initialized = true;
|
|
@@ -11160,8 +10894,7 @@ var SharedEventStore = class {
|
|
|
11160
10894
|
this.db = createDatabase(dbPath);
|
|
11161
10895
|
}
|
|
11162
10896
|
async initialize() {
|
|
11163
|
-
if (this.initialized)
|
|
11164
|
-
return;
|
|
10897
|
+
if (this.initialized) return;
|
|
11165
10898
|
await dbRun(this.db, `
|
|
11166
10899
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11167
10900
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11251,6 +10984,10 @@ var SharedPromoter = class {
|
|
|
11251
10984
|
this.embedder = embedder;
|
|
11252
10985
|
this.config = config;
|
|
11253
10986
|
}
|
|
10987
|
+
sharedStore;
|
|
10988
|
+
sharedVectorStore;
|
|
10989
|
+
embedder;
|
|
10990
|
+
config;
|
|
11254
10991
|
/**
|
|
11255
10992
|
* Check if an entry is eligible for promotion
|
|
11256
10993
|
*/
|
|
@@ -11432,6 +11169,7 @@ var SharedStore = class {
|
|
|
11432
11169
|
constructor(sharedEventStore) {
|
|
11433
11170
|
this.sharedEventStore = sharedEventStore;
|
|
11434
11171
|
}
|
|
11172
|
+
sharedEventStore;
|
|
11435
11173
|
get db() {
|
|
11436
11174
|
return this.sharedEventStore.getDatabase();
|
|
11437
11175
|
}
|
|
@@ -11536,8 +11274,7 @@ var SharedStore = class {
|
|
|
11536
11274
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11537
11275
|
[entryId]
|
|
11538
11276
|
);
|
|
11539
|
-
if (rows.length === 0)
|
|
11540
|
-
return null;
|
|
11277
|
+
if (rows.length === 0) return null;
|
|
11541
11278
|
return this.rowToEntry(rows[0]);
|
|
11542
11279
|
}
|
|
11543
11280
|
/**
|
|
@@ -11550,8 +11287,7 @@ var SharedStore = class {
|
|
|
11550
11287
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11551
11288
|
[projectHash, sourceEntryId]
|
|
11552
11289
|
);
|
|
11553
|
-
if (rows.length === 0)
|
|
11554
|
-
return null;
|
|
11290
|
+
if (rows.length === 0) return null;
|
|
11555
11291
|
return this.rowToEntry(rows[0]);
|
|
11556
11292
|
}
|
|
11557
11293
|
/**
|
|
@@ -11661,6 +11397,7 @@ var SharedVectorStore = class {
|
|
|
11661
11397
|
constructor(dbPath) {
|
|
11662
11398
|
this.dbPath = dbPath;
|
|
11663
11399
|
}
|
|
11400
|
+
dbPath;
|
|
11664
11401
|
db = null;
|
|
11665
11402
|
table = null;
|
|
11666
11403
|
tableName = "shared_knowledge";
|
|
@@ -11668,8 +11405,7 @@ var SharedVectorStore = class {
|
|
|
11668
11405
|
* Initialize LanceDB connection
|
|
11669
11406
|
*/
|
|
11670
11407
|
async initialize() {
|
|
11671
|
-
if (this.db)
|
|
11672
|
-
return;
|
|
11408
|
+
if (this.db) return;
|
|
11673
11409
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11674
11410
|
try {
|
|
11675
11411
|
const tables = await this.db.tableNames();
|
|
@@ -11711,8 +11447,7 @@ var SharedVectorStore = class {
|
|
|
11711
11447
|
* Add multiple records in batch
|
|
11712
11448
|
*/
|
|
11713
11449
|
async upsertBatch(records) {
|
|
11714
|
-
if (records.length === 0)
|
|
11715
|
-
return;
|
|
11450
|
+
if (records.length === 0) return;
|
|
11716
11451
|
await this.initialize();
|
|
11717
11452
|
if (!this.db) {
|
|
11718
11453
|
throw new Error("Database not initialized");
|
|
@@ -11773,24 +11508,21 @@ var SharedVectorStore = class {
|
|
|
11773
11508
|
* Delete vector by entry ID
|
|
11774
11509
|
*/
|
|
11775
11510
|
async delete(entryId) {
|
|
11776
|
-
if (!this.table)
|
|
11777
|
-
return;
|
|
11511
|
+
if (!this.table) return;
|
|
11778
11512
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11779
11513
|
}
|
|
11780
11514
|
/**
|
|
11781
11515
|
* Get total count
|
|
11782
11516
|
*/
|
|
11783
11517
|
async count() {
|
|
11784
|
-
if (!this.table)
|
|
11785
|
-
return 0;
|
|
11518
|
+
if (!this.table) return 0;
|
|
11786
11519
|
return this.table.countRows();
|
|
11787
11520
|
}
|
|
11788
11521
|
/**
|
|
11789
11522
|
* Check if vector exists for entry
|
|
11790
11523
|
*/
|
|
11791
11524
|
async exists(entryId) {
|
|
11792
|
-
if (!this.table)
|
|
11793
|
-
return false;
|
|
11525
|
+
if (!this.table) return false;
|
|
11794
11526
|
try {
|
|
11795
11527
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11796
11528
|
return results.length > 0;
|
|
@@ -11808,6 +11540,7 @@ var SharedMemoryServices = class {
|
|
|
11808
11540
|
constructor(options) {
|
|
11809
11541
|
this.options = options;
|
|
11810
11542
|
}
|
|
11543
|
+
options;
|
|
11811
11544
|
sharedEventStore = null;
|
|
11812
11545
|
sharedStore = null;
|
|
11813
11546
|
sharedVectorStore = null;
|
|
@@ -11832,8 +11565,7 @@ var SharedMemoryServices = class {
|
|
|
11832
11565
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
11833
11566
|
}
|
|
11834
11567
|
async initialize() {
|
|
11835
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
11836
|
-
return;
|
|
11568
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
11837
11569
|
const sharedPath = this.getSharedStoragePath();
|
|
11838
11570
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
11839
11571
|
const store = await this.openStore(sharedPath);
|
|
@@ -11850,14 +11582,11 @@ var SharedMemoryServices = class {
|
|
|
11850
11582
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
11851
11583
|
}
|
|
11852
11584
|
async ensureStoreForRead() {
|
|
11853
|
-
if (this.options.config?.enabled === false)
|
|
11854
|
-
|
|
11855
|
-
if (this.sharedStore)
|
|
11856
|
-
return this.sharedStore;
|
|
11585
|
+
if (this.options.config?.enabled === false) return null;
|
|
11586
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11857
11587
|
const sharedPath = this.getSharedStoragePath();
|
|
11858
11588
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
11859
|
-
if (!directoryReady)
|
|
11860
|
-
return null;
|
|
11589
|
+
if (!directoryReady) return null;
|
|
11861
11590
|
return this.openStore(sharedPath);
|
|
11862
11591
|
}
|
|
11863
11592
|
async getEntryForDisclosure(entryId) {
|
|
@@ -11874,13 +11603,11 @@ var SharedMemoryServices = class {
|
|
|
11874
11603
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
11875
11604
|
}
|
|
11876
11605
|
async getStats() {
|
|
11877
|
-
if (!this.sharedStore)
|
|
11878
|
-
return null;
|
|
11606
|
+
if (!this.sharedStore) return null;
|
|
11879
11607
|
return this.sharedStore.getStats();
|
|
11880
11608
|
}
|
|
11881
11609
|
async search(query, options) {
|
|
11882
|
-
if (!this.sharedStore)
|
|
11883
|
-
return [];
|
|
11610
|
+
if (!this.sharedStore) return [];
|
|
11884
11611
|
return this.sharedStore.search(query, options);
|
|
11885
11612
|
}
|
|
11886
11613
|
async close() {
|
|
@@ -11897,8 +11624,7 @@ var SharedMemoryServices = class {
|
|
|
11897
11624
|
this.openStorePromise = null;
|
|
11898
11625
|
}
|
|
11899
11626
|
async openStore(sharedPath) {
|
|
11900
|
-
if (this.sharedStore)
|
|
11901
|
-
return this.sharedStore;
|
|
11627
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11902
11628
|
if (!this.openStorePromise) {
|
|
11903
11629
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
11904
11630
|
}
|
|
@@ -11922,10 +11648,8 @@ var SharedMemoryServices = class {
|
|
|
11922
11648
|
return this.sharedStore;
|
|
11923
11649
|
}
|
|
11924
11650
|
ensureDirectory(sharedPath, options) {
|
|
11925
|
-
if (this.factories.existsSync(sharedPath))
|
|
11926
|
-
|
|
11927
|
-
if (!options.allowCreate)
|
|
11928
|
-
return false;
|
|
11651
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11652
|
+
if (!options.allowCreate) return false;
|
|
11929
11653
|
this.factories.mkdirSync(sharedPath);
|
|
11930
11654
|
return true;
|
|
11931
11655
|
}
|