claude-memory-layer 1.0.43 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/cli/index.js +940 -1480
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +1191 -1490
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +411 -749
- package/dist/hooks/post-tool-use.js.map +1 -1
- package/dist/hooks/semantic-daemon.js +400 -727
- package/dist/hooks/semantic-daemon.js.map +1 -1
- package/dist/hooks/session-end.js +396 -719
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.js +397 -721
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/stop.js +404 -735
- package/dist/hooks/stop.js.map +1 -1
- package/dist/hooks/user-prompt-submit.js +440 -807
- package/dist/hooks/user-prompt-submit.js.map +1 -1
- package/dist/index.js +1269 -1604
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1443 -1637
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +430 -785
- package/dist/server/api/index.js.map +1 -1
- package/dist/server/index.js +438 -801
- package/dist/server/index.js.map +1 -1
- package/dist/services/memory-service.js +396 -719
- package/dist/services/memory-service.js.map +1 -1
- package/package.json +15 -3
package/dist/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;
|
|
@@ -8780,55 +8599,42 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8780
8599
|
]);
|
|
8781
8600
|
function isCommandArtifactQuery(query) {
|
|
8782
8601
|
const trimmed = query.trim();
|
|
8783
|
-
if (!trimmed)
|
|
8784
|
-
return false;
|
|
8602
|
+
if (!trimmed) return false;
|
|
8785
8603
|
const normalized = trimmed.toLowerCase();
|
|
8786
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8787
|
-
|
|
8788
|
-
if (normalized.includes("command-name") || normalized.includes("command-message"))
|
|
8789
|
-
return true;
|
|
8604
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8605
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8790
8606
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8791
8607
|
}
|
|
8792
8608
|
function isGenericContinuationQuery(query) {
|
|
8793
8609
|
const trimmed = query.trim();
|
|
8794
|
-
if (!trimmed)
|
|
8795
|
-
|
|
8796
|
-
if (
|
|
8797
|
-
return false;
|
|
8798
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8799
|
-
return false;
|
|
8610
|
+
if (!trimmed) return false;
|
|
8611
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8612
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8800
8613
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8801
|
-
if (tokens.length > 10)
|
|
8802
|
-
return false;
|
|
8614
|
+
if (tokens.length > 10) return false;
|
|
8803
8615
|
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
8616
|
}
|
|
8805
8617
|
function isShortRepairFollowUpQuery(query) {
|
|
8806
8618
|
const trimmed = query.trim();
|
|
8807
|
-
if (!trimmed)
|
|
8808
|
-
|
|
8809
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8810
|
-
return false;
|
|
8619
|
+
if (!trimmed) return false;
|
|
8620
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8811
8621
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8812
|
-
if (tokens.length > 8)
|
|
8813
|
-
return false;
|
|
8622
|
+
if (tokens.length > 8) return false;
|
|
8814
8623
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8815
8624
|
}
|
|
8816
8625
|
function isCurrentStateQuery(query) {
|
|
8817
8626
|
const trimmed = query.trim();
|
|
8818
|
-
if (!trimmed)
|
|
8819
|
-
return false;
|
|
8627
|
+
if (!trimmed) return false;
|
|
8820
8628
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8821
8629
|
}
|
|
8822
8630
|
function isStaleOrSupersededContent(content) {
|
|
8823
8631
|
const trimmed = content.trim();
|
|
8824
|
-
if (!trimmed)
|
|
8825
|
-
return false;
|
|
8632
|
+
if (!trimmed) return false;
|
|
8826
8633
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8827
8634
|
}
|
|
8828
8635
|
function buildRetrievalQualityQuery(query) {
|
|
8829
8636
|
const trimmed = query.trim();
|
|
8830
|
-
if (!trimmed)
|
|
8831
|
-
return query;
|
|
8637
|
+
if (!trimmed) return query;
|
|
8832
8638
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8833
8639
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8834
8640
|
}
|
|
@@ -8842,12 +8648,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
8842
8648
|
}
|
|
8843
8649
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
8844
8650
|
const trimmed = query.trim();
|
|
8845
|
-
if (!trimmed)
|
|
8846
|
-
return false;
|
|
8651
|
+
if (!trimmed) return false;
|
|
8847
8652
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8848
8653
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8849
|
-
if (!hasDecisionSignal)
|
|
8850
|
-
return false;
|
|
8654
|
+
if (!hasDecisionSignal) return false;
|
|
8851
8655
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
8852
8656
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
8853
8657
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -8860,16 +8664,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
8860
8664
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
8861
8665
|
const terms = matches.filter((term) => {
|
|
8862
8666
|
const lower = term.toLowerCase();
|
|
8863
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
8864
|
-
return false;
|
|
8667
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
8865
8668
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
8866
8669
|
});
|
|
8867
8670
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
8868
8671
|
}
|
|
8869
8672
|
function hasTechnicalTermOverlap(query, content) {
|
|
8870
8673
|
const terms = extractTechnicalQueryTerms(query);
|
|
8871
|
-
if (terms.length === 0)
|
|
8872
|
-
return true;
|
|
8674
|
+
if (terms.length === 0) return true;
|
|
8873
8675
|
const normalizedContent = content.toLowerCase();
|
|
8874
8676
|
return terms.some((term) => normalizedContent.includes(term));
|
|
8875
8677
|
}
|
|
@@ -8885,15 +8687,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
8885
8687
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
8886
8688
|
}
|
|
8887
8689
|
}
|
|
8888
|
-
if (queryTerms.length < 3)
|
|
8889
|
-
return true;
|
|
8690
|
+
if (queryTerms.length < 3) return true;
|
|
8890
8691
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
8891
8692
|
let hits = 0;
|
|
8892
8693
|
for (const term of queryTerms) {
|
|
8893
|
-
if (contentTerms.has(term))
|
|
8894
|
-
|
|
8895
|
-
if (hits >= requiredHits)
|
|
8896
|
-
return true;
|
|
8694
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8695
|
+
if (hits >= requiredHits) return true;
|
|
8897
8696
|
}
|
|
8898
8697
|
return false;
|
|
8899
8698
|
}
|
|
@@ -8903,17 +8702,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
8903
8702
|
function hasAnyTerm(terms, expectedTerms) {
|
|
8904
8703
|
let found = false;
|
|
8905
8704
|
expectedTerms.forEach((term) => {
|
|
8906
|
-
if (terms.has(term))
|
|
8907
|
-
found = true;
|
|
8705
|
+
if (terms.has(term)) found = true;
|
|
8908
8706
|
});
|
|
8909
8707
|
return found;
|
|
8910
8708
|
}
|
|
8911
8709
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
8912
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
8913
|
-
return false;
|
|
8710
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
8914
8711
|
const trimmed = query.trim();
|
|
8915
|
-
if (!trimmed)
|
|
8916
|
-
return false;
|
|
8712
|
+
if (!trimmed) return false;
|
|
8917
8713
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8918
8714
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8919
8715
|
}
|
|
@@ -8921,12 +8717,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
8921
8717
|
const seen = /* @__PURE__ */ new Set();
|
|
8922
8718
|
const terms = [];
|
|
8923
8719
|
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;
|
|
8720
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8721
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8722
|
+
if (seen.has(token)) continue;
|
|
8930
8723
|
seen.add(token);
|
|
8931
8724
|
terms.push(token);
|
|
8932
8725
|
}
|
|
@@ -8941,14 +8734,10 @@ function tokenizeQualityText(text) {
|
|
|
8941
8734
|
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
8735
|
}
|
|
8943
8736
|
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`;
|
|
8737
|
+
if (token === "apis") return "api";
|
|
8738
|
+
if (token === "ids") return "id";
|
|
8739
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8740
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
8952
8741
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
8953
8742
|
return token.slice(0, -1);
|
|
8954
8743
|
}
|
|
@@ -9130,8 +8919,7 @@ var Retriever = class {
|
|
|
9130
8919
|
const sharedMemories = [];
|
|
9131
8920
|
for (const result of sharedVectorResults) {
|
|
9132
8921
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9133
|
-
if (!entry)
|
|
9134
|
-
continue;
|
|
8922
|
+
if (!entry) continue;
|
|
9135
8923
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9136
8924
|
sharedMemories.push(entry);
|
|
9137
8925
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9212,18 +9000,15 @@ var Retriever = class {
|
|
|
9212
9000
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9213
9001
|
);
|
|
9214
9002
|
}
|
|
9215
|
-
if (filtered.length <= 2)
|
|
9216
|
-
return filtered;
|
|
9003
|
+
if (filtered.length <= 2) return filtered;
|
|
9217
9004
|
const topScore = filtered[0].score;
|
|
9218
|
-
if (topScore < 0.8)
|
|
9219
|
-
return filtered;
|
|
9005
|
+
if (topScore < 0.8) return filtered;
|
|
9220
9006
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9221
9007
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9222
9008
|
}
|
|
9223
9009
|
mergeResults(primary, secondary, limit) {
|
|
9224
9010
|
const byId = /* @__PURE__ */ new Map();
|
|
9225
|
-
for (const row of primary)
|
|
9226
|
-
byId.set(row.eventId, row);
|
|
9011
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9227
9012
|
for (const row of secondary) {
|
|
9228
9013
|
const prev = byId.get(row.eventId);
|
|
9229
9014
|
if (!prev || row.score > prev.score) {
|
|
@@ -9234,23 +9019,19 @@ var Retriever = class {
|
|
|
9234
9019
|
}
|
|
9235
9020
|
async expandGraphHops(seeds, opts) {
|
|
9236
9021
|
const byId = /* @__PURE__ */ new Map();
|
|
9237
|
-
for (const s of seeds)
|
|
9238
|
-
byId.set(s.eventId, s);
|
|
9022
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9239
9023
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9240
9024
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9241
9025
|
const next = [];
|
|
9242
9026
|
for (const f of frontier) {
|
|
9243
9027
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9244
|
-
if (!ev)
|
|
9245
|
-
continue;
|
|
9028
|
+
if (!ev) continue;
|
|
9246
9029
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9247
9030
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9248
9031
|
for (const rid of relatedIds) {
|
|
9249
|
-
if (byId.has(rid))
|
|
9250
|
-
continue;
|
|
9032
|
+
if (byId.has(rid)) continue;
|
|
9251
9033
|
const target = await this.eventStore.getEvent(rid);
|
|
9252
|
-
if (!target)
|
|
9253
|
-
continue;
|
|
9034
|
+
if (!target) continue;
|
|
9254
9035
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9255
9036
|
const row = {
|
|
9256
9037
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9264,15 +9045,12 @@ var Retriever = class {
|
|
|
9264
9045
|
};
|
|
9265
9046
|
byId.set(row.eventId, row);
|
|
9266
9047
|
next.push({ row, hop });
|
|
9267
|
-
if (byId.size >= opts.limit)
|
|
9268
|
-
break;
|
|
9048
|
+
if (byId.size >= opts.limit) break;
|
|
9269
9049
|
}
|
|
9270
|
-
if (byId.size >= opts.limit)
|
|
9271
|
-
break;
|
|
9050
|
+
if (byId.size >= opts.limit) break;
|
|
9272
9051
|
}
|
|
9273
9052
|
frontier = next;
|
|
9274
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9275
|
-
break;
|
|
9053
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9276
9054
|
}
|
|
9277
9055
|
if (opts.queryGraphEnabled) {
|
|
9278
9056
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9280,8 +9058,7 @@ var Retriever = class {
|
|
|
9280
9058
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9281
9059
|
}
|
|
9282
9060
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9283
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9284
|
-
return;
|
|
9061
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9285
9062
|
try {
|
|
9286
9063
|
const db = this.eventStore.getDatabase();
|
|
9287
9064
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9290,8 +9067,7 @@ var Retriever = class {
|
|
|
9290
9067
|
});
|
|
9291
9068
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9292
9069
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9293
|
-
if (startNodes.length === 0)
|
|
9294
|
-
return;
|
|
9070
|
+
if (startNodes.length === 0) return;
|
|
9295
9071
|
const expansion = new GraphPathService(db).expand({
|
|
9296
9072
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9297
9073
|
maxHops: opts.maxHops,
|
|
@@ -9300,11 +9076,9 @@ var Retriever = class {
|
|
|
9300
9076
|
});
|
|
9301
9077
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9302
9078
|
for (const path13 of expansion.paths) {
|
|
9303
|
-
if (path13.target.type !== "event")
|
|
9304
|
-
continue;
|
|
9079
|
+
if (path13.target.type !== "event") continue;
|
|
9305
9080
|
const target = await this.eventStore.getEvent(path13.target.id);
|
|
9306
|
-
if (!target)
|
|
9307
|
-
continue;
|
|
9081
|
+
if (!target) continue;
|
|
9308
9082
|
const graphPath = toRetrievalGraphPathDebug(path13, titleByEntityId);
|
|
9309
9083
|
const score = graphPathScore(path13, opts.hopPenalty);
|
|
9310
9084
|
const existing = byId.get(target.id);
|
|
@@ -9330,17 +9104,14 @@ var Retriever = class {
|
|
|
9330
9104
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9331
9105
|
};
|
|
9332
9106
|
byId.set(row.eventId, row);
|
|
9333
|
-
if (byId.size >= opts.limit)
|
|
9334
|
-
break;
|
|
9107
|
+
if (byId.size >= opts.limit) break;
|
|
9335
9108
|
}
|
|
9336
9109
|
} catch {
|
|
9337
9110
|
}
|
|
9338
9111
|
}
|
|
9339
9112
|
shouldFallback(matchResult, results) {
|
|
9340
|
-
if (results.length === 0)
|
|
9341
|
-
|
|
9342
|
-
if (matchResult.confidence === "none")
|
|
9343
|
-
return true;
|
|
9113
|
+
if (results.length === 0) return true;
|
|
9114
|
+
if (matchResult.confidence === "none") return true;
|
|
9344
9115
|
return false;
|
|
9345
9116
|
}
|
|
9346
9117
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9445,29 +9216,21 @@ var Retriever = class {
|
|
|
9445
9216
|
(value) => typeof value === "string" && value.length > 0
|
|
9446
9217
|
)
|
|
9447
9218
|
);
|
|
9448
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9449
|
-
return results;
|
|
9219
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9450
9220
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9451
9221
|
const filtered = [];
|
|
9452
9222
|
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;
|
|
9223
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9224
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9225
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9459
9226
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9460
|
-
if (!event)
|
|
9461
|
-
|
|
9462
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9463
|
-
continue;
|
|
9227
|
+
if (!event) continue;
|
|
9228
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9464
9229
|
if (normalizedIncludes.length > 0) {
|
|
9465
9230
|
const lc = event.content.toLowerCase();
|
|
9466
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9467
|
-
continue;
|
|
9231
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9468
9232
|
}
|
|
9469
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9470
|
-
continue;
|
|
9233
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9471
9234
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9472
9235
|
filtered.push({ result, projectHash });
|
|
9473
9236
|
}
|
|
@@ -9484,27 +9247,21 @@ var Retriever = class {
|
|
|
9484
9247
|
});
|
|
9485
9248
|
}
|
|
9486
9249
|
normalizeFacetFilters(facets) {
|
|
9487
|
-
if (!facets || facets.length === 0)
|
|
9488
|
-
return null;
|
|
9250
|
+
if (!facets || facets.length === 0) return null;
|
|
9489
9251
|
const normalized = [];
|
|
9490
9252
|
for (const facet of facets) {
|
|
9491
9253
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9492
9254
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9493
|
-
if (!parsedDimension.success || !value)
|
|
9494
|
-
return [];
|
|
9255
|
+
if (!parsedDimension.success || !value) return [];
|
|
9495
9256
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9496
9257
|
}
|
|
9497
9258
|
return normalized;
|
|
9498
9259
|
}
|
|
9499
9260
|
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 [];
|
|
9261
|
+
if (options.facets === null) return results;
|
|
9262
|
+
if (options.facets.length === 0) return [];
|
|
9263
|
+
if (!options.projectHash) return [];
|
|
9264
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9508
9265
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9509
9266
|
const filtered = [];
|
|
9510
9267
|
for (const result of results) {
|
|
@@ -9561,14 +9318,11 @@ var Retriever = class {
|
|
|
9561
9318
|
return (result.graphPaths || []).length > 0;
|
|
9562
9319
|
}
|
|
9563
9320
|
extractProjectHash(metadata) {
|
|
9564
|
-
if (!metadata || typeof metadata !== "object")
|
|
9565
|
-
return void 0;
|
|
9321
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9566
9322
|
const scope = metadata.scope;
|
|
9567
|
-
if (!scope || typeof scope !== "object")
|
|
9568
|
-
return void 0;
|
|
9323
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9569
9324
|
const project = scope.project;
|
|
9570
|
-
if (!project || typeof project !== "object")
|
|
9571
|
-
return void 0;
|
|
9325
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9572
9326
|
const hash = project.hash;
|
|
9573
9327
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9574
9328
|
}
|
|
@@ -9582,8 +9336,7 @@ var Retriever = class {
|
|
|
9582
9336
|
const memories = [];
|
|
9583
9337
|
for (const result of results) {
|
|
9584
9338
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9585
|
-
if (!event)
|
|
9586
|
-
continue;
|
|
9339
|
+
if (!event) continue;
|
|
9587
9340
|
if (this.graduation) {
|
|
9588
9341
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9589
9342
|
}
|
|
@@ -9598,32 +9351,27 @@ var Retriever = class {
|
|
|
9598
9351
|
async getSessionContext(sessionId, eventId) {
|
|
9599
9352
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9600
9353
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9601
|
-
if (eventIndex === -1)
|
|
9602
|
-
return void 0;
|
|
9354
|
+
if (eventIndex === -1) return void 0;
|
|
9603
9355
|
const start = Math.max(0, eventIndex - 1);
|
|
9604
9356
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9605
9357
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9606
|
-
if (contextEvents.length <= 1)
|
|
9607
|
-
return void 0;
|
|
9358
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9608
9359
|
return contextEvents.filter((e) => e.id !== eventId).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`).join("\n");
|
|
9609
9360
|
}
|
|
9610
9361
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9611
9362
|
let context = projectResult.context;
|
|
9612
|
-
if (sharedMemories.length === 0)
|
|
9613
|
-
return context;
|
|
9363
|
+
if (sharedMemories.length === 0) return context;
|
|
9614
9364
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9615
9365
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9616
9366
|
context += `### ${memory.title}
|
|
9617
9367
|
`;
|
|
9618
|
-
if (memory.symptoms.length > 0)
|
|
9619
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9368
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9620
9369
|
`;
|
|
9621
9370
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9622
9371
|
`;
|
|
9623
9372
|
context += `**Solution:** ${memory.solution}
|
|
9624
9373
|
`;
|
|
9625
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9626
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9374
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9627
9375
|
`;
|
|
9628
9376
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9629
9377
|
|
|
@@ -9637,13 +9385,11 @@ var Retriever = class {
|
|
|
9637
9385
|
for (const memory of memories) {
|
|
9638
9386
|
const memoryText = this.formatMemory(memory);
|
|
9639
9387
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9640
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9641
|
-
break;
|
|
9388
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9642
9389
|
parts.push(memoryText);
|
|
9643
9390
|
currentTokens += memoryTokens;
|
|
9644
9391
|
}
|
|
9645
|
-
if (parts.length === 0)
|
|
9646
|
-
return "";
|
|
9392
|
+
if (parts.length === 0) return "";
|
|
9647
9393
|
return `## Relevant Memories
|
|
9648
9394
|
|
|
9649
9395
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9653,19 +9399,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9653
9399
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9654
9400
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9655
9401
|
${event.content}`;
|
|
9656
|
-
if (sessionContext)
|
|
9657
|
-
text += `
|
|
9402
|
+
if (sessionContext) text += `
|
|
9658
9403
|
|
|
9659
9404
|
_Context:_ ${sessionContext}`;
|
|
9660
9405
|
return text;
|
|
9661
9406
|
}
|
|
9662
9407
|
matchesMetadataScope(metadata, expected) {
|
|
9663
|
-
if (!metadata)
|
|
9664
|
-
return false;
|
|
9408
|
+
if (!metadata) return false;
|
|
9665
9409
|
return Object.entries(expected).every(([path13, value]) => {
|
|
9666
9410
|
const actual = path13.split(".").reduce((acc, key) => {
|
|
9667
|
-
if (typeof acc !== "object" || acc === null)
|
|
9668
|
-
return void 0;
|
|
9411
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9669
9412
|
return acc[key];
|
|
9670
9413
|
}, metadata);
|
|
9671
9414
|
return actual === value;
|
|
@@ -9675,27 +9418,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9675
9418
|
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
9419
|
}
|
|
9677
9420
|
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`;
|
|
9421
|
+
if (token === "apis") return "api";
|
|
9422
|
+
if (token === "ids") return "id";
|
|
9423
|
+
if (token === "does") return token;
|
|
9424
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9686
9425
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9687
9426
|
return token.slice(0, -1);
|
|
9688
9427
|
}
|
|
9689
9428
|
return token;
|
|
9690
9429
|
}
|
|
9691
9430
|
keywordOverlap(a, b) {
|
|
9692
|
-
if (a.length === 0 || b.length === 0)
|
|
9693
|
-
return 0;
|
|
9431
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9694
9432
|
const bs = new Set(b);
|
|
9695
9433
|
let hit = 0;
|
|
9696
|
-
for (const t of a)
|
|
9697
|
-
if (bs.has(t))
|
|
9698
|
-
hit += 1;
|
|
9434
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9699
9435
|
return hit / a.length;
|
|
9700
9436
|
}
|
|
9701
9437
|
estimateTokens(text) {
|
|
@@ -9716,8 +9452,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9716
9452
|
const seen = /* @__PURE__ */ new Set();
|
|
9717
9453
|
const nodes = [];
|
|
9718
9454
|
for (const candidate of candidates) {
|
|
9719
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9720
|
-
continue;
|
|
9455
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9721
9456
|
seen.add(candidate.entityId);
|
|
9722
9457
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9723
9458
|
}
|
|
@@ -9741,16 +9476,14 @@ function graphPathScore(path13, hopPenalty) {
|
|
|
9741
9476
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path13.hops - 1));
|
|
9742
9477
|
}
|
|
9743
9478
|
function clampGraphHops(maxHops) {
|
|
9744
|
-
if (!Number.isFinite(maxHops))
|
|
9745
|
-
return 2;
|
|
9479
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9746
9480
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9747
9481
|
}
|
|
9748
9482
|
function mergeGraphPaths(existing, incoming) {
|
|
9749
9483
|
const byKey = /* @__PURE__ */ new Map();
|
|
9750
9484
|
for (const path13 of [...existing, ...incoming]) {
|
|
9751
9485
|
const key = [path13.startEntityId, path13.targetType, path13.targetId, path13.hops, ...path13.relationPath].join("\0");
|
|
9752
|
-
if (!byKey.has(key))
|
|
9753
|
-
byKey.set(key, path13);
|
|
9486
|
+
if (!byKey.has(key)) byKey.set(key, path13);
|
|
9754
9487
|
}
|
|
9755
9488
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9756
9489
|
}
|
|
@@ -9758,10 +9491,8 @@ function graphPathSignature(path13) {
|
|
|
9758
9491
|
return [path13.startEntityId, path13.targetType, path13.targetId, path13.hops, ...path13.relationPath].join("|");
|
|
9759
9492
|
}
|
|
9760
9493
|
function compareStable(a, b) {
|
|
9761
|
-
if (a < b)
|
|
9762
|
-
|
|
9763
|
-
if (a > b)
|
|
9764
|
-
return 1;
|
|
9494
|
+
if (a < b) return -1;
|
|
9495
|
+
if (a > b) return 1;
|
|
9765
9496
|
return 0;
|
|
9766
9497
|
}
|
|
9767
9498
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9773,6 +9504,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9773
9504
|
constructor(deps) {
|
|
9774
9505
|
this.deps = deps;
|
|
9775
9506
|
}
|
|
9507
|
+
deps;
|
|
9776
9508
|
async getRetrievalTraceStats() {
|
|
9777
9509
|
await this.deps.initialize();
|
|
9778
9510
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -9850,6 +9582,7 @@ var RetrievalDisclosureService = class {
|
|
|
9850
9582
|
constructor(deps) {
|
|
9851
9583
|
this.deps = deps;
|
|
9852
9584
|
}
|
|
9585
|
+
deps;
|
|
9853
9586
|
async search(query, options) {
|
|
9854
9587
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
9855
9588
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -9879,8 +9612,7 @@ var RetrievalDisclosureService = class {
|
|
|
9879
9612
|
return this.expandShared(parsedId.entryId);
|
|
9880
9613
|
}
|
|
9881
9614
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9882
|
-
if (!targetEvent)
|
|
9883
|
-
return null;
|
|
9615
|
+
if (!targetEvent) return null;
|
|
9884
9616
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
9885
9617
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
9886
9618
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -9904,8 +9636,7 @@ var RetrievalDisclosureService = class {
|
|
|
9904
9636
|
return this.sourceShared(parsedId.entryId);
|
|
9905
9637
|
}
|
|
9906
9638
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9907
|
-
if (!rawEvent)
|
|
9908
|
-
return null;
|
|
9639
|
+
if (!rawEvent) return null;
|
|
9909
9640
|
return {
|
|
9910
9641
|
...this.sourceReferenceForEvent(rawEvent),
|
|
9911
9642
|
rawEvents: [rawEvent],
|
|
@@ -9914,8 +9645,7 @@ var RetrievalDisclosureService = class {
|
|
|
9914
9645
|
}
|
|
9915
9646
|
async expandShared(entryId) {
|
|
9916
9647
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9917
|
-
if (!entry)
|
|
9918
|
-
return null;
|
|
9648
|
+
if (!entry) return null;
|
|
9919
9649
|
return {
|
|
9920
9650
|
target: this.sharedToEnvelope(entry),
|
|
9921
9651
|
surroundingFacts: [],
|
|
@@ -9926,8 +9656,7 @@ var RetrievalDisclosureService = class {
|
|
|
9926
9656
|
}
|
|
9927
9657
|
async sourceShared(entryId) {
|
|
9928
9658
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9929
|
-
if (!entry)
|
|
9930
|
-
return null;
|
|
9659
|
+
if (!entry) return null;
|
|
9931
9660
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
9932
9661
|
return {
|
|
9933
9662
|
...sourceReference,
|
|
@@ -10013,38 +9742,25 @@ var RetrievalDisclosureService = class {
|
|
|
10013
9742
|
const reasons = /* @__PURE__ */ new Set();
|
|
10014
9743
|
const usedVector = this.usedVector(result);
|
|
10015
9744
|
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");
|
|
9745
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9746
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9747
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9748
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9749
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9750
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9751
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9752
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9753
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10034
9754
|
return Array.from(reasons);
|
|
10035
9755
|
}
|
|
10036
9756
|
reasonsForContextEvent(event) {
|
|
10037
|
-
if (event.eventType === "tool_observation")
|
|
10038
|
-
|
|
10039
|
-
if (event.eventType === "session_summary")
|
|
10040
|
-
return ["summary_fallback"];
|
|
9757
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9758
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10041
9759
|
return ["continuity_link"];
|
|
10042
9760
|
}
|
|
10043
9761
|
resultTypeForEvent(event) {
|
|
10044
|
-
if (event.eventType === "session_summary")
|
|
10045
|
-
|
|
10046
|
-
if (event.eventType === "tool_observation")
|
|
10047
|
-
return "tool_evidence";
|
|
9762
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9763
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10048
9764
|
return "source";
|
|
10049
9765
|
}
|
|
10050
9766
|
sourceReferenceForEvent(event) {
|
|
@@ -10068,21 +9784,15 @@ var RetrievalDisclosureService = class {
|
|
|
10068
9784
|
}
|
|
10069
9785
|
sourceTypeForEvent(event) {
|
|
10070
9786
|
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";
|
|
9787
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9788
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9789
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10077
9790
|
return "raw_event";
|
|
10078
9791
|
}
|
|
10079
9792
|
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";
|
|
9793
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9794
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9795
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10086
9796
|
return "User prompt";
|
|
10087
9797
|
}
|
|
10088
9798
|
usedVector(result) {
|
|
@@ -10108,8 +9818,7 @@ var RetrievalDisclosureService = class {
|
|
|
10108
9818
|
}
|
|
10109
9819
|
preview(content, maxLength) {
|
|
10110
9820
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10111
|
-
if (normalized.length <= maxLength)
|
|
10112
|
-
return normalized;
|
|
9821
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10113
9822
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10114
9823
|
}
|
|
10115
9824
|
};
|
|
@@ -10138,6 +9847,7 @@ var RetrievalOrchestrator = class {
|
|
|
10138
9847
|
this.deps = deps;
|
|
10139
9848
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10140
9849
|
}
|
|
9850
|
+
deps;
|
|
10141
9851
|
/**
|
|
10142
9852
|
* Retrieve relevant memories for a query.
|
|
10143
9853
|
*/
|
|
@@ -10219,8 +9929,7 @@ var RetrievalOrchestrator = class {
|
|
|
10219
9929
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10220
9930
|
*/
|
|
10221
9931
|
async incrementMemoryAccess(eventIds) {
|
|
10222
|
-
if (eventIds.length === 0)
|
|
10223
|
-
return;
|
|
9932
|
+
if (eventIds.length === 0) return;
|
|
10224
9933
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10225
9934
|
}
|
|
10226
9935
|
/**
|
|
@@ -10233,10 +9942,8 @@ var RetrievalOrchestrator = class {
|
|
|
10233
9942
|
resolveGraphHopOptions(callerOptions) {
|
|
10234
9943
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10235
9944
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10236
|
-
if (!callerOptions)
|
|
10237
|
-
|
|
10238
|
-
if (!graphExpansion)
|
|
10239
|
-
return callerOptions;
|
|
9945
|
+
if (!callerOptions) return durableOptions;
|
|
9946
|
+
if (!graphExpansion) return callerOptions;
|
|
10240
9947
|
if (graphExpansion.enabled !== true) {
|
|
10241
9948
|
return {
|
|
10242
9949
|
...callerOptions,
|
|
@@ -10296,12 +10003,10 @@ var RetrievalOrchestrator = class {
|
|
|
10296
10003
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10297
10004
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10298
10005
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10299
|
-
if (!allFinite)
|
|
10300
|
-
return void 0;
|
|
10006
|
+
if (!allFinite) return void 0;
|
|
10301
10007
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10302
10008
|
const total = semantic + lexical + recency;
|
|
10303
|
-
if (!nonNegative || total <= 0)
|
|
10304
|
-
return void 0;
|
|
10009
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10305
10010
|
return {
|
|
10306
10011
|
semantic: semantic / total,
|
|
10307
10012
|
lexical: lexical / total,
|
|
@@ -10310,17 +10015,14 @@ var RetrievalOrchestrator = class {
|
|
|
10310
10015
|
}
|
|
10311
10016
|
async getRerankWeights(adaptive) {
|
|
10312
10017
|
const configured = this.getConfiguredRerankWeights();
|
|
10313
|
-
if (configured)
|
|
10314
|
-
|
|
10315
|
-
if (adaptive)
|
|
10316
|
-
return this.getAdaptiveRerankWeights();
|
|
10018
|
+
if (configured) return configured;
|
|
10019
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10317
10020
|
return void 0;
|
|
10318
10021
|
}
|
|
10319
10022
|
async getAdaptiveRerankWeights() {
|
|
10320
10023
|
try {
|
|
10321
10024
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10322
|
-
if (stats.totalEvaluated < 20)
|
|
10323
|
-
return void 0;
|
|
10025
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10324
10026
|
let semantic = 0.7;
|
|
10325
10027
|
let lexical = 0.2;
|
|
10326
10028
|
let recency = 0.1;
|
|
@@ -10342,11 +10044,9 @@ var RetrievalOrchestrator = class {
|
|
|
10342
10044
|
}
|
|
10343
10045
|
}
|
|
10344
10046
|
async rewriteQueryIntent(query) {
|
|
10345
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10346
|
-
return null;
|
|
10047
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10347
10048
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10348
|
-
if (!apiUrl)
|
|
10349
|
-
return null;
|
|
10049
|
+
if (!apiUrl) return null;
|
|
10350
10050
|
const controller = new AbortController();
|
|
10351
10051
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10352
10052
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10372,11 +10072,9 @@ var RetrievalOrchestrator = class {
|
|
|
10372
10072
|
signal: controller.signal
|
|
10373
10073
|
});
|
|
10374
10074
|
const text = (await res.text()).trim();
|
|
10375
|
-
if (!text)
|
|
10376
|
-
return null;
|
|
10075
|
+
if (!text) return null;
|
|
10377
10076
|
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;
|
|
10077
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10380
10078
|
return oneLine;
|
|
10381
10079
|
} catch {
|
|
10382
10080
|
return null;
|
|
@@ -10518,8 +10216,7 @@ function createMemoryEngineServices(options) {
|
|
|
10518
10216
|
};
|
|
10519
10217
|
}
|
|
10520
10218
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10521
|
-
if (options.readOnly)
|
|
10522
|
-
return false;
|
|
10219
|
+
if (options.readOnly) return false;
|
|
10523
10220
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10524
10221
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10525
10222
|
}
|
|
@@ -10553,6 +10250,9 @@ var GraduationWorker = class {
|
|
|
10553
10250
|
this.graduation = graduation;
|
|
10554
10251
|
this.config = config;
|
|
10555
10252
|
}
|
|
10253
|
+
eventStore;
|
|
10254
|
+
graduation;
|
|
10255
|
+
config;
|
|
10556
10256
|
running = false;
|
|
10557
10257
|
timeout = null;
|
|
10558
10258
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10560,8 +10260,7 @@ var GraduationWorker = class {
|
|
|
10560
10260
|
* Start the graduation worker
|
|
10561
10261
|
*/
|
|
10562
10262
|
start() {
|
|
10563
|
-
if (this.running)
|
|
10564
|
-
return;
|
|
10263
|
+
if (this.running) return;
|
|
10565
10264
|
this.running = true;
|
|
10566
10265
|
this.scheduleNext();
|
|
10567
10266
|
}
|
|
@@ -10591,8 +10290,7 @@ var GraduationWorker = class {
|
|
|
10591
10290
|
* Schedule the next graduation check
|
|
10592
10291
|
*/
|
|
10593
10292
|
scheduleNext() {
|
|
10594
|
-
if (!this.running)
|
|
10595
|
-
return;
|
|
10293
|
+
if (!this.running) return;
|
|
10596
10294
|
this.timeout = setTimeout(
|
|
10597
10295
|
() => this.run(),
|
|
10598
10296
|
this.config.evaluationIntervalMs
|
|
@@ -10602,8 +10300,7 @@ var GraduationWorker = class {
|
|
|
10602
10300
|
* Run graduation evaluation
|
|
10603
10301
|
*/
|
|
10604
10302
|
async run() {
|
|
10605
|
-
if (!this.running)
|
|
10606
|
-
return;
|
|
10303
|
+
if (!this.running) return;
|
|
10607
10304
|
try {
|
|
10608
10305
|
await this.runGraduation();
|
|
10609
10306
|
} catch (error) {
|
|
@@ -10667,10 +10364,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10667
10364
|
maxRetries: 3
|
|
10668
10365
|
};
|
|
10669
10366
|
function parseJsonArray(value) {
|
|
10670
|
-
if (Array.isArray(value))
|
|
10671
|
-
|
|
10672
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10673
|
-
return [];
|
|
10367
|
+
if (Array.isArray(value)) return value;
|
|
10368
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10674
10369
|
try {
|
|
10675
10370
|
const parsed = JSON.parse(value);
|
|
10676
10371
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10700,8 +10395,7 @@ var VectorWorker = class {
|
|
|
10700
10395
|
* Start the worker polling loop
|
|
10701
10396
|
*/
|
|
10702
10397
|
start() {
|
|
10703
|
-
if (this.running)
|
|
10704
|
-
return;
|
|
10398
|
+
if (this.running) return;
|
|
10705
10399
|
this.running = true;
|
|
10706
10400
|
this.stopping = false;
|
|
10707
10401
|
this.poll();
|
|
@@ -10777,8 +10471,7 @@ var VectorWorker = class {
|
|
|
10777
10471
|
* Poll for new items
|
|
10778
10472
|
*/
|
|
10779
10473
|
async poll() {
|
|
10780
|
-
if (!this.running || this.stopping)
|
|
10781
|
-
return;
|
|
10474
|
+
if (!this.running || this.stopping) return;
|
|
10782
10475
|
try {
|
|
10783
10476
|
await this.processBatch();
|
|
10784
10477
|
} catch (error) {
|
|
@@ -10823,6 +10516,7 @@ var DefaultContentProvider = class {
|
|
|
10823
10516
|
constructor(db) {
|
|
10824
10517
|
this.db = db;
|
|
10825
10518
|
}
|
|
10519
|
+
db;
|
|
10826
10520
|
async getContent(itemKind, itemId) {
|
|
10827
10521
|
switch (itemKind) {
|
|
10828
10522
|
case "entry":
|
|
@@ -10843,8 +10537,7 @@ var DefaultContentProvider = class {
|
|
|
10843
10537
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
10844
10538
|
[entryId]
|
|
10845
10539
|
);
|
|
10846
|
-
if (rows.length === 0)
|
|
10847
|
-
return null;
|
|
10540
|
+
if (rows.length === 0) return null;
|
|
10848
10541
|
const row = rows[0];
|
|
10849
10542
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
10850
10543
|
return {
|
|
@@ -10863,8 +10556,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10863
10556
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
10864
10557
|
[taskId]
|
|
10865
10558
|
);
|
|
10866
|
-
if (rows.length === 0)
|
|
10867
|
-
return null;
|
|
10559
|
+
if (rows.length === 0) return null;
|
|
10868
10560
|
const row = rows[0];
|
|
10869
10561
|
return {
|
|
10870
10562
|
content: row.search_text || row.title,
|
|
@@ -10880,8 +10572,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10880
10572
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
10881
10573
|
[eventId]
|
|
10882
10574
|
);
|
|
10883
|
-
if (rows.length === 0)
|
|
10884
|
-
return null;
|
|
10575
|
+
if (rows.length === 0) return null;
|
|
10885
10576
|
const row = rows[0];
|
|
10886
10577
|
return {
|
|
10887
10578
|
content: row.content,
|
|
@@ -10909,8 +10600,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10909
10600
|
}
|
|
10910
10601
|
throw error;
|
|
10911
10602
|
}
|
|
10912
|
-
if (rows.length === 0)
|
|
10913
|
-
return null;
|
|
10603
|
+
if (rows.length === 0) return null;
|
|
10914
10604
|
const row = rows[0];
|
|
10915
10605
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
10916
10606
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -10952,8 +10642,7 @@ var VectorWorkerV2 = class {
|
|
|
10952
10642
|
* Start the worker polling loop
|
|
10953
10643
|
*/
|
|
10954
10644
|
start() {
|
|
10955
|
-
if (this.running)
|
|
10956
|
-
return;
|
|
10645
|
+
if (this.running) return;
|
|
10957
10646
|
this.running = true;
|
|
10958
10647
|
this.stopping = false;
|
|
10959
10648
|
this.poll();
|
|
@@ -11023,8 +10712,7 @@ var VectorWorkerV2 = class {
|
|
|
11023
10712
|
* Poll for new jobs
|
|
11024
10713
|
*/
|
|
11025
10714
|
async poll() {
|
|
11026
|
-
if (!this.running || this.stopping)
|
|
11027
|
-
return;
|
|
10715
|
+
if (!this.running || this.stopping) return;
|
|
11028
10716
|
try {
|
|
11029
10717
|
await this.processBatch();
|
|
11030
10718
|
} catch (error) {
|
|
@@ -11091,8 +10779,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11091
10779
|
let graduationWorker = null;
|
|
11092
10780
|
return {
|
|
11093
10781
|
async initialize() {
|
|
11094
|
-
if (initialized)
|
|
11095
|
-
return;
|
|
10782
|
+
if (initialized) return;
|
|
11096
10783
|
await deps.sqliteStore.initialize();
|
|
11097
10784
|
if (deps.lightweightMode) {
|
|
11098
10785
|
initialized = true;
|
|
@@ -11186,8 +10873,7 @@ var SharedEventStore = class {
|
|
|
11186
10873
|
this.db = createDatabase(dbPath);
|
|
11187
10874
|
}
|
|
11188
10875
|
async initialize() {
|
|
11189
|
-
if (this.initialized)
|
|
11190
|
-
return;
|
|
10876
|
+
if (this.initialized) return;
|
|
11191
10877
|
await dbRun(this.db, `
|
|
11192
10878
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11193
10879
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11277,6 +10963,10 @@ var SharedPromoter = class {
|
|
|
11277
10963
|
this.embedder = embedder;
|
|
11278
10964
|
this.config = config;
|
|
11279
10965
|
}
|
|
10966
|
+
sharedStore;
|
|
10967
|
+
sharedVectorStore;
|
|
10968
|
+
embedder;
|
|
10969
|
+
config;
|
|
11280
10970
|
/**
|
|
11281
10971
|
* Check if an entry is eligible for promotion
|
|
11282
10972
|
*/
|
|
@@ -11458,6 +11148,7 @@ var SharedStore = class {
|
|
|
11458
11148
|
constructor(sharedEventStore) {
|
|
11459
11149
|
this.sharedEventStore = sharedEventStore;
|
|
11460
11150
|
}
|
|
11151
|
+
sharedEventStore;
|
|
11461
11152
|
get db() {
|
|
11462
11153
|
return this.sharedEventStore.getDatabase();
|
|
11463
11154
|
}
|
|
@@ -11562,8 +11253,7 @@ var SharedStore = class {
|
|
|
11562
11253
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11563
11254
|
[entryId]
|
|
11564
11255
|
);
|
|
11565
|
-
if (rows.length === 0)
|
|
11566
|
-
return null;
|
|
11256
|
+
if (rows.length === 0) return null;
|
|
11567
11257
|
return this.rowToEntry(rows[0]);
|
|
11568
11258
|
}
|
|
11569
11259
|
/**
|
|
@@ -11576,8 +11266,7 @@ var SharedStore = class {
|
|
|
11576
11266
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11577
11267
|
[projectHash, sourceEntryId]
|
|
11578
11268
|
);
|
|
11579
|
-
if (rows.length === 0)
|
|
11580
|
-
return null;
|
|
11269
|
+
if (rows.length === 0) return null;
|
|
11581
11270
|
return this.rowToEntry(rows[0]);
|
|
11582
11271
|
}
|
|
11583
11272
|
/**
|
|
@@ -11687,6 +11376,7 @@ var SharedVectorStore = class {
|
|
|
11687
11376
|
constructor(dbPath) {
|
|
11688
11377
|
this.dbPath = dbPath;
|
|
11689
11378
|
}
|
|
11379
|
+
dbPath;
|
|
11690
11380
|
db = null;
|
|
11691
11381
|
table = null;
|
|
11692
11382
|
tableName = "shared_knowledge";
|
|
@@ -11694,8 +11384,7 @@ var SharedVectorStore = class {
|
|
|
11694
11384
|
* Initialize LanceDB connection
|
|
11695
11385
|
*/
|
|
11696
11386
|
async initialize() {
|
|
11697
|
-
if (this.db)
|
|
11698
|
-
return;
|
|
11387
|
+
if (this.db) return;
|
|
11699
11388
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11700
11389
|
try {
|
|
11701
11390
|
const tables = await this.db.tableNames();
|
|
@@ -11737,8 +11426,7 @@ var SharedVectorStore = class {
|
|
|
11737
11426
|
* Add multiple records in batch
|
|
11738
11427
|
*/
|
|
11739
11428
|
async upsertBatch(records) {
|
|
11740
|
-
if (records.length === 0)
|
|
11741
|
-
return;
|
|
11429
|
+
if (records.length === 0) return;
|
|
11742
11430
|
await this.initialize();
|
|
11743
11431
|
if (!this.db) {
|
|
11744
11432
|
throw new Error("Database not initialized");
|
|
@@ -11799,24 +11487,21 @@ var SharedVectorStore = class {
|
|
|
11799
11487
|
* Delete vector by entry ID
|
|
11800
11488
|
*/
|
|
11801
11489
|
async delete(entryId) {
|
|
11802
|
-
if (!this.table)
|
|
11803
|
-
return;
|
|
11490
|
+
if (!this.table) return;
|
|
11804
11491
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11805
11492
|
}
|
|
11806
11493
|
/**
|
|
11807
11494
|
* Get total count
|
|
11808
11495
|
*/
|
|
11809
11496
|
async count() {
|
|
11810
|
-
if (!this.table)
|
|
11811
|
-
return 0;
|
|
11497
|
+
if (!this.table) return 0;
|
|
11812
11498
|
return this.table.countRows();
|
|
11813
11499
|
}
|
|
11814
11500
|
/**
|
|
11815
11501
|
* Check if vector exists for entry
|
|
11816
11502
|
*/
|
|
11817
11503
|
async exists(entryId) {
|
|
11818
|
-
if (!this.table)
|
|
11819
|
-
return false;
|
|
11504
|
+
if (!this.table) return false;
|
|
11820
11505
|
try {
|
|
11821
11506
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11822
11507
|
return results.length > 0;
|
|
@@ -11834,6 +11519,7 @@ var SharedMemoryServices = class {
|
|
|
11834
11519
|
constructor(options) {
|
|
11835
11520
|
this.options = options;
|
|
11836
11521
|
}
|
|
11522
|
+
options;
|
|
11837
11523
|
sharedEventStore = null;
|
|
11838
11524
|
sharedStore = null;
|
|
11839
11525
|
sharedVectorStore = null;
|
|
@@ -11858,8 +11544,7 @@ var SharedMemoryServices = class {
|
|
|
11858
11544
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
11859
11545
|
}
|
|
11860
11546
|
async initialize() {
|
|
11861
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
11862
|
-
return;
|
|
11547
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
11863
11548
|
const sharedPath = this.getSharedStoragePath();
|
|
11864
11549
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
11865
11550
|
const store = await this.openStore(sharedPath);
|
|
@@ -11876,14 +11561,11 @@ var SharedMemoryServices = class {
|
|
|
11876
11561
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
11877
11562
|
}
|
|
11878
11563
|
async ensureStoreForRead() {
|
|
11879
|
-
if (this.options.config?.enabled === false)
|
|
11880
|
-
|
|
11881
|
-
if (this.sharedStore)
|
|
11882
|
-
return this.sharedStore;
|
|
11564
|
+
if (this.options.config?.enabled === false) return null;
|
|
11565
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11883
11566
|
const sharedPath = this.getSharedStoragePath();
|
|
11884
11567
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
11885
|
-
if (!directoryReady)
|
|
11886
|
-
return null;
|
|
11568
|
+
if (!directoryReady) return null;
|
|
11887
11569
|
return this.openStore(sharedPath);
|
|
11888
11570
|
}
|
|
11889
11571
|
async getEntryForDisclosure(entryId) {
|
|
@@ -11900,13 +11582,11 @@ var SharedMemoryServices = class {
|
|
|
11900
11582
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
11901
11583
|
}
|
|
11902
11584
|
async getStats() {
|
|
11903
|
-
if (!this.sharedStore)
|
|
11904
|
-
return null;
|
|
11585
|
+
if (!this.sharedStore) return null;
|
|
11905
11586
|
return this.sharedStore.getStats();
|
|
11906
11587
|
}
|
|
11907
11588
|
async search(query, options) {
|
|
11908
|
-
if (!this.sharedStore)
|
|
11909
|
-
return [];
|
|
11589
|
+
if (!this.sharedStore) return [];
|
|
11910
11590
|
return this.sharedStore.search(query, options);
|
|
11911
11591
|
}
|
|
11912
11592
|
async close() {
|
|
@@ -11923,8 +11603,7 @@ var SharedMemoryServices = class {
|
|
|
11923
11603
|
this.openStorePromise = null;
|
|
11924
11604
|
}
|
|
11925
11605
|
async openStore(sharedPath) {
|
|
11926
|
-
if (this.sharedStore)
|
|
11927
|
-
return this.sharedStore;
|
|
11606
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11928
11607
|
if (!this.openStorePromise) {
|
|
11929
11608
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
11930
11609
|
}
|
|
@@ -11948,10 +11627,8 @@ var SharedMemoryServices = class {
|
|
|
11948
11627
|
return this.sharedStore;
|
|
11949
11628
|
}
|
|
11950
11629
|
ensureDirectory(sharedPath, options) {
|
|
11951
|
-
if (this.factories.existsSync(sharedPath))
|
|
11952
|
-
|
|
11953
|
-
if (!options.allowCreate)
|
|
11954
|
-
return false;
|
|
11630
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11631
|
+
if (!options.allowCreate) return false;
|
|
11955
11632
|
this.factories.mkdirSync(sharedPath);
|
|
11956
11633
|
return true;
|
|
11957
11634
|
}
|
|
@@ -13158,15 +12835,13 @@ function countRowValue(db, sql, params = []) {
|
|
|
13158
12835
|
return Number(row?.count ?? 0);
|
|
13159
12836
|
}
|
|
13160
12837
|
function projectFilter(projectHash, column = "project_hash") {
|
|
13161
|
-
if (!projectHash)
|
|
13162
|
-
return { clause: "", params: [] };
|
|
12838
|
+
if (!projectHash) return { clause: "", params: [] };
|
|
13163
12839
|
return { clause: `WHERE ${column} = ?`, params: [projectHash] };
|
|
13164
12840
|
}
|
|
13165
12841
|
function sanitizeAggregateLabel(value) {
|
|
13166
12842
|
const raw = typeof value === "string" ? value : String(value ?? "unknown");
|
|
13167
12843
|
const sanitized = String(sanitizeGovernanceAuditValue(raw));
|
|
13168
|
-
if (sanitized !== raw || sanitized.includes("[REDACTED]"))
|
|
13169
|
-
return "[REDACTED]";
|
|
12844
|
+
if (sanitized !== raw || sanitized.includes("[REDACTED]")) return "[REDACTED]";
|
|
13170
12845
|
const trimmed = sanitized.trim();
|
|
13171
12846
|
return trimmed.length > 0 ? trimmed.slice(0, 96) : "unknown";
|
|
13172
12847
|
}
|
|
@@ -13510,8 +13185,7 @@ function buildPerspectiveSourceEvidence(db, projectHash) {
|
|
|
13510
13185
|
function sortCountRows(rows, labelKey) {
|
|
13511
13186
|
return [...rows].sort((a, b) => {
|
|
13512
13187
|
const countDiff = Number(b.count ?? 0) - Number(a.count ?? 0);
|
|
13513
|
-
if (countDiff !== 0)
|
|
13514
|
-
return countDiff;
|
|
13188
|
+
if (countDiff !== 0) return countDiff;
|
|
13515
13189
|
return String(a[labelKey] ?? "").localeCompare(String(b[labelKey] ?? ""));
|
|
13516
13190
|
});
|
|
13517
13191
|
}
|
|
@@ -13594,8 +13268,7 @@ var DEFAULT_KPI_THRESHOLDS = {
|
|
|
13594
13268
|
function loadKpiThresholds() {
|
|
13595
13269
|
try {
|
|
13596
13270
|
const filePath = path11.resolve(process.cwd(), "config", "kpi-thresholds.json");
|
|
13597
|
-
if (!fs9.existsSync(filePath))
|
|
13598
|
-
return DEFAULT_KPI_THRESHOLDS;
|
|
13271
|
+
if (!fs9.existsSync(filePath)) return DEFAULT_KPI_THRESHOLDS;
|
|
13599
13272
|
const parsed = JSON.parse(fs9.readFileSync(filePath, "utf-8"));
|
|
13600
13273
|
return {
|
|
13601
13274
|
usefulRecallRateMin: Number(parsed.usefulRecallRateMin ?? DEFAULT_KPI_THRESHOLDS.usefulRecallRateMin),
|
|
@@ -13609,10 +13282,8 @@ function loadKpiThresholds() {
|
|
|
13609
13282
|
}
|
|
13610
13283
|
}
|
|
13611
13284
|
function windowToMs(window) {
|
|
13612
|
-
if (window === "24h")
|
|
13613
|
-
|
|
13614
|
-
if (window === "7d")
|
|
13615
|
-
return 7 * 24 * 60 * 60 * 1e3;
|
|
13285
|
+
if (window === "24h") return 24 * 60 * 60 * 1e3;
|
|
13286
|
+
if (window === "7d") return 7 * 24 * 60 * 60 * 1e3;
|
|
13616
13287
|
return 30 * 24 * 60 * 60 * 1e3;
|
|
13617
13288
|
}
|
|
13618
13289
|
function inWindow(e, now, window) {
|
|
@@ -13622,8 +13293,7 @@ function isEditToolName(name) {
|
|
|
13622
13293
|
return ["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(name);
|
|
13623
13294
|
}
|
|
13624
13295
|
function parseToolPayload(e) {
|
|
13625
|
-
if (e.eventType !== "tool_observation")
|
|
13626
|
-
return null;
|
|
13296
|
+
if (e.eventType !== "tool_observation") return null;
|
|
13627
13297
|
try {
|
|
13628
13298
|
const payload = JSON.parse(e.content);
|
|
13629
13299
|
return {
|
|
@@ -13642,13 +13312,11 @@ function parseToolPayload(e) {
|
|
|
13642
13312
|
}
|
|
13643
13313
|
}
|
|
13644
13314
|
function isTestLikeCommand(command) {
|
|
13645
|
-
if (!command)
|
|
13646
|
-
return false;
|
|
13315
|
+
if (!command) return false;
|
|
13647
13316
|
return /(test|jest|vitest|pytest|go test|cargo test|lint|eslint|build|tsc)/i.test(command);
|
|
13648
13317
|
}
|
|
13649
13318
|
function safeRatio(num, den) {
|
|
13650
|
-
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0)
|
|
13651
|
-
return 0;
|
|
13319
|
+
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0) return 0;
|
|
13652
13320
|
return num / den;
|
|
13653
13321
|
}
|
|
13654
13322
|
function round(value, digits = 4) {
|
|
@@ -13659,28 +13327,23 @@ function computeSessionTurnCount(sessionEvents) {
|
|
|
13659
13327
|
const turnIds = /* @__PURE__ */ new Set();
|
|
13660
13328
|
for (const e of sessionEvents) {
|
|
13661
13329
|
const turnId = e.metadata?.turnId;
|
|
13662
|
-
if (typeof turnId === "string" && turnId.length > 0)
|
|
13663
|
-
turnIds.add(turnId);
|
|
13330
|
+
if (typeof turnId === "string" && turnId.length > 0) turnIds.add(turnId);
|
|
13664
13331
|
}
|
|
13665
|
-
if (turnIds.size > 0)
|
|
13666
|
-
return turnIds.size;
|
|
13332
|
+
if (turnIds.size > 0) return turnIds.size;
|
|
13667
13333
|
return sessionEvents.filter((e) => e.eventType === "user_prompt").length;
|
|
13668
13334
|
}
|
|
13669
13335
|
function normalizeQueryRewriteKind2(value) {
|
|
13670
13336
|
const normalized = (value || "").trim().toLowerCase();
|
|
13671
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
13672
|
-
return normalized;
|
|
13337
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
13673
13338
|
return "none";
|
|
13674
13339
|
}
|
|
13675
13340
|
function normalizeMetric(value) {
|
|
13676
13341
|
const numberValue = Number(value || 0);
|
|
13677
|
-
if (!Number.isFinite(numberValue))
|
|
13678
|
-
return 0;
|
|
13342
|
+
if (!Number.isFinite(numberValue)) return 0;
|
|
13679
13343
|
return Math.max(0, Math.min(1, numberValue));
|
|
13680
13344
|
}
|
|
13681
13345
|
function getTimestampMs(value) {
|
|
13682
|
-
if (value instanceof Date)
|
|
13683
|
-
return value.getTime();
|
|
13346
|
+
if (value instanceof Date) return value.getTime();
|
|
13684
13347
|
if (typeof value === "string") {
|
|
13685
13348
|
const parsed = new Date(value).getTime();
|
|
13686
13349
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
@@ -13738,8 +13401,7 @@ function makeRetrievalReviewItem(trace) {
|
|
|
13738
13401
|
detail = `${selectedCount} of ${candidateCount} candidates were selected.`;
|
|
13739
13402
|
action = "Inspect score distribution and MMR/diversity settings before lowering thresholds.";
|
|
13740
13403
|
}
|
|
13741
|
-
if (!reason)
|
|
13742
|
-
return null;
|
|
13404
|
+
if (!reason) return null;
|
|
13743
13405
|
return {
|
|
13744
13406
|
traceId: trace.traceId || "unknown-trace",
|
|
13745
13407
|
reason,
|
|
@@ -13788,24 +13450,17 @@ function buildRetrievalReviewQueue(traces, limit) {
|
|
|
13788
13450
|
};
|
|
13789
13451
|
}
|
|
13790
13452
|
function parseStatsLimit(value, fallback, max) {
|
|
13791
|
-
if (!value)
|
|
13792
|
-
|
|
13793
|
-
if (!/^\d+$/.test(value))
|
|
13794
|
-
return fallback;
|
|
13453
|
+
if (!value) return fallback;
|
|
13454
|
+
if (!/^\d+$/.test(value)) return fallback;
|
|
13795
13455
|
const parsed = Number(value);
|
|
13796
|
-
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
13797
|
-
return fallback;
|
|
13456
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
13798
13457
|
return Math.min(parsed, max);
|
|
13799
13458
|
}
|
|
13800
13459
|
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";
|
|
13460
|
+
if (confidence <= 0) return "unknown";
|
|
13461
|
+
if (score >= 80) return "excellent";
|
|
13462
|
+
if (score >= 60) return "good";
|
|
13463
|
+
if (score >= 40) return "watch";
|
|
13809
13464
|
return "low";
|
|
13810
13465
|
}
|
|
13811
13466
|
function buildMemoryUsefulnessDiagnostics(input) {
|
|
@@ -14051,8 +13706,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14051
13706
|
let seenEdit = false;
|
|
14052
13707
|
for (const e of sorted) {
|
|
14053
13708
|
const payload = parseToolPayload(e);
|
|
14054
|
-
if (!payload?.toolName)
|
|
14055
|
-
continue;
|
|
13709
|
+
if (!payload?.toolName) continue;
|
|
14056
13710
|
if (isEditToolName(payload.toolName) && payload.success === true) {
|
|
14057
13711
|
editActions.push({ sessionId, timestamp: e.timestamp.getTime(), filePath: payload.filePath });
|
|
14058
13712
|
seenEdit = true;
|
|
@@ -14060,8 +13714,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14060
13714
|
}
|
|
14061
13715
|
if (seenEdit && isTestLikeCommand(payload.command)) {
|
|
14062
13716
|
testRunsAfterEdit++;
|
|
14063
|
-
if (payload.success === false)
|
|
14064
|
-
failedTestRunsAfterEdit++;
|
|
13717
|
+
if (payload.success === false) failedTestRunsAfterEdit++;
|
|
14065
13718
|
}
|
|
14066
13719
|
}
|
|
14067
13720
|
}
|
|
@@ -14070,8 +13723,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14070
13723
|
const bySessionFile = /* @__PURE__ */ new Map();
|
|
14071
13724
|
const sortedEdits = [...editActions].sort((a, b) => a.timestamp - b.timestamp);
|
|
14072
13725
|
for (const edit of sortedEdits) {
|
|
14073
|
-
if (!edit.filePath)
|
|
14074
|
-
continue;
|
|
13726
|
+
if (!edit.filePath) continue;
|
|
14075
13727
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14076
13728
|
const prev = bySessionFile.get(key);
|
|
14077
13729
|
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) {
|
|
@@ -14446,12 +14098,9 @@ statsRouter.get("/timeline", async (c) => {
|
|
|
14446
14098
|
acc[day] = { date: day, total: 0, prompts: 0, responses: 0, tools: 0 };
|
|
14447
14099
|
}
|
|
14448
14100
|
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++;
|
|
14101
|
+
if (e.eventType === "user_prompt") acc[day].prompts++;
|
|
14102
|
+
if (e.eventType === "agent_response") acc[day].responses++;
|
|
14103
|
+
if (e.eventType === "tool_observation") acc[day].tools++;
|
|
14455
14104
|
return acc;
|
|
14456
14105
|
}, {});
|
|
14457
14106
|
return c.json({
|
|
@@ -14662,8 +14311,7 @@ statsRouter.get("/kpi", async (c) => {
|
|
|
14662
14311
|
for (const edit of dayEditActions) {
|
|
14663
14312
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14664
14313
|
const prev = dayBySessionFile.get(key);
|
|
14665
|
-
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS)
|
|
14666
|
-
dayReworkCount++;
|
|
14314
|
+
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) dayReworkCount++;
|
|
14667
14315
|
dayBySessionFile.set(key, edit.timestamp);
|
|
14668
14316
|
}
|
|
14669
14317
|
const dayTests = dayEvents.filter((e) => {
|
|
@@ -15003,8 +14651,7 @@ projectsRouter.get("/", async (c) => {
|
|
|
15003
14651
|
}
|
|
15004
14652
|
});
|
|
15005
14653
|
function formatBytes(bytes) {
|
|
15006
|
-
if (bytes === 0)
|
|
15007
|
-
return "0 B";
|
|
14654
|
+
if (bytes === 0) return "0 B";
|
|
15008
14655
|
const k = 1024;
|
|
15009
14656
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
15010
14657
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
@@ -15022,6 +14669,7 @@ var ProviderFailure = class extends Error {
|
|
|
15022
14669
|
this.code = code;
|
|
15023
14670
|
this.name = "ProviderFailure";
|
|
15024
14671
|
}
|
|
14672
|
+
code;
|
|
15025
14673
|
};
|
|
15026
14674
|
var CLAUDE_TIMEOUT_MS = 12e4;
|
|
15027
14675
|
chatRouter.post("/", async (c) => {
|
|
@@ -15098,8 +14746,7 @@ async function collectMemoryContext(memoryService, query) {
|
|
|
15098
14746
|
async function collectStatsContext(memoryService) {
|
|
15099
14747
|
try {
|
|
15100
14748
|
const stats = await memoryService.getStats?.();
|
|
15101
|
-
if (!stats)
|
|
15102
|
-
return "";
|
|
14749
|
+
if (!stats) return "";
|
|
15103
14750
|
const levels = stats.levelStats.map((l) => `${l.level}: ${l.count}`).join(", ");
|
|
15104
14751
|
return [
|
|
15105
14752
|
"## Memory Stats",
|
|
@@ -15112,8 +14759,7 @@ async function collectStatsContext(memoryService) {
|
|
|
15112
14759
|
}
|
|
15113
14760
|
}
|
|
15114
14761
|
function formatMemoryContext(memoryHits) {
|
|
15115
|
-
if (memoryHits.length === 0)
|
|
15116
|
-
return "";
|
|
14762
|
+
if (memoryHits.length === 0) return "";
|
|
15117
14763
|
const parts = ["## Relevant Memories\n"];
|
|
15118
14764
|
for (const m of memoryHits) {
|
|
15119
14765
|
const date = m.event.timestamp ? new Date(m.event.timestamp).toISOString().split("T")[0] : "unknown-date";
|
|
@@ -15235,8 +14881,7 @@ function streamClaudeResponse(prompt, stream) {
|
|
|
15235
14881
|
const lines = buffer.split("\n");
|
|
15236
14882
|
buffer = lines.pop() || "";
|
|
15237
14883
|
for (const line of lines) {
|
|
15238
|
-
if (!line.trim())
|
|
15239
|
-
continue;
|
|
14884
|
+
if (!line.trim()) continue;
|
|
15240
14885
|
try {
|
|
15241
14886
|
const parsed = JSON.parse(line);
|
|
15242
14887
|
if (parsed.type === "assistant" && parsed.message?.content) {
|