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/server/api/index.js
CHANGED
|
@@ -56,6 +56,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
56
56
|
this.options = options;
|
|
57
57
|
this.fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
58
58
|
}
|
|
59
|
+
options;
|
|
59
60
|
fileSystem;
|
|
60
61
|
getEmbeddingModelName() {
|
|
61
62
|
return this.options.getEmbeddingModelName();
|
|
@@ -90,8 +91,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
90
91
|
}
|
|
91
92
|
const worker = this.options.getVectorWorker();
|
|
92
93
|
const wasRunning = worker?.isRunning() || false;
|
|
93
|
-
if (wasRunning)
|
|
94
|
-
worker?.stop();
|
|
94
|
+
if (wasRunning) worker?.stop();
|
|
95
95
|
await this.options.vectorStore.clearAll();
|
|
96
96
|
await this.options.eventStore.clearEmbeddingOutbox();
|
|
97
97
|
const enqueued = await this.reenqueueAllEvents();
|
|
@@ -108,8 +108,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
108
108
|
2
|
|
109
109
|
)
|
|
110
110
|
);
|
|
111
|
-
if (wasRunning)
|
|
112
|
-
worker?.start();
|
|
111
|
+
if (wasRunning) worker?.start();
|
|
113
112
|
return {
|
|
114
113
|
changed: true,
|
|
115
114
|
previousModel,
|
|
@@ -134,15 +133,13 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
134
133
|
let enqueued = 0;
|
|
135
134
|
while (true) {
|
|
136
135
|
const page = await this.options.eventStore.getEventsPage(DEFAULT_PAGE_SIZE, offset);
|
|
137
|
-
if (page.length === 0)
|
|
138
|
-
break;
|
|
136
|
+
if (page.length === 0) break;
|
|
139
137
|
for (const event of page) {
|
|
140
138
|
await this.options.eventStore.enqueueForEmbedding(event.id, event.content);
|
|
141
139
|
enqueued += 1;
|
|
142
140
|
}
|
|
143
141
|
offset += page.length;
|
|
144
|
-
if (page.length < DEFAULT_PAGE_SIZE)
|
|
145
|
-
break;
|
|
142
|
+
if (page.length < DEFAULT_PAGE_SIZE) break;
|
|
146
143
|
}
|
|
147
144
|
return enqueued;
|
|
148
145
|
}
|
|
@@ -160,12 +157,9 @@ import { randomUUID } from "crypto";
|
|
|
160
157
|
// src/core/db-wrapper.ts
|
|
161
158
|
import BetterSqlite3 from "better-sqlite3";
|
|
162
159
|
function toDate(value) {
|
|
163
|
-
if (value instanceof Date)
|
|
164
|
-
|
|
165
|
-
if (typeof value === "
|
|
166
|
-
return new Date(value);
|
|
167
|
-
if (typeof value === "number")
|
|
168
|
-
return new Date(value);
|
|
160
|
+
if (value instanceof Date) return value;
|
|
161
|
+
if (typeof value === "string") return new Date(value);
|
|
162
|
+
if (typeof value === "number") return new Date(value);
|
|
169
163
|
return new Date(String(value));
|
|
170
164
|
}
|
|
171
165
|
function createDatabase(dbPath, options) {
|
|
@@ -189,6 +183,8 @@ var WorkingSetStore = class {
|
|
|
189
183
|
this.eventStore = eventStore;
|
|
190
184
|
this.config = config;
|
|
191
185
|
}
|
|
186
|
+
eventStore;
|
|
187
|
+
config;
|
|
192
188
|
get db() {
|
|
193
189
|
return this.eventStore.getDatabase();
|
|
194
190
|
}
|
|
@@ -274,8 +270,7 @@ var WorkingSetStore = class {
|
|
|
274
270
|
* Prune specific events from working set (after consolidation)
|
|
275
271
|
*/
|
|
276
272
|
async prune(eventIds) {
|
|
277
|
-
if (eventIds.length === 0)
|
|
278
|
-
return;
|
|
273
|
+
if (eventIds.length === 0) return;
|
|
279
274
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
280
275
|
await dbRun(
|
|
281
276
|
this.db,
|
|
@@ -345,8 +340,7 @@ var WorkingSetStore = class {
|
|
|
345
340
|
LIMIT ?`,
|
|
346
341
|
[maxEvents]
|
|
347
342
|
);
|
|
348
|
-
if (keepIds.length === 0)
|
|
349
|
-
return;
|
|
343
|
+
if (keepIds.length === 0) return;
|
|
350
344
|
const keepIdList = keepIds.map((r) => r.id);
|
|
351
345
|
const placeholders = keepIdList.map(() => "?").join(",");
|
|
352
346
|
await dbRun(
|
|
@@ -393,6 +387,7 @@ var ConsolidatedStore = class {
|
|
|
393
387
|
constructor(eventStore) {
|
|
394
388
|
this.eventStore = eventStore;
|
|
395
389
|
}
|
|
390
|
+
eventStore;
|
|
396
391
|
get db() {
|
|
397
392
|
return this.eventStore.getDatabase();
|
|
398
393
|
}
|
|
@@ -425,8 +420,7 @@ var ConsolidatedStore = class {
|
|
|
425
420
|
`SELECT * FROM consolidated_memories WHERE memory_id = ?`,
|
|
426
421
|
[memoryId]
|
|
427
422
|
);
|
|
428
|
-
if (rows.length === 0)
|
|
429
|
-
return null;
|
|
423
|
+
if (rows.length === 0) return null;
|
|
430
424
|
return this.rowToMemory(rows[0]);
|
|
431
425
|
}
|
|
432
426
|
/**
|
|
@@ -644,8 +638,7 @@ var ConsolidatedStore = class {
|
|
|
644
638
|
WHERE source_events LIKE ?`,
|
|
645
639
|
[`%"${eventId}"%`]
|
|
646
640
|
);
|
|
647
|
-
if ((result[0]?.count || 0) > 0)
|
|
648
|
-
return true;
|
|
641
|
+
if ((result[0]?.count || 0) > 0) return true;
|
|
649
642
|
}
|
|
650
643
|
return false;
|
|
651
644
|
}
|
|
@@ -659,8 +652,7 @@ var ConsolidatedStore = class {
|
|
|
659
652
|
ORDER BY created_at DESC
|
|
660
653
|
LIMIT 1`
|
|
661
654
|
);
|
|
662
|
-
if (result.length === 0)
|
|
663
|
-
return null;
|
|
655
|
+
if (result.length === 0) return null;
|
|
664
656
|
return new Date(result[0].created_at);
|
|
665
657
|
}
|
|
666
658
|
/**
|
|
@@ -690,6 +682,9 @@ var ConsolidationWorker = class {
|
|
|
690
682
|
this.consolidatedStore = consolidatedStore;
|
|
691
683
|
this.config = config;
|
|
692
684
|
}
|
|
685
|
+
workingSetStore;
|
|
686
|
+
consolidatedStore;
|
|
687
|
+
config;
|
|
693
688
|
running = false;
|
|
694
689
|
timeout = null;
|
|
695
690
|
lastActivity = /* @__PURE__ */ new Date();
|
|
@@ -697,8 +692,7 @@ var ConsolidationWorker = class {
|
|
|
697
692
|
* Start the consolidation worker
|
|
698
693
|
*/
|
|
699
694
|
start() {
|
|
700
|
-
if (this.running)
|
|
701
|
-
return;
|
|
695
|
+
if (this.running) return;
|
|
702
696
|
this.running = true;
|
|
703
697
|
this.scheduleNext();
|
|
704
698
|
}
|
|
@@ -741,8 +735,7 @@ var ConsolidationWorker = class {
|
|
|
741
735
|
* Schedule the next consolidation check
|
|
742
736
|
*/
|
|
743
737
|
scheduleNext() {
|
|
744
|
-
if (!this.running)
|
|
745
|
-
return;
|
|
738
|
+
if (!this.running) return;
|
|
746
739
|
this.timeout = setTimeout(
|
|
747
740
|
() => this.run(),
|
|
748
741
|
this.config.consolidation.triggerIntervalMs
|
|
@@ -752,8 +745,7 @@ var ConsolidationWorker = class {
|
|
|
752
745
|
* Run consolidation check
|
|
753
746
|
*/
|
|
754
747
|
async run() {
|
|
755
|
-
if (!this.running)
|
|
756
|
-
return;
|
|
748
|
+
if (!this.running) return;
|
|
757
749
|
try {
|
|
758
750
|
await this.checkAndConsolidate();
|
|
759
751
|
} catch (error) {
|
|
@@ -791,12 +783,10 @@ var ConsolidationWorker = class {
|
|
|
791
783
|
let consolidatedCount = 0;
|
|
792
784
|
const createdMemoryIds = [];
|
|
793
785
|
for (const group of groups) {
|
|
794
|
-
if (group.events.length < 3)
|
|
795
|
-
continue;
|
|
786
|
+
if (group.events.length < 3) continue;
|
|
796
787
|
const eventIds = group.events.map((e) => e.id);
|
|
797
788
|
const alreadyConsolidated = await this.consolidatedStore.isAlreadyConsolidated(eventIds);
|
|
798
|
-
if (alreadyConsolidated)
|
|
799
|
-
continue;
|
|
789
|
+
if (alreadyConsolidated) continue;
|
|
800
790
|
const summary = await this.summarize(group);
|
|
801
791
|
const memoryId = await this.consolidatedStore.create({
|
|
802
792
|
summary,
|
|
@@ -812,8 +802,7 @@ var ConsolidationWorker = class {
|
|
|
812
802
|
const consolidatedEventIds = groups.filter((g) => g.events.length >= 3).flatMap((g) => g.events.map((e) => e.id));
|
|
813
803
|
const oldEventIds = consolidatedEventIds.filter((id) => {
|
|
814
804
|
const event = workingSet.recentEvents.find((e) => e.id === id);
|
|
815
|
-
if (!event)
|
|
816
|
-
return false;
|
|
805
|
+
if (!event) return false;
|
|
817
806
|
const ageHours = (Date.now() - event.timestamp.getTime()) / (1e3 * 60 * 60);
|
|
818
807
|
return ageHours > this.config.workingSet.timeWindowHours / 2;
|
|
819
808
|
});
|
|
@@ -828,18 +817,13 @@ var ConsolidationWorker = class {
|
|
|
828
817
|
let promoted = 0;
|
|
829
818
|
for (const memoryId of memoryIds) {
|
|
830
819
|
const memory = await this.consolidatedStore.get(memoryId);
|
|
831
|
-
if (!memory)
|
|
832
|
-
|
|
833
|
-
if (memory.
|
|
834
|
-
continue;
|
|
835
|
-
if (memory.sourceEvents.length < 4)
|
|
836
|
-
continue;
|
|
820
|
+
if (!memory) continue;
|
|
821
|
+
if (memory.confidence < 0.55) continue;
|
|
822
|
+
if (memory.sourceEvents.length < 4) continue;
|
|
837
823
|
const exists = await this.consolidatedStore.hasRuleForSourceMemory(memoryId);
|
|
838
|
-
if (exists)
|
|
839
|
-
continue;
|
|
824
|
+
if (exists) continue;
|
|
840
825
|
const rule = this.buildRuleFromSummary(memory.summary, memory.topics);
|
|
841
|
-
if (!rule)
|
|
842
|
-
continue;
|
|
826
|
+
if (!rule) continue;
|
|
843
827
|
await this.consolidatedStore.createRule({
|
|
844
828
|
rule,
|
|
845
829
|
topics: memory.topics,
|
|
@@ -855,8 +839,7 @@ var ConsolidationWorker = class {
|
|
|
855
839
|
const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).filter((l) => !l.toLowerCase().startsWith("topics:"));
|
|
856
840
|
const bullet = lines.find((l) => l.startsWith("- "))?.replace(/^-\s*/, "");
|
|
857
841
|
const seed = bullet || lines[0];
|
|
858
|
-
if (!seed || seed.length < 8)
|
|
859
|
-
return null;
|
|
842
|
+
if (!seed || seed.length < 8) return null;
|
|
860
843
|
const topicPrefix = topics.length > 0 ? `[${topics.slice(0, 2).join(", ")}] ` : "";
|
|
861
844
|
return `${topicPrefix}${seed}`;
|
|
862
845
|
}
|
|
@@ -1017,8 +1000,7 @@ var ConsolidationWorker = class {
|
|
|
1017
1000
|
*/
|
|
1018
1001
|
extractKeyPoint(content) {
|
|
1019
1002
|
const sentences = content.split(/[.!?\n]+/).filter((s) => s.trim().length > 10);
|
|
1020
|
-
if (sentences.length === 0)
|
|
1021
|
-
return null;
|
|
1003
|
+
if (sentences.length === 0) return null;
|
|
1022
1004
|
const firstSentence = sentences[0].trim();
|
|
1023
1005
|
if (firstSentence.length > 100) {
|
|
1024
1006
|
return firstSentence.slice(0, 100) + "...";
|
|
@@ -1038,8 +1020,7 @@ var ConsolidationWorker = class {
|
|
|
1038
1020
|
* Calculate time proximity score
|
|
1039
1021
|
*/
|
|
1040
1022
|
calculateTimeProximity(events) {
|
|
1041
|
-
if (events.length < 2)
|
|
1042
|
-
return 1;
|
|
1023
|
+
if (events.length < 2) return 1;
|
|
1043
1024
|
const timestamps = events.map((e) => e.timestamp.getTime()).sort((a, b) => a - b);
|
|
1044
1025
|
const timeSpan = timestamps[timestamps.length - 1] - timestamps[0];
|
|
1045
1026
|
const avgGap = timeSpan / (events.length - 1);
|
|
@@ -1058,6 +1039,8 @@ var ContinuityManager = class {
|
|
|
1058
1039
|
this.eventStore = eventStore;
|
|
1059
1040
|
this.config = config;
|
|
1060
1041
|
}
|
|
1042
|
+
eventStore;
|
|
1043
|
+
config;
|
|
1061
1044
|
lastContext = null;
|
|
1062
1045
|
get db() {
|
|
1063
1046
|
return this.eventStore.getDatabase();
|
|
@@ -1177,8 +1160,7 @@ var ContinuityManager = class {
|
|
|
1177
1160
|
* Calculate overlap between two arrays
|
|
1178
1161
|
*/
|
|
1179
1162
|
calculateOverlap(a, b) {
|
|
1180
|
-
if (a.length === 0 || b.length === 0)
|
|
1181
|
-
return 0;
|
|
1163
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
1182
1164
|
const setA = new Set(a.map((s) => s.toLowerCase()));
|
|
1183
1165
|
const setB = new Set(b.map((s) => s.toLowerCase()));
|
|
1184
1166
|
const intersection = [...setA].filter((x) => setB.has(x));
|
|
@@ -1351,6 +1333,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1351
1333
|
this.options = options;
|
|
1352
1334
|
this.factories = options.factories ? { ...options.factories, randomUUID: options.factories.randomUUID ?? randomUUID4 } : defaultFactories;
|
|
1353
1335
|
}
|
|
1336
|
+
options;
|
|
1354
1337
|
factories;
|
|
1355
1338
|
workingSetStore = null;
|
|
1356
1339
|
consolidatedStore = null;
|
|
@@ -1365,8 +1348,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1365
1348
|
}
|
|
1366
1349
|
}
|
|
1367
1350
|
async initializeEndlessMode() {
|
|
1368
|
-
if (this.consolidationWorker)
|
|
1369
|
-
return;
|
|
1351
|
+
if (this.consolidationWorker) return;
|
|
1370
1352
|
const config = await this.getEndlessConfig();
|
|
1371
1353
|
const workingSetStore = this.factories.createWorkingSetStore(this.options.eventStore, config);
|
|
1372
1354
|
const consolidatedStore = this.factories.createConsolidatedStore(this.options.eventStore);
|
|
@@ -1398,8 +1380,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1398
1380
|
}
|
|
1399
1381
|
async setMode(mode) {
|
|
1400
1382
|
await this.options.initialize();
|
|
1401
|
-
if (mode === this.mode)
|
|
1402
|
-
return;
|
|
1383
|
+
if (mode === this.mode) return;
|
|
1403
1384
|
this.mode = mode;
|
|
1404
1385
|
await this.options.configStore.setEndlessConfig("mode", mode);
|
|
1405
1386
|
if (mode === "endless") {
|
|
@@ -1415,33 +1396,27 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1415
1396
|
return this.mode === "endless";
|
|
1416
1397
|
}
|
|
1417
1398
|
async addToWorkingSet(eventId, relevanceScore) {
|
|
1418
|
-
if (!this.workingSetStore)
|
|
1419
|
-
return;
|
|
1399
|
+
if (!this.workingSetStore) return;
|
|
1420
1400
|
await this.workingSetStore.add(eventId, relevanceScore);
|
|
1421
1401
|
}
|
|
1422
1402
|
async getWorkingSet() {
|
|
1423
|
-
if (!this.workingSetStore)
|
|
1424
|
-
return null;
|
|
1403
|
+
if (!this.workingSetStore) return null;
|
|
1425
1404
|
return this.workingSetStore.get();
|
|
1426
1405
|
}
|
|
1427
1406
|
async searchConsolidated(query, options) {
|
|
1428
|
-
if (!this.consolidatedStore)
|
|
1429
|
-
return [];
|
|
1407
|
+
if (!this.consolidatedStore) return [];
|
|
1430
1408
|
return this.consolidatedStore.search(query, options);
|
|
1431
1409
|
}
|
|
1432
1410
|
async getConsolidatedMemories(limit) {
|
|
1433
|
-
if (!this.consolidatedStore)
|
|
1434
|
-
return [];
|
|
1411
|
+
if (!this.consolidatedStore) return [];
|
|
1435
1412
|
return this.consolidatedStore.getAll({ limit });
|
|
1436
1413
|
}
|
|
1437
1414
|
async markMemoryAccessed(memoryId) {
|
|
1438
|
-
if (!this.consolidatedStore)
|
|
1439
|
-
return;
|
|
1415
|
+
if (!this.consolidatedStore) return;
|
|
1440
1416
|
await this.consolidatedStore.markAccessed(memoryId);
|
|
1441
1417
|
}
|
|
1442
1418
|
async calculateContinuity(content, metadata) {
|
|
1443
|
-
if (!this.continuityManager)
|
|
1444
|
-
return null;
|
|
1419
|
+
if (!this.continuityManager) return null;
|
|
1445
1420
|
const snapshot = this.continuityManager.createSnapshot(
|
|
1446
1421
|
this.factories.randomUUID(),
|
|
1447
1422
|
content,
|
|
@@ -1453,8 +1428,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1453
1428
|
this.consolidationWorker?.recordActivity();
|
|
1454
1429
|
}
|
|
1455
1430
|
async forceConsolidation() {
|
|
1456
|
-
if (!this.consolidationWorker)
|
|
1457
|
-
return 0;
|
|
1431
|
+
if (!this.consolidationWorker) return 0;
|
|
1458
1432
|
return this.consolidationWorker.forceRun();
|
|
1459
1433
|
}
|
|
1460
1434
|
async getEndlessModeStatus() {
|
|
@@ -1546,8 +1520,7 @@ var Embedder = class _Embedder {
|
|
|
1546
1520
|
* Initialize the embedding pipeline
|
|
1547
1521
|
*/
|
|
1548
1522
|
async initialize() {
|
|
1549
|
-
if (this.initialized)
|
|
1550
|
-
return;
|
|
1523
|
+
if (this.initialized) return;
|
|
1551
1524
|
const pipeline = await withSuppressedKnownTransformersWarnings(async () => {
|
|
1552
1525
|
try {
|
|
1553
1526
|
return await loadTransformersPipeline();
|
|
@@ -1664,8 +1637,7 @@ async function withSuppressedKnownTransformersWarnings(fn) {
|
|
|
1664
1637
|
originalConsoleWarn = console.warn;
|
|
1665
1638
|
console.warn = (...args) => {
|
|
1666
1639
|
const message = args.map(String).join(" ");
|
|
1667
|
-
if (isKnownBenignTransformersWarning(message))
|
|
1668
|
-
return;
|
|
1640
|
+
if (isKnownBenignTransformersWarning(message)) return;
|
|
1669
1641
|
(originalConsoleWarn ?? console.warn)(...args);
|
|
1670
1642
|
};
|
|
1671
1643
|
}
|
|
@@ -1947,8 +1919,7 @@ var GraduationPipeline = class {
|
|
|
1947
1919
|
const preferenceKeywords = ["prefer", "like", "want", "always", "never", "favorite"];
|
|
1948
1920
|
const preferences = [];
|
|
1949
1921
|
for (const event of events) {
|
|
1950
|
-
if (event.eventType !== "user_prompt")
|
|
1951
|
-
continue;
|
|
1922
|
+
if (event.eventType !== "user_prompt") continue;
|
|
1952
1923
|
const lowerContent = event.content.toLowerCase();
|
|
1953
1924
|
for (const keyword of preferenceKeywords) {
|
|
1954
1925
|
if (lowerContent.includes(keyword)) {
|
|
@@ -2114,11 +2085,9 @@ function sanitizeSegment(input, fallback) {
|
|
|
2114
2085
|
return v || fallback;
|
|
2115
2086
|
}
|
|
2116
2087
|
function getAtPath(obj, dotted) {
|
|
2117
|
-
if (!obj)
|
|
2118
|
-
return void 0;
|
|
2088
|
+
if (!obj) return void 0;
|
|
2119
2089
|
return dotted.split(".").reduce((acc, key) => {
|
|
2120
|
-
if (!acc || typeof acc !== "object")
|
|
2121
|
-
return void 0;
|
|
2090
|
+
if (!acc || typeof acc !== "object") return void 0;
|
|
2122
2091
|
return acc[key];
|
|
2123
2092
|
}, obj);
|
|
2124
2093
|
}
|
|
@@ -2138,6 +2107,7 @@ var MarkdownMirror = class {
|
|
|
2138
2107
|
constructor(rootDir) {
|
|
2139
2108
|
this.rootDir = rootDir;
|
|
2140
2109
|
}
|
|
2110
|
+
rootDir;
|
|
2141
2111
|
async append(event, eventId) {
|
|
2142
2112
|
const out = buildMirrorPath(this.rootDir, event);
|
|
2143
2113
|
fs2.mkdirSync(path2.dirname(out), { recursive: true });
|
|
@@ -2273,10 +2243,8 @@ function sqliteClose(db) {
|
|
|
2273
2243
|
db.close();
|
|
2274
2244
|
}
|
|
2275
2245
|
function toDateFromSQLite(value) {
|
|
2276
|
-
if (value instanceof Date)
|
|
2277
|
-
|
|
2278
|
-
if (typeof value === "number")
|
|
2279
|
-
return new Date(value);
|
|
2246
|
+
if (value instanceof Date) return value;
|
|
2247
|
+
if (typeof value === "number") return new Date(value);
|
|
2280
2248
|
if (typeof value === "string") {
|
|
2281
2249
|
const trimmed = value.trim();
|
|
2282
2250
|
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
|
|
@@ -2298,8 +2266,7 @@ var DEFAULT_CATEGORY = "uncategorized";
|
|
|
2298
2266
|
function sanitizeSegment2(input, fallback) {
|
|
2299
2267
|
const raw = String(input ?? "").trim().toLowerCase();
|
|
2300
2268
|
const safe = raw.normalize("NFKD").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2301
|
-
if (!safe || safe === "." || safe === "..")
|
|
2302
|
-
return fallback;
|
|
2269
|
+
if (!safe || safe === "." || safe === "..") return fallback;
|
|
2303
2270
|
return safe;
|
|
2304
2271
|
}
|
|
2305
2272
|
function getCategorySegments(metadata, eventType) {
|
|
@@ -2340,6 +2307,7 @@ var MarkdownMirror2 = class {
|
|
|
2340
2307
|
constructor(rootDir) {
|
|
2341
2308
|
this.rootDir = rootDir;
|
|
2342
2309
|
}
|
|
2310
|
+
rootDir;
|
|
2343
2311
|
async append(event) {
|
|
2344
2312
|
const outPath = buildMirrorPath2(this.rootDir, event);
|
|
2345
2313
|
await fs5.mkdir(path4.dirname(outPath), { recursive: true });
|
|
@@ -2362,6 +2330,7 @@ var VectorOutbox = class {
|
|
|
2362
2330
|
this.db = db;
|
|
2363
2331
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
2364
2332
|
}
|
|
2333
|
+
db;
|
|
2365
2334
|
config;
|
|
2366
2335
|
/**
|
|
2367
2336
|
* Enqueue item for vectorization (idempotent).
|
|
@@ -2458,8 +2427,7 @@ var VectorOutbox = class {
|
|
|
2458
2427
|
`SELECT retry_count FROM vector_outbox WHERE job_id = ?`,
|
|
2459
2428
|
[jobId]
|
|
2460
2429
|
);
|
|
2461
|
-
if (rows.length === 0)
|
|
2462
|
-
return;
|
|
2430
|
+
if (rows.length === 0) return;
|
|
2463
2431
|
const retryCount = rows[0].retry_count;
|
|
2464
2432
|
const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
|
|
2465
2433
|
await dbRun(
|
|
@@ -2479,8 +2447,7 @@ var VectorOutbox = class {
|
|
|
2479
2447
|
`SELECT * FROM vector_outbox WHERE job_id = ?`,
|
|
2480
2448
|
[jobId]
|
|
2481
2449
|
);
|
|
2482
|
-
if (rows.length === 0)
|
|
2483
|
-
return null;
|
|
2450
|
+
if (rows.length === 0) return null;
|
|
2484
2451
|
return this.rowToJob(rows[0]);
|
|
2485
2452
|
}
|
|
2486
2453
|
/**
|
|
@@ -2614,30 +2581,24 @@ function isRetrievalDebugLaneName(value) {
|
|
|
2614
2581
|
return typeof value === "string" && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);
|
|
2615
2582
|
}
|
|
2616
2583
|
function normalizeRetrievalDebugLanes(value, maxItems = 6) {
|
|
2617
|
-
if (!Array.isArray(value) || maxItems <= 0)
|
|
2618
|
-
return [];
|
|
2584
|
+
if (!Array.isArray(value) || maxItems <= 0) return [];
|
|
2619
2585
|
const normalized = [];
|
|
2620
2586
|
const seen = /* @__PURE__ */ new Set();
|
|
2621
2587
|
for (const item of value) {
|
|
2622
2588
|
const lane = normalizeRetrievalDebugLane(item);
|
|
2623
|
-
if (!lane)
|
|
2624
|
-
continue;
|
|
2589
|
+
if (!lane) continue;
|
|
2625
2590
|
const key = [lane.lane, lane.reason, lane.score ?? ""].join("\0");
|
|
2626
|
-
if (seen.has(key))
|
|
2627
|
-
continue;
|
|
2591
|
+
if (seen.has(key)) continue;
|
|
2628
2592
|
seen.add(key);
|
|
2629
2593
|
normalized.push(lane);
|
|
2630
|
-
if (normalized.length >= maxItems)
|
|
2631
|
-
break;
|
|
2594
|
+
if (normalized.length >= maxItems) break;
|
|
2632
2595
|
}
|
|
2633
2596
|
return normalized;
|
|
2634
2597
|
}
|
|
2635
2598
|
function normalizeRetrievalDebugLane(value) {
|
|
2636
|
-
if (!value || typeof value !== "object")
|
|
2637
|
-
return null;
|
|
2599
|
+
if (!value || typeof value !== "object") return null;
|
|
2638
2600
|
const raw = value;
|
|
2639
|
-
if (!isRetrievalDebugLaneName(raw.lane))
|
|
2640
|
-
return null;
|
|
2601
|
+
if (!isRetrievalDebugLaneName(raw.lane)) return null;
|
|
2641
2602
|
const reason = sanitizeRetrievalLaneReason(typeof raw.reason === "string" ? raw.reason : "") || "unspecified";
|
|
2642
2603
|
const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? Math.max(0, Math.min(1, raw.score)) : void 0;
|
|
2643
2604
|
return score === void 0 ? { lane: raw.lane, reason } : { lane: raw.lane, reason, score };
|
|
@@ -2660,27 +2621,21 @@ function normalizeRetrievalTraceDetails(details) {
|
|
|
2660
2621
|
eventId: detail.eventId,
|
|
2661
2622
|
score: detail.score
|
|
2662
2623
|
};
|
|
2663
|
-
if (detail.semanticScore !== void 0)
|
|
2664
|
-
|
|
2665
|
-
if (detail.
|
|
2666
|
-
|
|
2667
|
-
if (detail.recencyScore !== void 0)
|
|
2668
|
-
normalized.recencyScore = detail.recencyScore;
|
|
2669
|
-
if (lanes.length > 0)
|
|
2670
|
-
normalized.lanes = lanes;
|
|
2624
|
+
if (detail.semanticScore !== void 0) normalized.semanticScore = detail.semanticScore;
|
|
2625
|
+
if (detail.lexicalScore !== void 0) normalized.lexicalScore = detail.lexicalScore;
|
|
2626
|
+
if (detail.recencyScore !== void 0) normalized.recencyScore = detail.recencyScore;
|
|
2627
|
+
if (lanes.length > 0) normalized.lanes = lanes;
|
|
2671
2628
|
return normalized;
|
|
2672
2629
|
});
|
|
2673
2630
|
}
|
|
2674
2631
|
function parseRetrievalTraceDetails(value) {
|
|
2675
|
-
if (typeof value !== "string" || value.length === 0)
|
|
2676
|
-
return [];
|
|
2632
|
+
if (typeof value !== "string" || value.length === 0) return [];
|
|
2677
2633
|
const parsed = JSON.parse(value);
|
|
2678
2634
|
return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed) : [];
|
|
2679
2635
|
}
|
|
2680
2636
|
function normalizeQueryRewriteKind(value) {
|
|
2681
2637
|
const normalized = (value || "").trim().toLowerCase();
|
|
2682
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
2683
|
-
return normalized;
|
|
2638
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
2684
2639
|
return "none";
|
|
2685
2640
|
}
|
|
2686
2641
|
var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
|
|
@@ -2698,8 +2653,7 @@ function isRecord(value) {
|
|
|
2698
2653
|
function getNestedRecord(root, path13) {
|
|
2699
2654
|
let cursor = root;
|
|
2700
2655
|
for (const key of path13) {
|
|
2701
|
-
if (!isRecord(cursor))
|
|
2702
|
-
return void 0;
|
|
2656
|
+
if (!isRecord(cursor)) return void 0;
|
|
2703
2657
|
cursor = cursor[key];
|
|
2704
2658
|
}
|
|
2705
2659
|
return isRecord(cursor) ? cursor : void 0;
|
|
@@ -2707,8 +2661,7 @@ function getNestedRecord(root, path13) {
|
|
|
2707
2661
|
function getNestedString(root, path13) {
|
|
2708
2662
|
let cursor = root;
|
|
2709
2663
|
for (const key of path13) {
|
|
2710
|
-
if (!isRecord(cursor))
|
|
2711
|
-
return void 0;
|
|
2664
|
+
if (!isRecord(cursor)) return void 0;
|
|
2712
2665
|
cursor = cursor[key];
|
|
2713
2666
|
}
|
|
2714
2667
|
return typeof cursor === "string" && cursor.length > 0 ? cursor : void 0;
|
|
@@ -2724,8 +2677,7 @@ function metadataProjectPaths(metadata) {
|
|
|
2724
2677
|
];
|
|
2725
2678
|
const paths = [];
|
|
2726
2679
|
for (const value of candidates) {
|
|
2727
|
-
if (value && !paths.includes(value))
|
|
2728
|
-
paths.push(value);
|
|
2680
|
+
if (value && !paths.includes(value)) paths.push(value);
|
|
2729
2681
|
}
|
|
2730
2682
|
return paths;
|
|
2731
2683
|
}
|
|
@@ -2746,12 +2698,9 @@ function maybeQuarantinePredicate(options, column = "metadata") {
|
|
|
2746
2698
|
return options?.includeQuarantined ? "1=1" : notActiveQuarantinedSql(column);
|
|
2747
2699
|
}
|
|
2748
2700
|
function safeParseMetadataValue(value) {
|
|
2749
|
-
if (!value)
|
|
2750
|
-
|
|
2751
|
-
if (typeof value
|
|
2752
|
-
return isRecord(value) ? value : void 0;
|
|
2753
|
-
if (typeof value !== "string")
|
|
2754
|
-
return void 0;
|
|
2701
|
+
if (!value) return void 0;
|
|
2702
|
+
if (typeof value === "object") return isRecord(value) ? value : void 0;
|
|
2703
|
+
if (typeof value !== "string") return void 0;
|
|
2755
2704
|
try {
|
|
2756
2705
|
const parsed = JSON.parse(value);
|
|
2757
2706
|
return isRecord(parsed) ? parsed : void 0;
|
|
@@ -2760,16 +2709,14 @@ function safeParseMetadataValue(value) {
|
|
|
2760
2709
|
}
|
|
2761
2710
|
}
|
|
2762
2711
|
function isImportedOrLegacyScopedMetadata(metadata) {
|
|
2763
|
-
if (!metadata)
|
|
2764
|
-
return false;
|
|
2712
|
+
if (!metadata) return false;
|
|
2765
2713
|
return Boolean(
|
|
2766
2714
|
metadata.importedFrom || metadata.sourceSessionId || metadata.sourceSessionHash || metadata.hermesSource || metadata.projectPath || metadata.sourceProjectPath || metadata.source === "hermes" || metadata.source === "claude" || metadata.source === "codex"
|
|
2767
2715
|
);
|
|
2768
2716
|
}
|
|
2769
2717
|
function addMetadataTag(metadata, tag) {
|
|
2770
2718
|
const current = Array.isArray(metadata.tags) ? metadata.tags.filter((value) => typeof value === "string") : [];
|
|
2771
|
-
if (!current.includes(tag))
|
|
2772
|
-
metadata.tags = [...current, tag];
|
|
2719
|
+
if (!current.includes(tag)) metadata.tags = [...current, tag];
|
|
2773
2720
|
}
|
|
2774
2721
|
function buildRepairResult(projectHash, dryRun) {
|
|
2775
2722
|
return {
|
|
@@ -2787,8 +2734,7 @@ function normalizeRepoName(value) {
|
|
|
2787
2734
|
return value.replace(/\.git$/i, "").trim().toLowerCase();
|
|
2788
2735
|
}
|
|
2789
2736
|
function projectBasename(projectPath) {
|
|
2790
|
-
if (!projectPath)
|
|
2791
|
-
return void 0;
|
|
2737
|
+
if (!projectPath) return void 0;
|
|
2792
2738
|
const trimmed = projectPath.replace(/[\\/]+$/, "");
|
|
2793
2739
|
const basename3 = nodePath2.basename(trimmed);
|
|
2794
2740
|
return basename3 ? normalizeRepoName(basename3) : void 0;
|
|
@@ -2801,23 +2747,19 @@ function isProjectScopeRepairExplanation(content) {
|
|
|
2801
2747
|
}
|
|
2802
2748
|
function hasConflictingContentProjectHint(content, projectPath) {
|
|
2803
2749
|
const currentName = projectBasename(projectPath);
|
|
2804
|
-
if (!currentName)
|
|
2805
|
-
|
|
2806
|
-
if (isProjectScopeRepairExplanation(content))
|
|
2807
|
-
return false;
|
|
2750
|
+
if (!currentName) return false;
|
|
2751
|
+
if (isProjectScopeRepairExplanation(content)) return false;
|
|
2808
2752
|
const githubRepoPattern = /github\.com[:/]([^/\s`'"#)]+)\/([^/\s`'"#)]+)(?:\.git)?/gi;
|
|
2809
2753
|
let githubMatch;
|
|
2810
2754
|
while ((githubMatch = githubRepoPattern.exec(content)) !== null) {
|
|
2811
2755
|
const repo = normalizeRepoName(githubMatch[2] || "");
|
|
2812
|
-
if (repo && repo !== currentName)
|
|
2813
|
-
return true;
|
|
2756
|
+
if (repo && repo !== currentName) return true;
|
|
2814
2757
|
}
|
|
2815
2758
|
const workspacePathPattern = /\/workspace\/([^/\s`'"#)]+)/gi;
|
|
2816
2759
|
let workspaceMatch;
|
|
2817
2760
|
while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {
|
|
2818
2761
|
const repo = normalizeRepoName(workspaceMatch[1] || "");
|
|
2819
|
-
if (repo && repo !== currentName)
|
|
2820
|
-
return true;
|
|
2762
|
+
if (repo && repo !== currentName) return true;
|
|
2821
2763
|
}
|
|
2822
2764
|
return false;
|
|
2823
2765
|
}
|
|
@@ -2837,15 +2779,12 @@ var SQLiteEventStore = class {
|
|
|
2837
2779
|
this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);
|
|
2838
2780
|
}
|
|
2839
2781
|
createVectorOutbox(option) {
|
|
2840
|
-
if (this.readOnly || option === false)
|
|
2841
|
-
|
|
2842
|
-
if (option instanceof VectorOutbox)
|
|
2843
|
-
return option;
|
|
2782
|
+
if (this.readOnly || option === false) return null;
|
|
2783
|
+
if (option instanceof VectorOutbox) return option;
|
|
2844
2784
|
return new VectorOutbox(this.db, option ?? {});
|
|
2845
2785
|
}
|
|
2846
2786
|
enqueueVectorOutboxEventSync(eventId) {
|
|
2847
|
-
if (!this.vectorOutbox)
|
|
2848
|
-
return;
|
|
2787
|
+
if (!this.vectorOutbox) return;
|
|
2849
2788
|
this.vectorOutbox.enqueueSync("event", eventId);
|
|
2850
2789
|
}
|
|
2851
2790
|
async enqueueVectorOutboxEvent(eventId) {
|
|
@@ -2855,8 +2794,7 @@ var SQLiteEventStore = class {
|
|
|
2855
2794
|
* Initialize database schema
|
|
2856
2795
|
*/
|
|
2857
2796
|
async initialize() {
|
|
2858
|
-
if (this.initialized)
|
|
2859
|
-
return;
|
|
2797
|
+
if (this.initialized) return;
|
|
2860
2798
|
if (this.readOnly) {
|
|
2861
2799
|
this.initialized = true;
|
|
2862
2800
|
return;
|
|
@@ -3414,10 +3352,8 @@ var SQLiteEventStore = class {
|
|
|
3414
3352
|
try {
|
|
3415
3353
|
const edgeIndexes = sqliteAll(this.db, `PRAGMA index_list(memory_action_edges)`, []);
|
|
3416
3354
|
const hasSourceAwareUnique = edgeIndexes.some((index) => {
|
|
3417
|
-
if (Number(index.unique) !== 1)
|
|
3418
|
-
|
|
3419
|
-
if (!/^[A-Za-z0-9_]+$/.test(index.name))
|
|
3420
|
-
return false;
|
|
3355
|
+
if (Number(index.unique) !== 1) return false;
|
|
3356
|
+
if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;
|
|
3421
3357
|
const escapedName = index.name.replace(/"/g, '""');
|
|
3422
3358
|
const columns = sqliteAll(this.db, 'PRAGMA index_info("' + escapedName + '")', []).map((column) => column.name);
|
|
3423
3359
|
return columns.length === 5 && columns[0] === "src_action_id" && columns[1] === "rel_type" && columns[2] === "dst_type" && columns[3] === "dst_id" && columns[4] === "source";
|
|
@@ -3657,8 +3593,7 @@ var SQLiteEventStore = class {
|
|
|
3657
3593
|
`SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,
|
|
3658
3594
|
[id]
|
|
3659
3595
|
);
|
|
3660
|
-
if (!row)
|
|
3661
|
-
return null;
|
|
3596
|
+
if (!row) return null;
|
|
3662
3597
|
return this.rowToEvent(row);
|
|
3663
3598
|
}
|
|
3664
3599
|
/**
|
|
@@ -3696,10 +3631,8 @@ var SQLiteEventStore = class {
|
|
|
3696
3631
|
* NOTE: This bypasses the append() id generation to preserve stable IDs.
|
|
3697
3632
|
*/
|
|
3698
3633
|
async importEvents(events) {
|
|
3699
|
-
if (events.length === 0)
|
|
3700
|
-
|
|
3701
|
-
if (this.readOnly)
|
|
3702
|
-
return { inserted: 0, skipped: events.length };
|
|
3634
|
+
if (events.length === 0) return { inserted: 0, skipped: 0 };
|
|
3635
|
+
if (this.readOnly) return { inserted: 0, skipped: events.length };
|
|
3703
3636
|
await this.initialize();
|
|
3704
3637
|
const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);
|
|
3705
3638
|
const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);
|
|
@@ -3817,8 +3750,7 @@ var SQLiteEventStore = class {
|
|
|
3817
3750
|
`SELECT * FROM sessions WHERE id = ?`,
|
|
3818
3751
|
[id]
|
|
3819
3752
|
);
|
|
3820
|
-
if (!row)
|
|
3821
|
-
return null;
|
|
3753
|
+
if (!row) return null;
|
|
3822
3754
|
return {
|
|
3823
3755
|
id: row.id,
|
|
3824
3756
|
startedAt: toDateFromSQLite(row.started_at),
|
|
@@ -3873,8 +3805,7 @@ var SQLiteEventStore = class {
|
|
|
3873
3805
|
LIMIT ?`,
|
|
3874
3806
|
[limit]
|
|
3875
3807
|
);
|
|
3876
|
-
if (pending.length === 0)
|
|
3877
|
-
return [];
|
|
3808
|
+
if (pending.length === 0) return [];
|
|
3878
3809
|
const ids = pending.map((r) => r.id);
|
|
3879
3810
|
const placeholders = ids.map(() => "?").join(",");
|
|
3880
3811
|
sqliteRun(
|
|
@@ -3898,8 +3829,7 @@ var SQLiteEventStore = class {
|
|
|
3898
3829
|
* Mark outbox items as done
|
|
3899
3830
|
*/
|
|
3900
3831
|
async completeOutboxItems(ids) {
|
|
3901
|
-
if (ids.length === 0)
|
|
3902
|
-
return;
|
|
3832
|
+
if (ids.length === 0) return;
|
|
3903
3833
|
const placeholders = ids.map(() => "?").join(",");
|
|
3904
3834
|
sqliteRun(
|
|
3905
3835
|
this.db,
|
|
@@ -3938,8 +3868,7 @@ var SQLiteEventStore = class {
|
|
|
3938
3868
|
* Mark outbox items as failed
|
|
3939
3869
|
*/
|
|
3940
3870
|
async failOutboxItems(ids, error) {
|
|
3941
|
-
if (ids.length === 0)
|
|
3942
|
-
return;
|
|
3871
|
+
if (ids.length === 0) return;
|
|
3943
3872
|
const placeholders = ids.map(() => "?").join(",");
|
|
3944
3873
|
sqliteRun(
|
|
3945
3874
|
this.db,
|
|
@@ -4066,8 +3995,7 @@ var SQLiteEventStore = class {
|
|
|
4066
3995
|
[]
|
|
4067
3996
|
);
|
|
4068
3997
|
const sample = (entry) => {
|
|
4069
|
-
if (result.samples.length < 20)
|
|
4070
|
-
result.samples.push(entry);
|
|
3998
|
+
if (result.samples.length < 20) result.samples.push(entry);
|
|
4071
3999
|
};
|
|
4072
4000
|
for (const row of rows) {
|
|
4073
4001
|
result.scanned++;
|
|
@@ -4194,12 +4122,10 @@ var SQLiteEventStore = class {
|
|
|
4194
4122
|
`SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`
|
|
4195
4123
|
);
|
|
4196
4124
|
const processingAgeMs = (value) => {
|
|
4197
|
-
if (value === null || value === void 0)
|
|
4198
|
-
return null;
|
|
4125
|
+
if (value === null || value === void 0) return null;
|
|
4199
4126
|
const date = toDateFromSQLite(value);
|
|
4200
4127
|
const time = date.getTime();
|
|
4201
|
-
if (!Number.isFinite(time))
|
|
4202
|
-
return null;
|
|
4128
|
+
if (!Number.isFinite(time)) return null;
|
|
4203
4129
|
return Math.max(0, now.getTime() - time);
|
|
4204
4130
|
};
|
|
4205
4131
|
const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs) => {
|
|
@@ -4348,8 +4274,7 @@ var SQLiteEventStore = class {
|
|
|
4348
4274
|
`SELECT value FROM endless_config WHERE key = ?`,
|
|
4349
4275
|
[key]
|
|
4350
4276
|
);
|
|
4351
|
-
if (!row)
|
|
4352
|
-
return null;
|
|
4277
|
+
if (!row) return null;
|
|
4353
4278
|
return JSON.parse(row.value);
|
|
4354
4279
|
}
|
|
4355
4280
|
/**
|
|
@@ -4368,8 +4293,7 @@ var SQLiteEventStore = class {
|
|
|
4368
4293
|
* Increment access count for events
|
|
4369
4294
|
*/
|
|
4370
4295
|
async incrementAccessCount(eventIds) {
|
|
4371
|
-
if (eventIds.length === 0 || this.readOnly)
|
|
4372
|
-
return;
|
|
4296
|
+
if (eventIds.length === 0 || this.readOnly) return;
|
|
4373
4297
|
await this.initialize();
|
|
4374
4298
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4375
4299
|
const currentTime = toSQLiteTimestamp(/* @__PURE__ */ new Date());
|
|
@@ -4412,8 +4336,7 @@ var SQLiteEventStore = class {
|
|
|
4412
4336
|
* Record a memory retrieval for helpfulness tracking
|
|
4413
4337
|
*/
|
|
4414
4338
|
async recordRetrieval(eventId, sessionId, score, query) {
|
|
4415
|
-
if (this.readOnly)
|
|
4416
|
-
return;
|
|
4339
|
+
if (this.readOnly) return;
|
|
4417
4340
|
await this.initialize();
|
|
4418
4341
|
const id = randomUUID6();
|
|
4419
4342
|
sqliteRun(
|
|
@@ -4443,16 +4366,14 @@ var SQLiteEventStore = class {
|
|
|
4443
4366
|
* Called at session end - uses behavioral signals to compute score
|
|
4444
4367
|
*/
|
|
4445
4368
|
async evaluateSessionHelpfulness(sessionId) {
|
|
4446
|
-
if (this.readOnly)
|
|
4447
|
-
return;
|
|
4369
|
+
if (this.readOnly) return;
|
|
4448
4370
|
await this.initialize();
|
|
4449
4371
|
const retrievals = sqliteAll(
|
|
4450
4372
|
this.db,
|
|
4451
4373
|
`SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,
|
|
4452
4374
|
[sessionId]
|
|
4453
4375
|
);
|
|
4454
|
-
if (retrievals.length === 0)
|
|
4455
|
-
return;
|
|
4376
|
+
if (retrievals.length === 0) return;
|
|
4456
4377
|
const sessionEvents = sqliteAll(
|
|
4457
4378
|
this.db,
|
|
4458
4379
|
`SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
|
|
@@ -4465,8 +4386,7 @@ var SQLiteEventStore = class {
|
|
|
4465
4386
|
for (const t of toolEvents) {
|
|
4466
4387
|
try {
|
|
4467
4388
|
const content = JSON.parse(t.content);
|
|
4468
|
-
if (content.success !== false)
|
|
4469
|
-
toolSuccessCount++;
|
|
4389
|
+
if (content.success !== false) toolSuccessCount++;
|
|
4470
4390
|
} catch {
|
|
4471
4391
|
toolSuccessCount++;
|
|
4472
4392
|
}
|
|
@@ -4484,8 +4404,7 @@ var SQLiteEventStore = class {
|
|
|
4484
4404
|
const pWords = new Set(p.content.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
4485
4405
|
let overlap = 0;
|
|
4486
4406
|
for (const w of queryWords) {
|
|
4487
|
-
if (pWords.has(w))
|
|
4488
|
-
overlap++;
|
|
4407
|
+
if (pWords.has(w)) overlap++;
|
|
4489
4408
|
}
|
|
4490
4409
|
if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {
|
|
4491
4410
|
wasReasked = 1;
|
|
@@ -4667,8 +4586,7 @@ var SQLiteEventStore = class {
|
|
|
4667
4586
|
return this.db;
|
|
4668
4587
|
}
|
|
4669
4588
|
hasTableColumn(tableName, columnName2) {
|
|
4670
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName))
|
|
4671
|
-
return false;
|
|
4589
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;
|
|
4672
4590
|
try {
|
|
4673
4591
|
const rows = sqliteAll(this.db, `PRAGMA table_info("${tableName}")`, []);
|
|
4674
4592
|
return rows.some((row) => row.name === columnName2);
|
|
@@ -4735,8 +4653,7 @@ var SQLiteEventStore = class {
|
|
|
4735
4653
|
createdAt: toDateFromSQLite(row.created_at)
|
|
4736
4654
|
}));
|
|
4737
4655
|
} catch (err) {
|
|
4738
|
-
if (err?.message?.includes("no such table"))
|
|
4739
|
-
return [];
|
|
4656
|
+
if (err?.message?.includes("no such table")) return [];
|
|
4740
4657
|
throw err;
|
|
4741
4658
|
}
|
|
4742
4659
|
}
|
|
@@ -4909,8 +4826,7 @@ var SQLiteEventStore = class {
|
|
|
4909
4826
|
`SELECT id FROM events WHERE session_id = ?`,
|
|
4910
4827
|
[sessionId]
|
|
4911
4828
|
);
|
|
4912
|
-
if (events.length === 0)
|
|
4913
|
-
return 0;
|
|
4829
|
+
if (events.length === 0) return 0;
|
|
4914
4830
|
const eventIds = events.map((e) => e.id);
|
|
4915
4831
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4916
4832
|
const ftsTriggersDropped = [];
|
|
@@ -5122,8 +5038,7 @@ function sanitizeGovernanceAuditValue(value, key) {
|
|
|
5122
5038
|
return value;
|
|
5123
5039
|
}
|
|
5124
5040
|
function sanitizeAuditJson(value) {
|
|
5125
|
-
if (value === void 0)
|
|
5126
|
-
return void 0;
|
|
5041
|
+
if (value === void 0) return void 0;
|
|
5127
5042
|
return sanitizeGovernanceAuditValue(value);
|
|
5128
5043
|
}
|
|
5129
5044
|
function normalizeSourceEventIds(sourceEventIds) {
|
|
@@ -5172,12 +5087,10 @@ async function writeGovernanceAuditEntry(db, input) {
|
|
|
5172
5087
|
|
|
5173
5088
|
// src/core/operations/facet-repository.ts
|
|
5174
5089
|
function parseStringArray(value) {
|
|
5175
|
-
if (typeof value !== "string")
|
|
5176
|
-
return [];
|
|
5090
|
+
if (typeof value !== "string") return [];
|
|
5177
5091
|
try {
|
|
5178
5092
|
const parsed = JSON.parse(value);
|
|
5179
|
-
if (!Array.isArray(parsed))
|
|
5180
|
-
return [];
|
|
5093
|
+
if (!Array.isArray(parsed)) return [];
|
|
5181
5094
|
return parsed.filter((item) => typeof item === "string" && item.length > 0);
|
|
5182
5095
|
} catch {
|
|
5183
5096
|
return [];
|
|
@@ -5221,6 +5134,7 @@ var FacetRepository = class {
|
|
|
5221
5134
|
constructor(db) {
|
|
5222
5135
|
this.db = db;
|
|
5223
5136
|
}
|
|
5137
|
+
db;
|
|
5224
5138
|
async assign(input) {
|
|
5225
5139
|
const assignment = parseFacetAssignmentInput(input);
|
|
5226
5140
|
const existing = this.findByUniqueKey(assignment);
|
|
@@ -5525,19 +5439,14 @@ var RetentionFacetSchema = z5.object({
|
|
|
5525
5439
|
confidence: z5.number().min(0).max(1).default(1)
|
|
5526
5440
|
});
|
|
5527
5441
|
var DateLikeSchema = z5.preprocess((value) => {
|
|
5528
|
-
if (value instanceof Date)
|
|
5529
|
-
|
|
5530
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5531
|
-
return new Date(value);
|
|
5442
|
+
if (value instanceof Date) return value;
|
|
5443
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5532
5444
|
return value;
|
|
5533
5445
|
}, z5.date());
|
|
5534
5446
|
var NullableDateLikeSchema = z5.preprocess((value) => {
|
|
5535
|
-
if (value === null || value === void 0 || value === "")
|
|
5536
|
-
|
|
5537
|
-
if (value
|
|
5538
|
-
return value;
|
|
5539
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5540
|
-
return new Date(value);
|
|
5447
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
5448
|
+
if (value instanceof Date) return value;
|
|
5449
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5541
5450
|
return value;
|
|
5542
5451
|
}, z5.date().nullable());
|
|
5543
5452
|
var OptionalTrimmedStringSchema2 = z5.preprocess(
|
|
@@ -5566,10 +5475,8 @@ import { z as z6 } from "zod";
|
|
|
5566
5475
|
var RequiredTrimmedStringSchema = z6.string().trim().min(1);
|
|
5567
5476
|
var OptionalTrimmedStringSchema3 = z6.string().trim().min(1).optional();
|
|
5568
5477
|
var DateLikeSchema2 = z6.preprocess((value) => {
|
|
5569
|
-
if (value instanceof Date)
|
|
5570
|
-
|
|
5571
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5572
|
-
return new Date(value);
|
|
5478
|
+
if (value instanceof Date) return value;
|
|
5479
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5573
5480
|
return value;
|
|
5574
5481
|
}, z6.date());
|
|
5575
5482
|
var RetentionReasonSchema = z6.object({
|
|
@@ -5758,8 +5665,7 @@ var MemoryOperationsConfigSchema = z7.object({
|
|
|
5758
5665
|
}).default({});
|
|
5759
5666
|
var MemoryLessonNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5760
5667
|
var MemoryLessonStringArraySchema = z7.preprocess((value) => {
|
|
5761
|
-
if (!Array.isArray(value))
|
|
5762
|
-
return value;
|
|
5668
|
+
if (!Array.isArray(value)) return value;
|
|
5763
5669
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5764
5670
|
}, z7.array(MemoryLessonNonEmptyStringSchema)).default([]);
|
|
5765
5671
|
var MemoryLessonSchema = z7.object({
|
|
@@ -5804,14 +5710,12 @@ var ListMemoryLessonsInputSchema = z7.object({
|
|
|
5804
5710
|
});
|
|
5805
5711
|
var PerspectiveMemoryNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5806
5712
|
var PerspectiveMemoryOptionalStringSchema = z7.preprocess((value) => {
|
|
5807
|
-
if (typeof value !== "string")
|
|
5808
|
-
return value;
|
|
5713
|
+
if (typeof value !== "string") return value;
|
|
5809
5714
|
const normalized = value.trim();
|
|
5810
5715
|
return normalized.length > 0 ? normalized : void 0;
|
|
5811
5716
|
}, PerspectiveMemoryNonEmptyStringSchema.optional());
|
|
5812
5717
|
var PerspectiveMemoryStringArraySchema = z7.preprocess((value) => {
|
|
5813
|
-
if (!Array.isArray(value))
|
|
5814
|
-
return value;
|
|
5718
|
+
if (!Array.isArray(value)) return value;
|
|
5815
5719
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5816
5720
|
}, z7.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);
|
|
5817
5721
|
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;
|
|
@@ -6469,6 +6373,7 @@ var GraphPathService = class {
|
|
|
6469
6373
|
constructor(db) {
|
|
6470
6374
|
this.db = db;
|
|
6471
6375
|
}
|
|
6376
|
+
db;
|
|
6472
6377
|
expand(input) {
|
|
6473
6378
|
const graph = this.loadGraph(input.direction ?? "both");
|
|
6474
6379
|
const effectiveMaxHops = normalizeMaxHops(input.maxHops);
|
|
@@ -6486,11 +6391,9 @@ var GraphPathService = class {
|
|
|
6486
6391
|
while (queue.length > 0) {
|
|
6487
6392
|
queue.sort((a, b) => a.totalCost - b.totalCost || a.hops - b.hops || a.key.localeCompare(b.key));
|
|
6488
6393
|
const current = queue.shift();
|
|
6489
|
-
if (current.hops >= effectiveMaxHops)
|
|
6490
|
-
continue;
|
|
6394
|
+
if (current.hops >= effectiveMaxHops) continue;
|
|
6491
6395
|
for (const edge of graph.adjacency.get(current.key) ?? []) {
|
|
6492
|
-
if (current.visited.has(edge.toKey))
|
|
6493
|
-
continue;
|
|
6396
|
+
if (current.visited.has(edge.toKey)) continue;
|
|
6494
6397
|
const nextHops = current.hops + 1;
|
|
6495
6398
|
const nextTotalCost = current.totalCost + edge.step.cost;
|
|
6496
6399
|
const nextSteps = [...current.steps, edge.step];
|
|
@@ -6570,17 +6473,13 @@ function addTraversal(adjacency, fromKey, edge) {
|
|
|
6570
6473
|
adjacency.set(fromKey, edges);
|
|
6571
6474
|
}
|
|
6572
6475
|
function normalizeMaxHops(maxHops) {
|
|
6573
|
-
if (maxHops === void 0)
|
|
6574
|
-
|
|
6575
|
-
if (!Number.isFinite(maxHops))
|
|
6576
|
-
return MAX_HOPS;
|
|
6476
|
+
if (maxHops === void 0) return 1;
|
|
6477
|
+
if (!Number.isFinite(maxHops)) return MAX_HOPS;
|
|
6577
6478
|
return Math.min(Math.max(0, Math.trunc(maxHops)), MAX_HOPS);
|
|
6578
6479
|
}
|
|
6579
6480
|
function normalizeMaxResults(maxResults) {
|
|
6580
|
-
if (maxResults === void 0)
|
|
6581
|
-
|
|
6582
|
-
if (!Number.isFinite(maxResults))
|
|
6583
|
-
return DEFAULT_MAX_RESULTS;
|
|
6481
|
+
if (maxResults === void 0) return DEFAULT_MAX_RESULTS;
|
|
6482
|
+
if (!Number.isFinite(maxResults)) return DEFAULT_MAX_RESULTS;
|
|
6584
6483
|
return Math.min(Math.max(0, Math.trunc(maxResults)), MAX_RESULTS);
|
|
6585
6484
|
}
|
|
6586
6485
|
function isBetterPath(totalCost, hops, signature, existing) {
|
|
@@ -6592,18 +6491,15 @@ function pathSignature(steps) {
|
|
|
6592
6491
|
function edgeWeight(metaJson) {
|
|
6593
6492
|
const meta = parseMeta(metaJson);
|
|
6594
6493
|
const raw = meta.weight;
|
|
6595
|
-
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
6596
|
-
return raw;
|
|
6494
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
6597
6495
|
if (typeof raw === "string") {
|
|
6598
6496
|
const parsed = Number(raw);
|
|
6599
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
6600
|
-
return parsed;
|
|
6497
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
6601
6498
|
}
|
|
6602
6499
|
return DEFAULT_WEIGHT;
|
|
6603
6500
|
}
|
|
6604
6501
|
function parseMeta(metaJson) {
|
|
6605
|
-
if (!metaJson)
|
|
6606
|
-
return {};
|
|
6502
|
+
if (!metaJson) return {};
|
|
6607
6503
|
try {
|
|
6608
6504
|
const parsed = JSON.parse(metaJson);
|
|
6609
6505
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -6616,8 +6512,7 @@ function nodeKey(node) {
|
|
|
6616
6512
|
}
|
|
6617
6513
|
function nodeFromKey(key) {
|
|
6618
6514
|
const index = key.indexOf(":");
|
|
6619
|
-
if (index === -1)
|
|
6620
|
-
return { type: "entity", id: key };
|
|
6515
|
+
if (index === -1) return { type: "entity", id: key };
|
|
6621
6516
|
return { type: key.slice(0, index), id: key.slice(index + 1) };
|
|
6622
6517
|
}
|
|
6623
6518
|
|
|
@@ -6673,6 +6568,7 @@ var QueryEntityExtractor = class {
|
|
|
6673
6568
|
constructor(db) {
|
|
6674
6569
|
this.db = db;
|
|
6675
6570
|
}
|
|
6571
|
+
db;
|
|
6676
6572
|
extract(query, options = {}) {
|
|
6677
6573
|
const maxCandidates = normalizeMaxCandidates(options.maxCandidates);
|
|
6678
6574
|
const candidates = [];
|
|
@@ -6694,8 +6590,7 @@ var QueryEntityExtractor = class {
|
|
|
6694
6590
|
let match;
|
|
6695
6591
|
while ((match = regex.exec(query)) !== null) {
|
|
6696
6592
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6697
|
-
if (!isUsefulCandidate(text))
|
|
6698
|
-
continue;
|
|
6593
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6699
6594
|
const start = match.index + 1;
|
|
6700
6595
|
const end = start + text.length;
|
|
6701
6596
|
ranges.push([match.index, match.index + match[0].length]);
|
|
@@ -6709,8 +6604,7 @@ var QueryEntityExtractor = class {
|
|
|
6709
6604
|
return ranges;
|
|
6710
6605
|
}
|
|
6711
6606
|
extractKnownAliases(query, candidates) {
|
|
6712
|
-
if (!this.db)
|
|
6713
|
-
return;
|
|
6607
|
+
if (!this.db) return;
|
|
6714
6608
|
const rows = sqliteAll(
|
|
6715
6609
|
this.db,
|
|
6716
6610
|
`SELECT
|
|
@@ -6734,11 +6628,9 @@ var QueryEntityExtractor = class {
|
|
|
6734
6628
|
]).filter(isUsefulCandidate);
|
|
6735
6629
|
for (const alias of aliasLabels) {
|
|
6736
6630
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6737
|
-
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias))
|
|
6738
|
-
continue;
|
|
6631
|
+
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias)) continue;
|
|
6739
6632
|
const aliasKey = `${row.entity_id}:${normalizedAlias}`;
|
|
6740
|
-
if (seenAliases.has(aliasKey))
|
|
6741
|
-
continue;
|
|
6633
|
+
if (seenAliases.has(aliasKey)) continue;
|
|
6742
6634
|
seenAliases.add(aliasKey);
|
|
6743
6635
|
const range = findRange(query, alias);
|
|
6744
6636
|
pushCandidate(candidates, {
|
|
@@ -6759,8 +6651,7 @@ var QueryEntityExtractor = class {
|
|
|
6759
6651
|
let match;
|
|
6760
6652
|
while ((match = regex.exec(query)) !== null) {
|
|
6761
6653
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6762
|
-
if (!isUsefulCandidate(text))
|
|
6763
|
-
continue;
|
|
6654
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6764
6655
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6765
6656
|
pushCandidate(candidates, {
|
|
6766
6657
|
text,
|
|
@@ -6775,8 +6666,7 @@ var QueryEntityExtractor = class {
|
|
|
6775
6666
|
let match;
|
|
6776
6667
|
while ((match = regex.exec(query)) !== null) {
|
|
6777
6668
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6778
|
-
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./"))
|
|
6779
|
-
continue;
|
|
6669
|
+
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./")) continue;
|
|
6780
6670
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6781
6671
|
pushCandidate(candidates, {
|
|
6782
6672
|
text,
|
|
@@ -6795,21 +6685,17 @@ var QueryEntityExtractor = class {
|
|
|
6795
6685
|
if (previous && query.slice(previous.end, token.start).match(/^\s+$/)) {
|
|
6796
6686
|
current.push(token);
|
|
6797
6687
|
} else {
|
|
6798
|
-
if (current.length > 0)
|
|
6799
|
-
groups.push(current);
|
|
6688
|
+
if (current.length > 0) groups.push(current);
|
|
6800
6689
|
current = [token];
|
|
6801
6690
|
}
|
|
6802
6691
|
}
|
|
6803
|
-
if (current.length > 0)
|
|
6804
|
-
groups.push(current);
|
|
6692
|
+
if (current.length > 0) groups.push(current);
|
|
6805
6693
|
for (const group of groups) {
|
|
6806
|
-
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text))
|
|
6807
|
-
continue;
|
|
6694
|
+
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text)) continue;
|
|
6808
6695
|
const start = group[0].start;
|
|
6809
6696
|
const end = group[group.length - 1].end;
|
|
6810
6697
|
const text = query.slice(start, end);
|
|
6811
|
-
if (!isUsefulCandidate(text))
|
|
6812
|
-
continue;
|
|
6698
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6813
6699
|
pushCandidate(candidates, {
|
|
6814
6700
|
text,
|
|
6815
6701
|
source: "capitalized_term",
|
|
@@ -6830,8 +6716,7 @@ function collectCapitalizedTokens(query) {
|
|
|
6830
6716
|
}
|
|
6831
6717
|
function pushCandidate(candidates, input) {
|
|
6832
6718
|
const text = cleanCandidateText(input.text);
|
|
6833
|
-
if (!isUsefulCandidate(text))
|
|
6834
|
-
return;
|
|
6719
|
+
if (!isUsefulCandidate(text)) return;
|
|
6835
6720
|
const source = input.source;
|
|
6836
6721
|
candidates.push({
|
|
6837
6722
|
...input,
|
|
@@ -6849,15 +6734,13 @@ function dedupeAndSort(candidates) {
|
|
|
6849
6734
|
for (const candidate of sorted) {
|
|
6850
6735
|
if (candidate.source === "entity_alias") {
|
|
6851
6736
|
const aliasKey = `alias:${candidate.entityId ?? ""}:${normalizeCandidate(candidate.matchedAlias ?? candidate.text)}`;
|
|
6852
|
-
if (seenAliasKeys.has(aliasKey))
|
|
6853
|
-
continue;
|
|
6737
|
+
if (seenAliasKeys.has(aliasKey)) continue;
|
|
6854
6738
|
seenAliasKeys.add(aliasKey);
|
|
6855
6739
|
seenNormalized.add(candidate.normalized);
|
|
6856
6740
|
result.push(candidate);
|
|
6857
6741
|
continue;
|
|
6858
6742
|
}
|
|
6859
|
-
if (seenNormalized.has(candidate.normalized))
|
|
6860
|
-
continue;
|
|
6743
|
+
if (seenNormalized.has(candidate.normalized)) continue;
|
|
6861
6744
|
seenNormalized.add(candidate.normalized);
|
|
6862
6745
|
result.push(candidate);
|
|
6863
6746
|
}
|
|
@@ -6867,8 +6750,7 @@ function compareCandidates(a, b) {
|
|
|
6867
6750
|
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 ?? "");
|
|
6868
6751
|
}
|
|
6869
6752
|
function compareStrings(a, b) {
|
|
6870
|
-
if (a === b)
|
|
6871
|
-
return 0;
|
|
6753
|
+
if (a === b) return 0;
|
|
6872
6754
|
return a < b ? -1 : 1;
|
|
6873
6755
|
}
|
|
6874
6756
|
function stripPriority(candidate) {
|
|
@@ -6876,10 +6758,8 @@ function stripPriority(candidate) {
|
|
|
6876
6758
|
return publicCandidate;
|
|
6877
6759
|
}
|
|
6878
6760
|
function normalizeMaxCandidates(maxCandidates) {
|
|
6879
|
-
if (maxCandidates === void 0)
|
|
6880
|
-
|
|
6881
|
-
if (!Number.isFinite(maxCandidates))
|
|
6882
|
-
return DEFAULT_MAX_CANDIDATES;
|
|
6761
|
+
if (maxCandidates === void 0) return DEFAULT_MAX_CANDIDATES;
|
|
6762
|
+
if (!Number.isFinite(maxCandidates)) return DEFAULT_MAX_CANDIDATES;
|
|
6883
6763
|
return Math.min(Math.max(0, Math.trunc(maxCandidates)), MAX_CANDIDATES);
|
|
6884
6764
|
}
|
|
6885
6765
|
function cleanCandidateText(text) {
|
|
@@ -6901,21 +6781,17 @@ function aliasLabelFromCanonicalKey(canonicalKey) {
|
|
|
6901
6781
|
function findRange(query, alias) {
|
|
6902
6782
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6903
6783
|
const directIndex = query.toLowerCase().indexOf(alias.toLowerCase());
|
|
6904
|
-
if (directIndex >= 0)
|
|
6905
|
-
return { start: directIndex, end: directIndex + alias.length };
|
|
6784
|
+
if (directIndex >= 0) return { start: directIndex, end: directIndex + alias.length };
|
|
6906
6785
|
const normalizedQuery = normalizeForContainment(query);
|
|
6907
6786
|
const normalizedIndex = normalizedQuery.indexOf(normalizedAlias);
|
|
6908
|
-
if (normalizedIndex < 0)
|
|
6909
|
-
return { start: 0, end: 0 };
|
|
6787
|
+
if (normalizedIndex < 0) return { start: 0, end: 0 };
|
|
6910
6788
|
const queryLower = query.toLowerCase();
|
|
6911
6789
|
const words = normalizedAlias.split(" ").filter(Boolean);
|
|
6912
|
-
if (words.length === 0)
|
|
6913
|
-
return { start: 0, end: 0 };
|
|
6790
|
+
if (words.length === 0) return { start: 0, end: 0 };
|
|
6914
6791
|
const first = queryLower.indexOf(words[0]);
|
|
6915
6792
|
const lastWord = words[words.length - 1];
|
|
6916
6793
|
const last = queryLower.indexOf(lastWord, first >= 0 ? first : 0);
|
|
6917
|
-
if (first >= 0 && last >= 0)
|
|
6918
|
-
return { start: first, end: last + lastWord.length };
|
|
6794
|
+
if (first >= 0 && last >= 0) return { start: first, end: last + lastWord.length };
|
|
6919
6795
|
return { start: normalizedIndex, end: normalizedIndex + normalizedAlias.length };
|
|
6920
6796
|
}
|
|
6921
6797
|
function isUsefulCandidate(text) {
|
|
@@ -6926,10 +6802,8 @@ function isInsideAnyRange(index, ranges) {
|
|
|
6926
6802
|
return ranges.some(([start, end]) => index >= start && index < end);
|
|
6927
6803
|
}
|
|
6928
6804
|
function isStrongSingleCapitalized(text) {
|
|
6929
|
-
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text))
|
|
6930
|
-
|
|
6931
|
-
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text))
|
|
6932
|
-
return true;
|
|
6805
|
+
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text)) return true;
|
|
6806
|
+
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text)) return true;
|
|
6933
6807
|
return text.length >= 4 && !SENTENCE_START_STOPWORDS.has(text);
|
|
6934
6808
|
}
|
|
6935
6809
|
function uniqueStrings(values) {
|
|
@@ -6937,8 +6811,7 @@ function uniqueStrings(values) {
|
|
|
6937
6811
|
const result = [];
|
|
6938
6812
|
for (const value of values) {
|
|
6939
6813
|
const key = normalizeForContainment(value);
|
|
6940
|
-
if (!key || seen.has(key))
|
|
6941
|
-
continue;
|
|
6814
|
+
if (!key || seen.has(key)) continue;
|
|
6942
6815
|
seen.add(key);
|
|
6943
6816
|
result.push(value);
|
|
6944
6817
|
}
|
|
@@ -6960,8 +6833,7 @@ var LessonCandidateInputSchema = z9.object({
|
|
|
6960
6833
|
import { z as z10 } from "zod";
|
|
6961
6834
|
var NonEmptyStringSchema5 = z10.string().transform((value) => value.trim()).pipe(z10.string().min(1));
|
|
6962
6835
|
var PromotionStringArraySchema = z10.preprocess((value) => {
|
|
6963
|
-
if (!Array.isArray(value))
|
|
6964
|
-
return value;
|
|
6836
|
+
if (!Array.isArray(value)) return value;
|
|
6965
6837
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
6966
6838
|
}, z10.array(NonEmptyStringSchema5).max(100));
|
|
6967
6839
|
var ReviewedLessonCandidateSchema = z10.object({
|
|
@@ -7009,8 +6881,7 @@ function projectHashFromStorage(projectHash) {
|
|
|
7009
6881
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7010
6882
|
}
|
|
7011
6883
|
function parseJsonRecord(value) {
|
|
7012
|
-
if (!value)
|
|
7013
|
-
return void 0;
|
|
6884
|
+
if (!value) return void 0;
|
|
7014
6885
|
try {
|
|
7015
6886
|
const parsed = JSON.parse(value);
|
|
7016
6887
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7022,8 +6893,7 @@ function sanitizeString(value) {
|
|
|
7022
6893
|
return String(sanitizeGovernanceAuditValue(value)).trim();
|
|
7023
6894
|
}
|
|
7024
6895
|
function sanitizeMetadata(metadata) {
|
|
7025
|
-
if (!metadata)
|
|
7026
|
-
return void 0;
|
|
6896
|
+
if (!metadata) return void 0;
|
|
7027
6897
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7028
6898
|
}
|
|
7029
6899
|
function slugActorPart(value) {
|
|
@@ -7031,8 +6901,7 @@ function slugActorPart(value) {
|
|
|
7031
6901
|
return slug.length > 0 ? slug : "unknown";
|
|
7032
6902
|
}
|
|
7033
6903
|
function stableActorId(input) {
|
|
7034
|
-
if (input.actorId)
|
|
7035
|
-
return sanitizeString(input.actorId);
|
|
6904
|
+
if (input.actorId) return sanitizeString(input.actorId);
|
|
7036
6905
|
const projectPart = input.projectHash ? `project:${slugActorPart(input.projectHash)}` : "global";
|
|
7037
6906
|
return [
|
|
7038
6907
|
"actor",
|
|
@@ -7055,12 +6924,10 @@ function rowToActor(row) {
|
|
|
7055
6924
|
});
|
|
7056
6925
|
}
|
|
7057
6926
|
function metadataString(metadata, keys) {
|
|
7058
|
-
if (!metadata)
|
|
7059
|
-
return void 0;
|
|
6927
|
+
if (!metadata) return void 0;
|
|
7060
6928
|
for (const key of keys) {
|
|
7061
6929
|
const value = metadata[key];
|
|
7062
|
-
if (typeof value === "string" && value.trim().length > 0)
|
|
7063
|
-
return value.trim();
|
|
6930
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
7064
6931
|
}
|
|
7065
6932
|
return void 0;
|
|
7066
6933
|
}
|
|
@@ -7110,6 +6977,7 @@ var ActorRepository = class {
|
|
|
7110
6977
|
constructor(db) {
|
|
7111
6978
|
this.db = db;
|
|
7112
6979
|
}
|
|
6980
|
+
db;
|
|
7113
6981
|
async upsert(input) {
|
|
7114
6982
|
const parsed = UpsertMemoryActorInputSchema.parse(input);
|
|
7115
6983
|
const actorId = stableActorId(parsed);
|
|
@@ -7163,8 +7031,7 @@ var ActorRepository = class {
|
|
|
7163
7031
|
}
|
|
7164
7032
|
require(actorId) {
|
|
7165
7033
|
const actor = this.get(actorId);
|
|
7166
|
-
if (!actor)
|
|
7167
|
-
throw new Error(`Memory actor not found: ${actorId}`);
|
|
7034
|
+
if (!actor) throw new Error(`Memory actor not found: ${actorId}`);
|
|
7168
7035
|
return actor;
|
|
7169
7036
|
}
|
|
7170
7037
|
async list(input = {}) {
|
|
@@ -7200,8 +7067,7 @@ function projectHashFromStorage2(projectHash) {
|
|
|
7200
7067
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7201
7068
|
}
|
|
7202
7069
|
function parseJsonRecord2(value) {
|
|
7203
|
-
if (!value)
|
|
7204
|
-
return void 0;
|
|
7070
|
+
if (!value) return void 0;
|
|
7205
7071
|
try {
|
|
7206
7072
|
const parsed = JSON.parse(value);
|
|
7207
7073
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7210,8 +7076,7 @@ function parseJsonRecord2(value) {
|
|
|
7210
7076
|
}
|
|
7211
7077
|
}
|
|
7212
7078
|
function sanitizeMetadata2(metadata) {
|
|
7213
|
-
if (!metadata)
|
|
7214
|
-
return void 0;
|
|
7079
|
+
if (!metadata) return void 0;
|
|
7215
7080
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7216
7081
|
}
|
|
7217
7082
|
function rowToSessionActor(row) {
|
|
@@ -7231,6 +7096,7 @@ var SessionActorRepository = class {
|
|
|
7231
7096
|
constructor(db) {
|
|
7232
7097
|
this.db = db;
|
|
7233
7098
|
}
|
|
7099
|
+
db;
|
|
7234
7100
|
async upsertMembership(input) {
|
|
7235
7101
|
const parsed = UpsertSessionActorInputSchema.parse(input);
|
|
7236
7102
|
const projectHash = projectHashToStorage3(parsed.projectHash);
|
|
@@ -7277,8 +7143,7 @@ var SessionActorRepository = class {
|
|
|
7277
7143
|
);
|
|
7278
7144
|
}
|
|
7279
7145
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7280
|
-
if (!saved)
|
|
7281
|
-
throw new Error("session actor membership was not saved");
|
|
7146
|
+
if (!saved) throw new Error("session actor membership was not saved");
|
|
7282
7147
|
return saved;
|
|
7283
7148
|
}
|
|
7284
7149
|
async listBySession(input) {
|
|
@@ -7314,8 +7179,7 @@ var SessionActorRepository = class {
|
|
|
7314
7179
|
]
|
|
7315
7180
|
);
|
|
7316
7181
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7317
|
-
if (!saved)
|
|
7318
|
-
throw new Error("session actor membership not found after update");
|
|
7182
|
+
if (!saved) throw new Error("session actor membership not found after update");
|
|
7319
7183
|
return saved;
|
|
7320
7184
|
}
|
|
7321
7185
|
get(projectHash, sessionId, actorId) {
|
|
@@ -7337,8 +7201,7 @@ function projectHashFromStorage3(projectHash) {
|
|
|
7337
7201
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7338
7202
|
}
|
|
7339
7203
|
function parseStringArray2(value) {
|
|
7340
|
-
if (!value)
|
|
7341
|
-
return [];
|
|
7204
|
+
if (!value) return [];
|
|
7342
7205
|
try {
|
|
7343
7206
|
const parsed = JSON.parse(value);
|
|
7344
7207
|
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
@@ -7347,8 +7210,7 @@ function parseStringArray2(value) {
|
|
|
7347
7210
|
}
|
|
7348
7211
|
}
|
|
7349
7212
|
function parseJsonRecord3(value) {
|
|
7350
|
-
if (!value)
|
|
7351
|
-
return void 0;
|
|
7213
|
+
if (!value) return void 0;
|
|
7352
7214
|
try {
|
|
7353
7215
|
const parsed = JSON.parse(value);
|
|
7354
7216
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7364,8 +7226,7 @@ function sanitizeStoredStringArray(values) {
|
|
|
7364
7226
|
return values.map(sanitizeStoredString).filter((value) => value.length > 0);
|
|
7365
7227
|
}
|
|
7366
7228
|
function sanitizeStoredRecord(value) {
|
|
7367
|
-
if (!value)
|
|
7368
|
-
return void 0;
|
|
7229
|
+
if (!value) return void 0;
|
|
7369
7230
|
return sanitizeGovernanceAuditValue(value);
|
|
7370
7231
|
}
|
|
7371
7232
|
function stableHash(value) {
|
|
@@ -7416,8 +7277,7 @@ function sanitizedObservationSnapshot(observation) {
|
|
|
7416
7277
|
});
|
|
7417
7278
|
}
|
|
7418
7279
|
function queryScore(observation, terms) {
|
|
7419
|
-
if (terms.length === 0)
|
|
7420
|
-
return 0;
|
|
7280
|
+
if (terms.length === 0) return 0;
|
|
7421
7281
|
const haystack = [observation.content, observation.level, observation.sessionId ?? ""].join(" ").toLowerCase();
|
|
7422
7282
|
return terms.reduce((score, term) => score + (haystack.includes(term) ? 1 : 0), 0);
|
|
7423
7283
|
}
|
|
@@ -7463,12 +7323,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7463
7323
|
this.vectorOutbox = options.vectorOutbox;
|
|
7464
7324
|
}
|
|
7465
7325
|
}
|
|
7326
|
+
db;
|
|
7466
7327
|
vectorOutbox = null;
|
|
7467
7328
|
vectorOutboxOption;
|
|
7468
7329
|
getVectorOutbox() {
|
|
7469
7330
|
const option = this.vectorOutboxOption;
|
|
7470
|
-
if (option === false)
|
|
7471
|
-
return null;
|
|
7331
|
+
if (option === false) return null;
|
|
7472
7332
|
if (option instanceof VectorOutbox) {
|
|
7473
7333
|
this.vectorOutbox = option;
|
|
7474
7334
|
return option;
|
|
@@ -7480,8 +7340,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7480
7340
|
}
|
|
7481
7341
|
enqueueObservationSync(observationId) {
|
|
7482
7342
|
const outbox = this.getVectorOutbox();
|
|
7483
|
-
if (!outbox)
|
|
7484
|
-
return;
|
|
7343
|
+
if (!outbox) return;
|
|
7485
7344
|
outbox.enqueueSync("perspective_observation", observationId);
|
|
7486
7345
|
}
|
|
7487
7346
|
async create(input) {
|
|
@@ -7543,14 +7402,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7543
7402
|
contentHash,
|
|
7544
7403
|
sourceHash
|
|
7545
7404
|
);
|
|
7546
|
-
if (!saved)
|
|
7547
|
-
throw new Error("perspective observation was not saved");
|
|
7405
|
+
if (!saved) throw new Error("perspective observation was not saved");
|
|
7548
7406
|
this.enqueueObservationSync(saved.observationId);
|
|
7549
7407
|
});
|
|
7550
7408
|
transaction();
|
|
7551
7409
|
const savedObservation = saved;
|
|
7552
|
-
if (!savedObservation)
|
|
7553
|
-
throw new Error("perspective observation was not saved");
|
|
7410
|
+
if (!savedObservation) throw new Error("perspective observation was not saved");
|
|
7554
7411
|
await this.writeCreateAudit({ ...parsed, observerActorId, observedActorId, sessionId, content, sourceEventIds, sourceObservationIds, createdBy, actor, metadata }, savedObservation);
|
|
7555
7412
|
return savedObservation;
|
|
7556
7413
|
}
|
|
@@ -7560,8 +7417,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7560
7417
|
const ftsQuery = buildObservationFtsQuery(parsed.query);
|
|
7561
7418
|
if (ftsQuery) {
|
|
7562
7419
|
const ftsResult = this.queryWithFts(parsed, ftsQuery);
|
|
7563
|
-
if (ftsResult)
|
|
7564
|
-
return ftsResult;
|
|
7420
|
+
if (ftsResult) return ftsResult;
|
|
7565
7421
|
}
|
|
7566
7422
|
}
|
|
7567
7423
|
return this.queryWithPrefetch(parsed);
|
|
@@ -7582,8 +7438,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7582
7438
|
);
|
|
7583
7439
|
return rows.map(rowToObservation);
|
|
7584
7440
|
} catch (error) {
|
|
7585
|
-
if (isFtsUnavailableError(error))
|
|
7586
|
-
return null;
|
|
7441
|
+
if (isFtsUnavailableError(error)) return null;
|
|
7587
7442
|
throw error;
|
|
7588
7443
|
}
|
|
7589
7444
|
}
|
|
@@ -7624,8 +7479,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7624
7479
|
const parsed = DeletePerspectiveObservationInputSchema.parse(input);
|
|
7625
7480
|
const projectHash = projectHashToStorage4(parsed.projectHash);
|
|
7626
7481
|
const before = this.get(projectHash, parsed.observationId);
|
|
7627
|
-
if (!before)
|
|
7628
|
-
throw new Error("perspective observation not found");
|
|
7482
|
+
if (!before) throw new Error("perspective observation not found");
|
|
7629
7483
|
const deletedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7630
7484
|
sqliteRun(
|
|
7631
7485
|
this.db,
|
|
@@ -7635,8 +7489,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7635
7489
|
[deletedAt, deletedAt, projectHash, parsed.observationId]
|
|
7636
7490
|
);
|
|
7637
7491
|
const after = this.get(projectHash, parsed.observationId);
|
|
7638
|
-
if (!after)
|
|
7639
|
-
throw new Error("perspective observation not found after delete");
|
|
7492
|
+
if (!after) throw new Error("perspective observation not found after delete");
|
|
7640
7493
|
await writeGovernanceAuditEntry(this.db, {
|
|
7641
7494
|
operation: "perspective_observation_delete",
|
|
7642
7495
|
actor: parsed.actor,
|
|
@@ -7692,11 +7545,9 @@ var DEFAULT_CONFIG3 = {
|
|
|
7692
7545
|
var MAX_OBSERVATION_CONTENT_CHARS = 600;
|
|
7693
7546
|
var RuleBasedPerspectiveObservationExtractor = class {
|
|
7694
7547
|
async extract(event) {
|
|
7695
|
-
if (!isSupportedSourceEvent(event))
|
|
7696
|
-
return [];
|
|
7548
|
+
if (!isSupportedSourceEvent(event)) return [];
|
|
7697
7549
|
const content = normalizeObservationContent(event.content);
|
|
7698
|
-
if (!content)
|
|
7699
|
-
return [];
|
|
7550
|
+
if (!content) return [];
|
|
7700
7551
|
return [{
|
|
7701
7552
|
content,
|
|
7702
7553
|
confidence: 0.6,
|
|
@@ -7767,8 +7618,7 @@ var PerspectiveDeriver = class {
|
|
|
7767
7618
|
for (const candidate of candidates) {
|
|
7768
7619
|
const observedActorId = candidate.observedActorId ?? sourceActor.actorId;
|
|
7769
7620
|
const observers = selectObservers(members, observedActorId, this.config.deriver.maxObserversPerSession);
|
|
7770
|
-
if (observers.length === 0)
|
|
7771
|
-
continue;
|
|
7621
|
+
if (observers.length === 0) continue;
|
|
7772
7622
|
for (const observerActorId of observers) {
|
|
7773
7623
|
await this.observations.create({
|
|
7774
7624
|
projectHash,
|
|
@@ -7821,28 +7671,22 @@ function normalizeConfig(config) {
|
|
|
7821
7671
|
};
|
|
7822
7672
|
}
|
|
7823
7673
|
function clampInteger(value, fallback, min, max) {
|
|
7824
|
-
if (!Number.isFinite(value))
|
|
7825
|
-
return fallback;
|
|
7674
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7826
7675
|
return Math.max(min, Math.min(max, Math.trunc(Number(value))));
|
|
7827
7676
|
}
|
|
7828
7677
|
function isSupportedSourceEvent(event) {
|
|
7829
7678
|
return event.eventType === "user_prompt" || event.eventType === "agent_response";
|
|
7830
7679
|
}
|
|
7831
7680
|
function roleForEvent(event) {
|
|
7832
|
-
if (event.eventType === "user_prompt")
|
|
7833
|
-
|
|
7834
|
-
if (event.eventType === "
|
|
7835
|
-
|
|
7836
|
-
if (event.eventType === "tool_observation")
|
|
7837
|
-
return "tool";
|
|
7838
|
-
if (event.eventType === "session_summary")
|
|
7839
|
-
return "system";
|
|
7681
|
+
if (event.eventType === "user_prompt") return "speaker";
|
|
7682
|
+
if (event.eventType === "agent_response") return "assistant";
|
|
7683
|
+
if (event.eventType === "tool_observation") return "tool";
|
|
7684
|
+
if (event.eventType === "session_summary") return "system";
|
|
7840
7685
|
return "unknown";
|
|
7841
7686
|
}
|
|
7842
7687
|
function normalizeCandidate2(candidate) {
|
|
7843
7688
|
const content = normalizeObservationContent(candidate.content);
|
|
7844
|
-
if (!content)
|
|
7845
|
-
return null;
|
|
7689
|
+
if (!content) return null;
|
|
7846
7690
|
return {
|
|
7847
7691
|
content,
|
|
7848
7692
|
confidence: clampNumber(candidate.confidence, 0.6, 0, 1),
|
|
@@ -7854,8 +7698,7 @@ function normalizeCandidate2(candidate) {
|
|
|
7854
7698
|
}
|
|
7855
7699
|
function normalizeObservationContent(content) {
|
|
7856
7700
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
7857
|
-
if (!normalized)
|
|
7858
|
-
return null;
|
|
7701
|
+
if (!normalized) return null;
|
|
7859
7702
|
return normalized.slice(0, MAX_OBSERVATION_CONTENT_CHARS);
|
|
7860
7703
|
}
|
|
7861
7704
|
function normalizeOptionalString2(value) {
|
|
@@ -7863,13 +7706,11 @@ function normalizeOptionalString2(value) {
|
|
|
7863
7706
|
return normalized.length > 0 ? normalized : void 0;
|
|
7864
7707
|
}
|
|
7865
7708
|
function clampNumber(value, fallback, min, max) {
|
|
7866
|
-
if (!Number.isFinite(value))
|
|
7867
|
-
return fallback;
|
|
7709
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7868
7710
|
return Math.max(min, Math.min(max, Number(value)));
|
|
7869
7711
|
}
|
|
7870
7712
|
function sanitizeCandidateMetadata(metadata) {
|
|
7871
|
-
if (!metadata)
|
|
7872
|
-
return void 0;
|
|
7713
|
+
if (!metadata) return void 0;
|
|
7873
7714
|
const result = {};
|
|
7874
7715
|
for (const [key, value] of Object.entries(metadata)) {
|
|
7875
7716
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -7882,12 +7723,9 @@ function selectObservers(members, observedActorId, maxObservers) {
|
|
|
7882
7723
|
const selected = [];
|
|
7883
7724
|
for (const member of members) {
|
|
7884
7725
|
const canObserve = member.actorId === observedActorId ? member.observeSelf : member.observeOthers;
|
|
7885
|
-
if (!canObserve)
|
|
7886
|
-
|
|
7887
|
-
if (
|
|
7888
|
-
selected.push(member.actorId);
|
|
7889
|
-
if (selected.length >= maxObservers)
|
|
7890
|
-
break;
|
|
7726
|
+
if (!canObserve) continue;
|
|
7727
|
+
if (!selected.includes(member.actorId)) selected.push(member.actorId);
|
|
7728
|
+
if (selected.length >= maxObservers) break;
|
|
7891
7729
|
}
|
|
7892
7730
|
return selected;
|
|
7893
7731
|
}
|
|
@@ -7923,6 +7761,7 @@ var VectorStore = class {
|
|
|
7923
7761
|
constructor(dbPath) {
|
|
7924
7762
|
this.dbPath = dbPath;
|
|
7925
7763
|
}
|
|
7764
|
+
dbPath;
|
|
7926
7765
|
db = null;
|
|
7927
7766
|
tableCache = /* @__PURE__ */ new Map();
|
|
7928
7767
|
defaultTableName = "conversations";
|
|
@@ -7934,8 +7773,7 @@ var VectorStore = class {
|
|
|
7934
7773
|
* conversations table.
|
|
7935
7774
|
*/
|
|
7936
7775
|
async initialize() {
|
|
7937
|
-
if (this.db)
|
|
7938
|
-
return;
|
|
7776
|
+
if (this.db) return;
|
|
7939
7777
|
this.db = await lancedb.connect(this.dbPath);
|
|
7940
7778
|
}
|
|
7941
7779
|
/**
|
|
@@ -7949,8 +7787,7 @@ var VectorStore = class {
|
|
|
7949
7787
|
* Add or update multiple vector records in batch, grouped by inferred table.
|
|
7950
7788
|
*/
|
|
7951
7789
|
async upsertBatch(records) {
|
|
7952
|
-
if (records.length === 0)
|
|
7953
|
-
return;
|
|
7790
|
+
if (records.length === 0) return;
|
|
7954
7791
|
await this.initialize();
|
|
7955
7792
|
if (!this.db) {
|
|
7956
7793
|
throw new Error("Database not initialized");
|
|
@@ -8005,8 +7842,7 @@ var VectorStore = class {
|
|
|
8005
7842
|
async delete(eventId) {
|
|
8006
7843
|
await this.initialize();
|
|
8007
7844
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8008
|
-
if (!table)
|
|
8009
|
-
return;
|
|
7845
|
+
if (!table) return;
|
|
8010
7846
|
await table.delete(`eventId = ${toLanceSqlString(eventId)}`);
|
|
8011
7847
|
}
|
|
8012
7848
|
/**
|
|
@@ -8015,8 +7851,7 @@ var VectorStore = class {
|
|
|
8015
7851
|
async count() {
|
|
8016
7852
|
await this.initialize();
|
|
8017
7853
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8018
|
-
if (!table)
|
|
8019
|
-
return 0;
|
|
7854
|
+
if (!table) return 0;
|
|
8020
7855
|
const result = await table.countRows();
|
|
8021
7856
|
return result;
|
|
8022
7857
|
}
|
|
@@ -8025,8 +7860,7 @@ var VectorStore = class {
|
|
|
8025
7860
|
*/
|
|
8026
7861
|
async clearAll() {
|
|
8027
7862
|
await this.initialize();
|
|
8028
|
-
if (!this.db)
|
|
8029
|
-
return;
|
|
7863
|
+
if (!this.db) return;
|
|
8030
7864
|
try {
|
|
8031
7865
|
if (typeof this.db.dropTable === "function") {
|
|
8032
7866
|
await this.db.dropTable(this.defaultTableName);
|
|
@@ -8043,8 +7877,7 @@ var VectorStore = class {
|
|
|
8043
7877
|
async exists(eventId) {
|
|
8044
7878
|
await this.initialize();
|
|
8045
7879
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8046
|
-
if (!table)
|
|
8047
|
-
return false;
|
|
7880
|
+
if (!table) return false;
|
|
8048
7881
|
const results = await table.search([]).where(`eventId = ${toLanceSqlString(eventId)}`).limit(1).toArray();
|
|
8049
7882
|
return results.length > 0;
|
|
8050
7883
|
}
|
|
@@ -8079,8 +7912,7 @@ var VectorStore = class {
|
|
|
8079
7912
|
throw new Error("Database not initialized");
|
|
8080
7913
|
}
|
|
8081
7914
|
const cached = this.tableCache.get(tableName);
|
|
8082
|
-
if (cached)
|
|
8083
|
-
return cached;
|
|
7915
|
+
if (cached) return cached;
|
|
8084
7916
|
const tableNames = await this.db.tableNames();
|
|
8085
7917
|
if (!tableNames.includes(tableName)) {
|
|
8086
7918
|
return null;
|
|
@@ -8159,12 +7991,9 @@ var IngestInterceptorRegistry = class {
|
|
|
8159
7991
|
}
|
|
8160
7992
|
};
|
|
8161
7993
|
function mergeHierarchicalMetadata(base, patch) {
|
|
8162
|
-
if (!base && !patch)
|
|
8163
|
-
|
|
8164
|
-
if (!base
|
|
8165
|
-
return patch;
|
|
8166
|
-
if (!patch)
|
|
8167
|
-
return base;
|
|
7994
|
+
if (!base && !patch) return void 0;
|
|
7995
|
+
if (!base) return patch;
|
|
7996
|
+
if (!patch) return base;
|
|
8168
7997
|
const result = { ...base };
|
|
8169
7998
|
for (const [key, value] of Object.entries(patch)) {
|
|
8170
7999
|
const current = result[key];
|
|
@@ -8194,33 +8023,26 @@ var VALID_TAG_NAMESPACES = new Set(Object.values(TAG_NAMESPACES));
|
|
|
8194
8023
|
function parseTag(tag) {
|
|
8195
8024
|
const value = (tag || "").trim();
|
|
8196
8025
|
const idx = value.indexOf(":");
|
|
8197
|
-
if (idx <= 0)
|
|
8198
|
-
return { value };
|
|
8026
|
+
if (idx <= 0) return { value };
|
|
8199
8027
|
const namespace = `${value.slice(0, idx)}:`;
|
|
8200
8028
|
const tagValue = value.slice(idx + 1);
|
|
8201
|
-
if (!tagValue)
|
|
8202
|
-
return { value };
|
|
8029
|
+
if (!tagValue) return { value };
|
|
8203
8030
|
return { namespace, value: tagValue };
|
|
8204
8031
|
}
|
|
8205
8032
|
function validateTag(tag) {
|
|
8206
8033
|
const normalized = (tag || "").trim();
|
|
8207
|
-
if (!normalized)
|
|
8208
|
-
return false;
|
|
8034
|
+
if (!normalized) return false;
|
|
8209
8035
|
const { namespace } = parseTag(normalized);
|
|
8210
|
-
if (!namespace)
|
|
8211
|
-
return true;
|
|
8036
|
+
if (!namespace) return true;
|
|
8212
8037
|
return VALID_TAG_NAMESPACES.has(namespace);
|
|
8213
8038
|
}
|
|
8214
8039
|
function normalizeTags(tags) {
|
|
8215
|
-
if (!Array.isArray(tags))
|
|
8216
|
-
return [];
|
|
8040
|
+
if (!Array.isArray(tags)) return [];
|
|
8217
8041
|
const dedup = /* @__PURE__ */ new Set();
|
|
8218
8042
|
for (const item of tags) {
|
|
8219
|
-
if (typeof item !== "string")
|
|
8220
|
-
continue;
|
|
8043
|
+
if (typeof item !== "string") continue;
|
|
8221
8044
|
const normalized = item.trim();
|
|
8222
|
-
if (!validateTag(normalized))
|
|
8223
|
-
continue;
|
|
8045
|
+
if (!validateTag(normalized)) continue;
|
|
8224
8046
|
dedup.add(normalized);
|
|
8225
8047
|
}
|
|
8226
8048
|
return [...dedup];
|
|
@@ -8237,10 +8059,8 @@ var SummaryDeriver = class {
|
|
|
8237
8059
|
* orchestration, while this class owns summary text and metadata decisions.
|
|
8238
8060
|
*/
|
|
8239
8061
|
deriveSessionSummary(events) {
|
|
8240
|
-
if (events.length < 3)
|
|
8241
|
-
|
|
8242
|
-
if (events.some((event) => event.eventType === "session_summary"))
|
|
8243
|
-
return null;
|
|
8062
|
+
if (events.length < 3) return null;
|
|
8063
|
+
if (events.some((event) => event.eventType === "session_summary")) return null;
|
|
8244
8064
|
const prompts = events.filter((event) => event.eventType === "user_prompt");
|
|
8245
8065
|
const toolObservations = events.filter((event) => event.eventType === "tool_observation");
|
|
8246
8066
|
const toolNames = Array.from(new Set(
|
|
@@ -8388,8 +8208,7 @@ var MemoryIngestService = class {
|
|
|
8388
8208
|
await this.initialize();
|
|
8389
8209
|
const events = await this.eventStore.getSessionEvents(sessionId);
|
|
8390
8210
|
const summary = this.summaryDeriver.deriveSessionSummary(events);
|
|
8391
|
-
if (!summary)
|
|
8392
|
-
return;
|
|
8211
|
+
if (!summary) return;
|
|
8393
8212
|
await this.storeSessionSummary(sessionId, summary.text, summary.metadata);
|
|
8394
8213
|
}
|
|
8395
8214
|
async storeToolObservation(sessionId, payload) {
|
|
@@ -8457,10 +8276,8 @@ var MemoryIngestService = class {
|
|
|
8457
8276
|
}
|
|
8458
8277
|
}
|
|
8459
8278
|
async runPerspectiveDeriver(input, eventId, operation) {
|
|
8460
|
-
if (!this.perspectiveDeriver)
|
|
8461
|
-
|
|
8462
|
-
if (operation !== "user_prompt" && operation !== "agent_response")
|
|
8463
|
-
return;
|
|
8279
|
+
if (!this.perspectiveDeriver) return;
|
|
8280
|
+
if (operation !== "user_prompt" && operation !== "agent_response") return;
|
|
8464
8281
|
const event = {
|
|
8465
8282
|
id: eventId,
|
|
8466
8283
|
eventType: input.eventType,
|
|
@@ -8530,11 +8347,13 @@ var MemoryQueryService = class {
|
|
|
8530
8347
|
this.queryStore = queryStore;
|
|
8531
8348
|
this.deps = deps;
|
|
8532
8349
|
}
|
|
8350
|
+
initialize;
|
|
8351
|
+
queryStore;
|
|
8352
|
+
deps;
|
|
8533
8353
|
async keywordSearch(query, options) {
|
|
8534
8354
|
await this.initialize();
|
|
8535
8355
|
const results = await this.queryStore.keywordSearch(query, options?.topK ?? 10);
|
|
8536
|
-
if (results.length === 0)
|
|
8537
|
-
return [];
|
|
8356
|
+
if (results.length === 0) return [];
|
|
8538
8357
|
const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
|
|
8539
8358
|
const minRank = Math.max(...results.map((r) => r.rank), -1e3);
|
|
8540
8359
|
const rankRange = maxRank - minRank || 1;
|
|
@@ -8629,6 +8448,18 @@ var COMMAND_ARTIFACT_PATTERNS = [
|
|
|
8629
8448
|
/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
|
|
8630
8449
|
/<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
|
|
8631
8450
|
];
|
|
8451
|
+
var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
8452
|
+
/<environment_context\b[\s\S]*<\/environment_context>/i,
|
|
8453
|
+
/<turn_aborted>/i,
|
|
8454
|
+
/^#\s*AGENTS\.md\s+instructions\b[\s\S]*<INSTRUCTIONS>/i,
|
|
8455
|
+
/^\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,
|
|
8456
|
+
/^\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,
|
|
8457
|
+
/^\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,
|
|
8458
|
+
/^\s*---\s*END\s+OF\s+CONTEXT\s+SUMMARY\b/i,
|
|
8459
|
+
/^\s*\[Your\s+active\s+task\s+list\s+was\s+preserved\s+across\s+context\s+compression\]/i,
|
|
8460
|
+
/^➜\s+\S+\s+git:\([^)]*\)\s+/i,
|
|
8461
|
+
/^\$\s+\S+/i
|
|
8462
|
+
];
|
|
8632
8463
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
8633
8464
|
/^\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,
|
|
8634
8465
|
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
@@ -8640,7 +8471,7 @@ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
|
8640
8471
|
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
8641
8472
|
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
8642
8473
|
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
8643
|
-
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|
|
|
8474
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|status)\b/i,
|
|
8644
8475
|
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
8645
8476
|
];
|
|
8646
8477
|
var STALE_CONTENT_PATTERNS = [
|
|
@@ -8780,55 +8611,67 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8780
8611
|
]);
|
|
8781
8612
|
function isCommandArtifactQuery(query) {
|
|
8782
8613
|
const trimmed = query.trim();
|
|
8783
|
-
if (!trimmed)
|
|
8784
|
-
return false;
|
|
8614
|
+
if (!trimmed) return false;
|
|
8785
8615
|
const normalized = trimmed.toLowerCase();
|
|
8786
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
8616
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8617
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8618
|
+
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8619
|
+
}
|
|
8620
|
+
function isCommandArtifactContent(content) {
|
|
8621
|
+
const trimmed = content.trim();
|
|
8622
|
+
if (!trimmed) return false;
|
|
8623
|
+
const normalized = trimmed.toLowerCase();
|
|
8624
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8625
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8790
8626
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8791
8627
|
}
|
|
8628
|
+
function isLowSignalContextContent(content) {
|
|
8629
|
+
const trimmed = content.trim();
|
|
8630
|
+
if (!trimmed) return true;
|
|
8631
|
+
if (isCommandArtifactContent(trimmed)) return true;
|
|
8632
|
+
if (LOW_SIGNAL_CONTEXT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
8633
|
+
return false;
|
|
8634
|
+
}
|
|
8792
8635
|
function isGenericContinuationQuery(query) {
|
|
8793
8636
|
const trimmed = query.trim();
|
|
8794
|
-
if (!trimmed)
|
|
8795
|
-
|
|
8796
|
-
if (
|
|
8797
|
-
return false;
|
|
8798
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8799
|
-
return false;
|
|
8637
|
+
if (!trimmed) return false;
|
|
8638
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8639
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8800
8640
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8801
|
-
if (tokens.length > 10)
|
|
8802
|
-
return false;
|
|
8641
|
+
if (tokens.length > 10) return false;
|
|
8803
8642
|
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);
|
|
8804
8643
|
}
|
|
8805
8644
|
function isShortRepairFollowUpQuery(query) {
|
|
8806
8645
|
const trimmed = query.trim();
|
|
8807
|
-
if (!trimmed)
|
|
8808
|
-
|
|
8809
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8810
|
-
return false;
|
|
8646
|
+
if (!trimmed) return false;
|
|
8647
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8811
8648
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8812
|
-
if (tokens.length > 8)
|
|
8813
|
-
return false;
|
|
8649
|
+
if (tokens.length > 8) return false;
|
|
8814
8650
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8815
8651
|
}
|
|
8652
|
+
function isLowConfidenceContextFallbackQuery(query) {
|
|
8653
|
+
const trimmed = query.trim();
|
|
8654
|
+
if (!trimmed) return false;
|
|
8655
|
+
if (isGenericContinuationQuery(trimmed) || isShortRepairFollowUpQuery(trimmed)) return true;
|
|
8656
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8657
|
+
if ((terms.has("compacted") || terms.has("compaction")) && terms.has("handoff")) return false;
|
|
8658
|
+
const hasContinuationRecall = /^(?:continue|resume)\b/i.test(trimmed) && (terms.has("work") || terms.has("step") || terms.has("task") || terms.has("last") || terms.has("completed"));
|
|
8659
|
+
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"));
|
|
8660
|
+
return hasContinuationRecall || hasValidationGateRecall;
|
|
8661
|
+
}
|
|
8816
8662
|
function isCurrentStateQuery(query) {
|
|
8817
8663
|
const trimmed = query.trim();
|
|
8818
|
-
if (!trimmed)
|
|
8819
|
-
return false;
|
|
8664
|
+
if (!trimmed) return false;
|
|
8820
8665
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8821
8666
|
}
|
|
8822
8667
|
function isStaleOrSupersededContent(content) {
|
|
8823
8668
|
const trimmed = content.trim();
|
|
8824
|
-
if (!trimmed)
|
|
8825
|
-
return false;
|
|
8669
|
+
if (!trimmed) return false;
|
|
8826
8670
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8827
8671
|
}
|
|
8828
8672
|
function buildRetrievalQualityQuery(query) {
|
|
8829
8673
|
const trimmed = query.trim();
|
|
8830
|
-
if (!trimmed)
|
|
8831
|
-
return query;
|
|
8674
|
+
if (!trimmed) return query;
|
|
8832
8675
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8833
8676
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8834
8677
|
}
|
|
@@ -8842,12 +8685,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
8842
8685
|
}
|
|
8843
8686
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
8844
8687
|
const trimmed = query.trim();
|
|
8845
|
-
if (!trimmed)
|
|
8846
|
-
return false;
|
|
8688
|
+
if (!trimmed) return false;
|
|
8847
8689
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8848
8690
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8849
|
-
if (!hasDecisionSignal)
|
|
8850
|
-
return false;
|
|
8691
|
+
if (!hasDecisionSignal) return false;
|
|
8851
8692
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
8852
8693
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
8853
8694
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -8860,16 +8701,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
8860
8701
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
8861
8702
|
const terms = matches.filter((term) => {
|
|
8862
8703
|
const lower = term.toLowerCase();
|
|
8863
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
8864
|
-
return false;
|
|
8704
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
8865
8705
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
8866
8706
|
});
|
|
8867
8707
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
8868
8708
|
}
|
|
8869
8709
|
function hasTechnicalTermOverlap(query, content) {
|
|
8870
8710
|
const terms = extractTechnicalQueryTerms(query);
|
|
8871
|
-
if (terms.length === 0)
|
|
8872
|
-
return true;
|
|
8711
|
+
if (terms.length === 0) return true;
|
|
8873
8712
|
const normalizedContent = content.toLowerCase();
|
|
8874
8713
|
return terms.some((term) => normalizedContent.includes(term));
|
|
8875
8714
|
}
|
|
@@ -8885,15 +8724,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
8885
8724
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
8886
8725
|
}
|
|
8887
8726
|
}
|
|
8888
|
-
if (queryTerms.length < 3)
|
|
8889
|
-
return true;
|
|
8727
|
+
if (queryTerms.length < 3) return true;
|
|
8890
8728
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
8891
8729
|
let hits = 0;
|
|
8892
8730
|
for (const term of queryTerms) {
|
|
8893
|
-
if (contentTerms.has(term))
|
|
8894
|
-
|
|
8895
|
-
if (hits >= requiredHits)
|
|
8896
|
-
return true;
|
|
8731
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8732
|
+
if (hits >= requiredHits) return true;
|
|
8897
8733
|
}
|
|
8898
8734
|
return false;
|
|
8899
8735
|
}
|
|
@@ -8903,17 +8739,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
8903
8739
|
function hasAnyTerm(terms, expectedTerms) {
|
|
8904
8740
|
let found = false;
|
|
8905
8741
|
expectedTerms.forEach((term) => {
|
|
8906
|
-
if (terms.has(term))
|
|
8907
|
-
found = true;
|
|
8742
|
+
if (terms.has(term)) found = true;
|
|
8908
8743
|
});
|
|
8909
8744
|
return found;
|
|
8910
8745
|
}
|
|
8911
8746
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
8912
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
8913
|
-
return false;
|
|
8747
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
8914
8748
|
const trimmed = query.trim();
|
|
8915
|
-
if (!trimmed)
|
|
8916
|
-
return false;
|
|
8749
|
+
if (!trimmed) return false;
|
|
8917
8750
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8918
8751
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8919
8752
|
}
|
|
@@ -8921,12 +8754,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
8921
8754
|
const seen = /* @__PURE__ */ new Set();
|
|
8922
8755
|
const terms = [];
|
|
8923
8756
|
for (const token of tokenizeQualityText(query)) {
|
|
8924
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
8925
|
-
|
|
8926
|
-
if (
|
|
8927
|
-
continue;
|
|
8928
|
-
if (seen.has(token))
|
|
8929
|
-
continue;
|
|
8757
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8758
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8759
|
+
if (seen.has(token)) continue;
|
|
8930
8760
|
seen.add(token);
|
|
8931
8761
|
terms.push(token);
|
|
8932
8762
|
}
|
|
@@ -8941,14 +8771,10 @@ function tokenizeQualityText(text) {
|
|
|
8941
8771
|
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);
|
|
8942
8772
|
}
|
|
8943
8773
|
function normalizeQualityToken(token) {
|
|
8944
|
-
if (token === "apis")
|
|
8945
|
-
|
|
8946
|
-
if (token
|
|
8947
|
-
|
|
8948
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
8949
|
-
return token;
|
|
8950
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
8951
|
-
return `${token.slice(0, -3)}y`;
|
|
8774
|
+
if (token === "apis") return "api";
|
|
8775
|
+
if (token === "ids") return "id";
|
|
8776
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8777
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
8952
8778
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
8953
8779
|
return token.slice(0, -1);
|
|
8954
8780
|
}
|
|
@@ -9100,7 +8926,14 @@ var Retriever = class {
|
|
|
9100
8926
|
};
|
|
9101
8927
|
fallbackTrace.push("fallback:summary");
|
|
9102
8928
|
}
|
|
9103
|
-
const
|
|
8929
|
+
const selectedResults = current.results.slice(0, opts.topK).filter((result) => {
|
|
8930
|
+
if (current.matchResult.confidence !== "none") return true;
|
|
8931
|
+
if (isLowConfidenceContextFallbackQuery(query)) {
|
|
8932
|
+
return (result.semanticScore ?? result.score) >= 0.5 || result.score >= 0.5;
|
|
8933
|
+
}
|
|
8934
|
+
return (result.semanticScore ?? result.score) >= 0.62 || result.score >= 0.62;
|
|
8935
|
+
});
|
|
8936
|
+
const memories = await this.enrichResults(selectedResults, opts, query);
|
|
9104
8937
|
const context = this.buildContext(memories, opts.maxTokens);
|
|
9105
8938
|
return {
|
|
9106
8939
|
memories,
|
|
@@ -9108,7 +8941,7 @@ var Retriever = class {
|
|
|
9108
8941
|
totalTokens: this.estimateTokens(context),
|
|
9109
8942
|
context,
|
|
9110
8943
|
fallbackTrace,
|
|
9111
|
-
selectedDebug:
|
|
8944
|
+
selectedDebug: selectedResults.map((r) => this.debugDetailForResult(r)),
|
|
9112
8945
|
candidateDebug: (current.candidateResults || []).slice(0, Math.max(opts.topK * 3, 20)).map((r) => this.debugDetailForResult(r)),
|
|
9113
8946
|
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
9114
8947
|
effectiveQueryText: current.effectiveQueryText,
|
|
@@ -9130,8 +8963,7 @@ var Retriever = class {
|
|
|
9130
8963
|
const sharedMemories = [];
|
|
9131
8964
|
for (const result of sharedVectorResults) {
|
|
9132
8965
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9133
|
-
if (!entry)
|
|
9134
|
-
continue;
|
|
8966
|
+
if (!entry) continue;
|
|
9135
8967
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9136
8968
|
sharedMemories.push(entry);
|
|
9137
8969
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9204,6 +9036,7 @@ var Retriever = class {
|
|
|
9204
9036
|
if (isCurrentStateQuery(options.query)) {
|
|
9205
9037
|
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
9206
9038
|
}
|
|
9039
|
+
filtered = filtered.filter((result) => !isLowSignalContextContent(result.content));
|
|
9207
9040
|
filtered = filtered.filter(
|
|
9208
9041
|
(result) => this.isGraphPathResult(result) || hasDiscriminativeTermOverlap(options.query, result.content)
|
|
9209
9042
|
);
|
|
@@ -9212,18 +9045,15 @@ var Retriever = class {
|
|
|
9212
9045
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9213
9046
|
);
|
|
9214
9047
|
}
|
|
9215
|
-
if (filtered.length <= 2)
|
|
9216
|
-
return filtered;
|
|
9048
|
+
if (filtered.length <= 2) return filtered;
|
|
9217
9049
|
const topScore = filtered[0].score;
|
|
9218
|
-
if (topScore < 0.8)
|
|
9219
|
-
return filtered;
|
|
9050
|
+
if (topScore < 0.8) return filtered;
|
|
9220
9051
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9221
9052
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9222
9053
|
}
|
|
9223
9054
|
mergeResults(primary, secondary, limit) {
|
|
9224
9055
|
const byId = /* @__PURE__ */ new Map();
|
|
9225
|
-
for (const row of primary)
|
|
9226
|
-
byId.set(row.eventId, row);
|
|
9056
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9227
9057
|
for (const row of secondary) {
|
|
9228
9058
|
const prev = byId.get(row.eventId);
|
|
9229
9059
|
if (!prev || row.score > prev.score) {
|
|
@@ -9234,23 +9064,19 @@ var Retriever = class {
|
|
|
9234
9064
|
}
|
|
9235
9065
|
async expandGraphHops(seeds, opts) {
|
|
9236
9066
|
const byId = /* @__PURE__ */ new Map();
|
|
9237
|
-
for (const s of seeds)
|
|
9238
|
-
byId.set(s.eventId, s);
|
|
9067
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9239
9068
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9240
9069
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9241
9070
|
const next = [];
|
|
9242
9071
|
for (const f of frontier) {
|
|
9243
9072
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9244
|
-
if (!ev)
|
|
9245
|
-
continue;
|
|
9073
|
+
if (!ev) continue;
|
|
9246
9074
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9247
9075
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9248
9076
|
for (const rid of relatedIds) {
|
|
9249
|
-
if (byId.has(rid))
|
|
9250
|
-
continue;
|
|
9077
|
+
if (byId.has(rid)) continue;
|
|
9251
9078
|
const target = await this.eventStore.getEvent(rid);
|
|
9252
|
-
if (!target)
|
|
9253
|
-
continue;
|
|
9079
|
+
if (!target) continue;
|
|
9254
9080
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9255
9081
|
const row = {
|
|
9256
9082
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9264,15 +9090,12 @@ var Retriever = class {
|
|
|
9264
9090
|
};
|
|
9265
9091
|
byId.set(row.eventId, row);
|
|
9266
9092
|
next.push({ row, hop });
|
|
9267
|
-
if (byId.size >= opts.limit)
|
|
9268
|
-
break;
|
|
9093
|
+
if (byId.size >= opts.limit) break;
|
|
9269
9094
|
}
|
|
9270
|
-
if (byId.size >= opts.limit)
|
|
9271
|
-
break;
|
|
9095
|
+
if (byId.size >= opts.limit) break;
|
|
9272
9096
|
}
|
|
9273
9097
|
frontier = next;
|
|
9274
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9275
|
-
break;
|
|
9098
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9276
9099
|
}
|
|
9277
9100
|
if (opts.queryGraphEnabled) {
|
|
9278
9101
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9280,8 +9103,7 @@ var Retriever = class {
|
|
|
9280
9103
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9281
9104
|
}
|
|
9282
9105
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9283
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9284
|
-
return;
|
|
9106
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9285
9107
|
try {
|
|
9286
9108
|
const db = this.eventStore.getDatabase();
|
|
9287
9109
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9290,8 +9112,7 @@ var Retriever = class {
|
|
|
9290
9112
|
});
|
|
9291
9113
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9292
9114
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9293
|
-
if (startNodes.length === 0)
|
|
9294
|
-
return;
|
|
9115
|
+
if (startNodes.length === 0) return;
|
|
9295
9116
|
const expansion = new GraphPathService(db).expand({
|
|
9296
9117
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9297
9118
|
maxHops: opts.maxHops,
|
|
@@ -9300,11 +9121,9 @@ var Retriever = class {
|
|
|
9300
9121
|
});
|
|
9301
9122
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9302
9123
|
for (const path13 of expansion.paths) {
|
|
9303
|
-
if (path13.target.type !== "event")
|
|
9304
|
-
continue;
|
|
9124
|
+
if (path13.target.type !== "event") continue;
|
|
9305
9125
|
const target = await this.eventStore.getEvent(path13.target.id);
|
|
9306
|
-
if (!target)
|
|
9307
|
-
continue;
|
|
9126
|
+
if (!target) continue;
|
|
9308
9127
|
const graphPath = toRetrievalGraphPathDebug(path13, titleByEntityId);
|
|
9309
9128
|
const score = graphPathScore(path13, opts.hopPenalty);
|
|
9310
9129
|
const existing = byId.get(target.id);
|
|
@@ -9330,17 +9149,14 @@ var Retriever = class {
|
|
|
9330
9149
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9331
9150
|
};
|
|
9332
9151
|
byId.set(row.eventId, row);
|
|
9333
|
-
if (byId.size >= opts.limit)
|
|
9334
|
-
break;
|
|
9152
|
+
if (byId.size >= opts.limit) break;
|
|
9335
9153
|
}
|
|
9336
9154
|
} catch {
|
|
9337
9155
|
}
|
|
9338
9156
|
}
|
|
9339
9157
|
shouldFallback(matchResult, results) {
|
|
9340
|
-
if (results.length === 0)
|
|
9341
|
-
|
|
9342
|
-
if (matchResult.confidence === "none")
|
|
9343
|
-
return true;
|
|
9158
|
+
if (results.length === 0) return true;
|
|
9159
|
+
if (matchResult.confidence === "none") return true;
|
|
9344
9160
|
return false;
|
|
9345
9161
|
}
|
|
9346
9162
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9445,29 +9261,21 @@ var Retriever = class {
|
|
|
9445
9261
|
(value) => typeof value === "string" && value.length > 0
|
|
9446
9262
|
)
|
|
9447
9263
|
);
|
|
9448
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9449
|
-
return results;
|
|
9264
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9450
9265
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9451
9266
|
const filtered = [];
|
|
9452
9267
|
for (const result of results) {
|
|
9453
|
-
if (scope?.sessionId && result.sessionId !== scope.sessionId)
|
|
9454
|
-
|
|
9455
|
-
if (scope?.
|
|
9456
|
-
continue;
|
|
9457
|
-
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType))
|
|
9458
|
-
continue;
|
|
9268
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9269
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9270
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9459
9271
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9460
|
-
if (!event)
|
|
9461
|
-
|
|
9462
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9463
|
-
continue;
|
|
9272
|
+
if (!event) continue;
|
|
9273
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9464
9274
|
if (normalizedIncludes.length > 0) {
|
|
9465
9275
|
const lc = event.content.toLowerCase();
|
|
9466
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9467
|
-
continue;
|
|
9276
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9468
9277
|
}
|
|
9469
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9470
|
-
continue;
|
|
9278
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9471
9279
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9472
9280
|
filtered.push({ result, projectHash });
|
|
9473
9281
|
}
|
|
@@ -9484,27 +9292,21 @@ var Retriever = class {
|
|
|
9484
9292
|
});
|
|
9485
9293
|
}
|
|
9486
9294
|
normalizeFacetFilters(facets) {
|
|
9487
|
-
if (!facets || facets.length === 0)
|
|
9488
|
-
return null;
|
|
9295
|
+
if (!facets || facets.length === 0) return null;
|
|
9489
9296
|
const normalized = [];
|
|
9490
9297
|
for (const facet of facets) {
|
|
9491
9298
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9492
9299
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9493
|
-
if (!parsedDimension.success || !value)
|
|
9494
|
-
return [];
|
|
9300
|
+
if (!parsedDimension.success || !value) return [];
|
|
9495
9301
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9496
9302
|
}
|
|
9497
9303
|
return normalized;
|
|
9498
9304
|
}
|
|
9499
9305
|
async applyFacetFilters(results, options) {
|
|
9500
|
-
if (options.facets === null)
|
|
9501
|
-
|
|
9502
|
-
if (options.
|
|
9503
|
-
|
|
9504
|
-
if (!options.projectHash)
|
|
9505
|
-
return [];
|
|
9506
|
-
if (!this.eventStore.getDatabase)
|
|
9507
|
-
return [];
|
|
9306
|
+
if (options.facets === null) return results;
|
|
9307
|
+
if (options.facets.length === 0) return [];
|
|
9308
|
+
if (!options.projectHash) return [];
|
|
9309
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9508
9310
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9509
9311
|
const filtered = [];
|
|
9510
9312
|
for (const result of results) {
|
|
@@ -9561,14 +9363,11 @@ var Retriever = class {
|
|
|
9561
9363
|
return (result.graphPaths || []).length > 0;
|
|
9562
9364
|
}
|
|
9563
9365
|
extractProjectHash(metadata) {
|
|
9564
|
-
if (!metadata || typeof metadata !== "object")
|
|
9565
|
-
return void 0;
|
|
9366
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9566
9367
|
const scope = metadata.scope;
|
|
9567
|
-
if (!scope || typeof scope !== "object")
|
|
9568
|
-
return void 0;
|
|
9368
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9569
9369
|
const project = scope.project;
|
|
9570
|
-
if (!project || typeof project !== "object")
|
|
9571
|
-
return void 0;
|
|
9370
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9572
9371
|
const hash = project.hash;
|
|
9573
9372
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9574
9373
|
}
|
|
@@ -9578,52 +9377,48 @@ var Retriever = class {
|
|
|
9578
9377
|
async retrieveRecent(limit = 100) {
|
|
9579
9378
|
return this.eventStore.getRecentEvents(limit);
|
|
9580
9379
|
}
|
|
9581
|
-
async enrichResults(results, options) {
|
|
9380
|
+
async enrichResults(results, options, query) {
|
|
9582
9381
|
const memories = [];
|
|
9583
9382
|
for (const result of results) {
|
|
9584
9383
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9585
|
-
if (!event)
|
|
9586
|
-
continue;
|
|
9384
|
+
if (!event) continue;
|
|
9587
9385
|
if (this.graduation) {
|
|
9588
9386
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9589
9387
|
}
|
|
9590
9388
|
let sessionContext;
|
|
9591
9389
|
if (options.includeSessionContext) {
|
|
9592
|
-
sessionContext = await this.getSessionContext(event.sessionId, event.id);
|
|
9390
|
+
sessionContext = await this.getSessionContext(event.sessionId, event.id, query);
|
|
9593
9391
|
}
|
|
9594
9392
|
memories.push({ event, score: result.score, sessionContext });
|
|
9595
9393
|
}
|
|
9596
9394
|
return memories;
|
|
9597
9395
|
}
|
|
9598
|
-
async getSessionContext(sessionId, eventId) {
|
|
9396
|
+
async getSessionContext(sessionId, eventId, query) {
|
|
9599
9397
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9600
9398
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9601
|
-
if (eventIndex === -1)
|
|
9602
|
-
return void 0;
|
|
9399
|
+
if (eventIndex === -1) return void 0;
|
|
9603
9400
|
const start = Math.max(0, eventIndex - 1);
|
|
9604
9401
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9605
9402
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9606
|
-
if (contextEvents.length <= 1)
|
|
9607
|
-
|
|
9608
|
-
|
|
9403
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9404
|
+
const suppressStaleState = isCurrentStateQuery(query);
|
|
9405
|
+
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)}...`);
|
|
9406
|
+
return contextLines.length > 0 ? contextLines.join("\n") : void 0;
|
|
9609
9407
|
}
|
|
9610
9408
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9611
9409
|
let context = projectResult.context;
|
|
9612
|
-
if (sharedMemories.length === 0)
|
|
9613
|
-
return context;
|
|
9410
|
+
if (sharedMemories.length === 0) return context;
|
|
9614
9411
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9615
9412
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9616
9413
|
context += `### ${memory.title}
|
|
9617
9414
|
`;
|
|
9618
|
-
if (memory.symptoms.length > 0)
|
|
9619
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9415
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9620
9416
|
`;
|
|
9621
9417
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9622
9418
|
`;
|
|
9623
9419
|
context += `**Solution:** ${memory.solution}
|
|
9624
9420
|
`;
|
|
9625
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9626
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9421
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9627
9422
|
`;
|
|
9628
9423
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9629
9424
|
|
|
@@ -9637,13 +9432,11 @@ var Retriever = class {
|
|
|
9637
9432
|
for (const memory of memories) {
|
|
9638
9433
|
const memoryText = this.formatMemory(memory);
|
|
9639
9434
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9640
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9641
|
-
break;
|
|
9435
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9642
9436
|
parts.push(memoryText);
|
|
9643
9437
|
currentTokens += memoryTokens;
|
|
9644
9438
|
}
|
|
9645
|
-
if (parts.length === 0)
|
|
9646
|
-
return "";
|
|
9439
|
+
if (parts.length === 0) return "";
|
|
9647
9440
|
return `## Relevant Memories
|
|
9648
9441
|
|
|
9649
9442
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9653,19 +9446,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9653
9446
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9654
9447
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9655
9448
|
${event.content}`;
|
|
9656
|
-
if (sessionContext)
|
|
9657
|
-
text += `
|
|
9449
|
+
if (sessionContext) text += `
|
|
9658
9450
|
|
|
9659
9451
|
_Context:_ ${sessionContext}`;
|
|
9660
9452
|
return text;
|
|
9661
9453
|
}
|
|
9662
9454
|
matchesMetadataScope(metadata, expected) {
|
|
9663
|
-
if (!metadata)
|
|
9664
|
-
return false;
|
|
9455
|
+
if (!metadata) return false;
|
|
9665
9456
|
return Object.entries(expected).every(([path13, value]) => {
|
|
9666
9457
|
const actual = path13.split(".").reduce((acc, key) => {
|
|
9667
|
-
if (typeof acc !== "object" || acc === null)
|
|
9668
|
-
return void 0;
|
|
9458
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9669
9459
|
return acc[key];
|
|
9670
9460
|
}, metadata);
|
|
9671
9461
|
return actual === value;
|
|
@@ -9675,27 +9465,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9675
9465
|
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);
|
|
9676
9466
|
}
|
|
9677
9467
|
normalizeToken(token) {
|
|
9678
|
-
if (token === "apis")
|
|
9679
|
-
|
|
9680
|
-
if (token === "
|
|
9681
|
-
|
|
9682
|
-
if (token === "does")
|
|
9683
|
-
return token;
|
|
9684
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9685
|
-
return `${token.slice(0, -3)}y`;
|
|
9468
|
+
if (token === "apis") return "api";
|
|
9469
|
+
if (token === "ids") return "id";
|
|
9470
|
+
if (token === "does") return token;
|
|
9471
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9686
9472
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9687
9473
|
return token.slice(0, -1);
|
|
9688
9474
|
}
|
|
9689
9475
|
return token;
|
|
9690
9476
|
}
|
|
9691
9477
|
keywordOverlap(a, b) {
|
|
9692
|
-
if (a.length === 0 || b.length === 0)
|
|
9693
|
-
return 0;
|
|
9478
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9694
9479
|
const bs = new Set(b);
|
|
9695
9480
|
let hit = 0;
|
|
9696
|
-
for (const t of a)
|
|
9697
|
-
if (bs.has(t))
|
|
9698
|
-
hit += 1;
|
|
9481
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9699
9482
|
return hit / a.length;
|
|
9700
9483
|
}
|
|
9701
9484
|
estimateTokens(text) {
|
|
@@ -9716,8 +9499,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9716
9499
|
const seen = /* @__PURE__ */ new Set();
|
|
9717
9500
|
const nodes = [];
|
|
9718
9501
|
for (const candidate of candidates) {
|
|
9719
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9720
|
-
continue;
|
|
9502
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9721
9503
|
seen.add(candidate.entityId);
|
|
9722
9504
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9723
9505
|
}
|
|
@@ -9741,16 +9523,14 @@ function graphPathScore(path13, hopPenalty) {
|
|
|
9741
9523
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path13.hops - 1));
|
|
9742
9524
|
}
|
|
9743
9525
|
function clampGraphHops(maxHops) {
|
|
9744
|
-
if (!Number.isFinite(maxHops))
|
|
9745
|
-
return 2;
|
|
9526
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9746
9527
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9747
9528
|
}
|
|
9748
9529
|
function mergeGraphPaths(existing, incoming) {
|
|
9749
9530
|
const byKey = /* @__PURE__ */ new Map();
|
|
9750
9531
|
for (const path13 of [...existing, ...incoming]) {
|
|
9751
9532
|
const key = [path13.startEntityId, path13.targetType, path13.targetId, path13.hops, ...path13.relationPath].join("\0");
|
|
9752
|
-
if (!byKey.has(key))
|
|
9753
|
-
byKey.set(key, path13);
|
|
9533
|
+
if (!byKey.has(key)) byKey.set(key, path13);
|
|
9754
9534
|
}
|
|
9755
9535
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9756
9536
|
}
|
|
@@ -9758,10 +9538,8 @@ function graphPathSignature(path13) {
|
|
|
9758
9538
|
return [path13.startEntityId, path13.targetType, path13.targetId, path13.hops, ...path13.relationPath].join("|");
|
|
9759
9539
|
}
|
|
9760
9540
|
function compareStable(a, b) {
|
|
9761
|
-
if (a < b)
|
|
9762
|
-
|
|
9763
|
-
if (a > b)
|
|
9764
|
-
return 1;
|
|
9541
|
+
if (a < b) return -1;
|
|
9542
|
+
if (a > b) return 1;
|
|
9765
9543
|
return 0;
|
|
9766
9544
|
}
|
|
9767
9545
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9773,6 +9551,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9773
9551
|
constructor(deps) {
|
|
9774
9552
|
this.deps = deps;
|
|
9775
9553
|
}
|
|
9554
|
+
deps;
|
|
9776
9555
|
async getRetrievalTraceStats() {
|
|
9777
9556
|
await this.deps.initialize();
|
|
9778
9557
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -9850,6 +9629,7 @@ var RetrievalDisclosureService = class {
|
|
|
9850
9629
|
constructor(deps) {
|
|
9851
9630
|
this.deps = deps;
|
|
9852
9631
|
}
|
|
9632
|
+
deps;
|
|
9853
9633
|
async search(query, options) {
|
|
9854
9634
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
9855
9635
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -9879,8 +9659,7 @@ var RetrievalDisclosureService = class {
|
|
|
9879
9659
|
return this.expandShared(parsedId.entryId);
|
|
9880
9660
|
}
|
|
9881
9661
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9882
|
-
if (!targetEvent)
|
|
9883
|
-
return null;
|
|
9662
|
+
if (!targetEvent) return null;
|
|
9884
9663
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
9885
9664
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
9886
9665
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -9904,8 +9683,7 @@ var RetrievalDisclosureService = class {
|
|
|
9904
9683
|
return this.sourceShared(parsedId.entryId);
|
|
9905
9684
|
}
|
|
9906
9685
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9907
|
-
if (!rawEvent)
|
|
9908
|
-
return null;
|
|
9686
|
+
if (!rawEvent) return null;
|
|
9909
9687
|
return {
|
|
9910
9688
|
...this.sourceReferenceForEvent(rawEvent),
|
|
9911
9689
|
rawEvents: [rawEvent],
|
|
@@ -9914,8 +9692,7 @@ var RetrievalDisclosureService = class {
|
|
|
9914
9692
|
}
|
|
9915
9693
|
async expandShared(entryId) {
|
|
9916
9694
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9917
|
-
if (!entry)
|
|
9918
|
-
return null;
|
|
9695
|
+
if (!entry) return null;
|
|
9919
9696
|
return {
|
|
9920
9697
|
target: this.sharedToEnvelope(entry),
|
|
9921
9698
|
surroundingFacts: [],
|
|
@@ -9926,8 +9703,7 @@ var RetrievalDisclosureService = class {
|
|
|
9926
9703
|
}
|
|
9927
9704
|
async sourceShared(entryId) {
|
|
9928
9705
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9929
|
-
if (!entry)
|
|
9930
|
-
return null;
|
|
9706
|
+
if (!entry) return null;
|
|
9931
9707
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
9932
9708
|
return {
|
|
9933
9709
|
...sourceReference,
|
|
@@ -10013,38 +9789,25 @@ var RetrievalDisclosureService = class {
|
|
|
10013
9789
|
const reasons = /* @__PURE__ */ new Set();
|
|
10014
9790
|
const usedVector = this.usedVector(result);
|
|
10015
9791
|
const usedKeyword = this.usedKeyword(result);
|
|
10016
|
-
if (usedVector && (debug?.semanticScore ?? 0) > 0)
|
|
10017
|
-
|
|
10018
|
-
if ((debug?.
|
|
10019
|
-
|
|
10020
|
-
if ((debug?.
|
|
10021
|
-
|
|
10022
|
-
if (
|
|
10023
|
-
|
|
10024
|
-
if (
|
|
10025
|
-
reasons.add("entity_overlap");
|
|
10026
|
-
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary"))
|
|
10027
|
-
reasons.add("summary_fallback");
|
|
10028
|
-
if (memory.sessionContext)
|
|
10029
|
-
reasons.add("continuity_link");
|
|
10030
|
-
if (memory.event.eventType === "tool_observation")
|
|
10031
|
-
reasons.add("tool_followup");
|
|
10032
|
-
if (reasons.size === 0)
|
|
10033
|
-
reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
9792
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9793
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9794
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9795
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9796
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9797
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9798
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9799
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9800
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10034
9801
|
return Array.from(reasons);
|
|
10035
9802
|
}
|
|
10036
9803
|
reasonsForContextEvent(event) {
|
|
10037
|
-
if (event.eventType === "tool_observation")
|
|
10038
|
-
|
|
10039
|
-
if (event.eventType === "session_summary")
|
|
10040
|
-
return ["summary_fallback"];
|
|
9804
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9805
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10041
9806
|
return ["continuity_link"];
|
|
10042
9807
|
}
|
|
10043
9808
|
resultTypeForEvent(event) {
|
|
10044
|
-
if (event.eventType === "session_summary")
|
|
10045
|
-
|
|
10046
|
-
if (event.eventType === "tool_observation")
|
|
10047
|
-
return "tool_evidence";
|
|
9809
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9810
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10048
9811
|
return "source";
|
|
10049
9812
|
}
|
|
10050
9813
|
sourceReferenceForEvent(event) {
|
|
@@ -10068,21 +9831,15 @@ var RetrievalDisclosureService = class {
|
|
|
10068
9831
|
}
|
|
10069
9832
|
sourceTypeForEvent(event) {
|
|
10070
9833
|
const metadata = event.metadata || {};
|
|
10071
|
-
if (event.eventType === "tool_observation")
|
|
10072
|
-
|
|
10073
|
-
if (typeof metadata.
|
|
10074
|
-
return "transcript";
|
|
10075
|
-
if (typeof metadata.importedFrom === "string")
|
|
10076
|
-
return "imported_history";
|
|
9834
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9835
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9836
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10077
9837
|
return "raw_event";
|
|
10078
9838
|
}
|
|
10079
9839
|
titleForEvent(event) {
|
|
10080
|
-
if (event.eventType === "session_summary")
|
|
10081
|
-
|
|
10082
|
-
if (event.eventType === "
|
|
10083
|
-
return "Tool evidence";
|
|
10084
|
-
if (event.eventType === "agent_response")
|
|
10085
|
-
return "Agent response";
|
|
9840
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9841
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9842
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10086
9843
|
return "User prompt";
|
|
10087
9844
|
}
|
|
10088
9845
|
usedVector(result) {
|
|
@@ -10108,8 +9865,7 @@ var RetrievalDisclosureService = class {
|
|
|
10108
9865
|
}
|
|
10109
9866
|
preview(content, maxLength) {
|
|
10110
9867
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10111
|
-
if (normalized.length <= maxLength)
|
|
10112
|
-
return normalized;
|
|
9868
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10113
9869
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10114
9870
|
}
|
|
10115
9871
|
};
|
|
@@ -10138,6 +9894,7 @@ var RetrievalOrchestrator = class {
|
|
|
10138
9894
|
this.deps = deps;
|
|
10139
9895
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10140
9896
|
}
|
|
9897
|
+
deps;
|
|
10141
9898
|
/**
|
|
10142
9899
|
* Retrieve relevant memories for a query.
|
|
10143
9900
|
*/
|
|
@@ -10219,8 +9976,7 @@ var RetrievalOrchestrator = class {
|
|
|
10219
9976
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10220
9977
|
*/
|
|
10221
9978
|
async incrementMemoryAccess(eventIds) {
|
|
10222
|
-
if (eventIds.length === 0)
|
|
10223
|
-
return;
|
|
9979
|
+
if (eventIds.length === 0) return;
|
|
10224
9980
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10225
9981
|
}
|
|
10226
9982
|
/**
|
|
@@ -10233,10 +9989,8 @@ var RetrievalOrchestrator = class {
|
|
|
10233
9989
|
resolveGraphHopOptions(callerOptions) {
|
|
10234
9990
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10235
9991
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10236
|
-
if (!callerOptions)
|
|
10237
|
-
|
|
10238
|
-
if (!graphExpansion)
|
|
10239
|
-
return callerOptions;
|
|
9992
|
+
if (!callerOptions) return durableOptions;
|
|
9993
|
+
if (!graphExpansion) return callerOptions;
|
|
10240
9994
|
if (graphExpansion.enabled !== true) {
|
|
10241
9995
|
return {
|
|
10242
9996
|
...callerOptions,
|
|
@@ -10296,12 +10050,10 @@ var RetrievalOrchestrator = class {
|
|
|
10296
10050
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10297
10051
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10298
10052
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10299
|
-
if (!allFinite)
|
|
10300
|
-
return void 0;
|
|
10053
|
+
if (!allFinite) return void 0;
|
|
10301
10054
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10302
10055
|
const total = semantic + lexical + recency;
|
|
10303
|
-
if (!nonNegative || total <= 0)
|
|
10304
|
-
return void 0;
|
|
10056
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10305
10057
|
return {
|
|
10306
10058
|
semantic: semantic / total,
|
|
10307
10059
|
lexical: lexical / total,
|
|
@@ -10310,17 +10062,14 @@ var RetrievalOrchestrator = class {
|
|
|
10310
10062
|
}
|
|
10311
10063
|
async getRerankWeights(adaptive) {
|
|
10312
10064
|
const configured = this.getConfiguredRerankWeights();
|
|
10313
|
-
if (configured)
|
|
10314
|
-
|
|
10315
|
-
if (adaptive)
|
|
10316
|
-
return this.getAdaptiveRerankWeights();
|
|
10065
|
+
if (configured) return configured;
|
|
10066
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10317
10067
|
return void 0;
|
|
10318
10068
|
}
|
|
10319
10069
|
async getAdaptiveRerankWeights() {
|
|
10320
10070
|
try {
|
|
10321
10071
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10322
|
-
if (stats.totalEvaluated < 20)
|
|
10323
|
-
return void 0;
|
|
10072
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10324
10073
|
let semantic = 0.7;
|
|
10325
10074
|
let lexical = 0.2;
|
|
10326
10075
|
let recency = 0.1;
|
|
@@ -10342,11 +10091,9 @@ var RetrievalOrchestrator = class {
|
|
|
10342
10091
|
}
|
|
10343
10092
|
}
|
|
10344
10093
|
async rewriteQueryIntent(query) {
|
|
10345
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10346
|
-
return null;
|
|
10094
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10347
10095
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10348
|
-
if (!apiUrl)
|
|
10349
|
-
return null;
|
|
10096
|
+
if (!apiUrl) return null;
|
|
10350
10097
|
const controller = new AbortController();
|
|
10351
10098
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10352
10099
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10372,11 +10119,9 @@ var RetrievalOrchestrator = class {
|
|
|
10372
10119
|
signal: controller.signal
|
|
10373
10120
|
});
|
|
10374
10121
|
const text = (await res.text()).trim();
|
|
10375
|
-
if (!text)
|
|
10376
|
-
return null;
|
|
10122
|
+
if (!text) return null;
|
|
10377
10123
|
const oneLine = text.replace(/^data:\s*/gm, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ").slice(0, 240);
|
|
10378
|
-
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase())
|
|
10379
|
-
return null;
|
|
10124
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10380
10125
|
return oneLine;
|
|
10381
10126
|
} catch {
|
|
10382
10127
|
return null;
|
|
@@ -10518,8 +10263,7 @@ function createMemoryEngineServices(options) {
|
|
|
10518
10263
|
};
|
|
10519
10264
|
}
|
|
10520
10265
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10521
|
-
if (options.readOnly)
|
|
10522
|
-
return false;
|
|
10266
|
+
if (options.readOnly) return false;
|
|
10523
10267
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10524
10268
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10525
10269
|
}
|
|
@@ -10553,6 +10297,9 @@ var GraduationWorker = class {
|
|
|
10553
10297
|
this.graduation = graduation;
|
|
10554
10298
|
this.config = config;
|
|
10555
10299
|
}
|
|
10300
|
+
eventStore;
|
|
10301
|
+
graduation;
|
|
10302
|
+
config;
|
|
10556
10303
|
running = false;
|
|
10557
10304
|
timeout = null;
|
|
10558
10305
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10560,8 +10307,7 @@ var GraduationWorker = class {
|
|
|
10560
10307
|
* Start the graduation worker
|
|
10561
10308
|
*/
|
|
10562
10309
|
start() {
|
|
10563
|
-
if (this.running)
|
|
10564
|
-
return;
|
|
10310
|
+
if (this.running) return;
|
|
10565
10311
|
this.running = true;
|
|
10566
10312
|
this.scheduleNext();
|
|
10567
10313
|
}
|
|
@@ -10591,8 +10337,7 @@ var GraduationWorker = class {
|
|
|
10591
10337
|
* Schedule the next graduation check
|
|
10592
10338
|
*/
|
|
10593
10339
|
scheduleNext() {
|
|
10594
|
-
if (!this.running)
|
|
10595
|
-
return;
|
|
10340
|
+
if (!this.running) return;
|
|
10596
10341
|
this.timeout = setTimeout(
|
|
10597
10342
|
() => this.run(),
|
|
10598
10343
|
this.config.evaluationIntervalMs
|
|
@@ -10602,8 +10347,7 @@ var GraduationWorker = class {
|
|
|
10602
10347
|
* Run graduation evaluation
|
|
10603
10348
|
*/
|
|
10604
10349
|
async run() {
|
|
10605
|
-
if (!this.running)
|
|
10606
|
-
return;
|
|
10350
|
+
if (!this.running) return;
|
|
10607
10351
|
try {
|
|
10608
10352
|
await this.runGraduation();
|
|
10609
10353
|
} catch (error) {
|
|
@@ -10667,10 +10411,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10667
10411
|
maxRetries: 3
|
|
10668
10412
|
};
|
|
10669
10413
|
function parseJsonArray(value) {
|
|
10670
|
-
if (Array.isArray(value))
|
|
10671
|
-
|
|
10672
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10673
|
-
return [];
|
|
10414
|
+
if (Array.isArray(value)) return value;
|
|
10415
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10674
10416
|
try {
|
|
10675
10417
|
const parsed = JSON.parse(value);
|
|
10676
10418
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10700,8 +10442,7 @@ var VectorWorker = class {
|
|
|
10700
10442
|
* Start the worker polling loop
|
|
10701
10443
|
*/
|
|
10702
10444
|
start() {
|
|
10703
|
-
if (this.running)
|
|
10704
|
-
return;
|
|
10445
|
+
if (this.running) return;
|
|
10705
10446
|
this.running = true;
|
|
10706
10447
|
this.stopping = false;
|
|
10707
10448
|
this.poll();
|
|
@@ -10777,8 +10518,7 @@ var VectorWorker = class {
|
|
|
10777
10518
|
* Poll for new items
|
|
10778
10519
|
*/
|
|
10779
10520
|
async poll() {
|
|
10780
|
-
if (!this.running || this.stopping)
|
|
10781
|
-
return;
|
|
10521
|
+
if (!this.running || this.stopping) return;
|
|
10782
10522
|
try {
|
|
10783
10523
|
await this.processBatch();
|
|
10784
10524
|
} catch (error) {
|
|
@@ -10823,6 +10563,7 @@ var DefaultContentProvider = class {
|
|
|
10823
10563
|
constructor(db) {
|
|
10824
10564
|
this.db = db;
|
|
10825
10565
|
}
|
|
10566
|
+
db;
|
|
10826
10567
|
async getContent(itemKind, itemId) {
|
|
10827
10568
|
switch (itemKind) {
|
|
10828
10569
|
case "entry":
|
|
@@ -10843,8 +10584,7 @@ var DefaultContentProvider = class {
|
|
|
10843
10584
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
10844
10585
|
[entryId]
|
|
10845
10586
|
);
|
|
10846
|
-
if (rows.length === 0)
|
|
10847
|
-
return null;
|
|
10587
|
+
if (rows.length === 0) return null;
|
|
10848
10588
|
const row = rows[0];
|
|
10849
10589
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
10850
10590
|
return {
|
|
@@ -10863,8 +10603,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10863
10603
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
10864
10604
|
[taskId]
|
|
10865
10605
|
);
|
|
10866
|
-
if (rows.length === 0)
|
|
10867
|
-
return null;
|
|
10606
|
+
if (rows.length === 0) return null;
|
|
10868
10607
|
const row = rows[0];
|
|
10869
10608
|
return {
|
|
10870
10609
|
content: row.search_text || row.title,
|
|
@@ -10880,8 +10619,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10880
10619
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
10881
10620
|
[eventId]
|
|
10882
10621
|
);
|
|
10883
|
-
if (rows.length === 0)
|
|
10884
|
-
return null;
|
|
10622
|
+
if (rows.length === 0) return null;
|
|
10885
10623
|
const row = rows[0];
|
|
10886
10624
|
return {
|
|
10887
10625
|
content: row.content,
|
|
@@ -10909,8 +10647,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10909
10647
|
}
|
|
10910
10648
|
throw error;
|
|
10911
10649
|
}
|
|
10912
|
-
if (rows.length === 0)
|
|
10913
|
-
return null;
|
|
10650
|
+
if (rows.length === 0) return null;
|
|
10914
10651
|
const row = rows[0];
|
|
10915
10652
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
10916
10653
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -10952,8 +10689,7 @@ var VectorWorkerV2 = class {
|
|
|
10952
10689
|
* Start the worker polling loop
|
|
10953
10690
|
*/
|
|
10954
10691
|
start() {
|
|
10955
|
-
if (this.running)
|
|
10956
|
-
return;
|
|
10692
|
+
if (this.running) return;
|
|
10957
10693
|
this.running = true;
|
|
10958
10694
|
this.stopping = false;
|
|
10959
10695
|
this.poll();
|
|
@@ -11023,8 +10759,7 @@ var VectorWorkerV2 = class {
|
|
|
11023
10759
|
* Poll for new jobs
|
|
11024
10760
|
*/
|
|
11025
10761
|
async poll() {
|
|
11026
|
-
if (!this.running || this.stopping)
|
|
11027
|
-
return;
|
|
10762
|
+
if (!this.running || this.stopping) return;
|
|
11028
10763
|
try {
|
|
11029
10764
|
await this.processBatch();
|
|
11030
10765
|
} catch (error) {
|
|
@@ -11091,8 +10826,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11091
10826
|
let graduationWorker = null;
|
|
11092
10827
|
return {
|
|
11093
10828
|
async initialize() {
|
|
11094
|
-
if (initialized)
|
|
11095
|
-
return;
|
|
10829
|
+
if (initialized) return;
|
|
11096
10830
|
await deps.sqliteStore.initialize();
|
|
11097
10831
|
if (deps.lightweightMode) {
|
|
11098
10832
|
initialized = true;
|
|
@@ -11186,8 +10920,7 @@ var SharedEventStore = class {
|
|
|
11186
10920
|
this.db = createDatabase(dbPath);
|
|
11187
10921
|
}
|
|
11188
10922
|
async initialize() {
|
|
11189
|
-
if (this.initialized)
|
|
11190
|
-
return;
|
|
10923
|
+
if (this.initialized) return;
|
|
11191
10924
|
await dbRun(this.db, `
|
|
11192
10925
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11193
10926
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11277,6 +11010,10 @@ var SharedPromoter = class {
|
|
|
11277
11010
|
this.embedder = embedder;
|
|
11278
11011
|
this.config = config;
|
|
11279
11012
|
}
|
|
11013
|
+
sharedStore;
|
|
11014
|
+
sharedVectorStore;
|
|
11015
|
+
embedder;
|
|
11016
|
+
config;
|
|
11280
11017
|
/**
|
|
11281
11018
|
* Check if an entry is eligible for promotion
|
|
11282
11019
|
*/
|
|
@@ -11458,6 +11195,7 @@ var SharedStore = class {
|
|
|
11458
11195
|
constructor(sharedEventStore) {
|
|
11459
11196
|
this.sharedEventStore = sharedEventStore;
|
|
11460
11197
|
}
|
|
11198
|
+
sharedEventStore;
|
|
11461
11199
|
get db() {
|
|
11462
11200
|
return this.sharedEventStore.getDatabase();
|
|
11463
11201
|
}
|
|
@@ -11562,8 +11300,7 @@ var SharedStore = class {
|
|
|
11562
11300
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11563
11301
|
[entryId]
|
|
11564
11302
|
);
|
|
11565
|
-
if (rows.length === 0)
|
|
11566
|
-
return null;
|
|
11303
|
+
if (rows.length === 0) return null;
|
|
11567
11304
|
return this.rowToEntry(rows[0]);
|
|
11568
11305
|
}
|
|
11569
11306
|
/**
|
|
@@ -11576,8 +11313,7 @@ var SharedStore = class {
|
|
|
11576
11313
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11577
11314
|
[projectHash, sourceEntryId]
|
|
11578
11315
|
);
|
|
11579
|
-
if (rows.length === 0)
|
|
11580
|
-
return null;
|
|
11316
|
+
if (rows.length === 0) return null;
|
|
11581
11317
|
return this.rowToEntry(rows[0]);
|
|
11582
11318
|
}
|
|
11583
11319
|
/**
|
|
@@ -11687,6 +11423,7 @@ var SharedVectorStore = class {
|
|
|
11687
11423
|
constructor(dbPath) {
|
|
11688
11424
|
this.dbPath = dbPath;
|
|
11689
11425
|
}
|
|
11426
|
+
dbPath;
|
|
11690
11427
|
db = null;
|
|
11691
11428
|
table = null;
|
|
11692
11429
|
tableName = "shared_knowledge";
|
|
@@ -11694,8 +11431,7 @@ var SharedVectorStore = class {
|
|
|
11694
11431
|
* Initialize LanceDB connection
|
|
11695
11432
|
*/
|
|
11696
11433
|
async initialize() {
|
|
11697
|
-
if (this.db)
|
|
11698
|
-
return;
|
|
11434
|
+
if (this.db) return;
|
|
11699
11435
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11700
11436
|
try {
|
|
11701
11437
|
const tables = await this.db.tableNames();
|
|
@@ -11737,8 +11473,7 @@ var SharedVectorStore = class {
|
|
|
11737
11473
|
* Add multiple records in batch
|
|
11738
11474
|
*/
|
|
11739
11475
|
async upsertBatch(records) {
|
|
11740
|
-
if (records.length === 0)
|
|
11741
|
-
return;
|
|
11476
|
+
if (records.length === 0) return;
|
|
11742
11477
|
await this.initialize();
|
|
11743
11478
|
if (!this.db) {
|
|
11744
11479
|
throw new Error("Database not initialized");
|
|
@@ -11799,24 +11534,21 @@ var SharedVectorStore = class {
|
|
|
11799
11534
|
* Delete vector by entry ID
|
|
11800
11535
|
*/
|
|
11801
11536
|
async delete(entryId) {
|
|
11802
|
-
if (!this.table)
|
|
11803
|
-
return;
|
|
11537
|
+
if (!this.table) return;
|
|
11804
11538
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11805
11539
|
}
|
|
11806
11540
|
/**
|
|
11807
11541
|
* Get total count
|
|
11808
11542
|
*/
|
|
11809
11543
|
async count() {
|
|
11810
|
-
if (!this.table)
|
|
11811
|
-
return 0;
|
|
11544
|
+
if (!this.table) return 0;
|
|
11812
11545
|
return this.table.countRows();
|
|
11813
11546
|
}
|
|
11814
11547
|
/**
|
|
11815
11548
|
* Check if vector exists for entry
|
|
11816
11549
|
*/
|
|
11817
11550
|
async exists(entryId) {
|
|
11818
|
-
if (!this.table)
|
|
11819
|
-
return false;
|
|
11551
|
+
if (!this.table) return false;
|
|
11820
11552
|
try {
|
|
11821
11553
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11822
11554
|
return results.length > 0;
|
|
@@ -11834,6 +11566,7 @@ var SharedMemoryServices = class {
|
|
|
11834
11566
|
constructor(options) {
|
|
11835
11567
|
this.options = options;
|
|
11836
11568
|
}
|
|
11569
|
+
options;
|
|
11837
11570
|
sharedEventStore = null;
|
|
11838
11571
|
sharedStore = null;
|
|
11839
11572
|
sharedVectorStore = null;
|
|
@@ -11858,8 +11591,7 @@ var SharedMemoryServices = class {
|
|
|
11858
11591
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
11859
11592
|
}
|
|
11860
11593
|
async initialize() {
|
|
11861
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
11862
|
-
return;
|
|
11594
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
11863
11595
|
const sharedPath = this.getSharedStoragePath();
|
|
11864
11596
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
11865
11597
|
const store = await this.openStore(sharedPath);
|
|
@@ -11876,14 +11608,11 @@ var SharedMemoryServices = class {
|
|
|
11876
11608
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
11877
11609
|
}
|
|
11878
11610
|
async ensureStoreForRead() {
|
|
11879
|
-
if (this.options.config?.enabled === false)
|
|
11880
|
-
|
|
11881
|
-
if (this.sharedStore)
|
|
11882
|
-
return this.sharedStore;
|
|
11611
|
+
if (this.options.config?.enabled === false) return null;
|
|
11612
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11883
11613
|
const sharedPath = this.getSharedStoragePath();
|
|
11884
11614
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
11885
|
-
if (!directoryReady)
|
|
11886
|
-
return null;
|
|
11615
|
+
if (!directoryReady) return null;
|
|
11887
11616
|
return this.openStore(sharedPath);
|
|
11888
11617
|
}
|
|
11889
11618
|
async getEntryForDisclosure(entryId) {
|
|
@@ -11900,13 +11629,11 @@ var SharedMemoryServices = class {
|
|
|
11900
11629
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
11901
11630
|
}
|
|
11902
11631
|
async getStats() {
|
|
11903
|
-
if (!this.sharedStore)
|
|
11904
|
-
return null;
|
|
11632
|
+
if (!this.sharedStore) return null;
|
|
11905
11633
|
return this.sharedStore.getStats();
|
|
11906
11634
|
}
|
|
11907
11635
|
async search(query, options) {
|
|
11908
|
-
if (!this.sharedStore)
|
|
11909
|
-
return [];
|
|
11636
|
+
if (!this.sharedStore) return [];
|
|
11910
11637
|
return this.sharedStore.search(query, options);
|
|
11911
11638
|
}
|
|
11912
11639
|
async close() {
|
|
@@ -11923,8 +11650,7 @@ var SharedMemoryServices = class {
|
|
|
11923
11650
|
this.openStorePromise = null;
|
|
11924
11651
|
}
|
|
11925
11652
|
async openStore(sharedPath) {
|
|
11926
|
-
if (this.sharedStore)
|
|
11927
|
-
return this.sharedStore;
|
|
11653
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11928
11654
|
if (!this.openStorePromise) {
|
|
11929
11655
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
11930
11656
|
}
|
|
@@ -11948,10 +11674,8 @@ var SharedMemoryServices = class {
|
|
|
11948
11674
|
return this.sharedStore;
|
|
11949
11675
|
}
|
|
11950
11676
|
ensureDirectory(sharedPath, options) {
|
|
11951
|
-
if (this.factories.existsSync(sharedPath))
|
|
11952
|
-
|
|
11953
|
-
if (!options.allowCreate)
|
|
11954
|
-
return false;
|
|
11677
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11678
|
+
if (!options.allowCreate) return false;
|
|
11955
11679
|
this.factories.mkdirSync(sharedPath);
|
|
11956
11680
|
return true;
|
|
11957
11681
|
}
|
|
@@ -13158,15 +12882,13 @@ function countRowValue(db, sql, params = []) {
|
|
|
13158
12882
|
return Number(row?.count ?? 0);
|
|
13159
12883
|
}
|
|
13160
12884
|
function projectFilter(projectHash, column = "project_hash") {
|
|
13161
|
-
if (!projectHash)
|
|
13162
|
-
return { clause: "", params: [] };
|
|
12885
|
+
if (!projectHash) return { clause: "", params: [] };
|
|
13163
12886
|
return { clause: `WHERE ${column} = ?`, params: [projectHash] };
|
|
13164
12887
|
}
|
|
13165
12888
|
function sanitizeAggregateLabel(value) {
|
|
13166
12889
|
const raw = typeof value === "string" ? value : String(value ?? "unknown");
|
|
13167
12890
|
const sanitized = String(sanitizeGovernanceAuditValue(raw));
|
|
13168
|
-
if (sanitized !== raw || sanitized.includes("[REDACTED]"))
|
|
13169
|
-
return "[REDACTED]";
|
|
12891
|
+
if (sanitized !== raw || sanitized.includes("[REDACTED]")) return "[REDACTED]";
|
|
13170
12892
|
const trimmed = sanitized.trim();
|
|
13171
12893
|
return trimmed.length > 0 ? trimmed.slice(0, 96) : "unknown";
|
|
13172
12894
|
}
|
|
@@ -13510,8 +13232,7 @@ function buildPerspectiveSourceEvidence(db, projectHash) {
|
|
|
13510
13232
|
function sortCountRows(rows, labelKey) {
|
|
13511
13233
|
return [...rows].sort((a, b) => {
|
|
13512
13234
|
const countDiff = Number(b.count ?? 0) - Number(a.count ?? 0);
|
|
13513
|
-
if (countDiff !== 0)
|
|
13514
|
-
return countDiff;
|
|
13235
|
+
if (countDiff !== 0) return countDiff;
|
|
13515
13236
|
return String(a[labelKey] ?? "").localeCompare(String(b[labelKey] ?? ""));
|
|
13516
13237
|
});
|
|
13517
13238
|
}
|
|
@@ -13594,8 +13315,7 @@ var DEFAULT_KPI_THRESHOLDS = {
|
|
|
13594
13315
|
function loadKpiThresholds() {
|
|
13595
13316
|
try {
|
|
13596
13317
|
const filePath = path11.resolve(process.cwd(), "config", "kpi-thresholds.json");
|
|
13597
|
-
if (!fs9.existsSync(filePath))
|
|
13598
|
-
return DEFAULT_KPI_THRESHOLDS;
|
|
13318
|
+
if (!fs9.existsSync(filePath)) return DEFAULT_KPI_THRESHOLDS;
|
|
13599
13319
|
const parsed = JSON.parse(fs9.readFileSync(filePath, "utf-8"));
|
|
13600
13320
|
return {
|
|
13601
13321
|
usefulRecallRateMin: Number(parsed.usefulRecallRateMin ?? DEFAULT_KPI_THRESHOLDS.usefulRecallRateMin),
|
|
@@ -13609,10 +13329,8 @@ function loadKpiThresholds() {
|
|
|
13609
13329
|
}
|
|
13610
13330
|
}
|
|
13611
13331
|
function windowToMs(window) {
|
|
13612
|
-
if (window === "24h")
|
|
13613
|
-
|
|
13614
|
-
if (window === "7d")
|
|
13615
|
-
return 7 * 24 * 60 * 60 * 1e3;
|
|
13332
|
+
if (window === "24h") return 24 * 60 * 60 * 1e3;
|
|
13333
|
+
if (window === "7d") return 7 * 24 * 60 * 60 * 1e3;
|
|
13616
13334
|
return 30 * 24 * 60 * 60 * 1e3;
|
|
13617
13335
|
}
|
|
13618
13336
|
function inWindow(e, now, window) {
|
|
@@ -13622,8 +13340,7 @@ function isEditToolName(name) {
|
|
|
13622
13340
|
return ["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(name);
|
|
13623
13341
|
}
|
|
13624
13342
|
function parseToolPayload(e) {
|
|
13625
|
-
if (e.eventType !== "tool_observation")
|
|
13626
|
-
return null;
|
|
13343
|
+
if (e.eventType !== "tool_observation") return null;
|
|
13627
13344
|
try {
|
|
13628
13345
|
const payload = JSON.parse(e.content);
|
|
13629
13346
|
return {
|
|
@@ -13642,13 +13359,11 @@ function parseToolPayload(e) {
|
|
|
13642
13359
|
}
|
|
13643
13360
|
}
|
|
13644
13361
|
function isTestLikeCommand(command) {
|
|
13645
|
-
if (!command)
|
|
13646
|
-
return false;
|
|
13362
|
+
if (!command) return false;
|
|
13647
13363
|
return /(test|jest|vitest|pytest|go test|cargo test|lint|eslint|build|tsc)/i.test(command);
|
|
13648
13364
|
}
|
|
13649
13365
|
function safeRatio(num, den) {
|
|
13650
|
-
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0)
|
|
13651
|
-
return 0;
|
|
13366
|
+
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0) return 0;
|
|
13652
13367
|
return num / den;
|
|
13653
13368
|
}
|
|
13654
13369
|
function round(value, digits = 4) {
|
|
@@ -13659,28 +13374,23 @@ function computeSessionTurnCount(sessionEvents) {
|
|
|
13659
13374
|
const turnIds = /* @__PURE__ */ new Set();
|
|
13660
13375
|
for (const e of sessionEvents) {
|
|
13661
13376
|
const turnId = e.metadata?.turnId;
|
|
13662
|
-
if (typeof turnId === "string" && turnId.length > 0)
|
|
13663
|
-
turnIds.add(turnId);
|
|
13377
|
+
if (typeof turnId === "string" && turnId.length > 0) turnIds.add(turnId);
|
|
13664
13378
|
}
|
|
13665
|
-
if (turnIds.size > 0)
|
|
13666
|
-
return turnIds.size;
|
|
13379
|
+
if (turnIds.size > 0) return turnIds.size;
|
|
13667
13380
|
return sessionEvents.filter((e) => e.eventType === "user_prompt").length;
|
|
13668
13381
|
}
|
|
13669
13382
|
function normalizeQueryRewriteKind2(value) {
|
|
13670
13383
|
const normalized = (value || "").trim().toLowerCase();
|
|
13671
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
13672
|
-
return normalized;
|
|
13384
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
13673
13385
|
return "none";
|
|
13674
13386
|
}
|
|
13675
13387
|
function normalizeMetric(value) {
|
|
13676
13388
|
const numberValue = Number(value || 0);
|
|
13677
|
-
if (!Number.isFinite(numberValue))
|
|
13678
|
-
return 0;
|
|
13389
|
+
if (!Number.isFinite(numberValue)) return 0;
|
|
13679
13390
|
return Math.max(0, Math.min(1, numberValue));
|
|
13680
13391
|
}
|
|
13681
13392
|
function getTimestampMs(value) {
|
|
13682
|
-
if (value instanceof Date)
|
|
13683
|
-
return value.getTime();
|
|
13393
|
+
if (value instanceof Date) return value.getTime();
|
|
13684
13394
|
if (typeof value === "string") {
|
|
13685
13395
|
const parsed = new Date(value).getTime();
|
|
13686
13396
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
@@ -13738,8 +13448,7 @@ function makeRetrievalReviewItem(trace) {
|
|
|
13738
13448
|
detail = `${selectedCount} of ${candidateCount} candidates were selected.`;
|
|
13739
13449
|
action = "Inspect score distribution and MMR/diversity settings before lowering thresholds.";
|
|
13740
13450
|
}
|
|
13741
|
-
if (!reason)
|
|
13742
|
-
return null;
|
|
13451
|
+
if (!reason) return null;
|
|
13743
13452
|
return {
|
|
13744
13453
|
traceId: trace.traceId || "unknown-trace",
|
|
13745
13454
|
reason,
|
|
@@ -13788,24 +13497,17 @@ function buildRetrievalReviewQueue(traces, limit) {
|
|
|
13788
13497
|
};
|
|
13789
13498
|
}
|
|
13790
13499
|
function parseStatsLimit(value, fallback, max) {
|
|
13791
|
-
if (!value)
|
|
13792
|
-
|
|
13793
|
-
if (!/^\d+$/.test(value))
|
|
13794
|
-
return fallback;
|
|
13500
|
+
if (!value) return fallback;
|
|
13501
|
+
if (!/^\d+$/.test(value)) return fallback;
|
|
13795
13502
|
const parsed = Number(value);
|
|
13796
|
-
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
13797
|
-
return fallback;
|
|
13503
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
13798
13504
|
return Math.min(parsed, max);
|
|
13799
13505
|
}
|
|
13800
13506
|
function usefulnessScoreLabel(score, confidence) {
|
|
13801
|
-
if (confidence <= 0)
|
|
13802
|
-
|
|
13803
|
-
if (score >=
|
|
13804
|
-
|
|
13805
|
-
if (score >= 60)
|
|
13806
|
-
return "good";
|
|
13807
|
-
if (score >= 40)
|
|
13808
|
-
return "watch";
|
|
13507
|
+
if (confidence <= 0) return "unknown";
|
|
13508
|
+
if (score >= 80) return "excellent";
|
|
13509
|
+
if (score >= 60) return "good";
|
|
13510
|
+
if (score >= 40) return "watch";
|
|
13809
13511
|
return "low";
|
|
13810
13512
|
}
|
|
13811
13513
|
function buildMemoryUsefulnessDiagnostics(input) {
|
|
@@ -14051,8 +13753,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14051
13753
|
let seenEdit = false;
|
|
14052
13754
|
for (const e of sorted) {
|
|
14053
13755
|
const payload = parseToolPayload(e);
|
|
14054
|
-
if (!payload?.toolName)
|
|
14055
|
-
continue;
|
|
13756
|
+
if (!payload?.toolName) continue;
|
|
14056
13757
|
if (isEditToolName(payload.toolName) && payload.success === true) {
|
|
14057
13758
|
editActions.push({ sessionId, timestamp: e.timestamp.getTime(), filePath: payload.filePath });
|
|
14058
13759
|
seenEdit = true;
|
|
@@ -14060,8 +13761,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14060
13761
|
}
|
|
14061
13762
|
if (seenEdit && isTestLikeCommand(payload.command)) {
|
|
14062
13763
|
testRunsAfterEdit++;
|
|
14063
|
-
if (payload.success === false)
|
|
14064
|
-
failedTestRunsAfterEdit++;
|
|
13764
|
+
if (payload.success === false) failedTestRunsAfterEdit++;
|
|
14065
13765
|
}
|
|
14066
13766
|
}
|
|
14067
13767
|
}
|
|
@@ -14070,8 +13770,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14070
13770
|
const bySessionFile = /* @__PURE__ */ new Map();
|
|
14071
13771
|
const sortedEdits = [...editActions].sort((a, b) => a.timestamp - b.timestamp);
|
|
14072
13772
|
for (const edit of sortedEdits) {
|
|
14073
|
-
if (!edit.filePath)
|
|
14074
|
-
continue;
|
|
13773
|
+
if (!edit.filePath) continue;
|
|
14075
13774
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14076
13775
|
const prev = bySessionFile.get(key);
|
|
14077
13776
|
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) {
|
|
@@ -14446,12 +14145,9 @@ statsRouter.get("/timeline", async (c) => {
|
|
|
14446
14145
|
acc[day] = { date: day, total: 0, prompts: 0, responses: 0, tools: 0 };
|
|
14447
14146
|
}
|
|
14448
14147
|
acc[day].total++;
|
|
14449
|
-
if (e.eventType === "user_prompt")
|
|
14450
|
-
|
|
14451
|
-
if (e.eventType === "
|
|
14452
|
-
acc[day].responses++;
|
|
14453
|
-
if (e.eventType === "tool_observation")
|
|
14454
|
-
acc[day].tools++;
|
|
14148
|
+
if (e.eventType === "user_prompt") acc[day].prompts++;
|
|
14149
|
+
if (e.eventType === "agent_response") acc[day].responses++;
|
|
14150
|
+
if (e.eventType === "tool_observation") acc[day].tools++;
|
|
14455
14151
|
return acc;
|
|
14456
14152
|
}, {});
|
|
14457
14153
|
return c.json({
|
|
@@ -14662,8 +14358,7 @@ statsRouter.get("/kpi", async (c) => {
|
|
|
14662
14358
|
for (const edit of dayEditActions) {
|
|
14663
14359
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14664
14360
|
const prev = dayBySessionFile.get(key);
|
|
14665
|
-
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS)
|
|
14666
|
-
dayReworkCount++;
|
|
14361
|
+
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) dayReworkCount++;
|
|
14667
14362
|
dayBySessionFile.set(key, edit.timestamp);
|
|
14668
14363
|
}
|
|
14669
14364
|
const dayTests = dayEvents.filter((e) => {
|
|
@@ -15003,8 +14698,7 @@ projectsRouter.get("/", async (c) => {
|
|
|
15003
14698
|
}
|
|
15004
14699
|
});
|
|
15005
14700
|
function formatBytes(bytes) {
|
|
15006
|
-
if (bytes === 0)
|
|
15007
|
-
return "0 B";
|
|
14701
|
+
if (bytes === 0) return "0 B";
|
|
15008
14702
|
const k = 1024;
|
|
15009
14703
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
15010
14704
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
@@ -15022,6 +14716,7 @@ var ProviderFailure = class extends Error {
|
|
|
15022
14716
|
this.code = code;
|
|
15023
14717
|
this.name = "ProviderFailure";
|
|
15024
14718
|
}
|
|
14719
|
+
code;
|
|
15025
14720
|
};
|
|
15026
14721
|
var CLAUDE_TIMEOUT_MS = 12e4;
|
|
15027
14722
|
chatRouter.post("/", async (c) => {
|
|
@@ -15098,8 +14793,7 @@ async function collectMemoryContext(memoryService, query) {
|
|
|
15098
14793
|
async function collectStatsContext(memoryService) {
|
|
15099
14794
|
try {
|
|
15100
14795
|
const stats = await memoryService.getStats?.();
|
|
15101
|
-
if (!stats)
|
|
15102
|
-
return "";
|
|
14796
|
+
if (!stats) return "";
|
|
15103
14797
|
const levels = stats.levelStats.map((l) => `${l.level}: ${l.count}`).join(", ");
|
|
15104
14798
|
return [
|
|
15105
14799
|
"## Memory Stats",
|
|
@@ -15112,8 +14806,7 @@ async function collectStatsContext(memoryService) {
|
|
|
15112
14806
|
}
|
|
15113
14807
|
}
|
|
15114
14808
|
function formatMemoryContext(memoryHits) {
|
|
15115
|
-
if (memoryHits.length === 0)
|
|
15116
|
-
return "";
|
|
14809
|
+
if (memoryHits.length === 0) return "";
|
|
15117
14810
|
const parts = ["## Relevant Memories\n"];
|
|
15118
14811
|
for (const m of memoryHits) {
|
|
15119
14812
|
const date = m.event.timestamp ? new Date(m.event.timestamp).toISOString().split("T")[0] : "unknown-date";
|
|
@@ -15235,8 +14928,7 @@ function streamClaudeResponse(prompt, stream) {
|
|
|
15235
14928
|
const lines = buffer.split("\n");
|
|
15236
14929
|
buffer = lines.pop() || "";
|
|
15237
14930
|
for (const line of lines) {
|
|
15238
|
-
if (!line.trim())
|
|
15239
|
-
continue;
|
|
14931
|
+
if (!line.trim()) continue;
|
|
15240
14932
|
try {
|
|
15241
14933
|
const parsed = JSON.parse(line);
|
|
15242
14934
|
if (parsed.type === "assistant" && parsed.message?.content) {
|