claude-memory-layer 1.0.44 → 1.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli/index.js +801 -1421
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +1319 -1501
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +465 -756
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +454 -734
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +450 -726
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +451 -728
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +458 -742
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +494 -814
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +1397 -1615
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1587 -1655
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +484 -792
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +492 -808
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +450 -726
- package/dist/services/memory-service.js.map +2 -2
- package/package.json +15 -3
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;
|
|
@@ -8787,6 +8602,18 @@ var COMMAND_ARTIFACT_PATTERNS = [
|
|
|
8787
8602
|
/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
|
|
8788
8603
|
/<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
|
|
8789
8604
|
];
|
|
8605
|
+
var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
8606
|
+
/<environment_context\b[\s\S]*<\/environment_context>/i,
|
|
8607
|
+
/<turn_aborted>/i,
|
|
8608
|
+
/^#\s*AGENTS\.md\s+instructions\b[\s\S]*<INSTRUCTIONS>/i,
|
|
8609
|
+
/^\s*(?:understood[,\s.]*)?(?:stopping|stopped|pausing|paused)\s+here\b[\s\S]{0,180}\blet\s+me\s+know\s+when\s+you(?:'d|\s+would)?\s+like\s+to\s+continue\b/i,
|
|
8610
|
+
/^\s*\[?CONTEXT\s+COMPACTION\s*[—-]\s*REFERENCE\s+ONLY\]?\b[\s\S]{0,600}\b(?:earlier\s+turns\s+were\s+compacted|handoff\s+from\s+a\s+previous\s+context\s+window|active\s+task)\b/i,
|
|
8611
|
+
/^\s*Summary\s+generation\s+was\s+unavailable\.\s*\d+\s+message\(s\)\s+were\s+removed\s+to\s+free\s+context\s+space\b/i,
|
|
8612
|
+
/^\s*---\s*END\s+OF\s+CONTEXT\s+SUMMARY\b/i,
|
|
8613
|
+
/^\s*\[Your\s+active\s+task\s+list\s+was\s+preserved\s+across\s+context\s+compression\]/i,
|
|
8614
|
+
/^➜\s+\S+\s+git:\([^)]*\)\s+/i,
|
|
8615
|
+
/^\$\s+\S+/i
|
|
8616
|
+
];
|
|
8790
8617
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
8791
8618
|
/^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
|
|
8792
8619
|
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
@@ -8798,7 +8625,7 @@ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
|
8798
8625
|
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
8799
8626
|
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
8800
8627
|
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
8801
|
-
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|
|
|
8628
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|status)\b/i,
|
|
8802
8629
|
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
8803
8630
|
];
|
|
8804
8631
|
var STALE_CONTENT_PATTERNS = [
|
|
@@ -8938,55 +8765,67 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8938
8765
|
]);
|
|
8939
8766
|
function isCommandArtifactQuery(query) {
|
|
8940
8767
|
const trimmed = query.trim();
|
|
8941
|
-
if (!trimmed)
|
|
8942
|
-
return false;
|
|
8768
|
+
if (!trimmed) return false;
|
|
8943
8769
|
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;
|
|
8770
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8771
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8948
8772
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8949
8773
|
}
|
|
8774
|
+
function isCommandArtifactContent(content) {
|
|
8775
|
+
const trimmed = content.trim();
|
|
8776
|
+
if (!trimmed) return false;
|
|
8777
|
+
const normalized = trimmed.toLowerCase();
|
|
8778
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8779
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8780
|
+
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8781
|
+
}
|
|
8782
|
+
function isLowSignalContextContent(content) {
|
|
8783
|
+
const trimmed = content.trim();
|
|
8784
|
+
if (!trimmed) return true;
|
|
8785
|
+
if (isCommandArtifactContent(trimmed)) return true;
|
|
8786
|
+
if (LOW_SIGNAL_CONTEXT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
8787
|
+
return false;
|
|
8788
|
+
}
|
|
8950
8789
|
function isGenericContinuationQuery(query) {
|
|
8951
8790
|
const trimmed = query.trim();
|
|
8952
|
-
if (!trimmed)
|
|
8953
|
-
|
|
8954
|
-
if (
|
|
8955
|
-
return false;
|
|
8956
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8957
|
-
return false;
|
|
8791
|
+
if (!trimmed) return false;
|
|
8792
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8793
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8958
8794
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8959
|
-
if (tokens.length > 10)
|
|
8960
|
-
return false;
|
|
8795
|
+
if (tokens.length > 10) return false;
|
|
8961
8796
|
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
8797
|
}
|
|
8963
8798
|
function isShortRepairFollowUpQuery(query) {
|
|
8964
8799
|
const trimmed = query.trim();
|
|
8965
|
-
if (!trimmed)
|
|
8966
|
-
|
|
8967
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8968
|
-
return false;
|
|
8800
|
+
if (!trimmed) return false;
|
|
8801
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8969
8802
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8970
|
-
if (tokens.length > 8)
|
|
8971
|
-
return false;
|
|
8803
|
+
if (tokens.length > 8) return false;
|
|
8972
8804
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8973
8805
|
}
|
|
8806
|
+
function isLowConfidenceContextFallbackQuery(query) {
|
|
8807
|
+
const trimmed = query.trim();
|
|
8808
|
+
if (!trimmed) return false;
|
|
8809
|
+
if (isGenericContinuationQuery(trimmed) || isShortRepairFollowUpQuery(trimmed)) return true;
|
|
8810
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8811
|
+
if ((terms.has("compacted") || terms.has("compaction")) && terms.has("handoff")) return false;
|
|
8812
|
+
const hasContinuationRecall = /^(?:continue|resume)\b/i.test(trimmed) && (terms.has("work") || terms.has("step") || terms.has("task") || terms.has("last") || terms.has("completed"));
|
|
8813
|
+
const hasValidationGateRecall = terms.has("validation") && (terms.has("gate") || terms.has("check")) && (terms.has("run") || terms.has("before") || terms.has("commit") || terms.has("committing") || terms.has("change"));
|
|
8814
|
+
return hasContinuationRecall || hasValidationGateRecall;
|
|
8815
|
+
}
|
|
8974
8816
|
function isCurrentStateQuery(query) {
|
|
8975
8817
|
const trimmed = query.trim();
|
|
8976
|
-
if (!trimmed)
|
|
8977
|
-
return false;
|
|
8818
|
+
if (!trimmed) return false;
|
|
8978
8819
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8979
8820
|
}
|
|
8980
8821
|
function isStaleOrSupersededContent(content) {
|
|
8981
8822
|
const trimmed = content.trim();
|
|
8982
|
-
if (!trimmed)
|
|
8983
|
-
return false;
|
|
8823
|
+
if (!trimmed) return false;
|
|
8984
8824
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8985
8825
|
}
|
|
8986
8826
|
function buildRetrievalQualityQuery(query) {
|
|
8987
8827
|
const trimmed = query.trim();
|
|
8988
|
-
if (!trimmed)
|
|
8989
|
-
return query;
|
|
8828
|
+
if (!trimmed) return query;
|
|
8990
8829
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8991
8830
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8992
8831
|
}
|
|
@@ -9000,12 +8839,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
9000
8839
|
}
|
|
9001
8840
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
9002
8841
|
const trimmed = query.trim();
|
|
9003
|
-
if (!trimmed)
|
|
9004
|
-
return false;
|
|
8842
|
+
if (!trimmed) return false;
|
|
9005
8843
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
9006
8844
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
9007
|
-
if (!hasDecisionSignal)
|
|
9008
|
-
return false;
|
|
8845
|
+
if (!hasDecisionSignal) return false;
|
|
9009
8846
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
9010
8847
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
9011
8848
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -9018,16 +8855,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
9018
8855
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
9019
8856
|
const terms = matches.filter((term) => {
|
|
9020
8857
|
const lower = term.toLowerCase();
|
|
9021
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
9022
|
-
return false;
|
|
8858
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
9023
8859
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
9024
8860
|
});
|
|
9025
8861
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
9026
8862
|
}
|
|
9027
8863
|
function hasTechnicalTermOverlap(query, content) {
|
|
9028
8864
|
const terms = extractTechnicalQueryTerms(query);
|
|
9029
|
-
if (terms.length === 0)
|
|
9030
|
-
return true;
|
|
8865
|
+
if (terms.length === 0) return true;
|
|
9031
8866
|
const normalizedContent = content.toLowerCase();
|
|
9032
8867
|
return terms.some((term) => normalizedContent.includes(term));
|
|
9033
8868
|
}
|
|
@@ -9043,15 +8878,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
9043
8878
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
9044
8879
|
}
|
|
9045
8880
|
}
|
|
9046
|
-
if (queryTerms.length < 3)
|
|
9047
|
-
return true;
|
|
8881
|
+
if (queryTerms.length < 3) return true;
|
|
9048
8882
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
9049
8883
|
let hits = 0;
|
|
9050
8884
|
for (const term of queryTerms) {
|
|
9051
|
-
if (contentTerms.has(term))
|
|
9052
|
-
|
|
9053
|
-
if (hits >= requiredHits)
|
|
9054
|
-
return true;
|
|
8885
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8886
|
+
if (hits >= requiredHits) return true;
|
|
9055
8887
|
}
|
|
9056
8888
|
return false;
|
|
9057
8889
|
}
|
|
@@ -9061,17 +8893,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
9061
8893
|
function hasAnyTerm(terms, expectedTerms) {
|
|
9062
8894
|
let found = false;
|
|
9063
8895
|
expectedTerms.forEach((term) => {
|
|
9064
|
-
if (terms.has(term))
|
|
9065
|
-
found = true;
|
|
8896
|
+
if (terms.has(term)) found = true;
|
|
9066
8897
|
});
|
|
9067
8898
|
return found;
|
|
9068
8899
|
}
|
|
9069
8900
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
9070
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
9071
|
-
return false;
|
|
8901
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
9072
8902
|
const trimmed = query.trim();
|
|
9073
|
-
if (!trimmed)
|
|
9074
|
-
return false;
|
|
8903
|
+
if (!trimmed) return false;
|
|
9075
8904
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
9076
8905
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
9077
8906
|
}
|
|
@@ -9079,12 +8908,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
9079
8908
|
const seen = /* @__PURE__ */ new Set();
|
|
9080
8909
|
const terms = [];
|
|
9081
8910
|
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;
|
|
8911
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8912
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8913
|
+
if (seen.has(token)) continue;
|
|
9088
8914
|
seen.add(token);
|
|
9089
8915
|
terms.push(token);
|
|
9090
8916
|
}
|
|
@@ -9099,14 +8925,10 @@ function tokenizeQualityText(text) {
|
|
|
9099
8925
|
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
8926
|
}
|
|
9101
8927
|
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`;
|
|
8928
|
+
if (token === "apis") return "api";
|
|
8929
|
+
if (token === "ids") return "id";
|
|
8930
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8931
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9110
8932
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
9111
8933
|
return token.slice(0, -1);
|
|
9112
8934
|
}
|
|
@@ -9258,7 +9080,14 @@ var Retriever = class {
|
|
|
9258
9080
|
};
|
|
9259
9081
|
fallbackTrace.push("fallback:summary");
|
|
9260
9082
|
}
|
|
9261
|
-
const
|
|
9083
|
+
const selectedResults = current.results.slice(0, opts.topK).filter((result) => {
|
|
9084
|
+
if (current.matchResult.confidence !== "none") return true;
|
|
9085
|
+
if (isLowConfidenceContextFallbackQuery(query)) {
|
|
9086
|
+
return (result.semanticScore ?? result.score) >= 0.5 || result.score >= 0.5;
|
|
9087
|
+
}
|
|
9088
|
+
return (result.semanticScore ?? result.score) >= 0.62 || result.score >= 0.62;
|
|
9089
|
+
});
|
|
9090
|
+
const memories = await this.enrichResults(selectedResults, opts, query);
|
|
9262
9091
|
const context = this.buildContext(memories, opts.maxTokens);
|
|
9263
9092
|
return {
|
|
9264
9093
|
memories,
|
|
@@ -9266,7 +9095,7 @@ var Retriever = class {
|
|
|
9266
9095
|
totalTokens: this.estimateTokens(context),
|
|
9267
9096
|
context,
|
|
9268
9097
|
fallbackTrace,
|
|
9269
|
-
selectedDebug:
|
|
9098
|
+
selectedDebug: selectedResults.map((r) => this.debugDetailForResult(r)),
|
|
9270
9099
|
candidateDebug: (current.candidateResults || []).slice(0, Math.max(opts.topK * 3, 20)).map((r) => this.debugDetailForResult(r)),
|
|
9271
9100
|
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
9272
9101
|
effectiveQueryText: current.effectiveQueryText,
|
|
@@ -9288,8 +9117,7 @@ var Retriever = class {
|
|
|
9288
9117
|
const sharedMemories = [];
|
|
9289
9118
|
for (const result of sharedVectorResults) {
|
|
9290
9119
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9291
|
-
if (!entry)
|
|
9292
|
-
continue;
|
|
9120
|
+
if (!entry) continue;
|
|
9293
9121
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9294
9122
|
sharedMemories.push(entry);
|
|
9295
9123
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9362,6 +9190,7 @@ var Retriever = class {
|
|
|
9362
9190
|
if (isCurrentStateQuery(options.query)) {
|
|
9363
9191
|
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
9364
9192
|
}
|
|
9193
|
+
filtered = filtered.filter((result) => !isLowSignalContextContent(result.content));
|
|
9365
9194
|
filtered = filtered.filter(
|
|
9366
9195
|
(result) => this.isGraphPathResult(result) || hasDiscriminativeTermOverlap(options.query, result.content)
|
|
9367
9196
|
);
|
|
@@ -9370,18 +9199,15 @@ var Retriever = class {
|
|
|
9370
9199
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9371
9200
|
);
|
|
9372
9201
|
}
|
|
9373
|
-
if (filtered.length <= 2)
|
|
9374
|
-
return filtered;
|
|
9202
|
+
if (filtered.length <= 2) return filtered;
|
|
9375
9203
|
const topScore = filtered[0].score;
|
|
9376
|
-
if (topScore < 0.8)
|
|
9377
|
-
return filtered;
|
|
9204
|
+
if (topScore < 0.8) return filtered;
|
|
9378
9205
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9379
9206
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9380
9207
|
}
|
|
9381
9208
|
mergeResults(primary, secondary, limit) {
|
|
9382
9209
|
const byId = /* @__PURE__ */ new Map();
|
|
9383
|
-
for (const row of primary)
|
|
9384
|
-
byId.set(row.eventId, row);
|
|
9210
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9385
9211
|
for (const row of secondary) {
|
|
9386
9212
|
const prev = byId.get(row.eventId);
|
|
9387
9213
|
if (!prev || row.score > prev.score) {
|
|
@@ -9392,23 +9218,19 @@ var Retriever = class {
|
|
|
9392
9218
|
}
|
|
9393
9219
|
async expandGraphHops(seeds, opts) {
|
|
9394
9220
|
const byId = /* @__PURE__ */ new Map();
|
|
9395
|
-
for (const s of seeds)
|
|
9396
|
-
byId.set(s.eventId, s);
|
|
9221
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9397
9222
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9398
9223
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9399
9224
|
const next = [];
|
|
9400
9225
|
for (const f of frontier) {
|
|
9401
9226
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9402
|
-
if (!ev)
|
|
9403
|
-
continue;
|
|
9227
|
+
if (!ev) continue;
|
|
9404
9228
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9405
9229
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9406
9230
|
for (const rid of relatedIds) {
|
|
9407
|
-
if (byId.has(rid))
|
|
9408
|
-
continue;
|
|
9231
|
+
if (byId.has(rid)) continue;
|
|
9409
9232
|
const target = await this.eventStore.getEvent(rid);
|
|
9410
|
-
if (!target)
|
|
9411
|
-
continue;
|
|
9233
|
+
if (!target) continue;
|
|
9412
9234
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9413
9235
|
const row = {
|
|
9414
9236
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9422,15 +9244,12 @@ var Retriever = class {
|
|
|
9422
9244
|
};
|
|
9423
9245
|
byId.set(row.eventId, row);
|
|
9424
9246
|
next.push({ row, hop });
|
|
9425
|
-
if (byId.size >= opts.limit)
|
|
9426
|
-
break;
|
|
9247
|
+
if (byId.size >= opts.limit) break;
|
|
9427
9248
|
}
|
|
9428
|
-
if (byId.size >= opts.limit)
|
|
9429
|
-
break;
|
|
9249
|
+
if (byId.size >= opts.limit) break;
|
|
9430
9250
|
}
|
|
9431
9251
|
frontier = next;
|
|
9432
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9433
|
-
break;
|
|
9252
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9434
9253
|
}
|
|
9435
9254
|
if (opts.queryGraphEnabled) {
|
|
9436
9255
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9438,8 +9257,7 @@ var Retriever = class {
|
|
|
9438
9257
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9439
9258
|
}
|
|
9440
9259
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9441
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9442
|
-
return;
|
|
9260
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9443
9261
|
try {
|
|
9444
9262
|
const db = this.eventStore.getDatabase();
|
|
9445
9263
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9448,8 +9266,7 @@ var Retriever = class {
|
|
|
9448
9266
|
});
|
|
9449
9267
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9450
9268
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9451
|
-
if (startNodes.length === 0)
|
|
9452
|
-
return;
|
|
9269
|
+
if (startNodes.length === 0) return;
|
|
9453
9270
|
const expansion = new GraphPathService(db).expand({
|
|
9454
9271
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9455
9272
|
maxHops: opts.maxHops,
|
|
@@ -9458,11 +9275,9 @@ var Retriever = class {
|
|
|
9458
9275
|
});
|
|
9459
9276
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9460
9277
|
for (const path12 of expansion.paths) {
|
|
9461
|
-
if (path12.target.type !== "event")
|
|
9462
|
-
continue;
|
|
9278
|
+
if (path12.target.type !== "event") continue;
|
|
9463
9279
|
const target = await this.eventStore.getEvent(path12.target.id);
|
|
9464
|
-
if (!target)
|
|
9465
|
-
continue;
|
|
9280
|
+
if (!target) continue;
|
|
9466
9281
|
const graphPath = toRetrievalGraphPathDebug(path12, titleByEntityId);
|
|
9467
9282
|
const score = graphPathScore(path12, opts.hopPenalty);
|
|
9468
9283
|
const existing = byId.get(target.id);
|
|
@@ -9488,17 +9303,14 @@ var Retriever = class {
|
|
|
9488
9303
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9489
9304
|
};
|
|
9490
9305
|
byId.set(row.eventId, row);
|
|
9491
|
-
if (byId.size >= opts.limit)
|
|
9492
|
-
break;
|
|
9306
|
+
if (byId.size >= opts.limit) break;
|
|
9493
9307
|
}
|
|
9494
9308
|
} catch {
|
|
9495
9309
|
}
|
|
9496
9310
|
}
|
|
9497
9311
|
shouldFallback(matchResult, results) {
|
|
9498
|
-
if (results.length === 0)
|
|
9499
|
-
|
|
9500
|
-
if (matchResult.confidence === "none")
|
|
9501
|
-
return true;
|
|
9312
|
+
if (results.length === 0) return true;
|
|
9313
|
+
if (matchResult.confidence === "none") return true;
|
|
9502
9314
|
return false;
|
|
9503
9315
|
}
|
|
9504
9316
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9603,29 +9415,21 @@ var Retriever = class {
|
|
|
9603
9415
|
(value) => typeof value === "string" && value.length > 0
|
|
9604
9416
|
)
|
|
9605
9417
|
);
|
|
9606
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9607
|
-
return results;
|
|
9418
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9608
9419
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9609
9420
|
const filtered = [];
|
|
9610
9421
|
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;
|
|
9422
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9423
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9424
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9617
9425
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9618
|
-
if (!event)
|
|
9619
|
-
|
|
9620
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9621
|
-
continue;
|
|
9426
|
+
if (!event) continue;
|
|
9427
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9622
9428
|
if (normalizedIncludes.length > 0) {
|
|
9623
9429
|
const lc = event.content.toLowerCase();
|
|
9624
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9625
|
-
continue;
|
|
9430
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9626
9431
|
}
|
|
9627
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9628
|
-
continue;
|
|
9432
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9629
9433
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9630
9434
|
filtered.push({ result, projectHash });
|
|
9631
9435
|
}
|
|
@@ -9642,27 +9446,21 @@ var Retriever = class {
|
|
|
9642
9446
|
});
|
|
9643
9447
|
}
|
|
9644
9448
|
normalizeFacetFilters(facets) {
|
|
9645
|
-
if (!facets || facets.length === 0)
|
|
9646
|
-
return null;
|
|
9449
|
+
if (!facets || facets.length === 0) return null;
|
|
9647
9450
|
const normalized = [];
|
|
9648
9451
|
for (const facet of facets) {
|
|
9649
9452
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9650
9453
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9651
|
-
if (!parsedDimension.success || !value)
|
|
9652
|
-
return [];
|
|
9454
|
+
if (!parsedDimension.success || !value) return [];
|
|
9653
9455
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9654
9456
|
}
|
|
9655
9457
|
return normalized;
|
|
9656
9458
|
}
|
|
9657
9459
|
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 [];
|
|
9460
|
+
if (options.facets === null) return results;
|
|
9461
|
+
if (options.facets.length === 0) return [];
|
|
9462
|
+
if (!options.projectHash) return [];
|
|
9463
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9666
9464
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9667
9465
|
const filtered = [];
|
|
9668
9466
|
for (const result of results) {
|
|
@@ -9719,14 +9517,11 @@ var Retriever = class {
|
|
|
9719
9517
|
return (result.graphPaths || []).length > 0;
|
|
9720
9518
|
}
|
|
9721
9519
|
extractProjectHash(metadata) {
|
|
9722
|
-
if (!metadata || typeof metadata !== "object")
|
|
9723
|
-
return void 0;
|
|
9520
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9724
9521
|
const scope = metadata.scope;
|
|
9725
|
-
if (!scope || typeof scope !== "object")
|
|
9726
|
-
return void 0;
|
|
9522
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9727
9523
|
const project = scope.project;
|
|
9728
|
-
if (!project || typeof project !== "object")
|
|
9729
|
-
return void 0;
|
|
9524
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9730
9525
|
const hash = project.hash;
|
|
9731
9526
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9732
9527
|
}
|
|
@@ -9736,52 +9531,48 @@ var Retriever = class {
|
|
|
9736
9531
|
async retrieveRecent(limit = 100) {
|
|
9737
9532
|
return this.eventStore.getRecentEvents(limit);
|
|
9738
9533
|
}
|
|
9739
|
-
async enrichResults(results, options) {
|
|
9534
|
+
async enrichResults(results, options, query) {
|
|
9740
9535
|
const memories = [];
|
|
9741
9536
|
for (const result of results) {
|
|
9742
9537
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9743
|
-
if (!event)
|
|
9744
|
-
continue;
|
|
9538
|
+
if (!event) continue;
|
|
9745
9539
|
if (this.graduation) {
|
|
9746
9540
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9747
9541
|
}
|
|
9748
9542
|
let sessionContext;
|
|
9749
9543
|
if (options.includeSessionContext) {
|
|
9750
|
-
sessionContext = await this.getSessionContext(event.sessionId, event.id);
|
|
9544
|
+
sessionContext = await this.getSessionContext(event.sessionId, event.id, query);
|
|
9751
9545
|
}
|
|
9752
9546
|
memories.push({ event, score: result.score, sessionContext });
|
|
9753
9547
|
}
|
|
9754
9548
|
return memories;
|
|
9755
9549
|
}
|
|
9756
|
-
async getSessionContext(sessionId, eventId) {
|
|
9550
|
+
async getSessionContext(sessionId, eventId, query) {
|
|
9757
9551
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9758
9552
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9759
|
-
if (eventIndex === -1)
|
|
9760
|
-
return void 0;
|
|
9553
|
+
if (eventIndex === -1) return void 0;
|
|
9761
9554
|
const start = Math.max(0, eventIndex - 1);
|
|
9762
9555
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9763
9556
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9764
|
-
if (contextEvents.length <= 1)
|
|
9765
|
-
|
|
9766
|
-
|
|
9557
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9558
|
+
const suppressStaleState = isCurrentStateQuery(query);
|
|
9559
|
+
const contextLines = contextEvents.filter((e) => e.id !== eventId).filter((e) => !isLowSignalContextContent(e.content)).filter((e) => !(suppressStaleState && isStaleOrSupersededContent(e.content))).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`);
|
|
9560
|
+
return contextLines.length > 0 ? contextLines.join("\n") : void 0;
|
|
9767
9561
|
}
|
|
9768
9562
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9769
9563
|
let context = projectResult.context;
|
|
9770
|
-
if (sharedMemories.length === 0)
|
|
9771
|
-
return context;
|
|
9564
|
+
if (sharedMemories.length === 0) return context;
|
|
9772
9565
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9773
9566
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9774
9567
|
context += `### ${memory.title}
|
|
9775
9568
|
`;
|
|
9776
|
-
if (memory.symptoms.length > 0)
|
|
9777
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9569
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9778
9570
|
`;
|
|
9779
9571
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9780
9572
|
`;
|
|
9781
9573
|
context += `**Solution:** ${memory.solution}
|
|
9782
9574
|
`;
|
|
9783
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9784
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9575
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9785
9576
|
`;
|
|
9786
9577
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9787
9578
|
|
|
@@ -9795,13 +9586,11 @@ var Retriever = class {
|
|
|
9795
9586
|
for (const memory of memories) {
|
|
9796
9587
|
const memoryText = this.formatMemory(memory);
|
|
9797
9588
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9798
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9799
|
-
break;
|
|
9589
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9800
9590
|
parts.push(memoryText);
|
|
9801
9591
|
currentTokens += memoryTokens;
|
|
9802
9592
|
}
|
|
9803
|
-
if (parts.length === 0)
|
|
9804
|
-
return "";
|
|
9593
|
+
if (parts.length === 0) return "";
|
|
9805
9594
|
return `## Relevant Memories
|
|
9806
9595
|
|
|
9807
9596
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9811,19 +9600,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9811
9600
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9812
9601
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9813
9602
|
${event.content}`;
|
|
9814
|
-
if (sessionContext)
|
|
9815
|
-
text += `
|
|
9603
|
+
if (sessionContext) text += `
|
|
9816
9604
|
|
|
9817
9605
|
_Context:_ ${sessionContext}`;
|
|
9818
9606
|
return text;
|
|
9819
9607
|
}
|
|
9820
9608
|
matchesMetadataScope(metadata, expected) {
|
|
9821
|
-
if (!metadata)
|
|
9822
|
-
return false;
|
|
9609
|
+
if (!metadata) return false;
|
|
9823
9610
|
return Object.entries(expected).every(([path12, value]) => {
|
|
9824
9611
|
const actual = path12.split(".").reduce((acc, key) => {
|
|
9825
|
-
if (typeof acc !== "object" || acc === null)
|
|
9826
|
-
return void 0;
|
|
9612
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9827
9613
|
return acc[key];
|
|
9828
9614
|
}, metadata);
|
|
9829
9615
|
return actual === value;
|
|
@@ -9833,27 +9619,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9833
9619
|
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
9620
|
}
|
|
9835
9621
|
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`;
|
|
9622
|
+
if (token === "apis") return "api";
|
|
9623
|
+
if (token === "ids") return "id";
|
|
9624
|
+
if (token === "does") return token;
|
|
9625
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9844
9626
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9845
9627
|
return token.slice(0, -1);
|
|
9846
9628
|
}
|
|
9847
9629
|
return token;
|
|
9848
9630
|
}
|
|
9849
9631
|
keywordOverlap(a, b) {
|
|
9850
|
-
if (a.length === 0 || b.length === 0)
|
|
9851
|
-
return 0;
|
|
9632
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9852
9633
|
const bs = new Set(b);
|
|
9853
9634
|
let hit = 0;
|
|
9854
|
-
for (const t of a)
|
|
9855
|
-
if (bs.has(t))
|
|
9856
|
-
hit += 1;
|
|
9635
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9857
9636
|
return hit / a.length;
|
|
9858
9637
|
}
|
|
9859
9638
|
estimateTokens(text) {
|
|
@@ -9874,8 +9653,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9874
9653
|
const seen = /* @__PURE__ */ new Set();
|
|
9875
9654
|
const nodes = [];
|
|
9876
9655
|
for (const candidate of candidates) {
|
|
9877
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9878
|
-
continue;
|
|
9656
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9879
9657
|
seen.add(candidate.entityId);
|
|
9880
9658
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9881
9659
|
}
|
|
@@ -9899,16 +9677,14 @@ function graphPathScore(path12, hopPenalty) {
|
|
|
9899
9677
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path12.hops - 1));
|
|
9900
9678
|
}
|
|
9901
9679
|
function clampGraphHops(maxHops) {
|
|
9902
|
-
if (!Number.isFinite(maxHops))
|
|
9903
|
-
return 2;
|
|
9680
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9904
9681
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9905
9682
|
}
|
|
9906
9683
|
function mergeGraphPaths(existing, incoming) {
|
|
9907
9684
|
const byKey = /* @__PURE__ */ new Map();
|
|
9908
9685
|
for (const path12 of [...existing, ...incoming]) {
|
|
9909
9686
|
const key = [path12.startEntityId, path12.targetType, path12.targetId, path12.hops, ...path12.relationPath].join("\0");
|
|
9910
|
-
if (!byKey.has(key))
|
|
9911
|
-
byKey.set(key, path12);
|
|
9687
|
+
if (!byKey.has(key)) byKey.set(key, path12);
|
|
9912
9688
|
}
|
|
9913
9689
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9914
9690
|
}
|
|
@@ -9916,10 +9692,8 @@ function graphPathSignature(path12) {
|
|
|
9916
9692
|
return [path12.startEntityId, path12.targetType, path12.targetId, path12.hops, ...path12.relationPath].join("|");
|
|
9917
9693
|
}
|
|
9918
9694
|
function compareStable(a, b) {
|
|
9919
|
-
if (a < b)
|
|
9920
|
-
|
|
9921
|
-
if (a > b)
|
|
9922
|
-
return 1;
|
|
9695
|
+
if (a < b) return -1;
|
|
9696
|
+
if (a > b) return 1;
|
|
9923
9697
|
return 0;
|
|
9924
9698
|
}
|
|
9925
9699
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9931,6 +9705,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9931
9705
|
constructor(deps) {
|
|
9932
9706
|
this.deps = deps;
|
|
9933
9707
|
}
|
|
9708
|
+
deps;
|
|
9934
9709
|
async getRetrievalTraceStats() {
|
|
9935
9710
|
await this.deps.initialize();
|
|
9936
9711
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -10008,6 +9783,7 @@ var RetrievalDisclosureService = class {
|
|
|
10008
9783
|
constructor(deps) {
|
|
10009
9784
|
this.deps = deps;
|
|
10010
9785
|
}
|
|
9786
|
+
deps;
|
|
10011
9787
|
async search(query, options) {
|
|
10012
9788
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
10013
9789
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -10037,8 +9813,7 @@ var RetrievalDisclosureService = class {
|
|
|
10037
9813
|
return this.expandShared(parsedId.entryId);
|
|
10038
9814
|
}
|
|
10039
9815
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
10040
|
-
if (!targetEvent)
|
|
10041
|
-
return null;
|
|
9816
|
+
if (!targetEvent) return null;
|
|
10042
9817
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
10043
9818
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
10044
9819
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -10062,8 +9837,7 @@ var RetrievalDisclosureService = class {
|
|
|
10062
9837
|
return this.sourceShared(parsedId.entryId);
|
|
10063
9838
|
}
|
|
10064
9839
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
10065
|
-
if (!rawEvent)
|
|
10066
|
-
return null;
|
|
9840
|
+
if (!rawEvent) return null;
|
|
10067
9841
|
return {
|
|
10068
9842
|
...this.sourceReferenceForEvent(rawEvent),
|
|
10069
9843
|
rawEvents: [rawEvent],
|
|
@@ -10072,8 +9846,7 @@ var RetrievalDisclosureService = class {
|
|
|
10072
9846
|
}
|
|
10073
9847
|
async expandShared(entryId) {
|
|
10074
9848
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
10075
|
-
if (!entry)
|
|
10076
|
-
return null;
|
|
9849
|
+
if (!entry) return null;
|
|
10077
9850
|
return {
|
|
10078
9851
|
target: this.sharedToEnvelope(entry),
|
|
10079
9852
|
surroundingFacts: [],
|
|
@@ -10084,8 +9857,7 @@ var RetrievalDisclosureService = class {
|
|
|
10084
9857
|
}
|
|
10085
9858
|
async sourceShared(entryId) {
|
|
10086
9859
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
10087
|
-
if (!entry)
|
|
10088
|
-
return null;
|
|
9860
|
+
if (!entry) return null;
|
|
10089
9861
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
10090
9862
|
return {
|
|
10091
9863
|
...sourceReference,
|
|
@@ -10171,38 +9943,25 @@ var RetrievalDisclosureService = class {
|
|
|
10171
9943
|
const reasons = /* @__PURE__ */ new Set();
|
|
10172
9944
|
const usedVector = this.usedVector(result);
|
|
10173
9945
|
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");
|
|
9946
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9947
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9948
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9949
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9950
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9951
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9952
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9953
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9954
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10192
9955
|
return Array.from(reasons);
|
|
10193
9956
|
}
|
|
10194
9957
|
reasonsForContextEvent(event) {
|
|
10195
|
-
if (event.eventType === "tool_observation")
|
|
10196
|
-
|
|
10197
|
-
if (event.eventType === "session_summary")
|
|
10198
|
-
return ["summary_fallback"];
|
|
9958
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9959
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10199
9960
|
return ["continuity_link"];
|
|
10200
9961
|
}
|
|
10201
9962
|
resultTypeForEvent(event) {
|
|
10202
|
-
if (event.eventType === "session_summary")
|
|
10203
|
-
|
|
10204
|
-
if (event.eventType === "tool_observation")
|
|
10205
|
-
return "tool_evidence";
|
|
9963
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9964
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10206
9965
|
return "source";
|
|
10207
9966
|
}
|
|
10208
9967
|
sourceReferenceForEvent(event) {
|
|
@@ -10226,21 +9985,15 @@ var RetrievalDisclosureService = class {
|
|
|
10226
9985
|
}
|
|
10227
9986
|
sourceTypeForEvent(event) {
|
|
10228
9987
|
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";
|
|
9988
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9989
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9990
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10235
9991
|
return "raw_event";
|
|
10236
9992
|
}
|
|
10237
9993
|
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";
|
|
9994
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9995
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9996
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10244
9997
|
return "User prompt";
|
|
10245
9998
|
}
|
|
10246
9999
|
usedVector(result) {
|
|
@@ -10266,8 +10019,7 @@ var RetrievalDisclosureService = class {
|
|
|
10266
10019
|
}
|
|
10267
10020
|
preview(content, maxLength) {
|
|
10268
10021
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10269
|
-
if (normalized.length <= maxLength)
|
|
10270
|
-
return normalized;
|
|
10022
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10271
10023
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10272
10024
|
}
|
|
10273
10025
|
};
|
|
@@ -10296,6 +10048,7 @@ var RetrievalOrchestrator = class {
|
|
|
10296
10048
|
this.deps = deps;
|
|
10297
10049
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10298
10050
|
}
|
|
10051
|
+
deps;
|
|
10299
10052
|
/**
|
|
10300
10053
|
* Retrieve relevant memories for a query.
|
|
10301
10054
|
*/
|
|
@@ -10377,8 +10130,7 @@ var RetrievalOrchestrator = class {
|
|
|
10377
10130
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10378
10131
|
*/
|
|
10379
10132
|
async incrementMemoryAccess(eventIds) {
|
|
10380
|
-
if (eventIds.length === 0)
|
|
10381
|
-
return;
|
|
10133
|
+
if (eventIds.length === 0) return;
|
|
10382
10134
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10383
10135
|
}
|
|
10384
10136
|
/**
|
|
@@ -10391,10 +10143,8 @@ var RetrievalOrchestrator = class {
|
|
|
10391
10143
|
resolveGraphHopOptions(callerOptions) {
|
|
10392
10144
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10393
10145
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10394
|
-
if (!callerOptions)
|
|
10395
|
-
|
|
10396
|
-
if (!graphExpansion)
|
|
10397
|
-
return callerOptions;
|
|
10146
|
+
if (!callerOptions) return durableOptions;
|
|
10147
|
+
if (!graphExpansion) return callerOptions;
|
|
10398
10148
|
if (graphExpansion.enabled !== true) {
|
|
10399
10149
|
return {
|
|
10400
10150
|
...callerOptions,
|
|
@@ -10454,12 +10204,10 @@ var RetrievalOrchestrator = class {
|
|
|
10454
10204
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10455
10205
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10456
10206
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10457
|
-
if (!allFinite)
|
|
10458
|
-
return void 0;
|
|
10207
|
+
if (!allFinite) return void 0;
|
|
10459
10208
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10460
10209
|
const total = semantic + lexical + recency;
|
|
10461
|
-
if (!nonNegative || total <= 0)
|
|
10462
|
-
return void 0;
|
|
10210
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10463
10211
|
return {
|
|
10464
10212
|
semantic: semantic / total,
|
|
10465
10213
|
lexical: lexical / total,
|
|
@@ -10468,17 +10216,14 @@ var RetrievalOrchestrator = class {
|
|
|
10468
10216
|
}
|
|
10469
10217
|
async getRerankWeights(adaptive) {
|
|
10470
10218
|
const configured = this.getConfiguredRerankWeights();
|
|
10471
|
-
if (configured)
|
|
10472
|
-
|
|
10473
|
-
if (adaptive)
|
|
10474
|
-
return this.getAdaptiveRerankWeights();
|
|
10219
|
+
if (configured) return configured;
|
|
10220
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10475
10221
|
return void 0;
|
|
10476
10222
|
}
|
|
10477
10223
|
async getAdaptiveRerankWeights() {
|
|
10478
10224
|
try {
|
|
10479
10225
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10480
|
-
if (stats.totalEvaluated < 20)
|
|
10481
|
-
return void 0;
|
|
10226
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10482
10227
|
let semantic = 0.7;
|
|
10483
10228
|
let lexical = 0.2;
|
|
10484
10229
|
let recency = 0.1;
|
|
@@ -10500,11 +10245,9 @@ var RetrievalOrchestrator = class {
|
|
|
10500
10245
|
}
|
|
10501
10246
|
}
|
|
10502
10247
|
async rewriteQueryIntent(query) {
|
|
10503
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10504
|
-
return null;
|
|
10248
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10505
10249
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10506
|
-
if (!apiUrl)
|
|
10507
|
-
return null;
|
|
10250
|
+
if (!apiUrl) return null;
|
|
10508
10251
|
const controller = new AbortController();
|
|
10509
10252
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10510
10253
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10530,11 +10273,9 @@ var RetrievalOrchestrator = class {
|
|
|
10530
10273
|
signal: controller.signal
|
|
10531
10274
|
});
|
|
10532
10275
|
const text = (await res.text()).trim();
|
|
10533
|
-
if (!text)
|
|
10534
|
-
return null;
|
|
10276
|
+
if (!text) return null;
|
|
10535
10277
|
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;
|
|
10278
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10538
10279
|
return oneLine;
|
|
10539
10280
|
} catch {
|
|
10540
10281
|
return null;
|
|
@@ -10676,8 +10417,7 @@ function createMemoryEngineServices(options) {
|
|
|
10676
10417
|
};
|
|
10677
10418
|
}
|
|
10678
10419
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10679
|
-
if (options.readOnly)
|
|
10680
|
-
return false;
|
|
10420
|
+
if (options.readOnly) return false;
|
|
10681
10421
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10682
10422
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10683
10423
|
}
|
|
@@ -10711,6 +10451,9 @@ var GraduationWorker = class {
|
|
|
10711
10451
|
this.graduation = graduation;
|
|
10712
10452
|
this.config = config;
|
|
10713
10453
|
}
|
|
10454
|
+
eventStore;
|
|
10455
|
+
graduation;
|
|
10456
|
+
config;
|
|
10714
10457
|
running = false;
|
|
10715
10458
|
timeout = null;
|
|
10716
10459
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10718,8 +10461,7 @@ var GraduationWorker = class {
|
|
|
10718
10461
|
* Start the graduation worker
|
|
10719
10462
|
*/
|
|
10720
10463
|
start() {
|
|
10721
|
-
if (this.running)
|
|
10722
|
-
return;
|
|
10464
|
+
if (this.running) return;
|
|
10723
10465
|
this.running = true;
|
|
10724
10466
|
this.scheduleNext();
|
|
10725
10467
|
}
|
|
@@ -10749,8 +10491,7 @@ var GraduationWorker = class {
|
|
|
10749
10491
|
* Schedule the next graduation check
|
|
10750
10492
|
*/
|
|
10751
10493
|
scheduleNext() {
|
|
10752
|
-
if (!this.running)
|
|
10753
|
-
return;
|
|
10494
|
+
if (!this.running) return;
|
|
10754
10495
|
this.timeout = setTimeout(
|
|
10755
10496
|
() => this.run(),
|
|
10756
10497
|
this.config.evaluationIntervalMs
|
|
@@ -10760,8 +10501,7 @@ var GraduationWorker = class {
|
|
|
10760
10501
|
* Run graduation evaluation
|
|
10761
10502
|
*/
|
|
10762
10503
|
async run() {
|
|
10763
|
-
if (!this.running)
|
|
10764
|
-
return;
|
|
10504
|
+
if (!this.running) return;
|
|
10765
10505
|
try {
|
|
10766
10506
|
await this.runGraduation();
|
|
10767
10507
|
} catch (error) {
|
|
@@ -10825,10 +10565,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10825
10565
|
maxRetries: 3
|
|
10826
10566
|
};
|
|
10827
10567
|
function parseJsonArray(value) {
|
|
10828
|
-
if (Array.isArray(value))
|
|
10829
|
-
|
|
10830
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10831
|
-
return [];
|
|
10568
|
+
if (Array.isArray(value)) return value;
|
|
10569
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10832
10570
|
try {
|
|
10833
10571
|
const parsed = JSON.parse(value);
|
|
10834
10572
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10858,8 +10596,7 @@ var VectorWorker = class {
|
|
|
10858
10596
|
* Start the worker polling loop
|
|
10859
10597
|
*/
|
|
10860
10598
|
start() {
|
|
10861
|
-
if (this.running)
|
|
10862
|
-
return;
|
|
10599
|
+
if (this.running) return;
|
|
10863
10600
|
this.running = true;
|
|
10864
10601
|
this.stopping = false;
|
|
10865
10602
|
this.poll();
|
|
@@ -10935,8 +10672,7 @@ var VectorWorker = class {
|
|
|
10935
10672
|
* Poll for new items
|
|
10936
10673
|
*/
|
|
10937
10674
|
async poll() {
|
|
10938
|
-
if (!this.running || this.stopping)
|
|
10939
|
-
return;
|
|
10675
|
+
if (!this.running || this.stopping) return;
|
|
10940
10676
|
try {
|
|
10941
10677
|
await this.processBatch();
|
|
10942
10678
|
} catch (error) {
|
|
@@ -10981,6 +10717,7 @@ var DefaultContentProvider = class {
|
|
|
10981
10717
|
constructor(db) {
|
|
10982
10718
|
this.db = db;
|
|
10983
10719
|
}
|
|
10720
|
+
db;
|
|
10984
10721
|
async getContent(itemKind, itemId) {
|
|
10985
10722
|
switch (itemKind) {
|
|
10986
10723
|
case "entry":
|
|
@@ -11001,8 +10738,7 @@ var DefaultContentProvider = class {
|
|
|
11001
10738
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
11002
10739
|
[entryId]
|
|
11003
10740
|
);
|
|
11004
|
-
if (rows.length === 0)
|
|
11005
|
-
return null;
|
|
10741
|
+
if (rows.length === 0) return null;
|
|
11006
10742
|
const row = rows[0];
|
|
11007
10743
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
11008
10744
|
return {
|
|
@@ -11021,8 +10757,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11021
10757
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
11022
10758
|
[taskId]
|
|
11023
10759
|
);
|
|
11024
|
-
if (rows.length === 0)
|
|
11025
|
-
return null;
|
|
10760
|
+
if (rows.length === 0) return null;
|
|
11026
10761
|
const row = rows[0];
|
|
11027
10762
|
return {
|
|
11028
10763
|
content: row.search_text || row.title,
|
|
@@ -11038,8 +10773,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11038
10773
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
11039
10774
|
[eventId]
|
|
11040
10775
|
);
|
|
11041
|
-
if (rows.length === 0)
|
|
11042
|
-
return null;
|
|
10776
|
+
if (rows.length === 0) return null;
|
|
11043
10777
|
const row = rows[0];
|
|
11044
10778
|
return {
|
|
11045
10779
|
content: row.content,
|
|
@@ -11067,8 +10801,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
11067
10801
|
}
|
|
11068
10802
|
throw error;
|
|
11069
10803
|
}
|
|
11070
|
-
if (rows.length === 0)
|
|
11071
|
-
return null;
|
|
10804
|
+
if (rows.length === 0) return null;
|
|
11072
10805
|
const row = rows[0];
|
|
11073
10806
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
11074
10807
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -11110,8 +10843,7 @@ var VectorWorkerV2 = class {
|
|
|
11110
10843
|
* Start the worker polling loop
|
|
11111
10844
|
*/
|
|
11112
10845
|
start() {
|
|
11113
|
-
if (this.running)
|
|
11114
|
-
return;
|
|
10846
|
+
if (this.running) return;
|
|
11115
10847
|
this.running = true;
|
|
11116
10848
|
this.stopping = false;
|
|
11117
10849
|
this.poll();
|
|
@@ -11181,8 +10913,7 @@ var VectorWorkerV2 = class {
|
|
|
11181
10913
|
* Poll for new jobs
|
|
11182
10914
|
*/
|
|
11183
10915
|
async poll() {
|
|
11184
|
-
if (!this.running || this.stopping)
|
|
11185
|
-
return;
|
|
10916
|
+
if (!this.running || this.stopping) return;
|
|
11186
10917
|
try {
|
|
11187
10918
|
await this.processBatch();
|
|
11188
10919
|
} catch (error) {
|
|
@@ -11249,8 +10980,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11249
10980
|
let graduationWorker = null;
|
|
11250
10981
|
return {
|
|
11251
10982
|
async initialize() {
|
|
11252
|
-
if (initialized)
|
|
11253
|
-
return;
|
|
10983
|
+
if (initialized) return;
|
|
11254
10984
|
await deps.sqliteStore.initialize();
|
|
11255
10985
|
if (deps.lightweightMode) {
|
|
11256
10986
|
initialized = true;
|
|
@@ -11344,8 +11074,7 @@ var SharedEventStore = class {
|
|
|
11344
11074
|
this.db = createDatabase(dbPath);
|
|
11345
11075
|
}
|
|
11346
11076
|
async initialize() {
|
|
11347
|
-
if (this.initialized)
|
|
11348
|
-
return;
|
|
11077
|
+
if (this.initialized) return;
|
|
11349
11078
|
await dbRun(this.db, `
|
|
11350
11079
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11351
11080
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11435,6 +11164,10 @@ var SharedPromoter = class {
|
|
|
11435
11164
|
this.embedder = embedder;
|
|
11436
11165
|
this.config = config;
|
|
11437
11166
|
}
|
|
11167
|
+
sharedStore;
|
|
11168
|
+
sharedVectorStore;
|
|
11169
|
+
embedder;
|
|
11170
|
+
config;
|
|
11438
11171
|
/**
|
|
11439
11172
|
* Check if an entry is eligible for promotion
|
|
11440
11173
|
*/
|
|
@@ -11616,6 +11349,7 @@ var SharedStore = class {
|
|
|
11616
11349
|
constructor(sharedEventStore) {
|
|
11617
11350
|
this.sharedEventStore = sharedEventStore;
|
|
11618
11351
|
}
|
|
11352
|
+
sharedEventStore;
|
|
11619
11353
|
get db() {
|
|
11620
11354
|
return this.sharedEventStore.getDatabase();
|
|
11621
11355
|
}
|
|
@@ -11720,8 +11454,7 @@ var SharedStore = class {
|
|
|
11720
11454
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11721
11455
|
[entryId]
|
|
11722
11456
|
);
|
|
11723
|
-
if (rows.length === 0)
|
|
11724
|
-
return null;
|
|
11457
|
+
if (rows.length === 0) return null;
|
|
11725
11458
|
return this.rowToEntry(rows[0]);
|
|
11726
11459
|
}
|
|
11727
11460
|
/**
|
|
@@ -11734,8 +11467,7 @@ var SharedStore = class {
|
|
|
11734
11467
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11735
11468
|
[projectHash, sourceEntryId]
|
|
11736
11469
|
);
|
|
11737
|
-
if (rows.length === 0)
|
|
11738
|
-
return null;
|
|
11470
|
+
if (rows.length === 0) return null;
|
|
11739
11471
|
return this.rowToEntry(rows[0]);
|
|
11740
11472
|
}
|
|
11741
11473
|
/**
|
|
@@ -11845,6 +11577,7 @@ var SharedVectorStore = class {
|
|
|
11845
11577
|
constructor(dbPath) {
|
|
11846
11578
|
this.dbPath = dbPath;
|
|
11847
11579
|
}
|
|
11580
|
+
dbPath;
|
|
11848
11581
|
db = null;
|
|
11849
11582
|
table = null;
|
|
11850
11583
|
tableName = "shared_knowledge";
|
|
@@ -11852,8 +11585,7 @@ var SharedVectorStore = class {
|
|
|
11852
11585
|
* Initialize LanceDB connection
|
|
11853
11586
|
*/
|
|
11854
11587
|
async initialize() {
|
|
11855
|
-
if (this.db)
|
|
11856
|
-
return;
|
|
11588
|
+
if (this.db) return;
|
|
11857
11589
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11858
11590
|
try {
|
|
11859
11591
|
const tables = await this.db.tableNames();
|
|
@@ -11895,8 +11627,7 @@ var SharedVectorStore = class {
|
|
|
11895
11627
|
* Add multiple records in batch
|
|
11896
11628
|
*/
|
|
11897
11629
|
async upsertBatch(records) {
|
|
11898
|
-
if (records.length === 0)
|
|
11899
|
-
return;
|
|
11630
|
+
if (records.length === 0) return;
|
|
11900
11631
|
await this.initialize();
|
|
11901
11632
|
if (!this.db) {
|
|
11902
11633
|
throw new Error("Database not initialized");
|
|
@@ -11957,24 +11688,21 @@ var SharedVectorStore = class {
|
|
|
11957
11688
|
* Delete vector by entry ID
|
|
11958
11689
|
*/
|
|
11959
11690
|
async delete(entryId) {
|
|
11960
|
-
if (!this.table)
|
|
11961
|
-
return;
|
|
11691
|
+
if (!this.table) return;
|
|
11962
11692
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11963
11693
|
}
|
|
11964
11694
|
/**
|
|
11965
11695
|
* Get total count
|
|
11966
11696
|
*/
|
|
11967
11697
|
async count() {
|
|
11968
|
-
if (!this.table)
|
|
11969
|
-
return 0;
|
|
11698
|
+
if (!this.table) return 0;
|
|
11970
11699
|
return this.table.countRows();
|
|
11971
11700
|
}
|
|
11972
11701
|
/**
|
|
11973
11702
|
* Check if vector exists for entry
|
|
11974
11703
|
*/
|
|
11975
11704
|
async exists(entryId) {
|
|
11976
|
-
if (!this.table)
|
|
11977
|
-
return false;
|
|
11705
|
+
if (!this.table) return false;
|
|
11978
11706
|
try {
|
|
11979
11707
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11980
11708
|
return results.length > 0;
|
|
@@ -11992,6 +11720,7 @@ var SharedMemoryServices = class {
|
|
|
11992
11720
|
constructor(options) {
|
|
11993
11721
|
this.options = options;
|
|
11994
11722
|
}
|
|
11723
|
+
options;
|
|
11995
11724
|
sharedEventStore = null;
|
|
11996
11725
|
sharedStore = null;
|
|
11997
11726
|
sharedVectorStore = null;
|
|
@@ -12016,8 +11745,7 @@ var SharedMemoryServices = class {
|
|
|
12016
11745
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
12017
11746
|
}
|
|
12018
11747
|
async initialize() {
|
|
12019
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
12020
|
-
return;
|
|
11748
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
12021
11749
|
const sharedPath = this.getSharedStoragePath();
|
|
12022
11750
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
12023
11751
|
const store = await this.openStore(sharedPath);
|
|
@@ -12034,14 +11762,11 @@ var SharedMemoryServices = class {
|
|
|
12034
11762
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
12035
11763
|
}
|
|
12036
11764
|
async ensureStoreForRead() {
|
|
12037
|
-
if (this.options.config?.enabled === false)
|
|
12038
|
-
|
|
12039
|
-
if (this.sharedStore)
|
|
12040
|
-
return this.sharedStore;
|
|
11765
|
+
if (this.options.config?.enabled === false) return null;
|
|
11766
|
+
if (this.sharedStore) return this.sharedStore;
|
|
12041
11767
|
const sharedPath = this.getSharedStoragePath();
|
|
12042
11768
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
12043
|
-
if (!directoryReady)
|
|
12044
|
-
return null;
|
|
11769
|
+
if (!directoryReady) return null;
|
|
12045
11770
|
return this.openStore(sharedPath);
|
|
12046
11771
|
}
|
|
12047
11772
|
async getEntryForDisclosure(entryId) {
|
|
@@ -12058,13 +11783,11 @@ var SharedMemoryServices = class {
|
|
|
12058
11783
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
12059
11784
|
}
|
|
12060
11785
|
async getStats() {
|
|
12061
|
-
if (!this.sharedStore)
|
|
12062
|
-
return null;
|
|
11786
|
+
if (!this.sharedStore) return null;
|
|
12063
11787
|
return this.sharedStore.getStats();
|
|
12064
11788
|
}
|
|
12065
11789
|
async search(query, options) {
|
|
12066
|
-
if (!this.sharedStore)
|
|
12067
|
-
return [];
|
|
11790
|
+
if (!this.sharedStore) return [];
|
|
12068
11791
|
return this.sharedStore.search(query, options);
|
|
12069
11792
|
}
|
|
12070
11793
|
async close() {
|
|
@@ -12081,8 +11804,7 @@ var SharedMemoryServices = class {
|
|
|
12081
11804
|
this.openStorePromise = null;
|
|
12082
11805
|
}
|
|
12083
11806
|
async openStore(sharedPath) {
|
|
12084
|
-
if (this.sharedStore)
|
|
12085
|
-
return this.sharedStore;
|
|
11807
|
+
if (this.sharedStore) return this.sharedStore;
|
|
12086
11808
|
if (!this.openStorePromise) {
|
|
12087
11809
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
12088
11810
|
}
|
|
@@ -12106,10 +11828,8 @@ var SharedMemoryServices = class {
|
|
|
12106
11828
|
return this.sharedStore;
|
|
12107
11829
|
}
|
|
12108
11830
|
ensureDirectory(sharedPath, options) {
|
|
12109
|
-
if (this.factories.existsSync(sharedPath))
|
|
12110
|
-
|
|
12111
|
-
if (!options.allowCreate)
|
|
12112
|
-
return false;
|
|
11831
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11832
|
+
if (!options.allowCreate) return false;
|
|
12113
11833
|
this.factories.mkdirSync(sharedPath);
|
|
12114
11834
|
return true;
|
|
12115
11835
|
}
|
|
@@ -12934,8 +12654,7 @@ import * as fs10 from "fs";
|
|
|
12934
12654
|
import * as readline from "readline";
|
|
12935
12655
|
var DEFAULT_MAX_BYTES = 200 * 1024;
|
|
12936
12656
|
async function readTranscriptTailEntries(transcriptPath, options = {}) {
|
|
12937
|
-
if (!fs10.existsSync(transcriptPath))
|
|
12938
|
-
return [];
|
|
12657
|
+
if (!fs10.existsSync(transcriptPath)) return [];
|
|
12939
12658
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
12940
12659
|
const stats = fs10.statSync(transcriptPath);
|
|
12941
12660
|
const readStart = Math.max(0, stats.size - maxBytes);
|
|
@@ -12964,11 +12683,9 @@ function isTextContentBlock(value) {
|
|
|
12964
12683
|
function extractAssistantTextMessages(entries) {
|
|
12965
12684
|
const messages = [];
|
|
12966
12685
|
for (const entry of entries) {
|
|
12967
|
-
if (entry.type !== "assistant")
|
|
12968
|
-
continue;
|
|
12686
|
+
if (entry.type !== "assistant") continue;
|
|
12969
12687
|
const content = entry.message?.content;
|
|
12970
|
-
if (!Array.isArray(content))
|
|
12971
|
-
continue;
|
|
12688
|
+
if (!Array.isArray(content)) continue;
|
|
12972
12689
|
const textParts = content.filter(isTextContentBlock).map((block) => block.text).filter(Boolean);
|
|
12973
12690
|
if (textParts.length > 0) {
|
|
12974
12691
|
messages.push(textParts.join("\n"));
|
|
@@ -13011,8 +12728,7 @@ async function main() {
|
|
|
13011
12728
|
if (content.length > 5e3) {
|
|
13012
12729
|
content = content.slice(0, 5e3) + "...[truncated]";
|
|
13013
12730
|
}
|
|
13014
|
-
if (!isLast && content.trim().length < MIN_AGENT_RESPONSE_LEN)
|
|
13015
|
-
continue;
|
|
12731
|
+
if (!isLast && content.trim().length < MIN_AGENT_RESPONSE_LEN) continue;
|
|
13016
12732
|
await memoryService.storeAgentResponse(
|
|
13017
12733
|
input.session_id,
|
|
13018
12734
|
content,
|