@remnic/core 9.3.636 → 9.3.638
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +12 -12
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +8 -6
- package/dist/access-mcp.d.ts +2 -2
- package/dist/access-mcp.js +7 -5
- package/dist/{access-service-GVOE5U3C.d.ts → access-service-DvEvBv9_.d.ts} +2 -1
- package/dist/access-service.d.ts +2 -2
- package/dist/access-service.js +6 -4
- package/dist/active-recall.js +1 -1
- package/dist/bootstrap.d.ts +1 -1
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +2 -2
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +1 -1
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-VTH5SKQW.js → chunk-2JIYTTQJ.js} +4 -4
- package/dist/{chunk-HZVIYZYN.js → chunk-7KRYJUTB.js} +6 -6
- package/dist/{chunk-7H5WCPBS.js → chunk-A3HKTPPV.js} +21 -6
- package/dist/chunk-A3HKTPPV.js.map +1 -0
- package/dist/{chunk-2IT7WFYE.js → chunk-FWIROLS6.js} +2 -1
- package/dist/chunk-FWIROLS6.js.map +1 -0
- package/dist/{chunk-JYFO32V4.js → chunk-I3YAA4BI.js} +9 -9
- package/dist/{chunk-A6D7A2FW.js → chunk-IHG27THY.js} +4 -4
- package/dist/{chunk-W25I7G6U.js → chunk-KXTLEB4L.js} +3 -3
- package/dist/{chunk-XM6M6DHG.js → chunk-MNDFVT4F.js} +195 -6
- package/dist/chunk-MNDFVT4F.js.map +1 -0
- package/dist/{chunk-7V2SGZ3H.js → chunk-NE566K4E.js} +2 -2
- package/dist/{chunk-NFNQ7TWF.js → chunk-OSPVAP56.js} +3 -3
- package/dist/{chunk-UXFOGILU.js → chunk-QDAWVW75.js} +1 -1
- package/dist/{chunk-TQOU3VAT.js → chunk-SSOMTUCA.js} +1 -1
- package/dist/{chunk-TFICNXXU.js → chunk-TJRV4MWX.js} +990 -252
- package/dist/chunk-TJRV4MWX.js.map +1 -0
- package/dist/{chunk-BK35NOJL.js → chunk-U2YPUWRB.js} +3 -3
- package/dist/{chunk-EWC6W6AB.js → chunk-UXA5L2DZ.js} +2 -2
- package/dist/{chunk-XL7FK7PJ.js → chunk-Y56J7CXW.js} +33 -16
- package/dist/{chunk-XL7FK7PJ.js.map → chunk-Y56J7CXW.js.map} +1 -1
- package/dist/{cli-B-fHk59D.d.ts → cli-BJBKNWIS.d.ts} +2 -2
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +13 -12
- package/dist/compounding/engine.js +1 -1
- package/dist/config.js +1 -1
- package/dist/explicit-capture.d.ts +1 -1
- package/dist/{graph-edge-decay-5ZOK7ZNO.js → graph-edge-decay-PUFNHOBS.js} +2 -2
- package/dist/graph-snapshot.js +2 -2
- package/dist/graph.d.ts +3 -0
- package/dist/graph.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +17 -17
- package/dist/mcp-memory-inspector-app.d.ts +2 -2
- package/dist/operator-toolkit.js +3 -3
- package/dist/{orchestrator-CoqytbK_.d.ts → orchestrator-ibTTeoUa.d.ts} +9 -0
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +9 -9
- package/dist/recall-state.d.ts +2 -0
- package/dist/recall-state.js +1 -1
- package/dist/resume-bundles.js +4 -4
- package/dist/summarizer.js +2 -2
- package/dist/transcript.js +2 -2
- package/package.json +1 -1
- package/src/access-service-namespace.test.ts +740 -0
- package/src/access-service.ts +222 -3
- package/src/config.test.ts +118 -0
- package/src/config.ts +45 -10
- package/src/graph.ts +39 -17
- package/src/orchestrator.ts +1286 -331
- package/src/recall-state.ts +3 -0
- package/dist/chunk-2IT7WFYE.js.map +0 -1
- package/dist/chunk-7H5WCPBS.js.map +0 -1
- package/dist/chunk-TFICNXXU.js.map +0 -1
- package/dist/chunk-XM6M6DHG.js.map +0 -1
- /package/dist/{chunk-VTH5SKQW.js.map → chunk-2JIYTTQJ.js.map} +0 -0
- /package/dist/{chunk-HZVIYZYN.js.map → chunk-7KRYJUTB.js.map} +0 -0
- /package/dist/{chunk-JYFO32V4.js.map → chunk-I3YAA4BI.js.map} +0 -0
- /package/dist/{chunk-A6D7A2FW.js.map → chunk-IHG27THY.js.map} +0 -0
- /package/dist/{chunk-W25I7G6U.js.map → chunk-KXTLEB4L.js.map} +0 -0
- /package/dist/{chunk-7V2SGZ3H.js.map → chunk-NE566K4E.js.map} +0 -0
- /package/dist/{chunk-NFNQ7TWF.js.map → chunk-OSPVAP56.js.map} +0 -0
- /package/dist/{chunk-UXFOGILU.js.map → chunk-QDAWVW75.js.map} +0 -0
- /package/dist/{chunk-TQOU3VAT.js.map → chunk-SSOMTUCA.js.map} +0 -0
- /package/dist/{chunk-BK35NOJL.js.map → chunk-U2YPUWRB.js.map} +0 -0
- /package/dist/{chunk-EWC6W6AB.js.map → chunk-UXA5L2DZ.js.map} +0 -0
- /package/dist/{graph-edge-decay-5ZOK7ZNO.js.map → graph-edge-decay-PUFNHOBS.js.map} +0 -0
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
import {
|
|
30
30
|
CompoundingEngine,
|
|
31
31
|
defaultTierMigrationCycleBudget
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-QDAWVW75.js";
|
|
33
33
|
import {
|
|
34
34
|
SharedContextManager
|
|
35
35
|
} from "./chunk-DRD2Q7HQ.js";
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
} from "./chunk-VOUOLGIP.js";
|
|
65
65
|
import {
|
|
66
66
|
HourlySummarizer
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-7KRYJUTB.js";
|
|
68
68
|
import {
|
|
69
69
|
SessionObserverState
|
|
70
70
|
} from "./chunk-MHQC2WU2.js";
|
|
@@ -113,7 +113,7 @@ import {
|
|
|
113
113
|
LastRecallStore,
|
|
114
114
|
TierMigrationStatusStore,
|
|
115
115
|
clampGraphRecallExpandedEntries
|
|
116
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-FWIROLS6.js";
|
|
117
117
|
import {
|
|
118
118
|
buildQmdRecallCacheKey,
|
|
119
119
|
getCachedQmdRecall,
|
|
@@ -231,7 +231,7 @@ import {
|
|
|
231
231
|
} from "./chunk-ZRWB5D4H.js";
|
|
232
232
|
import {
|
|
233
233
|
TranscriptManager
|
|
234
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-IHG27THY.js";
|
|
235
235
|
import {
|
|
236
236
|
NamespaceStorageRouter
|
|
237
237
|
} from "./chunk-LEG7XWS2.js";
|
|
@@ -308,6 +308,9 @@ import {
|
|
|
308
308
|
listTrustZoneRecords,
|
|
309
309
|
searchTrustZoneRecords
|
|
310
310
|
} from "./chunk-JGSKJHF7.js";
|
|
311
|
+
import {
|
|
312
|
+
isPathInsideStorageRoot
|
|
313
|
+
} from "./chunk-FF4KLI5W.js";
|
|
311
314
|
import {
|
|
312
315
|
buildXraySnapshot
|
|
313
316
|
} from "./chunk-YQNADJCT.js";
|
|
@@ -345,7 +348,7 @@ import {
|
|
|
345
348
|
} from "./chunk-H3PHZLMF.js";
|
|
346
349
|
import {
|
|
347
350
|
GraphIndex
|
|
348
|
-
} from "./chunk-
|
|
351
|
+
} from "./chunk-Y56J7CXW.js";
|
|
349
352
|
import {
|
|
350
353
|
buildChainFollowupGenerator
|
|
351
354
|
} from "./chunk-CMN5AWAZ.js";
|
|
@@ -387,7 +390,7 @@ import {
|
|
|
387
390
|
} from "./chunk-FVQJYWH7.js";
|
|
388
391
|
import {
|
|
389
392
|
searchCausalTrajectories
|
|
390
|
-
} from "./chunk-
|
|
393
|
+
} from "./chunk-SSOMTUCA.js";
|
|
391
394
|
import {
|
|
392
395
|
canReadNamespace,
|
|
393
396
|
defaultNamespaceForPrincipal,
|
|
@@ -416,6 +419,9 @@ import {
|
|
|
416
419
|
keyring_exports,
|
|
417
420
|
secureStoreDir
|
|
418
421
|
} from "./chunk-BJMBJZ2Y.js";
|
|
422
|
+
import {
|
|
423
|
+
SecureStoreLockedError
|
|
424
|
+
} from "./chunk-ILXTATKK.js";
|
|
419
425
|
import {
|
|
420
426
|
parseFlexibleIsoTimestamp
|
|
421
427
|
} from "./chunk-P7FMDTKL.js";
|
|
@@ -1633,6 +1639,42 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
|
|
|
1633
1639
|
}
|
|
1634
1640
|
}
|
|
1635
1641
|
}
|
|
1642
|
+
function qmdCollectionPathParts(resultPath) {
|
|
1643
|
+
if (!resultPath || path2.isAbsolute(resultPath)) return null;
|
|
1644
|
+
const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
1645
|
+
const slashIndex = normalized.indexOf("/");
|
|
1646
|
+
if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
|
|
1647
|
+
const collection = normalized.slice(0, slashIndex);
|
|
1648
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(collection)) return null;
|
|
1649
|
+
return {
|
|
1650
|
+
collection,
|
|
1651
|
+
relativePath: normalized.slice(slashIndex + 1)
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
function qmdResultPathCandidates(storageDir, resultPath) {
|
|
1655
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
1656
|
+
const storageRoot = path2.resolve(storageDir);
|
|
1657
|
+
const addCandidate = (candidate) => {
|
|
1658
|
+
const resolved = path2.resolve(candidate);
|
|
1659
|
+
if (isPathInsideStorageRoot(storageRoot, resolved)) {
|
|
1660
|
+
candidates.add(resolved);
|
|
1661
|
+
}
|
|
1662
|
+
};
|
|
1663
|
+
const addRelativeCandidates = (relativePath) => {
|
|
1664
|
+
const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
1665
|
+
if (!normalized) return;
|
|
1666
|
+
addCandidate(path2.join(storageRoot, normalized));
|
|
1667
|
+
if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
|
|
1668
|
+
addCandidate(path2.join(storageRoot, "facts", normalized));
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
if (path2.isAbsolute(resultPath)) {
|
|
1672
|
+
addCandidate(resultPath);
|
|
1673
|
+
} else {
|
|
1674
|
+
addRelativeCandidates(resultPath);
|
|
1675
|
+
}
|
|
1676
|
+
return [...candidates];
|
|
1677
|
+
}
|
|
1636
1678
|
var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
1637
1679
|
var DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS = 1e4;
|
|
1638
1680
|
function qmdStartupCollectionCheckTimeoutMs() {
|
|
@@ -5334,16 +5376,74 @@ ${r.snippet.trim()}
|
|
|
5334
5376
|
return capped;
|
|
5335
5377
|
}
|
|
5336
5378
|
async expandResultsViaGraph(options) {
|
|
5379
|
+
const deadlineExpired = () => typeof options.deadlineAtMs === "number" && Date.now() >= options.deadlineAtMs;
|
|
5337
5380
|
const byNamespace = /* @__PURE__ */ new Map();
|
|
5338
|
-
|
|
5339
|
-
const
|
|
5340
|
-
if (!options.recallNamespaces.includes(ns)) continue;
|
|
5341
|
-
const existing = byNamespace.get(ns);
|
|
5381
|
+
const addResultForNamespace = (namespace, result) => {
|
|
5382
|
+
const existing = byNamespace.get(namespace);
|
|
5342
5383
|
if (existing) {
|
|
5343
5384
|
existing.push(result);
|
|
5344
5385
|
} else {
|
|
5345
|
-
byNamespace.set(
|
|
5386
|
+
byNamespace.set(namespace, [result]);
|
|
5346
5387
|
}
|
|
5388
|
+
};
|
|
5389
|
+
const resolvedAmbiguousSeeds = /* @__PURE__ */ new Map();
|
|
5390
|
+
const resolveAmbiguousSeedOwner = async (result, parts) => {
|
|
5391
|
+
const cached = resolvedAmbiguousSeeds.get(result.path);
|
|
5392
|
+
if (cached !== void 0) return cached;
|
|
5393
|
+
if (deadlineExpired()) {
|
|
5394
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
5395
|
+
return null;
|
|
5396
|
+
}
|
|
5397
|
+
let resolvedPath = result.path;
|
|
5398
|
+
let resolvedResult = result;
|
|
5399
|
+
if (parts) {
|
|
5400
|
+
const resolvedCold = await this.resolveColdQmdResultForRecall(
|
|
5401
|
+
result,
|
|
5402
|
+
this.storage,
|
|
5403
|
+
options.recallNamespaces
|
|
5404
|
+
);
|
|
5405
|
+
if (!resolvedCold || deadlineExpired()) {
|
|
5406
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
5407
|
+
return null;
|
|
5408
|
+
}
|
|
5409
|
+
resolvedPath = resolvedCold.result.path;
|
|
5410
|
+
resolvedResult = resolvedCold.result;
|
|
5411
|
+
}
|
|
5412
|
+
if (!path2.isAbsolute(resolvedPath)) {
|
|
5413
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
5414
|
+
return null;
|
|
5415
|
+
}
|
|
5416
|
+
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
5417
|
+
resolvedPath,
|
|
5418
|
+
this.storage,
|
|
5419
|
+
options.recallNamespaces
|
|
5420
|
+
);
|
|
5421
|
+
const ownerNamespace = ownerStorage?.namespace ?? null;
|
|
5422
|
+
const resolved = ownerNamespace && options.recallNamespaces.includes(ownerNamespace) ? { namespace: ownerNamespace, result: resolvedResult } : null;
|
|
5423
|
+
resolvedAmbiguousSeeds.set(result.path, resolved);
|
|
5424
|
+
return resolved;
|
|
5425
|
+
};
|
|
5426
|
+
const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
5427
|
+
for (const result of options.memoryResults) {
|
|
5428
|
+
if (deadlineExpired()) break;
|
|
5429
|
+
const parts = qmdCollectionPathParts(result.path);
|
|
5430
|
+
if (parts?.collection === coldCollection) {
|
|
5431
|
+
const resolved = await resolveAmbiguousSeedOwner(result, parts);
|
|
5432
|
+
if (resolved) {
|
|
5433
|
+
addResultForNamespace(resolved.namespace, resolved.result);
|
|
5434
|
+
}
|
|
5435
|
+
continue;
|
|
5436
|
+
}
|
|
5437
|
+
if (path2.isAbsolute(result.path)) {
|
|
5438
|
+
const resolved = await resolveAmbiguousSeedOwner(result, null);
|
|
5439
|
+
if (resolved) {
|
|
5440
|
+
addResultForNamespace(resolved.namespace, resolved.result);
|
|
5441
|
+
}
|
|
5442
|
+
continue;
|
|
5443
|
+
}
|
|
5444
|
+
const ns = this.namespaceFromPath(result.path);
|
|
5445
|
+
if (!options.recallNamespaces.includes(ns)) continue;
|
|
5446
|
+
addResultForNamespace(ns, result);
|
|
5347
5447
|
}
|
|
5348
5448
|
const perNamespaceSeedCap = Math.max(3, options.recallResultLimit);
|
|
5349
5449
|
const perNamespaceExpandedCap = Math.max(8, options.recallResultLimit * 2);
|
|
@@ -5352,12 +5452,25 @@ ${r.snippet.trim()}
|
|
|
5352
5452
|
const expandedPaths = [];
|
|
5353
5453
|
const expandedResults = [];
|
|
5354
5454
|
for (const [namespace, nsResults] of byNamespace.entries()) {
|
|
5455
|
+
if (deadlineExpired()) break;
|
|
5355
5456
|
const storage = await this.storageRouter.storageFor(namespace);
|
|
5356
5457
|
const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);
|
|
5357
5458
|
seedResults.push(...seedCandidates);
|
|
5358
|
-
const seedRelativePaths =
|
|
5459
|
+
const seedRelativePaths = typeof options.deadlineAtMs === "number" ? await this.graphSeedPathsWithinDeadline(
|
|
5460
|
+
storage,
|
|
5461
|
+
seedCandidates,
|
|
5462
|
+
options.deadlineAtMs,
|
|
5463
|
+
[namespace]
|
|
5464
|
+
) : (await Promise.all(
|
|
5465
|
+
seedCandidates.map(
|
|
5466
|
+
(result) => this.graphSeedPathRelativeToStorage(storage, result, [
|
|
5467
|
+
namespace
|
|
5468
|
+
])
|
|
5469
|
+
)
|
|
5470
|
+
)).filter(
|
|
5359
5471
|
(value) => typeof value === "string" && value.length > 0
|
|
5360
5472
|
);
|
|
5473
|
+
if (deadlineExpired()) break;
|
|
5361
5474
|
if (seedRelativePaths.length === 0) continue;
|
|
5362
5475
|
const seedRecallScore = seedCandidates.reduce(
|
|
5363
5476
|
(max, item) => Math.max(max, item.score),
|
|
@@ -5370,13 +5483,19 @@ ${r.snippet.trim()}
|
|
|
5370
5483
|
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
5371
5484
|
seedRelativePaths,
|
|
5372
5485
|
this.config.maxGraphTraversalSteps,
|
|
5373
|
-
|
|
5486
|
+
{
|
|
5487
|
+
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {},
|
|
5488
|
+
...typeof options.deadlineAtMs === "number" ? { deadlineAtMs: options.deadlineAtMs } : {}
|
|
5489
|
+
}
|
|
5374
5490
|
);
|
|
5375
5491
|
if (expanded.length === 0) continue;
|
|
5492
|
+
if (deadlineExpired()) break;
|
|
5376
5493
|
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
5494
|
+
if (deadlineExpired()) break;
|
|
5377
5495
|
if (seedSet.has(candidate.path)) continue;
|
|
5378
5496
|
const memoryPath = path2.resolve(storage.dir, candidate.path);
|
|
5379
5497
|
const memory = await storage.readMemoryByPath(memoryPath);
|
|
5498
|
+
if (deadlineExpired()) break;
|
|
5380
5499
|
if (!memory) continue;
|
|
5381
5500
|
if (isArtifactMemoryPath(memory.path)) continue;
|
|
5382
5501
|
if (memory.frontmatter.status && memory.frontmatter.status !== "active")
|
|
@@ -7505,10 +7624,12 @@ ${formatted}`;
|
|
|
7505
7624
|
return section;
|
|
7506
7625
|
})()
|
|
7507
7626
|
);
|
|
7508
|
-
const recentBoxesPromise =
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7627
|
+
const recentBoxesPromise = observeEnrichmentPromise(
|
|
7628
|
+
this.isRecallSectionEnabled(
|
|
7629
|
+
"memory-boxes",
|
|
7630
|
+
this.config.memoryBoxesEnabled === true
|
|
7631
|
+
) && this.config.memoryBoxesEnabled && this.config.boxRecallDays > 0 ? this.boxBuilderFor(profileStorage).readRecentBoxes(this.config.boxRecallDays).catch(() => []) : Promise.resolve([])
|
|
7632
|
+
);
|
|
7512
7633
|
this.profiler.startSpan("phase-1-parallel", profileTraceId);
|
|
7513
7634
|
const phase1Start = Date.now();
|
|
7514
7635
|
log.info(
|
|
@@ -7637,6 +7758,48 @@ ${formatted}`;
|
|
|
7637
7758
|
}
|
|
7638
7759
|
return finalizeEnrichmentOutcome(outcome);
|
|
7639
7760
|
};
|
|
7761
|
+
const remainingEnrichmentAssemblyMs = () => enrichmentAssemblyDeadlineAtMs === null ? null : Math.max(0, enrichmentAssemblyDeadlineAtMs - Date.now());
|
|
7762
|
+
const awaitAssemblyStep = async (name, task, fallback) => {
|
|
7763
|
+
if (options.abortSignal?.aborted) {
|
|
7764
|
+
log.debug(
|
|
7765
|
+
`recall phase-1 assembly [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`
|
|
7766
|
+
);
|
|
7767
|
+
return fallback;
|
|
7768
|
+
}
|
|
7769
|
+
const timeoutMs = remainingEnrichmentAssemblyMs();
|
|
7770
|
+
if (timeoutMs === 0) {
|
|
7771
|
+
log.debug(
|
|
7772
|
+
`recall phase-1 assembly [${name}]: skipped after shared ${enrichmentSectionDeadlineMs}ms budget expired at +${Date.now() - phase1Start}ms`
|
|
7773
|
+
);
|
|
7774
|
+
return fallback;
|
|
7775
|
+
}
|
|
7776
|
+
let timeoutHandle;
|
|
7777
|
+
try {
|
|
7778
|
+
const result = await (timeoutMs !== null ? Promise.race([
|
|
7779
|
+
task(),
|
|
7780
|
+
new Promise((resolve) => {
|
|
7781
|
+
timeoutHandle = setTimeout(
|
|
7782
|
+
() => resolve({ status: "timed_out" }),
|
|
7783
|
+
timeoutMs
|
|
7784
|
+
);
|
|
7785
|
+
})
|
|
7786
|
+
]) : task());
|
|
7787
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
7788
|
+
if (typeof result === "object" && result !== null && "status" in result && result.status === "timed_out") {
|
|
7789
|
+
log.debug(
|
|
7790
|
+
`recall phase-1 assembly [${name}]: timed out within shared ${enrichmentSectionDeadlineMs}ms budget at +${Date.now() - phase1Start}ms`
|
|
7791
|
+
);
|
|
7792
|
+
return fallback;
|
|
7793
|
+
}
|
|
7794
|
+
return result;
|
|
7795
|
+
} catch (err) {
|
|
7796
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
7797
|
+
log.warn(
|
|
7798
|
+
`recall phase-1 assembly [${name}] failed open: ${err instanceof Error ? err.message : String(err)}`
|
|
7799
|
+
);
|
|
7800
|
+
return fallback;
|
|
7801
|
+
}
|
|
7802
|
+
};
|
|
7640
7803
|
this.profiler.startSpan("assembly", profileTraceId);
|
|
7641
7804
|
if (sharedCtx)
|
|
7642
7805
|
this.appendRecallSection(sectionBuckets, "shared-context", sharedCtx);
|
|
@@ -7855,8 +8018,11 @@ ${lines.join("\n")}`
|
|
|
7855
8018
|
);
|
|
7856
8019
|
}
|
|
7857
8020
|
{
|
|
7858
|
-
const recentBoxes = await
|
|
7859
|
-
|
|
8021
|
+
const recentBoxes = await awaitEnrichmentSection(
|
|
8022
|
+
"memory-boxes",
|
|
8023
|
+
recentBoxesPromise
|
|
8024
|
+
);
|
|
8025
|
+
if (recentBoxes && recentBoxes.length > 0) {
|
|
7860
8026
|
const boxLines = recentBoxes.slice(0, 5).map((b) => {
|
|
7861
8027
|
const sealedDate = b.sealedAt ? b.sealedAt.slice(0, 16).replace("T", " ") : "?";
|
|
7862
8028
|
const traceNote = b.traceId ? ` [trace: ${b.traceId.slice(0, 12)}]` : "";
|
|
@@ -7986,6 +8152,7 @@ ${tmtNode.summary}`
|
|
|
7986
8152
|
workProductsSection
|
|
7987
8153
|
);
|
|
7988
8154
|
}
|
|
8155
|
+
const qmdWasSettledBeforeAssemblyWait = qmdPromise.getSettledOutcome() !== void 0;
|
|
7989
8156
|
const qmdResult = await awaitEnrichmentSection("qmd", qmdPromise);
|
|
7990
8157
|
if (qmdResult) {
|
|
7991
8158
|
const t0 = Date.now();
|
|
@@ -8032,48 +8199,69 @@ ${tmtNode.summary}`
|
|
|
8032
8199
|
graphExpandedResultPaths.clear();
|
|
8033
8200
|
} else {
|
|
8034
8201
|
try {
|
|
8035
|
-
const
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
});
|
|
8046
|
-
graphSnapshotStatus = "completed";
|
|
8047
|
-
graphDecisionStatus = "completed";
|
|
8048
|
-
graphDecisionReason = graphShadowEvalEnabled ? "graph shadow evaluation completed without altering injected context" : "graph expansion merged into recall ranking";
|
|
8049
|
-
graphSnapshotReason = graphDecisionReason;
|
|
8050
|
-
graphSnapshotSeedPaths = seedPaths;
|
|
8051
|
-
graphSnapshotExpandedPaths = expandedPaths;
|
|
8052
|
-
graphSnapshotSeedResults = this.buildGraphRecallRankedResults(
|
|
8053
|
-
seedResults,
|
|
8054
|
-
() => ["baseline"]
|
|
8055
|
-
);
|
|
8056
|
-
graphExpandedResultPaths.clear();
|
|
8057
|
-
expandedPaths.forEach(
|
|
8058
|
-
(entry) => graphExpandedResultPaths.add(entry.path)
|
|
8202
|
+
const graphExpansion = await awaitAssemblyStep(
|
|
8203
|
+
"graph-expansion",
|
|
8204
|
+
() => this.expandResultsViaGraph({
|
|
8205
|
+
memoryResults,
|
|
8206
|
+
recallNamespaces,
|
|
8207
|
+
recallResultLimit,
|
|
8208
|
+
deadlineAtMs: enrichmentAssemblyDeadlineAtMs,
|
|
8209
|
+
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
8210
|
+
}),
|
|
8211
|
+
null
|
|
8059
8212
|
);
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8213
|
+
if (!graphExpansion) {
|
|
8214
|
+
graphSnapshotStatus = "aborted";
|
|
8215
|
+
graphDecisionStatus = "aborted";
|
|
8216
|
+
graphDecisionReason = options.abortSignal?.aborted ? "graph expansion skipped because recall assembly was aborted" : "graph expansion skipped because shared post-retrieval assembly budget expired";
|
|
8217
|
+
graphSnapshotReason = graphDecisionReason;
|
|
8218
|
+
graphSnapshotSeedPaths = baselineMemoryResults.slice(0, Math.max(1, recallResultLimit)).map((result) => result.path);
|
|
8219
|
+
graphSnapshotSeedResults = this.buildGraphRecallRankedResults(
|
|
8063
8220
|
baselineMemoryResults,
|
|
8221
|
+
() => ["baseline"]
|
|
8222
|
+
);
|
|
8223
|
+
graphSnapshotExpandedPaths = [];
|
|
8224
|
+
graphExpandedResultPaths.clear();
|
|
8225
|
+
memoryResults = baselineMemoryResults;
|
|
8226
|
+
} else {
|
|
8227
|
+
const {
|
|
8064
8228
|
merged,
|
|
8065
|
-
|
|
8229
|
+
seedPaths,
|
|
8230
|
+
expandedPaths,
|
|
8231
|
+
seedResults = baselineMemoryResults
|
|
8232
|
+
} = graphExpansion;
|
|
8233
|
+
graphSnapshotStatus = "completed";
|
|
8234
|
+
graphDecisionStatus = "completed";
|
|
8235
|
+
graphDecisionReason = graphShadowEvalEnabled ? "graph shadow evaluation completed without altering injected context" : "graph expansion merged into recall ranking";
|
|
8236
|
+
graphSnapshotReason = graphDecisionReason;
|
|
8237
|
+
graphSnapshotSeedPaths = seedPaths;
|
|
8238
|
+
graphSnapshotExpandedPaths = expandedPaths;
|
|
8239
|
+
graphSnapshotSeedResults = this.buildGraphRecallRankedResults(
|
|
8240
|
+
seedResults,
|
|
8241
|
+
() => ["baseline"]
|
|
8066
8242
|
);
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8243
|
+
graphExpandedResultPaths.clear();
|
|
8244
|
+
expandedPaths.forEach(
|
|
8245
|
+
(entry) => graphExpandedResultPaths.add(entry.path)
|
|
8246
|
+
);
|
|
8247
|
+
memoryResults = graphShadowEvalEnabled ? baselineMemoryResults : merged;
|
|
8248
|
+
if (graphShadowEvalEnabled) {
|
|
8249
|
+
const comparison = summarizeGraphShadowComparison(
|
|
8250
|
+
baselineMemoryResults,
|
|
8251
|
+
merged,
|
|
8252
|
+
recallResultLimit
|
|
8253
|
+
);
|
|
8254
|
+
graphSnapshotShadowComparison = comparison;
|
|
8255
|
+
recordRecallSectionMetric({
|
|
8256
|
+
section: "graphShadow",
|
|
8257
|
+
priority: "enrichment",
|
|
8258
|
+
durationMs: Date.now() - t0,
|
|
8259
|
+
deadlineMs: enrichmentSectionDeadlineMs,
|
|
8260
|
+
source: "fresh",
|
|
8261
|
+
success: true,
|
|
8262
|
+
timing: `on b=${comparison.baselineCount} g=${comparison.graphCount} ov=${comparison.overlapCount} (${comparison.overlapRatio.toFixed(2)}) avgDelta=${comparison.averageOverlapDelta.toFixed(3)}`
|
|
8263
|
+
});
|
|
8264
|
+
}
|
|
8077
8265
|
}
|
|
8078
8266
|
} catch (err) {
|
|
8079
8267
|
graphSnapshotStatus = "aborted";
|
|
@@ -8092,12 +8280,31 @@ ${tmtNode.summary}`
|
|
|
8092
8280
|
}
|
|
8093
8281
|
}
|
|
8094
8282
|
}
|
|
8095
|
-
|
|
8283
|
+
const qmdBoostInput = await this.filterSearchResultsForRecall(
|
|
8096
8284
|
memoryResults,
|
|
8097
|
-
recallNamespaces,
|
|
8098
|
-
retrievalQuery,
|
|
8099
8285
|
void 0,
|
|
8100
|
-
{
|
|
8286
|
+
{
|
|
8287
|
+
asOfMs,
|
|
8288
|
+
// If QMD had already settled before the ordered assembly reached it,
|
|
8289
|
+
// do not let unrelated slow enrichment turn those known results into
|
|
8290
|
+
// unchecked misses. QMD that only settles during its own wait remains
|
|
8291
|
+
// bounded by the shared post-retrieval assembly deadline.
|
|
8292
|
+
deadlineAtMs: qmdWasSettledBeforeAssemblyWait ? null : enrichmentAssemblyDeadlineAtMs,
|
|
8293
|
+
abortSignal: options.abortSignal,
|
|
8294
|
+
dropUnresolved: true,
|
|
8295
|
+
recallNamespaces
|
|
8296
|
+
}
|
|
8297
|
+
);
|
|
8298
|
+
memoryResults = await awaitAssemblyStep(
|
|
8299
|
+
"qmd-boost",
|
|
8300
|
+
() => this.boostSearchResults(
|
|
8301
|
+
qmdBoostInput.results,
|
|
8302
|
+
recallNamespaces,
|
|
8303
|
+
retrievalQuery,
|
|
8304
|
+
qmdBoostInput.memoryByPath,
|
|
8305
|
+
{ asOfMs }
|
|
8306
|
+
),
|
|
8307
|
+
qmdBoostInput.results
|
|
8101
8308
|
);
|
|
8102
8309
|
if (this.config.rerankEnabled && this.config.rerankProvider === "local") {
|
|
8103
8310
|
const ranked = await rerankLocalOrNoop({
|
|
@@ -8224,39 +8431,45 @@ ${tmtNode.summary}`
|
|
|
8224
8431
|
} else if (!confidenceGateRejected) {
|
|
8225
8432
|
const queryAwarePrefilter = await queryAwarePrefilterPromise;
|
|
8226
8433
|
if (queryAwarePrefilter.candidatePaths?.size !== 0) {
|
|
8227
|
-
const
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8434
|
+
const scoped = await awaitAssemblyStep(
|
|
8435
|
+
"embedding-fallback",
|
|
8436
|
+
async () => {
|
|
8437
|
+
const embeddingResults = await this.searchEmbeddingFallback(
|
|
8438
|
+
retrievalQuery,
|
|
8439
|
+
embeddingFetchLimit
|
|
8440
|
+
);
|
|
8441
|
+
const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(
|
|
8442
|
+
embeddingResults,
|
|
8443
|
+
queryAwarePrefilter.candidatePaths
|
|
8444
|
+
);
|
|
8445
|
+
const scopedCandidates = filterRecallCandidates(
|
|
8446
|
+
prefilteredEmbeddingResults,
|
|
8447
|
+
{
|
|
8448
|
+
namespacesEnabled: this.config.namespacesEnabled,
|
|
8449
|
+
recallNamespaces,
|
|
8450
|
+
resolveNamespace: (p) => this.namespaceFromPath(p),
|
|
8451
|
+
limit: embeddingFetchLimit
|
|
8452
|
+
}
|
|
8453
|
+
);
|
|
8454
|
+
const boostedScoped = await this.boostSearchResults(
|
|
8455
|
+
scopedCandidates,
|
|
8456
|
+
recallNamespaces,
|
|
8457
|
+
retrievalQuery,
|
|
8458
|
+
void 0,
|
|
8459
|
+
{ asOfMs }
|
|
8460
|
+
);
|
|
8461
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8462
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8463
|
+
boostedScoped.length
|
|
8464
|
+
);
|
|
8465
|
+
return this.diversifyAndLimitRecallResults(
|
|
8466
|
+
"memories",
|
|
8467
|
+
boostedScoped,
|
|
8468
|
+
recallResultLimit,
|
|
8469
|
+
retrievalQuery
|
|
8470
|
+
);
|
|
8471
|
+
},
|
|
8472
|
+
[]
|
|
8260
8473
|
);
|
|
8261
8474
|
if (scoped.length > 0) {
|
|
8262
8475
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8292,6 +8505,7 @@ ${tmtNode.summary}`
|
|
|
8292
8505
|
queryAwarePrefilter,
|
|
8293
8506
|
abortSignal: options.abortSignal,
|
|
8294
8507
|
xrayPoolSizeSink: xrayColdPoolSink,
|
|
8508
|
+
deadlineAtMs: enrichmentAssemblyDeadlineAtMs,
|
|
8295
8509
|
asOfMs,
|
|
8296
8510
|
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
8297
8511
|
});
|
|
@@ -8358,39 +8572,45 @@ ${tmtNode.summary}`
|
|
|
8358
8572
|
} else if (recallResultLimit > 0 && !this.qmd.isAvailable()) {
|
|
8359
8573
|
const queryAwarePrefilter = await queryAwarePrefilterPromise;
|
|
8360
8574
|
if (queryAwarePrefilter.candidatePaths?.size !== 0) {
|
|
8361
|
-
const
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8575
|
+
const scoped = await awaitAssemblyStep(
|
|
8576
|
+
"embedding-fallback",
|
|
8577
|
+
async () => {
|
|
8578
|
+
const embeddingResults = await this.searchEmbeddingFallback(
|
|
8579
|
+
retrievalQuery,
|
|
8580
|
+
embeddingFetchLimit
|
|
8581
|
+
);
|
|
8582
|
+
const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(
|
|
8583
|
+
embeddingResults,
|
|
8584
|
+
queryAwarePrefilter.candidatePaths
|
|
8585
|
+
);
|
|
8586
|
+
const scopedCandidates = filterRecallCandidates(
|
|
8587
|
+
prefilteredEmbeddingResults,
|
|
8588
|
+
{
|
|
8589
|
+
namespacesEnabled: this.config.namespacesEnabled,
|
|
8590
|
+
recallNamespaces,
|
|
8591
|
+
resolveNamespace: (p) => this.namespaceFromPath(p),
|
|
8592
|
+
limit: embeddingFetchLimit
|
|
8593
|
+
}
|
|
8594
|
+
);
|
|
8595
|
+
const boostedScoped = await this.boostSearchResults(
|
|
8596
|
+
scopedCandidates,
|
|
8597
|
+
recallNamespaces,
|
|
8598
|
+
retrievalQuery,
|
|
8599
|
+
void 0,
|
|
8600
|
+
{ asOfMs }
|
|
8601
|
+
);
|
|
8602
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8603
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8604
|
+
boostedScoped.length
|
|
8605
|
+
);
|
|
8606
|
+
return this.diversifyAndLimitRecallResults(
|
|
8607
|
+
"memories",
|
|
8608
|
+
boostedScoped,
|
|
8609
|
+
recallResultLimit,
|
|
8610
|
+
retrievalQuery
|
|
8611
|
+
);
|
|
8612
|
+
},
|
|
8613
|
+
[]
|
|
8394
8614
|
);
|
|
8395
8615
|
if (scoped.length > 0) {
|
|
8396
8616
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8418,7 +8638,11 @@ ${tmtNode.summary}`
|
|
|
8418
8638
|
xrayRecalledResults = scoped;
|
|
8419
8639
|
impressionRecorded = true;
|
|
8420
8640
|
} else {
|
|
8421
|
-
const memories = await
|
|
8641
|
+
const memories = await awaitAssemblyStep(
|
|
8642
|
+
"recent-memory-read",
|
|
8643
|
+
() => this.readAllMemoriesForNamespaces(recallNamespaces),
|
|
8644
|
+
[]
|
|
8645
|
+
);
|
|
8422
8646
|
if (memories.length > 0) {
|
|
8423
8647
|
const supersessionOptions = {
|
|
8424
8648
|
enabled: this.config.temporalSupersessionEnabled,
|
|
@@ -8449,6 +8673,7 @@ ${tmtNode.summary}`
|
|
|
8449
8673
|
queryAwarePrefilter,
|
|
8450
8674
|
abortSignal: options.abortSignal,
|
|
8451
8675
|
xrayPoolSizeSink: xrayColdPoolSink,
|
|
8676
|
+
deadlineAtMs: enrichmentAssemblyDeadlineAtMs,
|
|
8452
8677
|
asOfMs,
|
|
8453
8678
|
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
8454
8679
|
});
|
|
@@ -8473,36 +8698,42 @@ ${tmtNode.summary}`
|
|
|
8473
8698
|
impressionRecorded = true;
|
|
8474
8699
|
}
|
|
8475
8700
|
} else {
|
|
8476
|
-
const
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8701
|
+
const recent = await awaitAssemblyStep(
|
|
8702
|
+
"recent-memory-scan",
|
|
8703
|
+
async () => {
|
|
8704
|
+
const recentSorted = queryAwareScopedMemories.sort(
|
|
8705
|
+
(a, b) => new Date(b.frontmatter.updated).getTime() - new Date(a.frontmatter.updated).getTime()
|
|
8706
|
+
);
|
|
8707
|
+
const preloadedMap = new Map(
|
|
8708
|
+
queryAwareScopedMemories.filter((m) => m.path).map((m) => [m.path, m])
|
|
8709
|
+
);
|
|
8710
|
+
const recentAsResults = recentSorted.map(
|
|
8711
|
+
(m, i) => ({
|
|
8712
|
+
docid: m.frontmatter.id,
|
|
8713
|
+
path: m.path,
|
|
8714
|
+
snippet: m.content,
|
|
8715
|
+
score: 1 - i / Math.max(recentSorted.length, 1)
|
|
8716
|
+
})
|
|
8717
|
+
);
|
|
8718
|
+
const boostedRecent = (await this.boostSearchResults(
|
|
8719
|
+
recentAsResults,
|
|
8720
|
+
recallNamespaces,
|
|
8721
|
+
retrievalQuery,
|
|
8722
|
+
preloadedMap,
|
|
8723
|
+
{ asOfMs }
|
|
8724
|
+
)).sort((a, b) => b.score - a.score);
|
|
8725
|
+
xrayBranchPoolSize.recent_scan = Math.max(
|
|
8726
|
+
xrayBranchPoolSize.recent_scan,
|
|
8727
|
+
boostedRecent.length
|
|
8728
|
+
);
|
|
8729
|
+
return this.diversifyAndLimitRecallResults(
|
|
8730
|
+
"memories",
|
|
8731
|
+
boostedRecent,
|
|
8732
|
+
recallResultLimit,
|
|
8733
|
+
retrievalQuery
|
|
8734
|
+
);
|
|
8735
|
+
},
|
|
8736
|
+
[]
|
|
8506
8737
|
);
|
|
8507
8738
|
if (recent.length > 0) {
|
|
8508
8739
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8538,6 +8769,7 @@ ${tmtNode.summary}`
|
|
|
8538
8769
|
queryAwarePrefilter,
|
|
8539
8770
|
abortSignal: options.abortSignal,
|
|
8540
8771
|
xrayPoolSizeSink: xrayColdPoolSink,
|
|
8772
|
+
deadlineAtMs: enrichmentAssemblyDeadlineAtMs,
|
|
8541
8773
|
asOfMs,
|
|
8542
8774
|
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
8543
8775
|
});
|
|
@@ -8578,6 +8810,7 @@ ${tmtNode.summary}`
|
|
|
8578
8810
|
queryAwarePrefilter,
|
|
8579
8811
|
abortSignal: options.abortSignal,
|
|
8580
8812
|
xrayPoolSizeSink: xrayColdPoolSink,
|
|
8813
|
+
deadlineAtMs: enrichmentAssemblyDeadlineAtMs,
|
|
8581
8814
|
asOfMs,
|
|
8582
8815
|
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
8583
8816
|
});
|
|
@@ -8872,6 +9105,7 @@ _Context: ${topQuestion.context}_`
|
|
|
8872
9105
|
query: retrievalQuery,
|
|
8873
9106
|
memoryIds: recalledMemoryIds,
|
|
8874
9107
|
namespace: selfNamespace,
|
|
9108
|
+
recallNamespaces,
|
|
8875
9109
|
traceId,
|
|
8876
9110
|
plannerMode: recallMode,
|
|
8877
9111
|
requestedMode,
|
|
@@ -12268,6 +12502,212 @@ ${lines.join("\n\n")}`;
|
|
|
12268
12502
|
*
|
|
12269
12503
|
* Callers must pass the full candidate pool (post-rerank, pre-slice).
|
|
12270
12504
|
*/
|
|
12505
|
+
qmdCollectionNamespaceFromPrefix(collectionPrefix) {
|
|
12506
|
+
const baseCollection = this.config.qmdCollection;
|
|
12507
|
+
if (collectionPrefix === baseCollection) return this.config.defaultNamespace;
|
|
12508
|
+
const namespaceSuffix = collectionPrefix.startsWith(`${baseCollection}--`) ? collectionPrefix.slice(baseCollection.length + 2) : "";
|
|
12509
|
+
if (!namespaceSuffix) return null;
|
|
12510
|
+
const decoded = namespaceIdentityFromToken(namespaceSuffix);
|
|
12511
|
+
if (decoded !== null) return decoded || this.config.defaultNamespace;
|
|
12512
|
+
if (namespaceSuffix.startsWith("ns--")) {
|
|
12513
|
+
const legacyNamespace = namespaceSuffix.slice("ns--".length).trim();
|
|
12514
|
+
return legacyNamespace || null;
|
|
12515
|
+
}
|
|
12516
|
+
return null;
|
|
12517
|
+
}
|
|
12518
|
+
async readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces = []) {
|
|
12519
|
+
const parts = qmdCollectionPathParts(resultPath);
|
|
12520
|
+
const storageDirFor = (storage) => typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
12521
|
+
const fallbackStorageDir = storageDirFor(fallbackStorage);
|
|
12522
|
+
const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
12523
|
+
if (parts && parts.collection === coldCollection) {
|
|
12524
|
+
const storages = [];
|
|
12525
|
+
const seenStorageDirs = /* @__PURE__ */ new Set();
|
|
12526
|
+
const addStorage = (storage) => {
|
|
12527
|
+
const storageDir = storageDirFor(storage);
|
|
12528
|
+
const storageKey = storageDir ? path2.resolve(storageDir) : `storage-without-dir-${storages.length}`;
|
|
12529
|
+
if (seenStorageDirs.has(storageKey)) return;
|
|
12530
|
+
seenStorageDirs.add(storageKey);
|
|
12531
|
+
storages.push(storage);
|
|
12532
|
+
};
|
|
12533
|
+
const fallbackNamespace = fallbackStorageDir !== null ? this.namespaceFromStorageDir(fallbackStorageDir) : this.config.defaultNamespace;
|
|
12534
|
+
if (recallNamespaces.length === 0 || !this.config.namespacesEnabled || recallNamespaces.includes(fallbackNamespace)) {
|
|
12535
|
+
addStorage(fallbackStorage);
|
|
12536
|
+
}
|
|
12537
|
+
if (recallNamespaces.length > 0) {
|
|
12538
|
+
for (const namespace of recallNamespaces) {
|
|
12539
|
+
try {
|
|
12540
|
+
addStorage(await this.storageRouter.storageFor(namespace));
|
|
12541
|
+
} catch (err) {
|
|
12542
|
+
log.debug("qmd cold result namespace storage lookup skipped", {
|
|
12543
|
+
path: resultPath,
|
|
12544
|
+
namespace,
|
|
12545
|
+
error: err.message
|
|
12546
|
+
});
|
|
12547
|
+
}
|
|
12548
|
+
}
|
|
12549
|
+
}
|
|
12550
|
+
for (const storage of storages) {
|
|
12551
|
+
const storageDir = storageDirFor(storage);
|
|
12552
|
+
if (!storageDir) {
|
|
12553
|
+
const memory = await storage.readMemoryByPath(resultPath);
|
|
12554
|
+
if (memory) return memory;
|
|
12555
|
+
continue;
|
|
12556
|
+
}
|
|
12557
|
+
try {
|
|
12558
|
+
const coldRoot = path2.join(storageDir, "cold");
|
|
12559
|
+
for (const candidate of qmdResultPathCandidates(
|
|
12560
|
+
coldRoot,
|
|
12561
|
+
parts.relativePath
|
|
12562
|
+
)) {
|
|
12563
|
+
const memory = await storage.readMemoryByPath(candidate);
|
|
12564
|
+
if (memory) return memory;
|
|
12565
|
+
}
|
|
12566
|
+
} catch (err) {
|
|
12567
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
12568
|
+
log.debug("qmd cold result path lookup failed open", {
|
|
12569
|
+
path: resultPath,
|
|
12570
|
+
collection: coldCollection,
|
|
12571
|
+
error: err.message
|
|
12572
|
+
});
|
|
12573
|
+
}
|
|
12574
|
+
}
|
|
12575
|
+
return null;
|
|
12576
|
+
}
|
|
12577
|
+
const collectionNamespace = parts ? this.qmdCollectionNamespaceFromPrefix(parts.collection) : null;
|
|
12578
|
+
if (parts && collectionNamespace) {
|
|
12579
|
+
try {
|
|
12580
|
+
const collectionStorage = await this.storageRouter.storageFor(collectionNamespace);
|
|
12581
|
+
for (const candidate of qmdResultPathCandidates(
|
|
12582
|
+
collectionStorage.dir,
|
|
12583
|
+
parts.relativePath
|
|
12584
|
+
)) {
|
|
12585
|
+
const memory = await collectionStorage.readMemoryByPath(candidate);
|
|
12586
|
+
if (memory) return memory;
|
|
12587
|
+
}
|
|
12588
|
+
return null;
|
|
12589
|
+
} catch (err) {
|
|
12590
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
12591
|
+
log.debug("qmd result namespace path lookup failed open", {
|
|
12592
|
+
path: resultPath,
|
|
12593
|
+
namespace: collectionNamespace,
|
|
12594
|
+
error: err.message
|
|
12595
|
+
});
|
|
12596
|
+
return null;
|
|
12597
|
+
}
|
|
12598
|
+
}
|
|
12599
|
+
if (path2.isAbsolute(resultPath)) {
|
|
12600
|
+
if (!fallbackStorageDir) {
|
|
12601
|
+
return await fallbackStorage.readMemoryByPath(resultPath);
|
|
12602
|
+
}
|
|
12603
|
+
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
12604
|
+
resultPath,
|
|
12605
|
+
fallbackStorage,
|
|
12606
|
+
recallNamespaces
|
|
12607
|
+
);
|
|
12608
|
+
if (!ownerStorage) return null;
|
|
12609
|
+
for (const candidate of qmdResultPathCandidates(
|
|
12610
|
+
ownerStorage.dir,
|
|
12611
|
+
resultPath
|
|
12612
|
+
)) {
|
|
12613
|
+
const memory = await ownerStorage.storage.readMemoryByPath(candidate);
|
|
12614
|
+
if (memory) return memory;
|
|
12615
|
+
}
|
|
12616
|
+
return null;
|
|
12617
|
+
}
|
|
12618
|
+
if (!fallbackStorageDir) {
|
|
12619
|
+
return await fallbackStorage.readMemoryByPath(resultPath);
|
|
12620
|
+
}
|
|
12621
|
+
for (const candidate of qmdResultPathCandidates(
|
|
12622
|
+
fallbackStorageDir,
|
|
12623
|
+
resultPath
|
|
12624
|
+
)) {
|
|
12625
|
+
const memory = await fallbackStorage.readMemoryByPath(candidate);
|
|
12626
|
+
if (memory) return memory;
|
|
12627
|
+
}
|
|
12628
|
+
return null;
|
|
12629
|
+
}
|
|
12630
|
+
async resolveColdQmdResultForRecall(result, fallbackStorage, recallNamespaces = []) {
|
|
12631
|
+
const memory = await this.readQmdResultMemory(
|
|
12632
|
+
result.path,
|
|
12633
|
+
fallbackStorage,
|
|
12634
|
+
recallNamespaces
|
|
12635
|
+
);
|
|
12636
|
+
if (!memory) return null;
|
|
12637
|
+
let ownerNamespace = null;
|
|
12638
|
+
if (path2.isAbsolute(memory.path)) {
|
|
12639
|
+
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
12640
|
+
memory.path,
|
|
12641
|
+
fallbackStorage,
|
|
12642
|
+
recallNamespaces
|
|
12643
|
+
);
|
|
12644
|
+
ownerNamespace = ownerStorage?.namespace ?? null;
|
|
12645
|
+
if (!ownerNamespace && this.config.namespacesEnabled) return null;
|
|
12646
|
+
}
|
|
12647
|
+
ownerNamespace ??= this.namespaceFromPath(memory.path);
|
|
12648
|
+
if (recallNamespaces.length > 0 && !recallNamespaces.includes(ownerNamespace)) {
|
|
12649
|
+
return null;
|
|
12650
|
+
}
|
|
12651
|
+
return {
|
|
12652
|
+
namespace: ownerNamespace,
|
|
12653
|
+
result: {
|
|
12654
|
+
...result,
|
|
12655
|
+
docid: result.docid || memory.frontmatter.id,
|
|
12656
|
+
path: memory.path,
|
|
12657
|
+
snippet: result.snippet || memory.content.slice(0, 400)
|
|
12658
|
+
}
|
|
12659
|
+
};
|
|
12660
|
+
}
|
|
12661
|
+
async storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces = []) {
|
|
12662
|
+
const resolvedPath = path2.resolve(resultPath);
|
|
12663
|
+
const memoryRoot = path2.resolve(this.config.memoryDir);
|
|
12664
|
+
const namespacesRoot = path2.join(memoryRoot, "namespaces");
|
|
12665
|
+
const fallbackStorageDir = typeof fallbackStorage.dir === "string" && fallbackStorage.dir ? fallbackStorage.dir : null;
|
|
12666
|
+
const matches = [];
|
|
12667
|
+
const seenDirs = /* @__PURE__ */ new Set();
|
|
12668
|
+
const maybeAddStorage = (storage, namespace) => {
|
|
12669
|
+
const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
12670
|
+
if (!storageDir) return;
|
|
12671
|
+
const candidateRoot = path2.resolve(storageDir);
|
|
12672
|
+
if (seenDirs.has(candidateRoot)) return;
|
|
12673
|
+
if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) return;
|
|
12674
|
+
if (candidateRoot === memoryRoot && isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
|
|
12675
|
+
return;
|
|
12676
|
+
}
|
|
12677
|
+
seenDirs.add(candidateRoot);
|
|
12678
|
+
matches.push({ storage, dir: candidateRoot, namespace });
|
|
12679
|
+
};
|
|
12680
|
+
const fallbackNamespace = fallbackStorageDir !== null ? this.namespaceFromStorageDir(fallbackStorageDir) : this.config.defaultNamespace;
|
|
12681
|
+
maybeAddStorage(fallbackStorage, fallbackNamespace);
|
|
12682
|
+
const candidateNamespaces = /* @__PURE__ */ new Set();
|
|
12683
|
+
candidateNamespaces.add(this.config.defaultNamespace);
|
|
12684
|
+
candidateNamespaces.add(this.config.sharedNamespace);
|
|
12685
|
+
for (const ns of recallNamespaces) {
|
|
12686
|
+
candidateNamespaces.add(ns);
|
|
12687
|
+
}
|
|
12688
|
+
if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
|
|
12689
|
+
const relativeToNamespaces = path2.relative(namespacesRoot, resolvedPath);
|
|
12690
|
+
const [namespaceSegment] = relativeToNamespaces.split(/[\\/]/);
|
|
12691
|
+
if (namespaceSegment) {
|
|
12692
|
+
candidateNamespaces.add(
|
|
12693
|
+
namespaceIdentityFromToken(namespaceSegment) ?? namespaceSegment
|
|
12694
|
+
);
|
|
12695
|
+
}
|
|
12696
|
+
}
|
|
12697
|
+
for (const policy of this.config.namespacePolicies ?? []) {
|
|
12698
|
+
candidateNamespaces.add(policy.name);
|
|
12699
|
+
}
|
|
12700
|
+
for (const ns of candidateNamespaces) {
|
|
12701
|
+
if (!ns) continue;
|
|
12702
|
+
try {
|
|
12703
|
+
maybeAddStorage(await this.storageRouter.storageFor(ns), ns);
|
|
12704
|
+
} catch {
|
|
12705
|
+
continue;
|
|
12706
|
+
}
|
|
12707
|
+
}
|
|
12708
|
+
matches.sort((a, b) => b.dir.length - a.dir.length);
|
|
12709
|
+
return matches[0] ?? null;
|
|
12710
|
+
}
|
|
12271
12711
|
async applyMemoryWorthRerank(results, namespaces) {
|
|
12272
12712
|
const counters = /* @__PURE__ */ new Map();
|
|
12273
12713
|
const seenNamespaces = /* @__PURE__ */ new Set();
|
|
@@ -12312,7 +12752,7 @@ ${lines.join("\n\n")}`;
|
|
|
12312
12752
|
if (reader) {
|
|
12313
12753
|
for (const r of missing) {
|
|
12314
12754
|
try {
|
|
12315
|
-
const memory = await
|
|
12755
|
+
const memory = await this.readQmdResultMemory(r.path, reader, namespaces);
|
|
12316
12756
|
if (!memory) continue;
|
|
12317
12757
|
const fm = memory.frontmatter;
|
|
12318
12758
|
if (fm.mw_success === void 0 && fm.mw_fail === void 0) continue;
|
|
@@ -12560,6 +13000,41 @@ ${lines.join("\n\n")}`;
|
|
|
12560
13000
|
if (options.xrayPoolSizeSink) options.xrayPoolSizeSink.size = 0;
|
|
12561
13001
|
return [];
|
|
12562
13002
|
}
|
|
13003
|
+
const deadlineRemainingMs = () => typeof options.deadlineAtMs === "number" ? Math.max(0, options.deadlineAtMs - Date.now()) : null;
|
|
13004
|
+
const runColdStepWithinDeadline = async (label, fallback, task) => {
|
|
13005
|
+
throwIfRecallAborted(options.abortSignal);
|
|
13006
|
+
const remainingMs = deadlineRemainingMs();
|
|
13007
|
+
if (remainingMs === 0) {
|
|
13008
|
+
log.debug(`cold-tier recall ${label} skipped: shared assembly deadline expired`);
|
|
13009
|
+
return fallback;
|
|
13010
|
+
}
|
|
13011
|
+
if (remainingMs === null) return task();
|
|
13012
|
+
let timeoutHandle;
|
|
13013
|
+
let timedOut = false;
|
|
13014
|
+
const taskPromise = task().catch((err) => {
|
|
13015
|
+
if (timedOut) {
|
|
13016
|
+
log.debug(`cold-tier recall ${label} failed after deadline: ${err}`);
|
|
13017
|
+
return fallback;
|
|
13018
|
+
}
|
|
13019
|
+
throw err;
|
|
13020
|
+
});
|
|
13021
|
+
try {
|
|
13022
|
+
return await Promise.race([
|
|
13023
|
+
taskPromise,
|
|
13024
|
+
new Promise((resolve) => {
|
|
13025
|
+
timeoutHandle = setTimeout(() => {
|
|
13026
|
+
timedOut = true;
|
|
13027
|
+
log.debug(
|
|
13028
|
+
`cold-tier recall ${label} skipped: shared assembly deadline expired`
|
|
13029
|
+
);
|
|
13030
|
+
resolve(fallback);
|
|
13031
|
+
}, remainingMs);
|
|
13032
|
+
})
|
|
13033
|
+
]);
|
|
13034
|
+
} finally {
|
|
13035
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
13036
|
+
}
|
|
13037
|
+
};
|
|
12563
13038
|
const coldQmdEnabled = this.config.qmdColdTierEnabled === true;
|
|
12564
13039
|
const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
12565
13040
|
const coldMaxResults = this.config.qmdColdMaxResults ?? this.config.qmdMaxResults;
|
|
@@ -12575,19 +13050,23 @@ ${lines.join("\n\n")}`;
|
|
|
12575
13050
|
false,
|
|
12576
13051
|
0
|
|
12577
13052
|
);
|
|
12578
|
-
longTerm = await
|
|
12579
|
-
|
|
12580
|
-
|
|
12581
|
-
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
13053
|
+
longTerm = await runColdStepWithinDeadline(
|
|
13054
|
+
"qmd lookup",
|
|
13055
|
+
[],
|
|
13056
|
+
() => this.fetchQmdMemoryResultsWithArtifactTopUp(
|
|
13057
|
+
options.prompt,
|
|
13058
|
+
coldFetchLimit,
|
|
13059
|
+
coldHybridLimit,
|
|
13060
|
+
{
|
|
13061
|
+
namespacesEnabled: this.config.namespacesEnabled,
|
|
13062
|
+
recallNamespaces: options.recallNamespaces,
|
|
13063
|
+
resolveNamespace: (p) => this.namespaceFromPath(p),
|
|
13064
|
+
collection: coldCollection,
|
|
13065
|
+
queryAwarePrefilter: options.queryAwarePrefilter,
|
|
13066
|
+
searchOptions: this.buildConfiguredQmdSearchOptions(options.prompt),
|
|
13067
|
+
abortSignal: options.abortSignal
|
|
13068
|
+
}
|
|
13069
|
+
)
|
|
12591
13070
|
);
|
|
12592
13071
|
if (longTerm.length > 0) {
|
|
12593
13072
|
log.debug(
|
|
@@ -12597,12 +13076,16 @@ ${lines.join("\n\n")}`;
|
|
|
12597
13076
|
}
|
|
12598
13077
|
}
|
|
12599
13078
|
if (longTerm.length === 0) {
|
|
12600
|
-
longTerm = await
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
|
|
12604
|
-
|
|
12605
|
-
|
|
13079
|
+
longTerm = await runColdStepWithinDeadline(
|
|
13080
|
+
"archive scan",
|
|
13081
|
+
[],
|
|
13082
|
+
() => this.searchLongTermArchiveFallback(
|
|
13083
|
+
options.prompt,
|
|
13084
|
+
options.recallNamespaces,
|
|
13085
|
+
options.recallResultLimit,
|
|
13086
|
+
options.queryAwarePrefilter,
|
|
13087
|
+
options.abortSignal
|
|
13088
|
+
)
|
|
12606
13089
|
);
|
|
12607
13090
|
if (longTerm.length > 0) {
|
|
12608
13091
|
log.debug("cold-tier recall source=archive-scan");
|
|
@@ -12611,9 +13094,51 @@ ${lines.join("\n\n")}`;
|
|
|
12611
13094
|
if (longTerm.length === 0) return [];
|
|
12612
13095
|
let results = longTerm;
|
|
12613
13096
|
if (this.config.namespacesEnabled) {
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
)
|
|
13097
|
+
const recallRoots = [];
|
|
13098
|
+
const seenRecallRoots = /* @__PURE__ */ new Set();
|
|
13099
|
+
for (const namespace of options.recallNamespaces) {
|
|
13100
|
+
try {
|
|
13101
|
+
const storage = await this.storageRouter.storageFor(namespace);
|
|
13102
|
+
const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
13103
|
+
if (!storageDir) continue;
|
|
13104
|
+
const recallRoot = path2.resolve(storageDir);
|
|
13105
|
+
if (seenRecallRoots.has(recallRoot)) continue;
|
|
13106
|
+
seenRecallRoots.add(recallRoot);
|
|
13107
|
+
recallRoots.push(recallRoot);
|
|
13108
|
+
} catch (err) {
|
|
13109
|
+
log.debug("cold-tier recall namespace root lookup skipped", {
|
|
13110
|
+
namespace,
|
|
13111
|
+
error: err.message
|
|
13112
|
+
});
|
|
13113
|
+
}
|
|
13114
|
+
}
|
|
13115
|
+
const scopedResults = [];
|
|
13116
|
+
for (const result of results) {
|
|
13117
|
+
if (options.abortSignal?.aborted || deadlineRemainingMs() === 0) break;
|
|
13118
|
+
const parts = qmdCollectionPathParts(result.path);
|
|
13119
|
+
if (parts?.collection === coldCollection) {
|
|
13120
|
+
const resolvedCold = await this.resolveColdQmdResultForRecall(
|
|
13121
|
+
result,
|
|
13122
|
+
this.storage,
|
|
13123
|
+
options.recallNamespaces
|
|
13124
|
+
);
|
|
13125
|
+
if (resolvedCold) scopedResults.push(resolvedCold.result);
|
|
13126
|
+
continue;
|
|
13127
|
+
}
|
|
13128
|
+
if (path2.isAbsolute(result.path)) {
|
|
13129
|
+
const resolvedPath = path2.resolve(result.path);
|
|
13130
|
+
if (recallRoots.some(
|
|
13131
|
+
(recallRoot) => isPathInsideStorageRoot(recallRoot, resolvedPath)
|
|
13132
|
+
)) {
|
|
13133
|
+
scopedResults.push(result);
|
|
13134
|
+
}
|
|
13135
|
+
continue;
|
|
13136
|
+
}
|
|
13137
|
+
if (options.recallNamespaces.includes(this.namespaceFromPath(result.path))) {
|
|
13138
|
+
scopedResults.push(result);
|
|
13139
|
+
}
|
|
13140
|
+
}
|
|
13141
|
+
results = scopedResults;
|
|
12617
13142
|
}
|
|
12618
13143
|
results = results.filter((r) => !isArtifactMemoryPath(r.path));
|
|
12619
13144
|
if (results.length === 0) return [];
|
|
@@ -12624,17 +13149,64 @@ ${lines.join("\n\n")}`;
|
|
|
12624
13149
|
memoryResults: results,
|
|
12625
13150
|
recallNamespaces: options.recallNamespaces,
|
|
12626
13151
|
recallResultLimit: options.recallResultLimit,
|
|
13152
|
+
deadlineAtMs: options.deadlineAtMs,
|
|
12627
13153
|
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {}
|
|
12628
13154
|
});
|
|
12629
13155
|
results = merged;
|
|
12630
13156
|
}
|
|
12631
|
-
|
|
13157
|
+
const boostInput = await this.filterSearchResultsForRecall(
|
|
12632
13158
|
results,
|
|
12633
|
-
options.recallNamespaces,
|
|
12634
|
-
options.prompt,
|
|
12635
13159
|
void 0,
|
|
12636
|
-
{
|
|
13160
|
+
{
|
|
13161
|
+
allowLifecycleFiltered: true,
|
|
13162
|
+
asOfMs: options.asOfMs,
|
|
13163
|
+
deadlineAtMs: options.deadlineAtMs,
|
|
13164
|
+
abortSignal: options.abortSignal,
|
|
13165
|
+
dropUnresolved: true,
|
|
13166
|
+
recallNamespaces: options.recallNamespaces
|
|
13167
|
+
}
|
|
12637
13168
|
);
|
|
13169
|
+
results = boostInput.results;
|
|
13170
|
+
const boostTimeoutMs = typeof options.deadlineAtMs === "number" ? Math.max(0, options.deadlineAtMs - Date.now()) : null;
|
|
13171
|
+
if (boostTimeoutMs !== 0) {
|
|
13172
|
+
let timeoutHandle;
|
|
13173
|
+
try {
|
|
13174
|
+
const boosted = await (boostTimeoutMs !== null ? Promise.race([
|
|
13175
|
+
this.boostSearchResults(
|
|
13176
|
+
boostInput.results,
|
|
13177
|
+
options.recallNamespaces,
|
|
13178
|
+
options.prompt,
|
|
13179
|
+
boostInput.memoryByPath,
|
|
13180
|
+
{ allowLifecycleFiltered: true, asOfMs: options.asOfMs }
|
|
13181
|
+
),
|
|
13182
|
+
new Promise((resolve) => {
|
|
13183
|
+
timeoutHandle = setTimeout(
|
|
13184
|
+
() => resolve({ status: "timed_out" }),
|
|
13185
|
+
boostTimeoutMs
|
|
13186
|
+
);
|
|
13187
|
+
})
|
|
13188
|
+
]) : this.boostSearchResults(
|
|
13189
|
+
boostInput.results,
|
|
13190
|
+
options.recallNamespaces,
|
|
13191
|
+
options.prompt,
|
|
13192
|
+
boostInput.memoryByPath,
|
|
13193
|
+
{ allowLifecycleFiltered: true, asOfMs: options.asOfMs }
|
|
13194
|
+
));
|
|
13195
|
+
if (typeof boosted === "object" && boosted !== null && "status" in boosted && boosted.status === "timed_out") {
|
|
13196
|
+
log.debug("cold-tier recall boost skipped: shared assembly deadline expired");
|
|
13197
|
+
} else if (Array.isArray(boosted)) {
|
|
13198
|
+
results = boosted;
|
|
13199
|
+
} else {
|
|
13200
|
+
results = boostInput.results;
|
|
13201
|
+
}
|
|
13202
|
+
} catch (err) {
|
|
13203
|
+
log.debug(`cold-tier recall boost failed open: ${err}`);
|
|
13204
|
+
} finally {
|
|
13205
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
13206
|
+
}
|
|
13207
|
+
} else {
|
|
13208
|
+
log.debug("cold-tier recall boost skipped: shared assembly deadline already expired");
|
|
13209
|
+
}
|
|
12638
13210
|
if (this.config.rerankEnabled && this.config.rerankProvider === "local") {
|
|
12639
13211
|
const ranked = await rerankLocalOrNoop({
|
|
12640
13212
|
query: options.prompt,
|
|
@@ -12755,64 +13327,101 @@ ${lines.join("\n\n")}`;
|
|
|
12755
13327
|
this.accessTrackingBuffer.clear();
|
|
12756
13328
|
log.debug(`flushed ${entries.length} access tracking entries`);
|
|
12757
13329
|
}
|
|
12758
|
-
|
|
12759
|
-
* Apply recency, access count, and importance boosting to QMD search results.
|
|
12760
|
-
* Returns re-ranked results.
|
|
12761
|
-
*/
|
|
12762
|
-
async boostSearchResults(results, _recallNamespaces, prompt, preloadedMemoryMap, options) {
|
|
12763
|
-
if (results.length === 0) return results;
|
|
12764
|
-
const now = Date.now();
|
|
13330
|
+
async loadSearchResultMemoryMap(results, preloadedMemoryMap, options) {
|
|
12765
13331
|
const memoryByPath = preloadedMemoryMap ? new Map(preloadedMemoryMap) : /* @__PURE__ */ new Map();
|
|
12766
|
-
const
|
|
12767
|
-
|
|
12768
|
-
)
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
if (
|
|
12773
|
-
|
|
13332
|
+
const checkedPaths = /* @__PURE__ */ new Set();
|
|
13333
|
+
const unreadablePaths = /* @__PURE__ */ new Set();
|
|
13334
|
+
const markChecked = (result) => {
|
|
13335
|
+
if (result.path) checkedPaths.add(result.path);
|
|
13336
|
+
};
|
|
13337
|
+
const markUnreadable = (result, err) => {
|
|
13338
|
+
if (!result.path) return;
|
|
13339
|
+
checkedPaths.add(result.path);
|
|
13340
|
+
unreadablePaths.add(result.path);
|
|
13341
|
+
log.warn("recall safety filter dropped unreadable secure-store candidate", {
|
|
13342
|
+
path: result.path,
|
|
13343
|
+
error: err.message
|
|
13344
|
+
});
|
|
13345
|
+
};
|
|
13346
|
+
const deadlineExpired = () => typeof options?.deadlineAtMs === "number" && Date.now() >= options.deadlineAtMs;
|
|
13347
|
+
if (options?.deadlineAtMs == null) {
|
|
13348
|
+
const batchSize = options?.abortSignal ? 16 : results.length;
|
|
13349
|
+
for (let offset = 0; offset < results.length; offset += batchSize) {
|
|
13350
|
+
if (options?.abortSignal?.aborted) {
|
|
13351
|
+
return {
|
|
13352
|
+
memoryByPath,
|
|
13353
|
+
checkedPaths,
|
|
13354
|
+
unreadablePaths,
|
|
13355
|
+
completed: false
|
|
13356
|
+
};
|
|
13357
|
+
}
|
|
13358
|
+
await Promise.all(
|
|
13359
|
+
results.slice(offset, offset + batchSize).map(async (r) => {
|
|
13360
|
+
if (!r.path) return;
|
|
13361
|
+
if (memoryByPath.has(r.path)) {
|
|
13362
|
+
markChecked(r);
|
|
13363
|
+
return;
|
|
13364
|
+
}
|
|
13365
|
+
try {
|
|
13366
|
+
const mem = await this.readQmdResultMemory(
|
|
13367
|
+
r.path,
|
|
13368
|
+
this.storage,
|
|
13369
|
+
options?.recallNamespaces
|
|
13370
|
+
);
|
|
13371
|
+
markChecked(r);
|
|
13372
|
+
if (mem) memoryByPath.set(r.path, mem);
|
|
13373
|
+
} catch (err) {
|
|
13374
|
+
if (err instanceof SecureStoreLockedError) {
|
|
13375
|
+
markUnreadable(r, err);
|
|
13376
|
+
return;
|
|
13377
|
+
}
|
|
13378
|
+
throw err;
|
|
13379
|
+
}
|
|
13380
|
+
})
|
|
13381
|
+
);
|
|
12774
13382
|
}
|
|
12775
|
-
|
|
13383
|
+
return { memoryByPath, checkedPaths, unreadablePaths, completed: true };
|
|
12776
13384
|
}
|
|
12777
|
-
const
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
if (mem) memoryByPath.set(r.path, mem);
|
|
12783
|
-
})
|
|
12784
|
-
),
|
|
12785
|
-
temporalFromDate !== null ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate) : Promise.resolve(null),
|
|
12786
|
-
promptTags.length > 0 ? queryByTagsAsync(this.config.memoryDir, promptTags) : Promise.resolve(null)
|
|
12787
|
-
]);
|
|
12788
|
-
const queryIntent = this.config.intentRoutingEnabled && prompt ? inferIntentFromText(prompt) : null;
|
|
12789
|
-
let temporalCandidates = null;
|
|
12790
|
-
let tagCandidates = null;
|
|
12791
|
-
if (this.config.queryAwareIndexingEnabled && prompt) {
|
|
12792
|
-
const maxCandidates = this.config.queryAwareIndexingMaxCandidates;
|
|
12793
|
-
const capSet = (s) => {
|
|
12794
|
-
if (!s) return null;
|
|
12795
|
-
const scoped = new Set(Array.from(s).filter((p) => resultPaths.has(p)));
|
|
12796
|
-
if (maxCandidates === 0 || scoped.size <= maxCandidates)
|
|
12797
|
-
return scoped;
|
|
12798
|
-
return new Set(Array.from(scoped).slice(0, maxCandidates));
|
|
12799
|
-
};
|
|
12800
|
-
if (temporalFromDate !== null) {
|
|
12801
|
-
temporalCandidates = capSet(rawTemporal);
|
|
13385
|
+
for (const result of results) {
|
|
13386
|
+
if (!result.path) continue;
|
|
13387
|
+
if (memoryByPath.has(result.path)) {
|
|
13388
|
+
markChecked(result);
|
|
13389
|
+
continue;
|
|
12802
13390
|
}
|
|
12803
|
-
if (
|
|
12804
|
-
|
|
13391
|
+
if (options?.abortSignal?.aborted || deadlineExpired()) {
|
|
13392
|
+
return { memoryByPath, checkedPaths, unreadablePaths, completed: false };
|
|
13393
|
+
}
|
|
13394
|
+
try {
|
|
13395
|
+
const mem = await this.readQmdResultMemory(
|
|
13396
|
+
result.path,
|
|
13397
|
+
this.storage,
|
|
13398
|
+
options?.recallNamespaces
|
|
13399
|
+
);
|
|
13400
|
+
markChecked(result);
|
|
13401
|
+
if (mem) memoryByPath.set(result.path, mem);
|
|
13402
|
+
} catch (err) {
|
|
13403
|
+
if (err instanceof SecureStoreLockedError) {
|
|
13404
|
+
markUnreadable(result, err);
|
|
13405
|
+
continue;
|
|
13406
|
+
}
|
|
13407
|
+
throw err;
|
|
12805
13408
|
}
|
|
12806
13409
|
}
|
|
13410
|
+
return { memoryByPath, checkedPaths, unreadablePaths, completed: true };
|
|
13411
|
+
}
|
|
13412
|
+
filterSearchResultsByRecallSafety(results, memoryByPath, options) {
|
|
12807
13413
|
let lifecycleFilteredCount = 0;
|
|
12808
13414
|
let temporalSupersededFilteredCount = 0;
|
|
12809
13415
|
let dedicatedSurfaceFilteredCount = 0;
|
|
12810
13416
|
let forgottenFilteredCount = 0;
|
|
12811
|
-
|
|
12812
|
-
const
|
|
13417
|
+
let blockedPathFilteredCount = 0;
|
|
13418
|
+
const filtered = [];
|
|
12813
13419
|
for (const r of results) {
|
|
13420
|
+
if (r.path && options?.blockedPaths?.has(r.path)) {
|
|
13421
|
+
blockedPathFilteredCount += 1;
|
|
13422
|
+
continue;
|
|
13423
|
+
}
|
|
12814
13424
|
const memory = memoryByPath.get(r.path);
|
|
12815
|
-
let score = r.score;
|
|
12816
13425
|
if (memory) {
|
|
12817
13426
|
if (memory.frontmatter.status === "forgotten") {
|
|
12818
13427
|
forgottenFilteredCount += 1;
|
|
@@ -12854,6 +13463,126 @@ ${lines.join("\n\n")}`;
|
|
|
12854
13463
|
dedicatedSurfaceFilteredCount += 1;
|
|
12855
13464
|
continue;
|
|
12856
13465
|
}
|
|
13466
|
+
}
|
|
13467
|
+
filtered.push(r);
|
|
13468
|
+
}
|
|
13469
|
+
if (lifecycleFilteredCount > 0) {
|
|
13470
|
+
log.debug(
|
|
13471
|
+
`lifecycle retrieval filter removed ${lifecycleFilteredCount} stale/archived candidates`
|
|
13472
|
+
);
|
|
13473
|
+
}
|
|
13474
|
+
if (temporalSupersededFilteredCount > 0) {
|
|
13475
|
+
log.debug(
|
|
13476
|
+
`temporal supersession filter removed ${temporalSupersededFilteredCount} superseded candidates`
|
|
13477
|
+
);
|
|
13478
|
+
}
|
|
13479
|
+
if (dedicatedSurfaceFilteredCount > 0) {
|
|
13480
|
+
log.debug(
|
|
13481
|
+
`dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural candidates from generic recall`
|
|
13482
|
+
);
|
|
13483
|
+
}
|
|
13484
|
+
if (forgottenFilteredCount > 0) {
|
|
13485
|
+
log.debug(
|
|
13486
|
+
`forgotten status filter removed ${forgottenFilteredCount} candidates from recall`
|
|
13487
|
+
);
|
|
13488
|
+
}
|
|
13489
|
+
if (blockedPathFilteredCount > 0) {
|
|
13490
|
+
log.debug(
|
|
13491
|
+
`unreadable-path filter removed ${blockedPathFilteredCount} candidates from recall`
|
|
13492
|
+
);
|
|
13493
|
+
}
|
|
13494
|
+
return filtered;
|
|
13495
|
+
}
|
|
13496
|
+
async filterSearchResultsForRecall(results, preloadedMemoryMap, options) {
|
|
13497
|
+
if (results.length === 0) {
|
|
13498
|
+
return {
|
|
13499
|
+
results,
|
|
13500
|
+
memoryByPath: preloadedMemoryMap ? new Map(preloadedMemoryMap) : /* @__PURE__ */ new Map()
|
|
13501
|
+
};
|
|
13502
|
+
}
|
|
13503
|
+
const loaded = await this.loadSearchResultMemoryMap(
|
|
13504
|
+
results,
|
|
13505
|
+
preloadedMemoryMap,
|
|
13506
|
+
options
|
|
13507
|
+
);
|
|
13508
|
+
const candidateResults = loaded.completed ? results : results.filter((result) => !result.path || loaded.checkedPaths.has(result.path));
|
|
13509
|
+
if (!loaded.completed) {
|
|
13510
|
+
log.debug(
|
|
13511
|
+
`recall safety filter stopped before validating all candidates (${candidateResults.length}/${results.length} eligible)`
|
|
13512
|
+
);
|
|
13513
|
+
}
|
|
13514
|
+
const blockedPaths = new Set(loaded.unreadablePaths);
|
|
13515
|
+
if (options?.dropUnresolved === true) {
|
|
13516
|
+
for (const resultPath of loaded.checkedPaths) {
|
|
13517
|
+
if (!loaded.memoryByPath.has(resultPath)) {
|
|
13518
|
+
blockedPaths.add(resultPath);
|
|
13519
|
+
}
|
|
13520
|
+
}
|
|
13521
|
+
}
|
|
13522
|
+
return {
|
|
13523
|
+
results: this.filterSearchResultsByRecallSafety(
|
|
13524
|
+
candidateResults,
|
|
13525
|
+
loaded.memoryByPath,
|
|
13526
|
+
{ ...options, blockedPaths }
|
|
13527
|
+
),
|
|
13528
|
+
memoryByPath: loaded.memoryByPath
|
|
13529
|
+
};
|
|
13530
|
+
}
|
|
13531
|
+
/**
|
|
13532
|
+
* Apply recency, access count, and importance boosting to QMD search results.
|
|
13533
|
+
* Returns re-ranked results.
|
|
13534
|
+
*/
|
|
13535
|
+
async boostSearchResults(results, _recallNamespaces, prompt, preloadedMemoryMap, options) {
|
|
13536
|
+
if (results.length === 0) return results;
|
|
13537
|
+
const safety = await this.filterSearchResultsForRecall(
|
|
13538
|
+
results,
|
|
13539
|
+
preloadedMemoryMap,
|
|
13540
|
+
{ ...options, recallNamespaces: _recallNamespaces }
|
|
13541
|
+
);
|
|
13542
|
+
const safeResults = safety.results;
|
|
13543
|
+
const memoryByPath = safety.memoryByPath;
|
|
13544
|
+
if (safeResults.length === 0) return safeResults;
|
|
13545
|
+
const now = Date.now();
|
|
13546
|
+
const resultPaths = new Set(
|
|
13547
|
+
safeResults.map((r) => r.path).filter(Boolean)
|
|
13548
|
+
);
|
|
13549
|
+
let temporalFromDate = null;
|
|
13550
|
+
let promptTags = [];
|
|
13551
|
+
if (this.config.queryAwareIndexingEnabled && prompt) {
|
|
13552
|
+
if (isTemporalQuery(prompt)) {
|
|
13553
|
+
temporalFromDate = recencyWindowFromPrompt(prompt, now);
|
|
13554
|
+
}
|
|
13555
|
+
promptTags = extractTagsFromPrompt(prompt);
|
|
13556
|
+
}
|
|
13557
|
+
const [rawTemporal, rawTags] = await Promise.all([
|
|
13558
|
+
temporalFromDate !== null ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate) : Promise.resolve(null),
|
|
13559
|
+
promptTags.length > 0 ? queryByTagsAsync(this.config.memoryDir, promptTags) : Promise.resolve(null)
|
|
13560
|
+
]);
|
|
13561
|
+
const queryIntent = this.config.intentRoutingEnabled && prompt ? inferIntentFromText(prompt) : null;
|
|
13562
|
+
let temporalCandidates = null;
|
|
13563
|
+
let tagCandidates = null;
|
|
13564
|
+
if (this.config.queryAwareIndexingEnabled && prompt) {
|
|
13565
|
+
const maxCandidates = this.config.queryAwareIndexingMaxCandidates;
|
|
13566
|
+
const capSet = (s) => {
|
|
13567
|
+
if (!s) return null;
|
|
13568
|
+
const scoped = new Set(Array.from(s).filter((p) => resultPaths.has(p)));
|
|
13569
|
+
if (maxCandidates === 0 || scoped.size <= maxCandidates)
|
|
13570
|
+
return scoped;
|
|
13571
|
+
return new Set(Array.from(scoped).slice(0, maxCandidates));
|
|
13572
|
+
};
|
|
13573
|
+
if (temporalFromDate !== null) {
|
|
13574
|
+
temporalCandidates = capSet(rawTemporal);
|
|
13575
|
+
}
|
|
13576
|
+
if (promptTags.length > 0) {
|
|
13577
|
+
tagCandidates = capSet(rawTags);
|
|
13578
|
+
}
|
|
13579
|
+
}
|
|
13580
|
+
const boosted = [];
|
|
13581
|
+
const recencyWeight = this.effectiveRecencyWeight();
|
|
13582
|
+
for (const r of safeResults) {
|
|
13583
|
+
const memory = memoryByPath.get(r.path);
|
|
13584
|
+
let score = r.score;
|
|
13585
|
+
if (memory) {
|
|
12857
13586
|
if (recencyWeight > 0) {
|
|
12858
13587
|
const createdAt = new Date(memory.frontmatter.created).getTime();
|
|
12859
13588
|
const ageMs = now - createdAt;
|
|
@@ -12964,26 +13693,6 @@ ${lines.join("\n\n")}`;
|
|
|
12964
13693
|
}
|
|
12965
13694
|
boosted.push({ ...r, score });
|
|
12966
13695
|
}
|
|
12967
|
-
if (lifecycleFilteredCount > 0) {
|
|
12968
|
-
log.debug(
|
|
12969
|
-
`lifecycle retrieval filter removed ${lifecycleFilteredCount} stale/archived candidates`
|
|
12970
|
-
);
|
|
12971
|
-
}
|
|
12972
|
-
if (temporalSupersededFilteredCount > 0) {
|
|
12973
|
-
log.debug(
|
|
12974
|
-
`temporal supersession filter removed ${temporalSupersededFilteredCount} superseded candidates`
|
|
12975
|
-
);
|
|
12976
|
-
}
|
|
12977
|
-
if (dedicatedSurfaceFilteredCount > 0) {
|
|
12978
|
-
log.debug(
|
|
12979
|
-
`dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural candidates from generic recall`
|
|
12980
|
-
);
|
|
12981
|
-
}
|
|
12982
|
-
if (forgottenFilteredCount > 0) {
|
|
12983
|
-
log.debug(
|
|
12984
|
-
`forgotten status filter removed ${forgottenFilteredCount} candidates from recall`
|
|
12985
|
-
);
|
|
12986
|
-
}
|
|
12987
13696
|
return boosted.sort((a, b) => b.score - a.score);
|
|
12988
13697
|
}
|
|
12989
13698
|
/**
|
|
@@ -13121,8 +13830,37 @@ ${lines.join("\n\n")}`;
|
|
|
13121
13830
|
reason: link.reason || void 0
|
|
13122
13831
|
}));
|
|
13123
13832
|
}
|
|
13833
|
+
async graphSeedPathRelativeToStorage(storage, result, recallNamespaces = []) {
|
|
13834
|
+
const parts = qmdCollectionPathParts(result.path);
|
|
13835
|
+
if (parts) {
|
|
13836
|
+
const memory = await this.readQmdResultMemory(
|
|
13837
|
+
result.path,
|
|
13838
|
+
storage,
|
|
13839
|
+
recallNamespaces
|
|
13840
|
+
);
|
|
13841
|
+
return memory ? graphPathRelativeToStorage(storage.dir, memory.path) : null;
|
|
13842
|
+
}
|
|
13843
|
+
return graphPathRelativeToStorage(storage.dir, result.path);
|
|
13844
|
+
}
|
|
13845
|
+
async graphSeedPathsWithinDeadline(storage, results, deadlineAtMs, recallNamespaces = []) {
|
|
13846
|
+
const resolved = [];
|
|
13847
|
+
for (const result of results) {
|
|
13848
|
+
if (Date.now() >= deadlineAtMs) break;
|
|
13849
|
+
const seedPath = await this.graphSeedPathRelativeToStorage(
|
|
13850
|
+
storage,
|
|
13851
|
+
result,
|
|
13852
|
+
recallNamespaces
|
|
13853
|
+
);
|
|
13854
|
+
if (Date.now() >= deadlineAtMs) break;
|
|
13855
|
+
if (seedPath) resolved.push(seedPath);
|
|
13856
|
+
}
|
|
13857
|
+
return resolved;
|
|
13858
|
+
}
|
|
13124
13859
|
namespaceFromPath(p) {
|
|
13125
13860
|
if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
|
|
13861
|
+
const parts = qmdCollectionPathParts(p);
|
|
13862
|
+
const collectionNamespace = parts ? this.qmdCollectionNamespaceFromPrefix(parts.collection) : null;
|
|
13863
|
+
if (collectionNamespace) return collectionNamespace;
|
|
13126
13864
|
const m = p.match(/[\\/]+namespaces[\\/]+([^\\/]+)(?:[\\/]|$)/);
|
|
13127
13865
|
if (!m?.[1]) return this.config.defaultNamespace;
|
|
13128
13866
|
return namespaceIdentityFromToken(m[1]) ?? m[1];
|
|
@@ -13206,4 +13944,4 @@ export {
|
|
|
13206
13944
|
resolvePersistedMemoryRelativePath,
|
|
13207
13945
|
Orchestrator
|
|
13208
13946
|
};
|
|
13209
|
-
//# sourceMappingURL=chunk-
|
|
13947
|
+
//# sourceMappingURL=chunk-TJRV4MWX.js.map
|