claude-memory-layer 1.0.44 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +747 -1414
- package/dist/cli/index.js.map +1 -1
- package/dist/core/index.js +1191 -1490
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +411 -749
- package/dist/hooks/post-tool-use.js.map +1 -1
- package/dist/hooks/semantic-daemon.js +400 -727
- package/dist/hooks/semantic-daemon.js.map +1 -1
- package/dist/hooks/session-end.js +396 -719
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.js +397 -721
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/stop.js +404 -735
- package/dist/hooks/stop.js.map +1 -1
- package/dist/hooks/user-prompt-submit.js +440 -807
- package/dist/hooks/user-prompt-submit.js.map +1 -1
- package/dist/index.js +1269 -1604
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1443 -1637
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +430 -785
- package/dist/server/api/index.js.map +1 -1
- package/dist/server/index.js +438 -801
- package/dist/server/index.js.map +1 -1
- package/dist/services/memory-service.js +396 -719
- package/dist/services/memory-service.js.map +1 -1
- package/package.json +15 -3
package/dist/hooks/stop.js
CHANGED
|
@@ -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, path12) {
|
|
2690
2645
|
let cursor = root;
|
|
2691
2646
|
for (const key of path12) {
|
|
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, path12) {
|
|
|
2698
2652
|
function getNestedString(root, path12) {
|
|
2699
2653
|
let cursor = root;
|
|
2700
2654
|
for (const key of path12) {
|
|
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({
|
|
@@ -5637,8 +5544,7 @@ function parsePrivateTags(text, options) {
|
|
|
5637
5544
|
let filtered = text;
|
|
5638
5545
|
for (const format of options.formats) {
|
|
5639
5546
|
const pattern = TAG_PATTERNS[format];
|
|
5640
|
-
if (!pattern)
|
|
5641
|
-
continue;
|
|
5547
|
+
if (!pattern) continue;
|
|
5642
5548
|
pattern.lastIndex = 0;
|
|
5643
5549
|
let match;
|
|
5644
5550
|
while ((match = pattern.exec(text)) !== null) {
|
|
@@ -5652,12 +5558,10 @@ function parsePrivateTags(text, options) {
|
|
|
5652
5558
|
}
|
|
5653
5559
|
for (const format of options.formats) {
|
|
5654
5560
|
const pattern = TAG_PATTERNS[format];
|
|
5655
|
-
if (!pattern)
|
|
5656
|
-
continue;
|
|
5561
|
+
if (!pattern) continue;
|
|
5657
5562
|
const replacePattern = new RegExp(pattern.source, "gi");
|
|
5658
5563
|
filtered = filtered.replace(replacePattern, (_match, content) => {
|
|
5659
|
-
if (!content.trim())
|
|
5660
|
-
return "";
|
|
5564
|
+
if (!content.trim()) return "";
|
|
5661
5565
|
return options.marker;
|
|
5662
5566
|
});
|
|
5663
5567
|
}
|
|
@@ -5735,8 +5639,7 @@ function looksLikePastedSecret(value) {
|
|
|
5735
5639
|
function maskUrlFollowingSecret(value) {
|
|
5736
5640
|
let count = 0;
|
|
5737
5641
|
const content = value.replace(URL_FOLLOWING_SECRET_PATTERN, (_match, prefix, secret) => {
|
|
5738
|
-
if (!looksLikePastedSecret(secret))
|
|
5739
|
-
return `${prefix}${secret}`;
|
|
5642
|
+
if (!looksLikePastedSecret(secret)) return `${prefix}${secret}`;
|
|
5740
5643
|
count++;
|
|
5741
5644
|
return `${prefix}[REDACTED]`;
|
|
5742
5645
|
});
|
|
@@ -5933,8 +5836,7 @@ var MemoryOperationsConfigSchema = z7.object({
|
|
|
5933
5836
|
}).default({});
|
|
5934
5837
|
var MemoryLessonNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5935
5838
|
var MemoryLessonStringArraySchema = z7.preprocess((value) => {
|
|
5936
|
-
if (!Array.isArray(value))
|
|
5937
|
-
return value;
|
|
5839
|
+
if (!Array.isArray(value)) return value;
|
|
5938
5840
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5939
5841
|
}, z7.array(MemoryLessonNonEmptyStringSchema)).default([]);
|
|
5940
5842
|
var MemoryLessonSchema = z7.object({
|
|
@@ -5979,14 +5881,12 @@ var ListMemoryLessonsInputSchema = z7.object({
|
|
|
5979
5881
|
});
|
|
5980
5882
|
var PerspectiveMemoryNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5981
5883
|
var PerspectiveMemoryOptionalStringSchema = z7.preprocess((value) => {
|
|
5982
|
-
if (typeof value !== "string")
|
|
5983
|
-
return value;
|
|
5884
|
+
if (typeof value !== "string") return value;
|
|
5984
5885
|
const normalized = value.trim();
|
|
5985
5886
|
return normalized.length > 0 ? normalized : void 0;
|
|
5986
5887
|
}, PerspectiveMemoryNonEmptyStringSchema.optional());
|
|
5987
5888
|
var PerspectiveMemoryStringArraySchema = z7.preprocess((value) => {
|
|
5988
|
-
if (!Array.isArray(value))
|
|
5989
|
-
return value;
|
|
5889
|
+
if (!Array.isArray(value)) return value;
|
|
5990
5890
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5991
5891
|
}, z7.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);
|
|
5992
5892
|
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;
|
|
@@ -6644,6 +6544,7 @@ var GraphPathService = class {
|
|
|
6644
6544
|
constructor(db) {
|
|
6645
6545
|
this.db = db;
|
|
6646
6546
|
}
|
|
6547
|
+
db;
|
|
6647
6548
|
expand(input) {
|
|
6648
6549
|
const graph = this.loadGraph(input.direction ?? "both");
|
|
6649
6550
|
const effectiveMaxHops = normalizeMaxHops(input.maxHops);
|
|
@@ -6661,11 +6562,9 @@ var GraphPathService = class {
|
|
|
6661
6562
|
while (queue.length > 0) {
|
|
6662
6563
|
queue.sort((a, b) => a.totalCost - b.totalCost || a.hops - b.hops || a.key.localeCompare(b.key));
|
|
6663
6564
|
const current = queue.shift();
|
|
6664
|
-
if (current.hops >= effectiveMaxHops)
|
|
6665
|
-
continue;
|
|
6565
|
+
if (current.hops >= effectiveMaxHops) continue;
|
|
6666
6566
|
for (const edge of graph.adjacency.get(current.key) ?? []) {
|
|
6667
|
-
if (current.visited.has(edge.toKey))
|
|
6668
|
-
continue;
|
|
6567
|
+
if (current.visited.has(edge.toKey)) continue;
|
|
6669
6568
|
const nextHops = current.hops + 1;
|
|
6670
6569
|
const nextTotalCost = current.totalCost + edge.step.cost;
|
|
6671
6570
|
const nextSteps = [...current.steps, edge.step];
|
|
@@ -6745,17 +6644,13 @@ function addTraversal(adjacency, fromKey, edge) {
|
|
|
6745
6644
|
adjacency.set(fromKey, edges);
|
|
6746
6645
|
}
|
|
6747
6646
|
function normalizeMaxHops(maxHops) {
|
|
6748
|
-
if (maxHops === void 0)
|
|
6749
|
-
|
|
6750
|
-
if (!Number.isFinite(maxHops))
|
|
6751
|
-
return MAX_HOPS;
|
|
6647
|
+
if (maxHops === void 0) return 1;
|
|
6648
|
+
if (!Number.isFinite(maxHops)) return MAX_HOPS;
|
|
6752
6649
|
return Math.min(Math.max(0, Math.trunc(maxHops)), MAX_HOPS);
|
|
6753
6650
|
}
|
|
6754
6651
|
function normalizeMaxResults(maxResults) {
|
|
6755
|
-
if (maxResults === void 0)
|
|
6756
|
-
|
|
6757
|
-
if (!Number.isFinite(maxResults))
|
|
6758
|
-
return DEFAULT_MAX_RESULTS;
|
|
6652
|
+
if (maxResults === void 0) return DEFAULT_MAX_RESULTS;
|
|
6653
|
+
if (!Number.isFinite(maxResults)) return DEFAULT_MAX_RESULTS;
|
|
6759
6654
|
return Math.min(Math.max(0, Math.trunc(maxResults)), MAX_RESULTS);
|
|
6760
6655
|
}
|
|
6761
6656
|
function isBetterPath(totalCost, hops, signature, existing) {
|
|
@@ -6767,18 +6662,15 @@ function pathSignature(steps) {
|
|
|
6767
6662
|
function edgeWeight(metaJson) {
|
|
6768
6663
|
const meta = parseMeta(metaJson);
|
|
6769
6664
|
const raw = meta.weight;
|
|
6770
|
-
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
6771
|
-
return raw;
|
|
6665
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
6772
6666
|
if (typeof raw === "string") {
|
|
6773
6667
|
const parsed = Number(raw);
|
|
6774
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
6775
|
-
return parsed;
|
|
6668
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
6776
6669
|
}
|
|
6777
6670
|
return DEFAULT_WEIGHT;
|
|
6778
6671
|
}
|
|
6779
6672
|
function parseMeta(metaJson) {
|
|
6780
|
-
if (!metaJson)
|
|
6781
|
-
return {};
|
|
6673
|
+
if (!metaJson) return {};
|
|
6782
6674
|
try {
|
|
6783
6675
|
const parsed = JSON.parse(metaJson);
|
|
6784
6676
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -6791,8 +6683,7 @@ function nodeKey(node) {
|
|
|
6791
6683
|
}
|
|
6792
6684
|
function nodeFromKey(key) {
|
|
6793
6685
|
const index = key.indexOf(":");
|
|
6794
|
-
if (index === -1)
|
|
6795
|
-
return { type: "entity", id: key };
|
|
6686
|
+
if (index === -1) return { type: "entity", id: key };
|
|
6796
6687
|
return { type: key.slice(0, index), id: key.slice(index + 1) };
|
|
6797
6688
|
}
|
|
6798
6689
|
|
|
@@ -6848,6 +6739,7 @@ var QueryEntityExtractor = class {
|
|
|
6848
6739
|
constructor(db) {
|
|
6849
6740
|
this.db = db;
|
|
6850
6741
|
}
|
|
6742
|
+
db;
|
|
6851
6743
|
extract(query, options = {}) {
|
|
6852
6744
|
const maxCandidates = normalizeMaxCandidates(options.maxCandidates);
|
|
6853
6745
|
const candidates = [];
|
|
@@ -6869,8 +6761,7 @@ var QueryEntityExtractor = class {
|
|
|
6869
6761
|
let match;
|
|
6870
6762
|
while ((match = regex.exec(query)) !== null) {
|
|
6871
6763
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6872
|
-
if (!isUsefulCandidate(text))
|
|
6873
|
-
continue;
|
|
6764
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6874
6765
|
const start = match.index + 1;
|
|
6875
6766
|
const end = start + text.length;
|
|
6876
6767
|
ranges.push([match.index, match.index + match[0].length]);
|
|
@@ -6884,8 +6775,7 @@ var QueryEntityExtractor = class {
|
|
|
6884
6775
|
return ranges;
|
|
6885
6776
|
}
|
|
6886
6777
|
extractKnownAliases(query, candidates) {
|
|
6887
|
-
if (!this.db)
|
|
6888
|
-
return;
|
|
6778
|
+
if (!this.db) return;
|
|
6889
6779
|
const rows = sqliteAll(
|
|
6890
6780
|
this.db,
|
|
6891
6781
|
`SELECT
|
|
@@ -6909,11 +6799,9 @@ var QueryEntityExtractor = class {
|
|
|
6909
6799
|
]).filter(isUsefulCandidate);
|
|
6910
6800
|
for (const alias of aliasLabels) {
|
|
6911
6801
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6912
|
-
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias))
|
|
6913
|
-
continue;
|
|
6802
|
+
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias)) continue;
|
|
6914
6803
|
const aliasKey = `${row.entity_id}:${normalizedAlias}`;
|
|
6915
|
-
if (seenAliases.has(aliasKey))
|
|
6916
|
-
continue;
|
|
6804
|
+
if (seenAliases.has(aliasKey)) continue;
|
|
6917
6805
|
seenAliases.add(aliasKey);
|
|
6918
6806
|
const range = findRange(query, alias);
|
|
6919
6807
|
pushCandidate(candidates, {
|
|
@@ -6934,8 +6822,7 @@ var QueryEntityExtractor = class {
|
|
|
6934
6822
|
let match;
|
|
6935
6823
|
while ((match = regex.exec(query)) !== null) {
|
|
6936
6824
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6937
|
-
if (!isUsefulCandidate(text))
|
|
6938
|
-
continue;
|
|
6825
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6939
6826
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6940
6827
|
pushCandidate(candidates, {
|
|
6941
6828
|
text,
|
|
@@ -6950,8 +6837,7 @@ var QueryEntityExtractor = class {
|
|
|
6950
6837
|
let match;
|
|
6951
6838
|
while ((match = regex.exec(query)) !== null) {
|
|
6952
6839
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6953
|
-
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./"))
|
|
6954
|
-
continue;
|
|
6840
|
+
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./")) continue;
|
|
6955
6841
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6956
6842
|
pushCandidate(candidates, {
|
|
6957
6843
|
text,
|
|
@@ -6970,21 +6856,17 @@ var QueryEntityExtractor = class {
|
|
|
6970
6856
|
if (previous && query.slice(previous.end, token.start).match(/^\s+$/)) {
|
|
6971
6857
|
current.push(token);
|
|
6972
6858
|
} else {
|
|
6973
|
-
if (current.length > 0)
|
|
6974
|
-
groups.push(current);
|
|
6859
|
+
if (current.length > 0) groups.push(current);
|
|
6975
6860
|
current = [token];
|
|
6976
6861
|
}
|
|
6977
6862
|
}
|
|
6978
|
-
if (current.length > 0)
|
|
6979
|
-
groups.push(current);
|
|
6863
|
+
if (current.length > 0) groups.push(current);
|
|
6980
6864
|
for (const group of groups) {
|
|
6981
|
-
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text))
|
|
6982
|
-
continue;
|
|
6865
|
+
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text)) continue;
|
|
6983
6866
|
const start = group[0].start;
|
|
6984
6867
|
const end = group[group.length - 1].end;
|
|
6985
6868
|
const text = query.slice(start, end);
|
|
6986
|
-
if (!isUsefulCandidate(text))
|
|
6987
|
-
continue;
|
|
6869
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6988
6870
|
pushCandidate(candidates, {
|
|
6989
6871
|
text,
|
|
6990
6872
|
source: "capitalized_term",
|
|
@@ -7005,8 +6887,7 @@ function collectCapitalizedTokens(query) {
|
|
|
7005
6887
|
}
|
|
7006
6888
|
function pushCandidate(candidates, input) {
|
|
7007
6889
|
const text = cleanCandidateText(input.text);
|
|
7008
|
-
if (!isUsefulCandidate(text))
|
|
7009
|
-
return;
|
|
6890
|
+
if (!isUsefulCandidate(text)) return;
|
|
7010
6891
|
const source = input.source;
|
|
7011
6892
|
candidates.push({
|
|
7012
6893
|
...input,
|
|
@@ -7024,15 +6905,13 @@ function dedupeAndSort(candidates) {
|
|
|
7024
6905
|
for (const candidate of sorted) {
|
|
7025
6906
|
if (candidate.source === "entity_alias") {
|
|
7026
6907
|
const aliasKey = `alias:${candidate.entityId ?? ""}:${normalizeCandidate(candidate.matchedAlias ?? candidate.text)}`;
|
|
7027
|
-
if (seenAliasKeys.has(aliasKey))
|
|
7028
|
-
continue;
|
|
6908
|
+
if (seenAliasKeys.has(aliasKey)) continue;
|
|
7029
6909
|
seenAliasKeys.add(aliasKey);
|
|
7030
6910
|
seenNormalized.add(candidate.normalized);
|
|
7031
6911
|
result.push(candidate);
|
|
7032
6912
|
continue;
|
|
7033
6913
|
}
|
|
7034
|
-
if (seenNormalized.has(candidate.normalized))
|
|
7035
|
-
continue;
|
|
6914
|
+
if (seenNormalized.has(candidate.normalized)) continue;
|
|
7036
6915
|
seenNormalized.add(candidate.normalized);
|
|
7037
6916
|
result.push(candidate);
|
|
7038
6917
|
}
|
|
@@ -7042,8 +6921,7 @@ function compareCandidates(a, b) {
|
|
|
7042
6921
|
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 ?? "");
|
|
7043
6922
|
}
|
|
7044
6923
|
function compareStrings(a, b) {
|
|
7045
|
-
if (a === b)
|
|
7046
|
-
return 0;
|
|
6924
|
+
if (a === b) return 0;
|
|
7047
6925
|
return a < b ? -1 : 1;
|
|
7048
6926
|
}
|
|
7049
6927
|
function stripPriority(candidate) {
|
|
@@ -7051,10 +6929,8 @@ function stripPriority(candidate) {
|
|
|
7051
6929
|
return publicCandidate;
|
|
7052
6930
|
}
|
|
7053
6931
|
function normalizeMaxCandidates(maxCandidates) {
|
|
7054
|
-
if (maxCandidates === void 0)
|
|
7055
|
-
|
|
7056
|
-
if (!Number.isFinite(maxCandidates))
|
|
7057
|
-
return DEFAULT_MAX_CANDIDATES;
|
|
6932
|
+
if (maxCandidates === void 0) return DEFAULT_MAX_CANDIDATES;
|
|
6933
|
+
if (!Number.isFinite(maxCandidates)) return DEFAULT_MAX_CANDIDATES;
|
|
7058
6934
|
return Math.min(Math.max(0, Math.trunc(maxCandidates)), MAX_CANDIDATES);
|
|
7059
6935
|
}
|
|
7060
6936
|
function cleanCandidateText(text) {
|
|
@@ -7076,21 +6952,17 @@ function aliasLabelFromCanonicalKey(canonicalKey) {
|
|
|
7076
6952
|
function findRange(query, alias) {
|
|
7077
6953
|
const normalizedAlias = normalizeForContainment(alias);
|
|
7078
6954
|
const directIndex = query.toLowerCase().indexOf(alias.toLowerCase());
|
|
7079
|
-
if (directIndex >= 0)
|
|
7080
|
-
return { start: directIndex, end: directIndex + alias.length };
|
|
6955
|
+
if (directIndex >= 0) return { start: directIndex, end: directIndex + alias.length };
|
|
7081
6956
|
const normalizedQuery = normalizeForContainment(query);
|
|
7082
6957
|
const normalizedIndex = normalizedQuery.indexOf(normalizedAlias);
|
|
7083
|
-
if (normalizedIndex < 0)
|
|
7084
|
-
return { start: 0, end: 0 };
|
|
6958
|
+
if (normalizedIndex < 0) return { start: 0, end: 0 };
|
|
7085
6959
|
const queryLower = query.toLowerCase();
|
|
7086
6960
|
const words = normalizedAlias.split(" ").filter(Boolean);
|
|
7087
|
-
if (words.length === 0)
|
|
7088
|
-
return { start: 0, end: 0 };
|
|
6961
|
+
if (words.length === 0) return { start: 0, end: 0 };
|
|
7089
6962
|
const first = queryLower.indexOf(words[0]);
|
|
7090
6963
|
const lastWord = words[words.length - 1];
|
|
7091
6964
|
const last = queryLower.indexOf(lastWord, first >= 0 ? first : 0);
|
|
7092
|
-
if (first >= 0 && last >= 0)
|
|
7093
|
-
return { start: first, end: last + lastWord.length };
|
|
6965
|
+
if (first >= 0 && last >= 0) return { start: first, end: last + lastWord.length };
|
|
7094
6966
|
return { start: normalizedIndex, end: normalizedIndex + normalizedAlias.length };
|
|
7095
6967
|
}
|
|
7096
6968
|
function isUsefulCandidate(text) {
|
|
@@ -7101,10 +6973,8 @@ function isInsideAnyRange(index, ranges) {
|
|
|
7101
6973
|
return ranges.some(([start, end]) => index >= start && index < end);
|
|
7102
6974
|
}
|
|
7103
6975
|
function isStrongSingleCapitalized(text) {
|
|
7104
|
-
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text))
|
|
7105
|
-
|
|
7106
|
-
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text))
|
|
7107
|
-
return true;
|
|
6976
|
+
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text)) return true;
|
|
6977
|
+
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text)) return true;
|
|
7108
6978
|
return text.length >= 4 && !SENTENCE_START_STOPWORDS.has(text);
|
|
7109
6979
|
}
|
|
7110
6980
|
function uniqueStrings(values) {
|
|
@@ -7112,8 +6982,7 @@ function uniqueStrings(values) {
|
|
|
7112
6982
|
const result = [];
|
|
7113
6983
|
for (const value of values) {
|
|
7114
6984
|
const key = normalizeForContainment(value);
|
|
7115
|
-
if (!key || seen.has(key))
|
|
7116
|
-
continue;
|
|
6985
|
+
if (!key || seen.has(key)) continue;
|
|
7117
6986
|
seen.add(key);
|
|
7118
6987
|
result.push(value);
|
|
7119
6988
|
}
|
|
@@ -7135,8 +7004,7 @@ var LessonCandidateInputSchema = z9.object({
|
|
|
7135
7004
|
import { z as z10 } from "zod";
|
|
7136
7005
|
var NonEmptyStringSchema5 = z10.string().transform((value) => value.trim()).pipe(z10.string().min(1));
|
|
7137
7006
|
var PromotionStringArraySchema = z10.preprocess((value) => {
|
|
7138
|
-
if (!Array.isArray(value))
|
|
7139
|
-
return value;
|
|
7007
|
+
if (!Array.isArray(value)) return value;
|
|
7140
7008
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
7141
7009
|
}, z10.array(NonEmptyStringSchema5).max(100));
|
|
7142
7010
|
var ReviewedLessonCandidateSchema = z10.object({
|
|
@@ -7184,8 +7052,7 @@ function projectHashFromStorage(projectHash) {
|
|
|
7184
7052
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7185
7053
|
}
|
|
7186
7054
|
function parseJsonRecord(value) {
|
|
7187
|
-
if (!value)
|
|
7188
|
-
return void 0;
|
|
7055
|
+
if (!value) return void 0;
|
|
7189
7056
|
try {
|
|
7190
7057
|
const parsed = JSON.parse(value);
|
|
7191
7058
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7197,8 +7064,7 @@ function sanitizeString(value) {
|
|
|
7197
7064
|
return String(sanitizeGovernanceAuditValue(value)).trim();
|
|
7198
7065
|
}
|
|
7199
7066
|
function sanitizeMetadata(metadata) {
|
|
7200
|
-
if (!metadata)
|
|
7201
|
-
return void 0;
|
|
7067
|
+
if (!metadata) return void 0;
|
|
7202
7068
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7203
7069
|
}
|
|
7204
7070
|
function slugActorPart(value) {
|
|
@@ -7206,8 +7072,7 @@ function slugActorPart(value) {
|
|
|
7206
7072
|
return slug.length > 0 ? slug : "unknown";
|
|
7207
7073
|
}
|
|
7208
7074
|
function stableActorId(input) {
|
|
7209
|
-
if (input.actorId)
|
|
7210
|
-
return sanitizeString(input.actorId);
|
|
7075
|
+
if (input.actorId) return sanitizeString(input.actorId);
|
|
7211
7076
|
const projectPart = input.projectHash ? `project:${slugActorPart(input.projectHash)}` : "global";
|
|
7212
7077
|
return [
|
|
7213
7078
|
"actor",
|
|
@@ -7230,12 +7095,10 @@ function rowToActor(row) {
|
|
|
7230
7095
|
});
|
|
7231
7096
|
}
|
|
7232
7097
|
function metadataString(metadata, keys) {
|
|
7233
|
-
if (!metadata)
|
|
7234
|
-
return void 0;
|
|
7098
|
+
if (!metadata) return void 0;
|
|
7235
7099
|
for (const key of keys) {
|
|
7236
7100
|
const value = metadata[key];
|
|
7237
|
-
if (typeof value === "string" && value.trim().length > 0)
|
|
7238
|
-
return value.trim();
|
|
7101
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
7239
7102
|
}
|
|
7240
7103
|
return void 0;
|
|
7241
7104
|
}
|
|
@@ -7285,6 +7148,7 @@ var ActorRepository = class {
|
|
|
7285
7148
|
constructor(db) {
|
|
7286
7149
|
this.db = db;
|
|
7287
7150
|
}
|
|
7151
|
+
db;
|
|
7288
7152
|
async upsert(input) {
|
|
7289
7153
|
const parsed = UpsertMemoryActorInputSchema.parse(input);
|
|
7290
7154
|
const actorId = stableActorId(parsed);
|
|
@@ -7338,8 +7202,7 @@ var ActorRepository = class {
|
|
|
7338
7202
|
}
|
|
7339
7203
|
require(actorId) {
|
|
7340
7204
|
const actor = this.get(actorId);
|
|
7341
|
-
if (!actor)
|
|
7342
|
-
throw new Error(`Memory actor not found: ${actorId}`);
|
|
7205
|
+
if (!actor) throw new Error(`Memory actor not found: ${actorId}`);
|
|
7343
7206
|
return actor;
|
|
7344
7207
|
}
|
|
7345
7208
|
async list(input = {}) {
|
|
@@ -7375,8 +7238,7 @@ function projectHashFromStorage2(projectHash) {
|
|
|
7375
7238
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7376
7239
|
}
|
|
7377
7240
|
function parseJsonRecord2(value) {
|
|
7378
|
-
if (!value)
|
|
7379
|
-
return void 0;
|
|
7241
|
+
if (!value) return void 0;
|
|
7380
7242
|
try {
|
|
7381
7243
|
const parsed = JSON.parse(value);
|
|
7382
7244
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7385,8 +7247,7 @@ function parseJsonRecord2(value) {
|
|
|
7385
7247
|
}
|
|
7386
7248
|
}
|
|
7387
7249
|
function sanitizeMetadata2(metadata) {
|
|
7388
|
-
if (!metadata)
|
|
7389
|
-
return void 0;
|
|
7250
|
+
if (!metadata) return void 0;
|
|
7390
7251
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7391
7252
|
}
|
|
7392
7253
|
function rowToSessionActor(row) {
|
|
@@ -7406,6 +7267,7 @@ var SessionActorRepository = class {
|
|
|
7406
7267
|
constructor(db) {
|
|
7407
7268
|
this.db = db;
|
|
7408
7269
|
}
|
|
7270
|
+
db;
|
|
7409
7271
|
async upsertMembership(input) {
|
|
7410
7272
|
const parsed = UpsertSessionActorInputSchema.parse(input);
|
|
7411
7273
|
const projectHash = projectHashToStorage3(parsed.projectHash);
|
|
@@ -7452,8 +7314,7 @@ var SessionActorRepository = class {
|
|
|
7452
7314
|
);
|
|
7453
7315
|
}
|
|
7454
7316
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7455
|
-
if (!saved)
|
|
7456
|
-
throw new Error("session actor membership was not saved");
|
|
7317
|
+
if (!saved) throw new Error("session actor membership was not saved");
|
|
7457
7318
|
return saved;
|
|
7458
7319
|
}
|
|
7459
7320
|
async listBySession(input) {
|
|
@@ -7489,8 +7350,7 @@ var SessionActorRepository = class {
|
|
|
7489
7350
|
]
|
|
7490
7351
|
);
|
|
7491
7352
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7492
|
-
if (!saved)
|
|
7493
|
-
throw new Error("session actor membership not found after update");
|
|
7353
|
+
if (!saved) throw new Error("session actor membership not found after update");
|
|
7494
7354
|
return saved;
|
|
7495
7355
|
}
|
|
7496
7356
|
get(projectHash, sessionId, actorId) {
|
|
@@ -7512,8 +7372,7 @@ function projectHashFromStorage3(projectHash) {
|
|
|
7512
7372
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7513
7373
|
}
|
|
7514
7374
|
function parseStringArray2(value) {
|
|
7515
|
-
if (!value)
|
|
7516
|
-
return [];
|
|
7375
|
+
if (!value) return [];
|
|
7517
7376
|
try {
|
|
7518
7377
|
const parsed = JSON.parse(value);
|
|
7519
7378
|
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
@@ -7522,8 +7381,7 @@ function parseStringArray2(value) {
|
|
|
7522
7381
|
}
|
|
7523
7382
|
}
|
|
7524
7383
|
function parseJsonRecord3(value) {
|
|
7525
|
-
if (!value)
|
|
7526
|
-
return void 0;
|
|
7384
|
+
if (!value) return void 0;
|
|
7527
7385
|
try {
|
|
7528
7386
|
const parsed = JSON.parse(value);
|
|
7529
7387
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7539,8 +7397,7 @@ function sanitizeStoredStringArray(values) {
|
|
|
7539
7397
|
return values.map(sanitizeStoredString).filter((value) => value.length > 0);
|
|
7540
7398
|
}
|
|
7541
7399
|
function sanitizeStoredRecord(value) {
|
|
7542
|
-
if (!value)
|
|
7543
|
-
return void 0;
|
|
7400
|
+
if (!value) return void 0;
|
|
7544
7401
|
return sanitizeGovernanceAuditValue(value);
|
|
7545
7402
|
}
|
|
7546
7403
|
function stableHash(value) {
|
|
@@ -7591,8 +7448,7 @@ function sanitizedObservationSnapshot(observation) {
|
|
|
7591
7448
|
});
|
|
7592
7449
|
}
|
|
7593
7450
|
function queryScore(observation, terms) {
|
|
7594
|
-
if (terms.length === 0)
|
|
7595
|
-
return 0;
|
|
7451
|
+
if (terms.length === 0) return 0;
|
|
7596
7452
|
const haystack = [observation.content, observation.level, observation.sessionId ?? ""].join(" ").toLowerCase();
|
|
7597
7453
|
return terms.reduce((score, term) => score + (haystack.includes(term) ? 1 : 0), 0);
|
|
7598
7454
|
}
|
|
@@ -7638,12 +7494,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7638
7494
|
this.vectorOutbox = options.vectorOutbox;
|
|
7639
7495
|
}
|
|
7640
7496
|
}
|
|
7497
|
+
db;
|
|
7641
7498
|
vectorOutbox = null;
|
|
7642
7499
|
vectorOutboxOption;
|
|
7643
7500
|
getVectorOutbox() {
|
|
7644
7501
|
const option = this.vectorOutboxOption;
|
|
7645
|
-
if (option === false)
|
|
7646
|
-
return null;
|
|
7502
|
+
if (option === false) return null;
|
|
7647
7503
|
if (option instanceof VectorOutbox) {
|
|
7648
7504
|
this.vectorOutbox = option;
|
|
7649
7505
|
return option;
|
|
@@ -7655,8 +7511,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7655
7511
|
}
|
|
7656
7512
|
enqueueObservationSync(observationId) {
|
|
7657
7513
|
const outbox = this.getVectorOutbox();
|
|
7658
|
-
if (!outbox)
|
|
7659
|
-
return;
|
|
7514
|
+
if (!outbox) return;
|
|
7660
7515
|
outbox.enqueueSync("perspective_observation", observationId);
|
|
7661
7516
|
}
|
|
7662
7517
|
async create(input) {
|
|
@@ -7718,14 +7573,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7718
7573
|
contentHash,
|
|
7719
7574
|
sourceHash
|
|
7720
7575
|
);
|
|
7721
|
-
if (!saved)
|
|
7722
|
-
throw new Error("perspective observation was not saved");
|
|
7576
|
+
if (!saved) throw new Error("perspective observation was not saved");
|
|
7723
7577
|
this.enqueueObservationSync(saved.observationId);
|
|
7724
7578
|
});
|
|
7725
7579
|
transaction();
|
|
7726
7580
|
const savedObservation = saved;
|
|
7727
|
-
if (!savedObservation)
|
|
7728
|
-
throw new Error("perspective observation was not saved");
|
|
7581
|
+
if (!savedObservation) throw new Error("perspective observation was not saved");
|
|
7729
7582
|
await this.writeCreateAudit({ ...parsed, observerActorId, observedActorId, sessionId, content, sourceEventIds, sourceObservationIds, createdBy, actor, metadata }, savedObservation);
|
|
7730
7583
|
return savedObservation;
|
|
7731
7584
|
}
|
|
@@ -7735,8 +7588,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7735
7588
|
const ftsQuery = buildObservationFtsQuery(parsed.query);
|
|
7736
7589
|
if (ftsQuery) {
|
|
7737
7590
|
const ftsResult = this.queryWithFts(parsed, ftsQuery);
|
|
7738
|
-
if (ftsResult)
|
|
7739
|
-
return ftsResult;
|
|
7591
|
+
if (ftsResult) return ftsResult;
|
|
7740
7592
|
}
|
|
7741
7593
|
}
|
|
7742
7594
|
return this.queryWithPrefetch(parsed);
|
|
@@ -7757,8 +7609,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7757
7609
|
);
|
|
7758
7610
|
return rows.map(rowToObservation);
|
|
7759
7611
|
} catch (error) {
|
|
7760
|
-
if (isFtsUnavailableError(error))
|
|
7761
|
-
return null;
|
|
7612
|
+
if (isFtsUnavailableError(error)) return null;
|
|
7762
7613
|
throw error;
|
|
7763
7614
|
}
|
|
7764
7615
|
}
|
|
@@ -7799,8 +7650,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7799
7650
|
const parsed = DeletePerspectiveObservationInputSchema.parse(input);
|
|
7800
7651
|
const projectHash = projectHashToStorage4(parsed.projectHash);
|
|
7801
7652
|
const before = this.get(projectHash, parsed.observationId);
|
|
7802
|
-
if (!before)
|
|
7803
|
-
throw new Error("perspective observation not found");
|
|
7653
|
+
if (!before) throw new Error("perspective observation not found");
|
|
7804
7654
|
const deletedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7805
7655
|
sqliteRun(
|
|
7806
7656
|
this.db,
|
|
@@ -7810,8 +7660,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7810
7660
|
[deletedAt, deletedAt, projectHash, parsed.observationId]
|
|
7811
7661
|
);
|
|
7812
7662
|
const after = this.get(projectHash, parsed.observationId);
|
|
7813
|
-
if (!after)
|
|
7814
|
-
throw new Error("perspective observation not found after delete");
|
|
7663
|
+
if (!after) throw new Error("perspective observation not found after delete");
|
|
7815
7664
|
await writeGovernanceAuditEntry(this.db, {
|
|
7816
7665
|
operation: "perspective_observation_delete",
|
|
7817
7666
|
actor: parsed.actor,
|
|
@@ -7867,11 +7716,9 @@ var DEFAULT_CONFIG3 = {
|
|
|
7867
7716
|
var MAX_OBSERVATION_CONTENT_CHARS = 600;
|
|
7868
7717
|
var RuleBasedPerspectiveObservationExtractor = class {
|
|
7869
7718
|
async extract(event) {
|
|
7870
|
-
if (!isSupportedSourceEvent(event))
|
|
7871
|
-
return [];
|
|
7719
|
+
if (!isSupportedSourceEvent(event)) return [];
|
|
7872
7720
|
const content = normalizeObservationContent(event.content);
|
|
7873
|
-
if (!content)
|
|
7874
|
-
return [];
|
|
7721
|
+
if (!content) return [];
|
|
7875
7722
|
return [{
|
|
7876
7723
|
content,
|
|
7877
7724
|
confidence: 0.6,
|
|
@@ -7942,8 +7789,7 @@ var PerspectiveDeriver = class {
|
|
|
7942
7789
|
for (const candidate of candidates) {
|
|
7943
7790
|
const observedActorId = candidate.observedActorId ?? sourceActor.actorId;
|
|
7944
7791
|
const observers = selectObservers(members, observedActorId, this.config.deriver.maxObserversPerSession);
|
|
7945
|
-
if (observers.length === 0)
|
|
7946
|
-
continue;
|
|
7792
|
+
if (observers.length === 0) continue;
|
|
7947
7793
|
for (const observerActorId of observers) {
|
|
7948
7794
|
await this.observations.create({
|
|
7949
7795
|
projectHash,
|
|
@@ -7996,28 +7842,22 @@ function normalizeConfig(config) {
|
|
|
7996
7842
|
};
|
|
7997
7843
|
}
|
|
7998
7844
|
function clampInteger(value, fallback, min, max) {
|
|
7999
|
-
if (!Number.isFinite(value))
|
|
8000
|
-
return fallback;
|
|
7845
|
+
if (!Number.isFinite(value)) return fallback;
|
|
8001
7846
|
return Math.max(min, Math.min(max, Math.trunc(Number(value))));
|
|
8002
7847
|
}
|
|
8003
7848
|
function isSupportedSourceEvent(event) {
|
|
8004
7849
|
return event.eventType === "user_prompt" || event.eventType === "agent_response";
|
|
8005
7850
|
}
|
|
8006
7851
|
function roleForEvent(event) {
|
|
8007
|
-
if (event.eventType === "user_prompt")
|
|
8008
|
-
|
|
8009
|
-
if (event.eventType === "
|
|
8010
|
-
|
|
8011
|
-
if (event.eventType === "tool_observation")
|
|
8012
|
-
return "tool";
|
|
8013
|
-
if (event.eventType === "session_summary")
|
|
8014
|
-
return "system";
|
|
7852
|
+
if (event.eventType === "user_prompt") return "speaker";
|
|
7853
|
+
if (event.eventType === "agent_response") return "assistant";
|
|
7854
|
+
if (event.eventType === "tool_observation") return "tool";
|
|
7855
|
+
if (event.eventType === "session_summary") return "system";
|
|
8015
7856
|
return "unknown";
|
|
8016
7857
|
}
|
|
8017
7858
|
function normalizeCandidate2(candidate) {
|
|
8018
7859
|
const content = normalizeObservationContent(candidate.content);
|
|
8019
|
-
if (!content)
|
|
8020
|
-
return null;
|
|
7860
|
+
if (!content) return null;
|
|
8021
7861
|
return {
|
|
8022
7862
|
content,
|
|
8023
7863
|
confidence: clampNumber(candidate.confidence, 0.6, 0, 1),
|
|
@@ -8029,8 +7869,7 @@ function normalizeCandidate2(candidate) {
|
|
|
8029
7869
|
}
|
|
8030
7870
|
function normalizeObservationContent(content) {
|
|
8031
7871
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
8032
|
-
if (!normalized)
|
|
8033
|
-
return null;
|
|
7872
|
+
if (!normalized) return null;
|
|
8034
7873
|
return normalized.slice(0, MAX_OBSERVATION_CONTENT_CHARS);
|
|
8035
7874
|
}
|
|
8036
7875
|
function normalizeOptionalString2(value) {
|
|
@@ -8038,13 +7877,11 @@ function normalizeOptionalString2(value) {
|
|
|
8038
7877
|
return normalized.length > 0 ? normalized : void 0;
|
|
8039
7878
|
}
|
|
8040
7879
|
function clampNumber(value, fallback, min, max) {
|
|
8041
|
-
if (!Number.isFinite(value))
|
|
8042
|
-
return fallback;
|
|
7880
|
+
if (!Number.isFinite(value)) return fallback;
|
|
8043
7881
|
return Math.max(min, Math.min(max, Number(value)));
|
|
8044
7882
|
}
|
|
8045
7883
|
function sanitizeCandidateMetadata(metadata) {
|
|
8046
|
-
if (!metadata)
|
|
8047
|
-
return void 0;
|
|
7884
|
+
if (!metadata) return void 0;
|
|
8048
7885
|
const result = {};
|
|
8049
7886
|
for (const [key, value] of Object.entries(metadata)) {
|
|
8050
7887
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -8057,12 +7894,9 @@ function selectObservers(members, observedActorId, maxObservers) {
|
|
|
8057
7894
|
const selected = [];
|
|
8058
7895
|
for (const member of members) {
|
|
8059
7896
|
const canObserve = member.actorId === observedActorId ? member.observeSelf : member.observeOthers;
|
|
8060
|
-
if (!canObserve)
|
|
8061
|
-
|
|
8062
|
-
if (
|
|
8063
|
-
selected.push(member.actorId);
|
|
8064
|
-
if (selected.length >= maxObservers)
|
|
8065
|
-
break;
|
|
7897
|
+
if (!canObserve) continue;
|
|
7898
|
+
if (!selected.includes(member.actorId)) selected.push(member.actorId);
|
|
7899
|
+
if (selected.length >= maxObservers) break;
|
|
8066
7900
|
}
|
|
8067
7901
|
return selected;
|
|
8068
7902
|
}
|
|
@@ -8081,6 +7915,7 @@ var VectorStore = class {
|
|
|
8081
7915
|
constructor(dbPath) {
|
|
8082
7916
|
this.dbPath = dbPath;
|
|
8083
7917
|
}
|
|
7918
|
+
dbPath;
|
|
8084
7919
|
db = null;
|
|
8085
7920
|
tableCache = /* @__PURE__ */ new Map();
|
|
8086
7921
|
defaultTableName = "conversations";
|
|
@@ -8092,8 +7927,7 @@ var VectorStore = class {
|
|
|
8092
7927
|
* conversations table.
|
|
8093
7928
|
*/
|
|
8094
7929
|
async initialize() {
|
|
8095
|
-
if (this.db)
|
|
8096
|
-
return;
|
|
7930
|
+
if (this.db) return;
|
|
8097
7931
|
this.db = await lancedb.connect(this.dbPath);
|
|
8098
7932
|
}
|
|
8099
7933
|
/**
|
|
@@ -8107,8 +7941,7 @@ var VectorStore = class {
|
|
|
8107
7941
|
* Add or update multiple vector records in batch, grouped by inferred table.
|
|
8108
7942
|
*/
|
|
8109
7943
|
async upsertBatch(records) {
|
|
8110
|
-
if (records.length === 0)
|
|
8111
|
-
return;
|
|
7944
|
+
if (records.length === 0) return;
|
|
8112
7945
|
await this.initialize();
|
|
8113
7946
|
if (!this.db) {
|
|
8114
7947
|
throw new Error("Database not initialized");
|
|
@@ -8163,8 +7996,7 @@ var VectorStore = class {
|
|
|
8163
7996
|
async delete(eventId) {
|
|
8164
7997
|
await this.initialize();
|
|
8165
7998
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8166
|
-
if (!table)
|
|
8167
|
-
return;
|
|
7999
|
+
if (!table) return;
|
|
8168
8000
|
await table.delete(`eventId = ${toLanceSqlString(eventId)}`);
|
|
8169
8001
|
}
|
|
8170
8002
|
/**
|
|
@@ -8173,8 +8005,7 @@ var VectorStore = class {
|
|
|
8173
8005
|
async count() {
|
|
8174
8006
|
await this.initialize();
|
|
8175
8007
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8176
|
-
if (!table)
|
|
8177
|
-
return 0;
|
|
8008
|
+
if (!table) return 0;
|
|
8178
8009
|
const result = await table.countRows();
|
|
8179
8010
|
return result;
|
|
8180
8011
|
}
|
|
@@ -8183,8 +8014,7 @@ var VectorStore = class {
|
|
|
8183
8014
|
*/
|
|
8184
8015
|
async clearAll() {
|
|
8185
8016
|
await this.initialize();
|
|
8186
|
-
if (!this.db)
|
|
8187
|
-
return;
|
|
8017
|
+
if (!this.db) return;
|
|
8188
8018
|
try {
|
|
8189
8019
|
if (typeof this.db.dropTable === "function") {
|
|
8190
8020
|
await this.db.dropTable(this.defaultTableName);
|
|
@@ -8201,8 +8031,7 @@ var VectorStore = class {
|
|
|
8201
8031
|
async exists(eventId) {
|
|
8202
8032
|
await this.initialize();
|
|
8203
8033
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8204
|
-
if (!table)
|
|
8205
|
-
return false;
|
|
8034
|
+
if (!table) return false;
|
|
8206
8035
|
const results = await table.search([]).where(`eventId = ${toLanceSqlString(eventId)}`).limit(1).toArray();
|
|
8207
8036
|
return results.length > 0;
|
|
8208
8037
|
}
|
|
@@ -8237,8 +8066,7 @@ var VectorStore = class {
|
|
|
8237
8066
|
throw new Error("Database not initialized");
|
|
8238
8067
|
}
|
|
8239
8068
|
const cached = this.tableCache.get(tableName);
|
|
8240
|
-
if (cached)
|
|
8241
|
-
return cached;
|
|
8069
|
+
if (cached) return cached;
|
|
8242
8070
|
const tableNames = await this.db.tableNames();
|
|
8243
8071
|
if (!tableNames.includes(tableName)) {
|
|
8244
8072
|
return null;
|
|
@@ -8317,12 +8145,9 @@ var IngestInterceptorRegistry = class {
|
|
|
8317
8145
|
}
|
|
8318
8146
|
};
|
|
8319
8147
|
function mergeHierarchicalMetadata(base, patch) {
|
|
8320
|
-
if (!base && !patch)
|
|
8321
|
-
|
|
8322
|
-
if (!base
|
|
8323
|
-
return patch;
|
|
8324
|
-
if (!patch)
|
|
8325
|
-
return base;
|
|
8148
|
+
if (!base && !patch) return void 0;
|
|
8149
|
+
if (!base) return patch;
|
|
8150
|
+
if (!patch) return base;
|
|
8326
8151
|
const result = { ...base };
|
|
8327
8152
|
for (const [key, value] of Object.entries(patch)) {
|
|
8328
8153
|
const current = result[key];
|
|
@@ -8352,33 +8177,26 @@ var VALID_TAG_NAMESPACES = new Set(Object.values(TAG_NAMESPACES));
|
|
|
8352
8177
|
function parseTag(tag) {
|
|
8353
8178
|
const value = (tag || "").trim();
|
|
8354
8179
|
const idx = value.indexOf(":");
|
|
8355
|
-
if (idx <= 0)
|
|
8356
|
-
return { value };
|
|
8180
|
+
if (idx <= 0) return { value };
|
|
8357
8181
|
const namespace = `${value.slice(0, idx)}:`;
|
|
8358
8182
|
const tagValue = value.slice(idx + 1);
|
|
8359
|
-
if (!tagValue)
|
|
8360
|
-
return { value };
|
|
8183
|
+
if (!tagValue) return { value };
|
|
8361
8184
|
return { namespace, value: tagValue };
|
|
8362
8185
|
}
|
|
8363
8186
|
function validateTag(tag) {
|
|
8364
8187
|
const normalized = (tag || "").trim();
|
|
8365
|
-
if (!normalized)
|
|
8366
|
-
return false;
|
|
8188
|
+
if (!normalized) return false;
|
|
8367
8189
|
const { namespace } = parseTag(normalized);
|
|
8368
|
-
if (!namespace)
|
|
8369
|
-
return true;
|
|
8190
|
+
if (!namespace) return true;
|
|
8370
8191
|
return VALID_TAG_NAMESPACES.has(namespace);
|
|
8371
8192
|
}
|
|
8372
8193
|
function normalizeTags(tags) {
|
|
8373
|
-
if (!Array.isArray(tags))
|
|
8374
|
-
return [];
|
|
8194
|
+
if (!Array.isArray(tags)) return [];
|
|
8375
8195
|
const dedup = /* @__PURE__ */ new Set();
|
|
8376
8196
|
for (const item of tags) {
|
|
8377
|
-
if (typeof item !== "string")
|
|
8378
|
-
continue;
|
|
8197
|
+
if (typeof item !== "string") continue;
|
|
8379
8198
|
const normalized = item.trim();
|
|
8380
|
-
if (!validateTag(normalized))
|
|
8381
|
-
continue;
|
|
8199
|
+
if (!validateTag(normalized)) continue;
|
|
8382
8200
|
dedup.add(normalized);
|
|
8383
8201
|
}
|
|
8384
8202
|
return [...dedup];
|
|
@@ -8395,10 +8213,8 @@ var SummaryDeriver = class {
|
|
|
8395
8213
|
* orchestration, while this class owns summary text and metadata decisions.
|
|
8396
8214
|
*/
|
|
8397
8215
|
deriveSessionSummary(events) {
|
|
8398
|
-
if (events.length < 3)
|
|
8399
|
-
|
|
8400
|
-
if (events.some((event) => event.eventType === "session_summary"))
|
|
8401
|
-
return null;
|
|
8216
|
+
if (events.length < 3) return null;
|
|
8217
|
+
if (events.some((event) => event.eventType === "session_summary")) return null;
|
|
8402
8218
|
const prompts = events.filter((event) => event.eventType === "user_prompt");
|
|
8403
8219
|
const toolObservations = events.filter((event) => event.eventType === "tool_observation");
|
|
8404
8220
|
const toolNames = Array.from(new Set(
|
|
@@ -8546,8 +8362,7 @@ var MemoryIngestService = class {
|
|
|
8546
8362
|
await this.initialize();
|
|
8547
8363
|
const events = await this.eventStore.getSessionEvents(sessionId);
|
|
8548
8364
|
const summary = this.summaryDeriver.deriveSessionSummary(events);
|
|
8549
|
-
if (!summary)
|
|
8550
|
-
return;
|
|
8365
|
+
if (!summary) return;
|
|
8551
8366
|
await this.storeSessionSummary(sessionId, summary.text, summary.metadata);
|
|
8552
8367
|
}
|
|
8553
8368
|
async storeToolObservation(sessionId, payload) {
|
|
@@ -8615,10 +8430,8 @@ var MemoryIngestService = class {
|
|
|
8615
8430
|
}
|
|
8616
8431
|
}
|
|
8617
8432
|
async runPerspectiveDeriver(input, eventId, operation) {
|
|
8618
|
-
if (!this.perspectiveDeriver)
|
|
8619
|
-
|
|
8620
|
-
if (operation !== "user_prompt" && operation !== "agent_response")
|
|
8621
|
-
return;
|
|
8433
|
+
if (!this.perspectiveDeriver) return;
|
|
8434
|
+
if (operation !== "user_prompt" && operation !== "agent_response") return;
|
|
8622
8435
|
const event = {
|
|
8623
8436
|
id: eventId,
|
|
8624
8437
|
eventType: input.eventType,
|
|
@@ -8688,11 +8501,13 @@ var MemoryQueryService = class {
|
|
|
8688
8501
|
this.queryStore = queryStore;
|
|
8689
8502
|
this.deps = deps;
|
|
8690
8503
|
}
|
|
8504
|
+
initialize;
|
|
8505
|
+
queryStore;
|
|
8506
|
+
deps;
|
|
8691
8507
|
async keywordSearch(query, options) {
|
|
8692
8508
|
await this.initialize();
|
|
8693
8509
|
const results = await this.queryStore.keywordSearch(query, options?.topK ?? 10);
|
|
8694
|
-
if (results.length === 0)
|
|
8695
|
-
return [];
|
|
8510
|
+
if (results.length === 0) return [];
|
|
8696
8511
|
const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
|
|
8697
8512
|
const minRank = Math.max(...results.map((r) => r.rank), -1e3);
|
|
8698
8513
|
const rankRange = maxRank - minRank || 1;
|
|
@@ -8938,55 +8753,42 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8938
8753
|
]);
|
|
8939
8754
|
function isCommandArtifactQuery(query) {
|
|
8940
8755
|
const trimmed = query.trim();
|
|
8941
|
-
if (!trimmed)
|
|
8942
|
-
return false;
|
|
8756
|
+
if (!trimmed) return false;
|
|
8943
8757
|
const normalized = trimmed.toLowerCase();
|
|
8944
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8945
|
-
|
|
8946
|
-
if (normalized.includes("command-name") || normalized.includes("command-message"))
|
|
8947
|
-
return true;
|
|
8758
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8759
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8948
8760
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8949
8761
|
}
|
|
8950
8762
|
function isGenericContinuationQuery(query) {
|
|
8951
8763
|
const trimmed = query.trim();
|
|
8952
|
-
if (!trimmed)
|
|
8953
|
-
|
|
8954
|
-
if (
|
|
8955
|
-
return false;
|
|
8956
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8957
|
-
return false;
|
|
8764
|
+
if (!trimmed) return false;
|
|
8765
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8766
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8958
8767
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8959
|
-
if (tokens.length > 10)
|
|
8960
|
-
return false;
|
|
8768
|
+
if (tokens.length > 10) return false;
|
|
8961
8769
|
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);
|
|
8962
8770
|
}
|
|
8963
8771
|
function isShortRepairFollowUpQuery(query) {
|
|
8964
8772
|
const trimmed = query.trim();
|
|
8965
|
-
if (!trimmed)
|
|
8966
|
-
|
|
8967
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8968
|
-
return false;
|
|
8773
|
+
if (!trimmed) return false;
|
|
8774
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8969
8775
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8970
|
-
if (tokens.length > 8)
|
|
8971
|
-
return false;
|
|
8776
|
+
if (tokens.length > 8) return false;
|
|
8972
8777
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8973
8778
|
}
|
|
8974
8779
|
function isCurrentStateQuery(query) {
|
|
8975
8780
|
const trimmed = query.trim();
|
|
8976
|
-
if (!trimmed)
|
|
8977
|
-
return false;
|
|
8781
|
+
if (!trimmed) return false;
|
|
8978
8782
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8979
8783
|
}
|
|
8980
8784
|
function isStaleOrSupersededContent(content) {
|
|
8981
8785
|
const trimmed = content.trim();
|
|
8982
|
-
if (!trimmed)
|
|
8983
|
-
return false;
|
|
8786
|
+
if (!trimmed) return false;
|
|
8984
8787
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8985
8788
|
}
|
|
8986
8789
|
function buildRetrievalQualityQuery(query) {
|
|
8987
8790
|
const trimmed = query.trim();
|
|
8988
|
-
if (!trimmed)
|
|
8989
|
-
return query;
|
|
8791
|
+
if (!trimmed) return query;
|
|
8990
8792
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8991
8793
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8992
8794
|
}
|
|
@@ -9000,12 +8802,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
9000
8802
|
}
|
|
9001
8803
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
9002
8804
|
const trimmed = query.trim();
|
|
9003
|
-
if (!trimmed)
|
|
9004
|
-
return false;
|
|
8805
|
+
if (!trimmed) return false;
|
|
9005
8806
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
9006
8807
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
9007
|
-
if (!hasDecisionSignal)
|
|
9008
|
-
return false;
|
|
8808
|
+
if (!hasDecisionSignal) return false;
|
|
9009
8809
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
9010
8810
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
9011
8811
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -9018,16 +8818,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
9018
8818
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
9019
8819
|
const terms = matches.filter((term) => {
|
|
9020
8820
|
const lower = term.toLowerCase();
|
|
9021
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
9022
|
-
return false;
|
|
8821
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
9023
8822
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
9024
8823
|
});
|
|
9025
8824
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
9026
8825
|
}
|
|
9027
8826
|
function hasTechnicalTermOverlap(query, content) {
|
|
9028
8827
|
const terms = extractTechnicalQueryTerms(query);
|
|
9029
|
-
if (terms.length === 0)
|
|
9030
|
-
return true;
|
|
8828
|
+
if (terms.length === 0) return true;
|
|
9031
8829
|
const normalizedContent = content.toLowerCase();
|
|
9032
8830
|
return terms.some((term) => normalizedContent.includes(term));
|
|
9033
8831
|
}
|
|
@@ -9043,15 +8841,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
9043
8841
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
9044
8842
|
}
|
|
9045
8843
|
}
|
|
9046
|
-
if (queryTerms.length < 3)
|
|
9047
|
-
return true;
|
|
8844
|
+
if (queryTerms.length < 3) return true;
|
|
9048
8845
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
9049
8846
|
let hits = 0;
|
|
9050
8847
|
for (const term of queryTerms) {
|
|
9051
|
-
if (contentTerms.has(term))
|
|
9052
|
-
|
|
9053
|
-
if (hits >= requiredHits)
|
|
9054
|
-
return true;
|
|
8848
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8849
|
+
if (hits >= requiredHits) return true;
|
|
9055
8850
|
}
|
|
9056
8851
|
return false;
|
|
9057
8852
|
}
|
|
@@ -9061,17 +8856,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
9061
8856
|
function hasAnyTerm(terms, expectedTerms) {
|
|
9062
8857
|
let found = false;
|
|
9063
8858
|
expectedTerms.forEach((term) => {
|
|
9064
|
-
if (terms.has(term))
|
|
9065
|
-
found = true;
|
|
8859
|
+
if (terms.has(term)) found = true;
|
|
9066
8860
|
});
|
|
9067
8861
|
return found;
|
|
9068
8862
|
}
|
|
9069
8863
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
9070
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
9071
|
-
return false;
|
|
8864
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
9072
8865
|
const trimmed = query.trim();
|
|
9073
|
-
if (!trimmed)
|
|
9074
|
-
return false;
|
|
8866
|
+
if (!trimmed) return false;
|
|
9075
8867
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
9076
8868
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
9077
8869
|
}
|
|
@@ -9079,12 +8871,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
9079
8871
|
const seen = /* @__PURE__ */ new Set();
|
|
9080
8872
|
const terms = [];
|
|
9081
8873
|
for (const token of tokenizeQualityText(query)) {
|
|
9082
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
9083
|
-
|
|
9084
|
-
if (
|
|
9085
|
-
continue;
|
|
9086
|
-
if (seen.has(token))
|
|
9087
|
-
continue;
|
|
8874
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8875
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8876
|
+
if (seen.has(token)) continue;
|
|
9088
8877
|
seen.add(token);
|
|
9089
8878
|
terms.push(token);
|
|
9090
8879
|
}
|
|
@@ -9099,14 +8888,10 @@ function tokenizeQualityText(text) {
|
|
|
9099
8888
|
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);
|
|
9100
8889
|
}
|
|
9101
8890
|
function normalizeQualityToken(token) {
|
|
9102
|
-
if (token === "apis")
|
|
9103
|
-
|
|
9104
|
-
if (token
|
|
9105
|
-
|
|
9106
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
9107
|
-
return token;
|
|
9108
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9109
|
-
return `${token.slice(0, -3)}y`;
|
|
8891
|
+
if (token === "apis") return "api";
|
|
8892
|
+
if (token === "ids") return "id";
|
|
8893
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8894
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9110
8895
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
9111
8896
|
return token.slice(0, -1);
|
|
9112
8897
|
}
|
|
@@ -9288,8 +9073,7 @@ var Retriever = class {
|
|
|
9288
9073
|
const sharedMemories = [];
|
|
9289
9074
|
for (const result of sharedVectorResults) {
|
|
9290
9075
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9291
|
-
if (!entry)
|
|
9292
|
-
continue;
|
|
9076
|
+
if (!entry) continue;
|
|
9293
9077
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9294
9078
|
sharedMemories.push(entry);
|
|
9295
9079
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9370,18 +9154,15 @@ var Retriever = class {
|
|
|
9370
9154
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9371
9155
|
);
|
|
9372
9156
|
}
|
|
9373
|
-
if (filtered.length <= 2)
|
|
9374
|
-
return filtered;
|
|
9157
|
+
if (filtered.length <= 2) return filtered;
|
|
9375
9158
|
const topScore = filtered[0].score;
|
|
9376
|
-
if (topScore < 0.8)
|
|
9377
|
-
return filtered;
|
|
9159
|
+
if (topScore < 0.8) return filtered;
|
|
9378
9160
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9379
9161
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9380
9162
|
}
|
|
9381
9163
|
mergeResults(primary, secondary, limit) {
|
|
9382
9164
|
const byId = /* @__PURE__ */ new Map();
|
|
9383
|
-
for (const row of primary)
|
|
9384
|
-
byId.set(row.eventId, row);
|
|
9165
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9385
9166
|
for (const row of secondary) {
|
|
9386
9167
|
const prev = byId.get(row.eventId);
|
|
9387
9168
|
if (!prev || row.score > prev.score) {
|
|
@@ -9392,23 +9173,19 @@ var Retriever = class {
|
|
|
9392
9173
|
}
|
|
9393
9174
|
async expandGraphHops(seeds, opts) {
|
|
9394
9175
|
const byId = /* @__PURE__ */ new Map();
|
|
9395
|
-
for (const s of seeds)
|
|
9396
|
-
byId.set(s.eventId, s);
|
|
9176
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9397
9177
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9398
9178
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9399
9179
|
const next = [];
|
|
9400
9180
|
for (const f of frontier) {
|
|
9401
9181
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9402
|
-
if (!ev)
|
|
9403
|
-
continue;
|
|
9182
|
+
if (!ev) continue;
|
|
9404
9183
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9405
9184
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9406
9185
|
for (const rid of relatedIds) {
|
|
9407
|
-
if (byId.has(rid))
|
|
9408
|
-
continue;
|
|
9186
|
+
if (byId.has(rid)) continue;
|
|
9409
9187
|
const target = await this.eventStore.getEvent(rid);
|
|
9410
|
-
if (!target)
|
|
9411
|
-
continue;
|
|
9188
|
+
if (!target) continue;
|
|
9412
9189
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9413
9190
|
const row = {
|
|
9414
9191
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9422,15 +9199,12 @@ var Retriever = class {
|
|
|
9422
9199
|
};
|
|
9423
9200
|
byId.set(row.eventId, row);
|
|
9424
9201
|
next.push({ row, hop });
|
|
9425
|
-
if (byId.size >= opts.limit)
|
|
9426
|
-
break;
|
|
9202
|
+
if (byId.size >= opts.limit) break;
|
|
9427
9203
|
}
|
|
9428
|
-
if (byId.size >= opts.limit)
|
|
9429
|
-
break;
|
|
9204
|
+
if (byId.size >= opts.limit) break;
|
|
9430
9205
|
}
|
|
9431
9206
|
frontier = next;
|
|
9432
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9433
|
-
break;
|
|
9207
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9434
9208
|
}
|
|
9435
9209
|
if (opts.queryGraphEnabled) {
|
|
9436
9210
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9438,8 +9212,7 @@ var Retriever = class {
|
|
|
9438
9212
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9439
9213
|
}
|
|
9440
9214
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9441
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9442
|
-
return;
|
|
9215
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9443
9216
|
try {
|
|
9444
9217
|
const db = this.eventStore.getDatabase();
|
|
9445
9218
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9448,8 +9221,7 @@ var Retriever = class {
|
|
|
9448
9221
|
});
|
|
9449
9222
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9450
9223
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9451
|
-
if (startNodes.length === 0)
|
|
9452
|
-
return;
|
|
9224
|
+
if (startNodes.length === 0) return;
|
|
9453
9225
|
const expansion = new GraphPathService(db).expand({
|
|
9454
9226
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9455
9227
|
maxHops: opts.maxHops,
|
|
@@ -9458,11 +9230,9 @@ var Retriever = class {
|
|
|
9458
9230
|
});
|
|
9459
9231
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9460
9232
|
for (const path12 of expansion.paths) {
|
|
9461
|
-
if (path12.target.type !== "event")
|
|
9462
|
-
continue;
|
|
9233
|
+
if (path12.target.type !== "event") continue;
|
|
9463
9234
|
const target = await this.eventStore.getEvent(path12.target.id);
|
|
9464
|
-
if (!target)
|
|
9465
|
-
continue;
|
|
9235
|
+
if (!target) continue;
|
|
9466
9236
|
const graphPath = toRetrievalGraphPathDebug(path12, titleByEntityId);
|
|
9467
9237
|
const score = graphPathScore(path12, opts.hopPenalty);
|
|
9468
9238
|
const existing = byId.get(target.id);
|
|
@@ -9488,17 +9258,14 @@ var Retriever = class {
|
|
|
9488
9258
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9489
9259
|
};
|
|
9490
9260
|
byId.set(row.eventId, row);
|
|
9491
|
-
if (byId.size >= opts.limit)
|
|
9492
|
-
break;
|
|
9261
|
+
if (byId.size >= opts.limit) break;
|
|
9493
9262
|
}
|
|
9494
9263
|
} catch {
|
|
9495
9264
|
}
|
|
9496
9265
|
}
|
|
9497
9266
|
shouldFallback(matchResult, results) {
|
|
9498
|
-
if (results.length === 0)
|
|
9499
|
-
|
|
9500
|
-
if (matchResult.confidence === "none")
|
|
9501
|
-
return true;
|
|
9267
|
+
if (results.length === 0) return true;
|
|
9268
|
+
if (matchResult.confidence === "none") return true;
|
|
9502
9269
|
return false;
|
|
9503
9270
|
}
|
|
9504
9271
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9603,29 +9370,21 @@ var Retriever = class {
|
|
|
9603
9370
|
(value) => typeof value === "string" && value.length > 0
|
|
9604
9371
|
)
|
|
9605
9372
|
);
|
|
9606
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9607
|
-
return results;
|
|
9373
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9608
9374
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9609
9375
|
const filtered = [];
|
|
9610
9376
|
for (const result of results) {
|
|
9611
|
-
if (scope?.sessionId && result.sessionId !== scope.sessionId)
|
|
9612
|
-
|
|
9613
|
-
if (scope?.
|
|
9614
|
-
continue;
|
|
9615
|
-
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType))
|
|
9616
|
-
continue;
|
|
9377
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9378
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9379
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9617
9380
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9618
|
-
if (!event)
|
|
9619
|
-
|
|
9620
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9621
|
-
continue;
|
|
9381
|
+
if (!event) continue;
|
|
9382
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9622
9383
|
if (normalizedIncludes.length > 0) {
|
|
9623
9384
|
const lc = event.content.toLowerCase();
|
|
9624
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9625
|
-
continue;
|
|
9385
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9626
9386
|
}
|
|
9627
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9628
|
-
continue;
|
|
9387
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9629
9388
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9630
9389
|
filtered.push({ result, projectHash });
|
|
9631
9390
|
}
|
|
@@ -9642,27 +9401,21 @@ var Retriever = class {
|
|
|
9642
9401
|
});
|
|
9643
9402
|
}
|
|
9644
9403
|
normalizeFacetFilters(facets) {
|
|
9645
|
-
if (!facets || facets.length === 0)
|
|
9646
|
-
return null;
|
|
9404
|
+
if (!facets || facets.length === 0) return null;
|
|
9647
9405
|
const normalized = [];
|
|
9648
9406
|
for (const facet of facets) {
|
|
9649
9407
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9650
9408
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9651
|
-
if (!parsedDimension.success || !value)
|
|
9652
|
-
return [];
|
|
9409
|
+
if (!parsedDimension.success || !value) return [];
|
|
9653
9410
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9654
9411
|
}
|
|
9655
9412
|
return normalized;
|
|
9656
9413
|
}
|
|
9657
9414
|
async applyFacetFilters(results, options) {
|
|
9658
|
-
if (options.facets === null)
|
|
9659
|
-
|
|
9660
|
-
if (options.
|
|
9661
|
-
|
|
9662
|
-
if (!options.projectHash)
|
|
9663
|
-
return [];
|
|
9664
|
-
if (!this.eventStore.getDatabase)
|
|
9665
|
-
return [];
|
|
9415
|
+
if (options.facets === null) return results;
|
|
9416
|
+
if (options.facets.length === 0) return [];
|
|
9417
|
+
if (!options.projectHash) return [];
|
|
9418
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9666
9419
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9667
9420
|
const filtered = [];
|
|
9668
9421
|
for (const result of results) {
|
|
@@ -9719,14 +9472,11 @@ var Retriever = class {
|
|
|
9719
9472
|
return (result.graphPaths || []).length > 0;
|
|
9720
9473
|
}
|
|
9721
9474
|
extractProjectHash(metadata) {
|
|
9722
|
-
if (!metadata || typeof metadata !== "object")
|
|
9723
|
-
return void 0;
|
|
9475
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9724
9476
|
const scope = metadata.scope;
|
|
9725
|
-
if (!scope || typeof scope !== "object")
|
|
9726
|
-
return void 0;
|
|
9477
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9727
9478
|
const project = scope.project;
|
|
9728
|
-
if (!project || typeof project !== "object")
|
|
9729
|
-
return void 0;
|
|
9479
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9730
9480
|
const hash = project.hash;
|
|
9731
9481
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9732
9482
|
}
|
|
@@ -9740,8 +9490,7 @@ var Retriever = class {
|
|
|
9740
9490
|
const memories = [];
|
|
9741
9491
|
for (const result of results) {
|
|
9742
9492
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9743
|
-
if (!event)
|
|
9744
|
-
continue;
|
|
9493
|
+
if (!event) continue;
|
|
9745
9494
|
if (this.graduation) {
|
|
9746
9495
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9747
9496
|
}
|
|
@@ -9756,32 +9505,27 @@ var Retriever = class {
|
|
|
9756
9505
|
async getSessionContext(sessionId, eventId) {
|
|
9757
9506
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9758
9507
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9759
|
-
if (eventIndex === -1)
|
|
9760
|
-
return void 0;
|
|
9508
|
+
if (eventIndex === -1) return void 0;
|
|
9761
9509
|
const start = Math.max(0, eventIndex - 1);
|
|
9762
9510
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9763
9511
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9764
|
-
if (contextEvents.length <= 1)
|
|
9765
|
-
return void 0;
|
|
9512
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9766
9513
|
return contextEvents.filter((e) => e.id !== eventId).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`).join("\n");
|
|
9767
9514
|
}
|
|
9768
9515
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9769
9516
|
let context = projectResult.context;
|
|
9770
|
-
if (sharedMemories.length === 0)
|
|
9771
|
-
return context;
|
|
9517
|
+
if (sharedMemories.length === 0) return context;
|
|
9772
9518
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9773
9519
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9774
9520
|
context += `### ${memory.title}
|
|
9775
9521
|
`;
|
|
9776
|
-
if (memory.symptoms.length > 0)
|
|
9777
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9522
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9778
9523
|
`;
|
|
9779
9524
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9780
9525
|
`;
|
|
9781
9526
|
context += `**Solution:** ${memory.solution}
|
|
9782
9527
|
`;
|
|
9783
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9784
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9528
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9785
9529
|
`;
|
|
9786
9530
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9787
9531
|
|
|
@@ -9795,13 +9539,11 @@ var Retriever = class {
|
|
|
9795
9539
|
for (const memory of memories) {
|
|
9796
9540
|
const memoryText = this.formatMemory(memory);
|
|
9797
9541
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9798
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9799
|
-
break;
|
|
9542
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9800
9543
|
parts.push(memoryText);
|
|
9801
9544
|
currentTokens += memoryTokens;
|
|
9802
9545
|
}
|
|
9803
|
-
if (parts.length === 0)
|
|
9804
|
-
return "";
|
|
9546
|
+
if (parts.length === 0) return "";
|
|
9805
9547
|
return `## Relevant Memories
|
|
9806
9548
|
|
|
9807
9549
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9811,19 +9553,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9811
9553
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9812
9554
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9813
9555
|
${event.content}`;
|
|
9814
|
-
if (sessionContext)
|
|
9815
|
-
text += `
|
|
9556
|
+
if (sessionContext) text += `
|
|
9816
9557
|
|
|
9817
9558
|
_Context:_ ${sessionContext}`;
|
|
9818
9559
|
return text;
|
|
9819
9560
|
}
|
|
9820
9561
|
matchesMetadataScope(metadata, expected) {
|
|
9821
|
-
if (!metadata)
|
|
9822
|
-
return false;
|
|
9562
|
+
if (!metadata) return false;
|
|
9823
9563
|
return Object.entries(expected).every(([path12, value]) => {
|
|
9824
9564
|
const actual = path12.split(".").reduce((acc, key) => {
|
|
9825
|
-
if (typeof acc !== "object" || acc === null)
|
|
9826
|
-
return void 0;
|
|
9565
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9827
9566
|
return acc[key];
|
|
9828
9567
|
}, metadata);
|
|
9829
9568
|
return actual === value;
|
|
@@ -9833,27 +9572,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9833
9572
|
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);
|
|
9834
9573
|
}
|
|
9835
9574
|
normalizeToken(token) {
|
|
9836
|
-
if (token === "apis")
|
|
9837
|
-
|
|
9838
|
-
if (token === "
|
|
9839
|
-
|
|
9840
|
-
if (token === "does")
|
|
9841
|
-
return token;
|
|
9842
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9843
|
-
return `${token.slice(0, -3)}y`;
|
|
9575
|
+
if (token === "apis") return "api";
|
|
9576
|
+
if (token === "ids") return "id";
|
|
9577
|
+
if (token === "does") return token;
|
|
9578
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9844
9579
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9845
9580
|
return token.slice(0, -1);
|
|
9846
9581
|
}
|
|
9847
9582
|
return token;
|
|
9848
9583
|
}
|
|
9849
9584
|
keywordOverlap(a, b) {
|
|
9850
|
-
if (a.length === 0 || b.length === 0)
|
|
9851
|
-
return 0;
|
|
9585
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9852
9586
|
const bs = new Set(b);
|
|
9853
9587
|
let hit = 0;
|
|
9854
|
-
for (const t of a)
|
|
9855
|
-
if (bs.has(t))
|
|
9856
|
-
hit += 1;
|
|
9588
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9857
9589
|
return hit / a.length;
|
|
9858
9590
|
}
|
|
9859
9591
|
estimateTokens(text) {
|
|
@@ -9874,8 +9606,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9874
9606
|
const seen = /* @__PURE__ */ new Set();
|
|
9875
9607
|
const nodes = [];
|
|
9876
9608
|
for (const candidate of candidates) {
|
|
9877
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9878
|
-
continue;
|
|
9609
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9879
9610
|
seen.add(candidate.entityId);
|
|
9880
9611
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9881
9612
|
}
|
|
@@ -9899,16 +9630,14 @@ function graphPathScore(path12, hopPenalty) {
|
|
|
9899
9630
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path12.hops - 1));
|
|
9900
9631
|
}
|
|
9901
9632
|
function clampGraphHops(maxHops) {
|
|
9902
|
-
if (!Number.isFinite(maxHops))
|
|
9903
|
-
return 2;
|
|
9633
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9904
9634
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9905
9635
|
}
|
|
9906
9636
|
function mergeGraphPaths(existing, incoming) {
|
|
9907
9637
|
const byKey = /* @__PURE__ */ new Map();
|
|
9908
9638
|
for (const path12 of [...existing, ...incoming]) {
|
|
9909
9639
|
const key = [path12.startEntityId, path12.targetType, path12.targetId, path12.hops, ...path12.relationPath].join("\0");
|
|
9910
|
-
if (!byKey.has(key))
|
|
9911
|
-
byKey.set(key, path12);
|
|
9640
|
+
if (!byKey.has(key)) byKey.set(key, path12);
|
|
9912
9641
|
}
|
|
9913
9642
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9914
9643
|
}
|
|
@@ -9916,10 +9645,8 @@ function graphPathSignature(path12) {
|
|
|
9916
9645
|
return [path12.startEntityId, path12.targetType, path12.targetId, path12.hops, ...path12.relationPath].join("|");
|
|
9917
9646
|
}
|
|
9918
9647
|
function compareStable(a, b) {
|
|
9919
|
-
if (a < b)
|
|
9920
|
-
|
|
9921
|
-
if (a > b)
|
|
9922
|
-
return 1;
|
|
9648
|
+
if (a < b) return -1;
|
|
9649
|
+
if (a > b) return 1;
|
|
9923
9650
|
return 0;
|
|
9924
9651
|
}
|
|
9925
9652
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9931,6 +9658,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9931
9658
|
constructor(deps) {
|
|
9932
9659
|
this.deps = deps;
|
|
9933
9660
|
}
|
|
9661
|
+
deps;
|
|
9934
9662
|
async getRetrievalTraceStats() {
|
|
9935
9663
|
await this.deps.initialize();
|
|
9936
9664
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -10008,6 +9736,7 @@ var RetrievalDisclosureService = class {
|
|
|
10008
9736
|
constructor(deps) {
|
|
10009
9737
|
this.deps = deps;
|
|
10010
9738
|
}
|
|
9739
|
+
deps;
|
|
10011
9740
|
async search(query, options) {
|
|
10012
9741
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
10013
9742
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -10037,8 +9766,7 @@ var RetrievalDisclosureService = class {
|
|
|
10037
9766
|
return this.expandShared(parsedId.entryId);
|
|
10038
9767
|
}
|
|
10039
9768
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
10040
|
-
if (!targetEvent)
|
|
10041
|
-
return null;
|
|
9769
|
+
if (!targetEvent) return null;
|
|
10042
9770
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
10043
9771
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
10044
9772
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -10062,8 +9790,7 @@ var RetrievalDisclosureService = class {
|
|
|
10062
9790
|
return this.sourceShared(parsedId.entryId);
|
|
10063
9791
|
}
|
|
10064
9792
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
10065
|
-
if (!rawEvent)
|
|
10066
|
-
return null;
|
|
9793
|
+
if (!rawEvent) return null;
|
|
10067
9794
|
return {
|
|
10068
9795
|
...this.sourceReferenceForEvent(rawEvent),
|
|
10069
9796
|
rawEvents: [rawEvent],
|
|
@@ -10072,8 +9799,7 @@ var RetrievalDisclosureService = class {
|
|
|
10072
9799
|
}
|
|
10073
9800
|
async expandShared(entryId) {
|
|
10074
9801
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
10075
|
-
if (!entry)
|
|
10076
|
-
return null;
|
|
9802
|
+
if (!entry) return null;
|
|
10077
9803
|
return {
|
|
10078
9804
|
target: this.sharedToEnvelope(entry),
|
|
10079
9805
|
surroundingFacts: [],
|
|
@@ -10084,8 +9810,7 @@ var RetrievalDisclosureService = class {
|
|
|
10084
9810
|
}
|
|
10085
9811
|
async sourceShared(entryId) {
|
|
10086
9812
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
10087
|
-
if (!entry)
|
|
10088
|
-
return null;
|
|
9813
|
+
if (!entry) return null;
|
|
10089
9814
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
10090
9815
|
return {
|
|
10091
9816
|
...sourceReference,
|
|
@@ -10171,38 +9896,25 @@ var RetrievalDisclosureService = class {
|
|
|
10171
9896
|
const reasons = /* @__PURE__ */ new Set();
|
|
10172
9897
|
const usedVector = this.usedVector(result);
|
|
10173
9898
|
const usedKeyword = this.usedKeyword(result);
|
|
10174
|
-
if (usedVector && (debug?.semanticScore ?? 0) > 0)
|
|
10175
|
-
|
|
10176
|
-
if ((debug?.
|
|
10177
|
-
|
|
10178
|
-
if ((debug?.
|
|
10179
|
-
|
|
10180
|
-
if (
|
|
10181
|
-
|
|
10182
|
-
if (
|
|
10183
|
-
reasons.add("entity_overlap");
|
|
10184
|
-
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary"))
|
|
10185
|
-
reasons.add("summary_fallback");
|
|
10186
|
-
if (memory.sessionContext)
|
|
10187
|
-
reasons.add("continuity_link");
|
|
10188
|
-
if (memory.event.eventType === "tool_observation")
|
|
10189
|
-
reasons.add("tool_followup");
|
|
10190
|
-
if (reasons.size === 0)
|
|
10191
|
-
reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
9899
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9900
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9901
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9902
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9903
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9904
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9905
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9906
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9907
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10192
9908
|
return Array.from(reasons);
|
|
10193
9909
|
}
|
|
10194
9910
|
reasonsForContextEvent(event) {
|
|
10195
|
-
if (event.eventType === "tool_observation")
|
|
10196
|
-
|
|
10197
|
-
if (event.eventType === "session_summary")
|
|
10198
|
-
return ["summary_fallback"];
|
|
9911
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9912
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10199
9913
|
return ["continuity_link"];
|
|
10200
9914
|
}
|
|
10201
9915
|
resultTypeForEvent(event) {
|
|
10202
|
-
if (event.eventType === "session_summary")
|
|
10203
|
-
|
|
10204
|
-
if (event.eventType === "tool_observation")
|
|
10205
|
-
return "tool_evidence";
|
|
9916
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9917
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10206
9918
|
return "source";
|
|
10207
9919
|
}
|
|
10208
9920
|
sourceReferenceForEvent(event) {
|
|
@@ -10226,21 +9938,15 @@ var RetrievalDisclosureService = class {
|
|
|
10226
9938
|
}
|
|
10227
9939
|
sourceTypeForEvent(event) {
|
|
10228
9940
|
const metadata = event.metadata || {};
|
|
10229
|
-
if (event.eventType === "tool_observation")
|
|
10230
|
-
|
|
10231
|
-
if (typeof metadata.
|
|
10232
|
-
return "transcript";
|
|
10233
|
-
if (typeof metadata.importedFrom === "string")
|
|
10234
|
-
return "imported_history";
|
|
9941
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9942
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9943
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10235
9944
|
return "raw_event";
|
|
10236
9945
|
}
|
|
10237
9946
|
titleForEvent(event) {
|
|
10238
|
-
if (event.eventType === "session_summary")
|
|
10239
|
-
|
|
10240
|
-
if (event.eventType === "
|
|
10241
|
-
return "Tool evidence";
|
|
10242
|
-
if (event.eventType === "agent_response")
|
|
10243
|
-
return "Agent response";
|
|
9947
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9948
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9949
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10244
9950
|
return "User prompt";
|
|
10245
9951
|
}
|
|
10246
9952
|
usedVector(result) {
|
|
@@ -10266,8 +9972,7 @@ var RetrievalDisclosureService = class {
|
|
|
10266
9972
|
}
|
|
10267
9973
|
preview(content, maxLength) {
|
|
10268
9974
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10269
|
-
if (normalized.length <= maxLength)
|
|
10270
|
-
return normalized;
|
|
9975
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10271
9976
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10272
9977
|
}
|
|
10273
9978
|
};
|
|
@@ -10296,6 +10001,7 @@ var RetrievalOrchestrator = class {
|
|
|
10296
10001
|
this.deps = deps;
|
|
10297
10002
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10298
10003
|
}
|
|
10004
|
+
deps;
|
|
10299
10005
|
/**
|
|
10300
10006
|
* Retrieve relevant memories for a query.
|
|
10301
10007
|
*/
|
|
@@ -10377,8 +10083,7 @@ var RetrievalOrchestrator = class {
|
|
|
10377
10083
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10378
10084
|
*/
|
|
10379
10085
|
async incrementMemoryAccess(eventIds) {
|
|
10380
|
-
if (eventIds.length === 0)
|
|
10381
|
-
return;
|
|
10086
|
+
if (eventIds.length === 0) return;
|
|
10382
10087
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10383
10088
|
}
|
|
10384
10089
|
/**
|
|
@@ -10391,10 +10096,8 @@ var RetrievalOrchestrator = class {
|
|
|
10391
10096
|
resolveGraphHopOptions(callerOptions) {
|
|
10392
10097
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10393
10098
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10394
|
-
if (!callerOptions)
|
|
10395
|
-
|
|
10396
|
-
if (!graphExpansion)
|
|
10397
|
-
return callerOptions;
|
|
10099
|
+
if (!callerOptions) return durableOptions;
|
|
10100
|
+
if (!graphExpansion) return callerOptions;
|
|
10398
10101
|
if (graphExpansion.enabled !== true) {
|
|
10399
10102
|
return {
|
|
10400
10103
|
...callerOptions,
|
|
@@ -10454,12 +10157,10 @@ var RetrievalOrchestrator = class {
|
|
|
10454
10157
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10455
10158
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10456
10159
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10457
|
-
if (!allFinite)
|
|
10458
|
-
return void 0;
|
|
10160
|
+
if (!allFinite) return void 0;
|
|
10459
10161
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10460
10162
|
const total = semantic + lexical + recency;
|
|
10461
|
-
if (!nonNegative || total <= 0)
|
|
10462
|
-
return void 0;
|
|
10163
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10463
10164
|
return {
|
|
10464
10165
|
semantic: semantic / total,
|
|
10465
10166
|
lexical: lexical / total,
|
|
@@ -10468,17 +10169,14 @@ var RetrievalOrchestrator = class {
|
|
|
10468
10169
|
}
|
|
10469
10170
|
async getRerankWeights(adaptive) {
|
|
10470
10171
|
const configured = this.getConfiguredRerankWeights();
|
|
10471
|
-
if (configured)
|
|
10472
|
-
|
|
10473
|
-
if (adaptive)
|
|
10474
|
-
return this.getAdaptiveRerankWeights();
|
|
10172
|
+
if (configured) return configured;
|
|
10173
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10475
10174
|
return void 0;
|
|
10476
10175
|
}
|
|
10477
10176
|
async getAdaptiveRerankWeights() {
|
|
10478
10177
|
try {
|
|
10479
10178
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10480
|
-
if (stats.totalEvaluated < 20)
|
|
10481
|
-
return void 0;
|
|
10179
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10482
10180
|
let semantic = 0.7;
|
|
10483
10181
|
let lexical = 0.2;
|
|
10484
10182
|
let recency = 0.1;
|
|
@@ -10500,11 +10198,9 @@ var RetrievalOrchestrator = class {
|
|
|
10500
10198
|
}
|
|
10501
10199
|
}
|
|
10502
10200
|
async rewriteQueryIntent(query) {
|
|
10503
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10504
|
-
return null;
|
|
10201
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10505
10202
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10506
|
-
if (!apiUrl)
|
|
10507
|
-
return null;
|
|
10203
|
+
if (!apiUrl) return null;
|
|
10508
10204
|
const controller = new AbortController();
|
|
10509
10205
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10510
10206
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10530,11 +10226,9 @@ var RetrievalOrchestrator = class {
|
|
|
10530
10226
|
signal: controller.signal
|
|
10531
10227
|
});
|
|
10532
10228
|
const text = (await res.text()).trim();
|
|
10533
|
-
if (!text)
|
|
10534
|
-
return null;
|
|
10229
|
+
if (!text) return null;
|
|
10535
10230
|
const oneLine = text.replace(/^data:\s*/gm, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ").slice(0, 240);
|
|
10536
|
-
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase())
|
|
10537
|
-
return null;
|
|
10231
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10538
10232
|
return oneLine;
|
|
10539
10233
|
} catch {
|
|
10540
10234
|
return null;
|
|
@@ -10676,8 +10370,7 @@ function createMemoryEngineServices(options) {
|
|
|
10676
10370
|
};
|
|
10677
10371
|
}
|
|
10678
10372
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10679
|
-
if (options.readOnly)
|
|
10680
|
-
return false;
|
|
10373
|
+
if (options.readOnly) return false;
|
|
10681
10374
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10682
10375
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10683
10376
|
}
|
|
@@ -10711,6 +10404,9 @@ var GraduationWorker = class {
|
|
|
10711
10404
|
this.graduation = graduation;
|
|
10712
10405
|
this.config = config;
|
|
10713
10406
|
}
|
|
10407
|
+
eventStore;
|
|
10408
|
+
graduation;
|
|
10409
|
+
config;
|
|
10714
10410
|
running = false;
|
|
10715
10411
|
timeout = null;
|
|
10716
10412
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10718,8 +10414,7 @@ var GraduationWorker = class {
|
|
|
10718
10414
|
* Start the graduation worker
|
|
10719
10415
|
*/
|
|
10720
10416
|
start() {
|
|
10721
|
-
if (this.running)
|
|
10722
|
-
return;
|
|
10417
|
+
if (this.running) return;
|
|
10723
10418
|
this.running = true;
|
|
10724
10419
|
this.scheduleNext();
|
|
10725
10420
|
}
|
|
@@ -10749,8 +10444,7 @@ var GraduationWorker = class {
|
|
|
10749
10444
|
* Schedule the next graduation check
|
|
10750
10445
|
*/
|
|
10751
10446
|
scheduleNext() {
|
|
10752
|
-
if (!this.running)
|
|
10753
|
-
return;
|
|
10447
|
+
if (!this.running) return;
|
|
10754
10448
|
this.timeout = setTimeout(
|
|
10755
10449
|
() => this.run(),
|
|
10756
10450
|
this.config.evaluationIntervalMs
|
|
@@ -10760,8 +10454,7 @@ var GraduationWorker = class {
|
|
|
10760
10454
|
* Run graduation evaluation
|
|
10761
10455
|
*/
|
|
10762
10456
|
async run() {
|
|
10763
|
-
if (!this.running)
|
|
10764
|
-
return;
|
|
10457
|
+
if (!this.running) return;
|
|
10765
10458
|
try {
|
|
10766
10459
|
await this.runGraduation();
|
|
10767
10460
|
} catch (error) {
|
|
@@ -10825,10 +10518,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10825
10518
|
maxRetries: 3
|
|
10826
10519
|
};
|
|
10827
10520
|
function parseJsonArray(value) {
|
|
10828
|
-
if (Array.isArray(value))
|
|
10829
|
-
|
|
10830
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10831
|
-
return [];
|
|
10521
|
+
if (Array.isArray(value)) return value;
|
|
10522
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10832
10523
|
try {
|
|
10833
10524
|
const parsed = JSON.parse(value);
|
|
10834
10525
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10858,8 +10549,7 @@ var VectorWorker = class {
|
|
|
10858
10549
|
* Start the worker polling loop
|
|
10859
10550
|
*/
|
|
10860
10551
|
start() {
|
|
10861
|
-
if (this.running)
|
|
10862
|
-
return;
|
|
10552
|
+
if (this.running) return;
|
|
10863
10553
|
this.running = true;
|
|
10864
10554
|
this.stopping = false;
|
|
10865
10555
|
this.poll();
|
|
@@ -10935,8 +10625,7 @@ var VectorWorker = class {
|
|
|
10935
10625
|
* Poll for new items
|
|
10936
10626
|
*/
|
|
10937
10627
|
async poll() {
|
|
10938
|
-
if (!this.running || this.stopping)
|
|
10939
|
-
return;
|
|
10628
|
+
if (!this.running || this.stopping) return;
|
|
10940
10629
|
try {
|
|
10941
10630
|
await this.processBatch();
|
|
10942
10631
|
} catch (error) {
|
|
@@ -10981,6 +10670,7 @@ var DefaultContentProvider = class {
|
|
|
10981
10670
|
constructor(db) {
|
|
10982
10671
|
this.db = db;
|
|
10983
10672
|
}
|
|
10673
|
+
db;
|
|
10984
10674
|
async getContent(itemKind, itemId) {
|
|
10985
10675
|
switch (itemKind) {
|
|
10986
10676
|
case "entry":
|
|
@@ -11001,8 +10691,7 @@ var DefaultContentProvider = class {
|
|
|
11001
10691
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
11002
10692
|
[entryId]
|
|
11003
10693
|
);
|
|
11004
|
-
if (rows.length === 0)
|
|
11005
|
-
return null;
|
|
10694
|
+
if (rows.length === 0) return null;
|
|
11006
10695
|
const row = rows[0];
|
|
11007
10696
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
11008
10697
|
return {
|
|
@@ -11021,8 +10710,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11021
10710
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
11022
10711
|
[taskId]
|
|
11023
10712
|
);
|
|
11024
|
-
if (rows.length === 0)
|
|
11025
|
-
return null;
|
|
10713
|
+
if (rows.length === 0) return null;
|
|
11026
10714
|
const row = rows[0];
|
|
11027
10715
|
return {
|
|
11028
10716
|
content: row.search_text || row.title,
|
|
@@ -11038,8 +10726,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11038
10726
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
11039
10727
|
[eventId]
|
|
11040
10728
|
);
|
|
11041
|
-
if (rows.length === 0)
|
|
11042
|
-
return null;
|
|
10729
|
+
if (rows.length === 0) return null;
|
|
11043
10730
|
const row = rows[0];
|
|
11044
10731
|
return {
|
|
11045
10732
|
content: row.content,
|
|
@@ -11067,8 +10754,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11067
10754
|
}
|
|
11068
10755
|
throw error;
|
|
11069
10756
|
}
|
|
11070
|
-
if (rows.length === 0)
|
|
11071
|
-
return null;
|
|
10757
|
+
if (rows.length === 0) return null;
|
|
11072
10758
|
const row = rows[0];
|
|
11073
10759
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
11074
10760
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -11110,8 +10796,7 @@ var VectorWorkerV2 = class {
|
|
|
11110
10796
|
* Start the worker polling loop
|
|
11111
10797
|
*/
|
|
11112
10798
|
start() {
|
|
11113
|
-
if (this.running)
|
|
11114
|
-
return;
|
|
10799
|
+
if (this.running) return;
|
|
11115
10800
|
this.running = true;
|
|
11116
10801
|
this.stopping = false;
|
|
11117
10802
|
this.poll();
|
|
@@ -11181,8 +10866,7 @@ var VectorWorkerV2 = class {
|
|
|
11181
10866
|
* Poll for new jobs
|
|
11182
10867
|
*/
|
|
11183
10868
|
async poll() {
|
|
11184
|
-
if (!this.running || this.stopping)
|
|
11185
|
-
return;
|
|
10869
|
+
if (!this.running || this.stopping) return;
|
|
11186
10870
|
try {
|
|
11187
10871
|
await this.processBatch();
|
|
11188
10872
|
} catch (error) {
|
|
@@ -11249,8 +10933,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11249
10933
|
let graduationWorker = null;
|
|
11250
10934
|
return {
|
|
11251
10935
|
async initialize() {
|
|
11252
|
-
if (initialized)
|
|
11253
|
-
return;
|
|
10936
|
+
if (initialized) return;
|
|
11254
10937
|
await deps.sqliteStore.initialize();
|
|
11255
10938
|
if (deps.lightweightMode) {
|
|
11256
10939
|
initialized = true;
|
|
@@ -11344,8 +11027,7 @@ var SharedEventStore = class {
|
|
|
11344
11027
|
this.db = createDatabase(dbPath);
|
|
11345
11028
|
}
|
|
11346
11029
|
async initialize() {
|
|
11347
|
-
if (this.initialized)
|
|
11348
|
-
return;
|
|
11030
|
+
if (this.initialized) return;
|
|
11349
11031
|
await dbRun(this.db, `
|
|
11350
11032
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11351
11033
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11435,6 +11117,10 @@ var SharedPromoter = class {
|
|
|
11435
11117
|
this.embedder = embedder;
|
|
11436
11118
|
this.config = config;
|
|
11437
11119
|
}
|
|
11120
|
+
sharedStore;
|
|
11121
|
+
sharedVectorStore;
|
|
11122
|
+
embedder;
|
|
11123
|
+
config;
|
|
11438
11124
|
/**
|
|
11439
11125
|
* Check if an entry is eligible for promotion
|
|
11440
11126
|
*/
|
|
@@ -11616,6 +11302,7 @@ var SharedStore = class {
|
|
|
11616
11302
|
constructor(sharedEventStore) {
|
|
11617
11303
|
this.sharedEventStore = sharedEventStore;
|
|
11618
11304
|
}
|
|
11305
|
+
sharedEventStore;
|
|
11619
11306
|
get db() {
|
|
11620
11307
|
return this.sharedEventStore.getDatabase();
|
|
11621
11308
|
}
|
|
@@ -11720,8 +11407,7 @@ var SharedStore = class {
|
|
|
11720
11407
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11721
11408
|
[entryId]
|
|
11722
11409
|
);
|
|
11723
|
-
if (rows.length === 0)
|
|
11724
|
-
return null;
|
|
11410
|
+
if (rows.length === 0) return null;
|
|
11725
11411
|
return this.rowToEntry(rows[0]);
|
|
11726
11412
|
}
|
|
11727
11413
|
/**
|
|
@@ -11734,8 +11420,7 @@ var SharedStore = class {
|
|
|
11734
11420
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11735
11421
|
[projectHash, sourceEntryId]
|
|
11736
11422
|
);
|
|
11737
|
-
if (rows.length === 0)
|
|
11738
|
-
return null;
|
|
11423
|
+
if (rows.length === 0) return null;
|
|
11739
11424
|
return this.rowToEntry(rows[0]);
|
|
11740
11425
|
}
|
|
11741
11426
|
/**
|
|
@@ -11845,6 +11530,7 @@ var SharedVectorStore = class {
|
|
|
11845
11530
|
constructor(dbPath) {
|
|
11846
11531
|
this.dbPath = dbPath;
|
|
11847
11532
|
}
|
|
11533
|
+
dbPath;
|
|
11848
11534
|
db = null;
|
|
11849
11535
|
table = null;
|
|
11850
11536
|
tableName = "shared_knowledge";
|
|
@@ -11852,8 +11538,7 @@ var SharedVectorStore = class {
|
|
|
11852
11538
|
* Initialize LanceDB connection
|
|
11853
11539
|
*/
|
|
11854
11540
|
async initialize() {
|
|
11855
|
-
if (this.db)
|
|
11856
|
-
return;
|
|
11541
|
+
if (this.db) return;
|
|
11857
11542
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11858
11543
|
try {
|
|
11859
11544
|
const tables = await this.db.tableNames();
|
|
@@ -11895,8 +11580,7 @@ var SharedVectorStore = class {
|
|
|
11895
11580
|
* Add multiple records in batch
|
|
11896
11581
|
*/
|
|
11897
11582
|
async upsertBatch(records) {
|
|
11898
|
-
if (records.length === 0)
|
|
11899
|
-
return;
|
|
11583
|
+
if (records.length === 0) return;
|
|
11900
11584
|
await this.initialize();
|
|
11901
11585
|
if (!this.db) {
|
|
11902
11586
|
throw new Error("Database not initialized");
|
|
@@ -11957,24 +11641,21 @@ var SharedVectorStore = class {
|
|
|
11957
11641
|
* Delete vector by entry ID
|
|
11958
11642
|
*/
|
|
11959
11643
|
async delete(entryId) {
|
|
11960
|
-
if (!this.table)
|
|
11961
|
-
return;
|
|
11644
|
+
if (!this.table) return;
|
|
11962
11645
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11963
11646
|
}
|
|
11964
11647
|
/**
|
|
11965
11648
|
* Get total count
|
|
11966
11649
|
*/
|
|
11967
11650
|
async count() {
|
|
11968
|
-
if (!this.table)
|
|
11969
|
-
return 0;
|
|
11651
|
+
if (!this.table) return 0;
|
|
11970
11652
|
return this.table.countRows();
|
|
11971
11653
|
}
|
|
11972
11654
|
/**
|
|
11973
11655
|
* Check if vector exists for entry
|
|
11974
11656
|
*/
|
|
11975
11657
|
async exists(entryId) {
|
|
11976
|
-
if (!this.table)
|
|
11977
|
-
return false;
|
|
11658
|
+
if (!this.table) return false;
|
|
11978
11659
|
try {
|
|
11979
11660
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11980
11661
|
return results.length > 0;
|
|
@@ -11992,6 +11673,7 @@ var SharedMemoryServices = class {
|
|
|
11992
11673
|
constructor(options) {
|
|
11993
11674
|
this.options = options;
|
|
11994
11675
|
}
|
|
11676
|
+
options;
|
|
11995
11677
|
sharedEventStore = null;
|
|
11996
11678
|
sharedStore = null;
|
|
11997
11679
|
sharedVectorStore = null;
|
|
@@ -12016,8 +11698,7 @@ var SharedMemoryServices = class {
|
|
|
12016
11698
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
12017
11699
|
}
|
|
12018
11700
|
async initialize() {
|
|
12019
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
12020
|
-
return;
|
|
11701
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
12021
11702
|
const sharedPath = this.getSharedStoragePath();
|
|
12022
11703
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
12023
11704
|
const store = await this.openStore(sharedPath);
|
|
@@ -12034,14 +11715,11 @@ var SharedMemoryServices = class {
|
|
|
12034
11715
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
12035
11716
|
}
|
|
12036
11717
|
async ensureStoreForRead() {
|
|
12037
|
-
if (this.options.config?.enabled === false)
|
|
12038
|
-
|
|
12039
|
-
if (this.sharedStore)
|
|
12040
|
-
return this.sharedStore;
|
|
11718
|
+
if (this.options.config?.enabled === false) return null;
|
|
11719
|
+
if (this.sharedStore) return this.sharedStore;
|
|
12041
11720
|
const sharedPath = this.getSharedStoragePath();
|
|
12042
11721
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
12043
|
-
if (!directoryReady)
|
|
12044
|
-
return null;
|
|
11722
|
+
if (!directoryReady) return null;
|
|
12045
11723
|
return this.openStore(sharedPath);
|
|
12046
11724
|
}
|
|
12047
11725
|
async getEntryForDisclosure(entryId) {
|
|
@@ -12058,13 +11736,11 @@ var SharedMemoryServices = class {
|
|
|
12058
11736
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
12059
11737
|
}
|
|
12060
11738
|
async getStats() {
|
|
12061
|
-
if (!this.sharedStore)
|
|
12062
|
-
return null;
|
|
11739
|
+
if (!this.sharedStore) return null;
|
|
12063
11740
|
return this.sharedStore.getStats();
|
|
12064
11741
|
}
|
|
12065
11742
|
async search(query, options) {
|
|
12066
|
-
if (!this.sharedStore)
|
|
12067
|
-
return [];
|
|
11743
|
+
if (!this.sharedStore) return [];
|
|
12068
11744
|
return this.sharedStore.search(query, options);
|
|
12069
11745
|
}
|
|
12070
11746
|
async close() {
|
|
@@ -12081,8 +11757,7 @@ var SharedMemoryServices = class {
|
|
|
12081
11757
|
this.openStorePromise = null;
|
|
12082
11758
|
}
|
|
12083
11759
|
async openStore(sharedPath) {
|
|
12084
|
-
if (this.sharedStore)
|
|
12085
|
-
return this.sharedStore;
|
|
11760
|
+
if (this.sharedStore) return this.sharedStore;
|
|
12086
11761
|
if (!this.openStorePromise) {
|
|
12087
11762
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
12088
11763
|
}
|
|
@@ -12106,10 +11781,8 @@ var SharedMemoryServices = class {
|
|
|
12106
11781
|
return this.sharedStore;
|
|
12107
11782
|
}
|
|
12108
11783
|
ensureDirectory(sharedPath, options) {
|
|
12109
|
-
if (this.factories.existsSync(sharedPath))
|
|
12110
|
-
|
|
12111
|
-
if (!options.allowCreate)
|
|
12112
|
-
return false;
|
|
11784
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11785
|
+
if (!options.allowCreate) return false;
|
|
12113
11786
|
this.factories.mkdirSync(sharedPath);
|
|
12114
11787
|
return true;
|
|
12115
11788
|
}
|
|
@@ -12934,8 +12607,7 @@ import * as fs10 from "fs";
|
|
|
12934
12607
|
import * as readline from "readline";
|
|
12935
12608
|
var DEFAULT_MAX_BYTES = 200 * 1024;
|
|
12936
12609
|
async function readTranscriptTailEntries(transcriptPath, options = {}) {
|
|
12937
|
-
if (!fs10.existsSync(transcriptPath))
|
|
12938
|
-
return [];
|
|
12610
|
+
if (!fs10.existsSync(transcriptPath)) return [];
|
|
12939
12611
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
12940
12612
|
const stats = fs10.statSync(transcriptPath);
|
|
12941
12613
|
const readStart = Math.max(0, stats.size - maxBytes);
|
|
@@ -12964,11 +12636,9 @@ function isTextContentBlock(value) {
|
|
|
12964
12636
|
function extractAssistantTextMessages(entries) {
|
|
12965
12637
|
const messages = [];
|
|
12966
12638
|
for (const entry of entries) {
|
|
12967
|
-
if (entry.type !== "assistant")
|
|
12968
|
-
continue;
|
|
12639
|
+
if (entry.type !== "assistant") continue;
|
|
12969
12640
|
const content = entry.message?.content;
|
|
12970
|
-
if (!Array.isArray(content))
|
|
12971
|
-
continue;
|
|
12641
|
+
if (!Array.isArray(content)) continue;
|
|
12972
12642
|
const textParts = content.filter(isTextContentBlock).map((block) => block.text).filter(Boolean);
|
|
12973
12643
|
if (textParts.length > 0) {
|
|
12974
12644
|
messages.push(textParts.join("\n"));
|
|
@@ -13011,8 +12681,7 @@ async function main() {
|
|
|
13011
12681
|
if (content.length > 5e3) {
|
|
13012
12682
|
content = content.slice(0, 5e3) + "...[truncated]";
|
|
13013
12683
|
}
|
|
13014
|
-
if (!isLast && content.trim().length < MIN_AGENT_RESPONSE_LEN)
|
|
13015
|
-
continue;
|
|
12684
|
+
if (!isLast && content.trim().length < MIN_AGENT_RESPONSE_LEN) continue;
|
|
13016
12685
|
await memoryService.storeAgentResponse(
|
|
13017
12686
|
input.session_id,
|
|
13018
12687
|
content,
|