@remnic/core 10.0.39 → 10.0.40
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-admin-ops-surface.js +12 -12
- package/dist/access-authorization-probe.js +13 -13
- package/dist/access-boundary.js +12 -12
- package/dist/access-cli.js +50 -50
- package/dist/access-extraction-force-flush.js +12 -12
- package/dist/access-http-briefing.js +13 -13
- package/dist/access-http-query.js +14 -14
- package/dist/access-http.js +28 -28
- package/dist/access-identity-continuity-surface.js +12 -12
- package/dist/access-lcm-surface.js +12 -12
- package/dist/access-mcp.js +21 -21
- package/dist/access-namespace-preflight.js +12 -12
- package/dist/access-observe-write-surface.js +12 -12
- package/dist/access-operations-batch.js +13 -13
- package/dist/access-operations.js +20 -20
- package/dist/access-recall-concurrency.js +12 -12
- package/dist/access-recall-response.js +12 -12
- package/dist/access-recall-surface.js +12 -12
- package/dist/access-service.d.ts +2 -2
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +12 -12
- package/dist/access-surface-catalog.js +14 -14
- package/dist/active-recall.js +2 -2
- package/dist/briefing.js +3 -3
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-NJ2DZYEK.js → chunk-2T6KEOUL.js} +2 -2
- package/dist/{chunk-BUKZ7MTN.js → chunk-5TRU6QQC.js} +2 -2
- package/dist/{chunk-SRPGA6WN.js → chunk-7BCYAJKP.js} +2 -2
- package/dist/{chunk-JRTKYFFY.js → chunk-AY6LO7GD.js} +2 -2
- package/dist/{chunk-5KZNWERU.js → chunk-BIYVUPC6.js} +19 -3
- package/dist/{chunk-5KZNWERU.js.map → chunk-BIYVUPC6.js.map} +1 -1
- package/dist/{chunk-V2XMG7GM.js → chunk-CHNZPOWX.js} +3 -2
- package/dist/{chunk-V2XMG7GM.js.map → chunk-CHNZPOWX.js.map} +1 -1
- package/dist/{chunk-GPVGAHXL.js → chunk-CNAL35D5.js} +2 -2
- package/dist/{chunk-CR72WZ3M.js → chunk-EPEDMEHO.js} +4 -4
- package/dist/{chunk-CR72WZ3M.js.map → chunk-EPEDMEHO.js.map} +1 -1
- package/dist/{chunk-U66CTIF5.js → chunk-F2RDRE7M.js} +2 -2
- package/dist/{chunk-B7VKRCAG.js → chunk-FNEYSTB6.js} +2 -2
- package/dist/{chunk-GSBSGT43.js → chunk-FPHU6KVI.js} +2 -2
- package/dist/{chunk-RO2NNWR5.js → chunk-GAUS4XGN.js} +3 -3
- package/dist/{chunk-4HJ2QK32.js → chunk-GDOI4U4D.js} +2 -2
- package/dist/{chunk-IZRNMXZC.js → chunk-GRN4BVPM.js} +2 -2
- package/dist/{chunk-VCOCOBUS.js → chunk-GZMHBRIR.js} +3 -3
- package/dist/{chunk-TTQYX7VU.js → chunk-HN35OH2C.js} +2 -2
- package/dist/{chunk-F2IU6A2L.js → chunk-HSNV4CSW.js} +16 -16
- package/dist/{chunk-EKR6OO4P.js → chunk-I7CWAJHX.js} +2 -2
- package/dist/{chunk-LJXBFVI2.js → chunk-ICTJOOWZ.js} +2 -2
- package/dist/{chunk-SJHFU52W.js → chunk-IF6EG22P.js} +5 -5
- package/dist/chunk-IF6EG22P.js.map +1 -0
- package/dist/{chunk-IAOW2L6K.js → chunk-IJJWM2ZA.js} +2 -2
- package/dist/{chunk-6Z2ZWBOV.js → chunk-IWDFHVPJ.js} +2 -2
- package/dist/{chunk-GCW7UT5I.js → chunk-JJSMSS45.js} +2 -2
- package/dist/{chunk-O2O4FDAH.js → chunk-JXQTECMU.js} +2 -2
- package/dist/{chunk-PJRKLB4Z.js → chunk-L5PM7B3I.js} +16 -2
- package/dist/{chunk-PJRKLB4Z.js.map → chunk-L5PM7B3I.js.map} +1 -1
- package/dist/{chunk-ZXFKG7VZ.js → chunk-LB6HIXQC.js} +2 -2
- package/dist/{chunk-B3I2QQU7.js → chunk-LWIU5BMA.js} +3 -3
- package/dist/{chunk-WQYS47G4.js → chunk-N3PUGD7E.js} +2 -2
- package/dist/{chunk-JORSMFL6.js → chunk-NBEM5QEH.js} +5 -5
- package/dist/{chunk-VIS23B6O.js → chunk-NFJWB27H.js} +14 -12
- package/dist/chunk-NFJWB27H.js.map +1 -0
- package/dist/{chunk-JQCP5QW3.js → chunk-O67H7OXJ.js} +2 -2
- package/dist/{chunk-4LLV2N3R.js → chunk-ONIVKGNC.js} +2 -2
- package/dist/{chunk-WT2VVYBM.js → chunk-PJXSBXEC.js} +2 -2
- package/dist/{chunk-ANV373S5.js → chunk-PW63SXFM.js} +2 -2
- package/dist/{chunk-RIAKNXZB.js → chunk-Q77SLBWT.js} +3 -3
- package/dist/{chunk-7IANFJ24.js → chunk-QFD7OANX.js} +15 -15
- package/dist/chunk-QFD7OANX.js.map +1 -0
- package/dist/{chunk-22YJQTPN.js → chunk-QGNZ5QPV.js} +2 -2
- package/dist/{chunk-GE5ZNDLE.js → chunk-R42VUN5V.js} +3 -3
- package/dist/{chunk-MD3W2H3G.js → chunk-RPHCSMTQ.js} +31 -31
- package/dist/{chunk-MD3W2H3G.js.map → chunk-RPHCSMTQ.js.map} +1 -1
- package/dist/{chunk-LPD6I2U6.js → chunk-SLVR3U4E.js} +2 -2
- package/dist/{chunk-JZFJZLJY.js → chunk-UGV256H3.js} +2 -2
- package/dist/{chunk-L74NWAD4.js → chunk-UKIIAEJF.js} +2 -2
- package/dist/{chunk-5Q6CR65T.js → chunk-VTZSIG6O.js} +2 -2
- package/dist/{chunk-4UT2NUAC.js → chunk-WJMAWDAU.js} +2 -2
- package/dist/{chunk-JT3IXJIL.js → chunk-XBHUMPIQ.js} +7 -7
- package/dist/{chunk-JM6U3SAE.js → chunk-XJ77IOAD.js} +2 -2
- package/dist/{chunk-RWW5KPIY.js → chunk-XLUMO5H2.js} +12 -12
- package/dist/chunk-XLUMO5H2.js.map +1 -0
- package/dist/{chunk-ODJ2HRFW.js → chunk-XXBCUIYQ.js} +7 -7
- package/dist/{chunk-JOOGPZJE.js → chunk-XXW3P3RX.js} +2 -2
- package/dist/{chunk-P3YUEPSQ.js → chunk-Y473XFTD.js} +2 -2
- package/dist/cli.js +38 -38
- package/dist/coding/export-okf-codegraph.js +2 -2
- package/dist/compounding/engine.js +4 -4
- package/dist/config.js +2 -2
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/index.js +3 -3
- package/dist/convergence-refresh.js +5 -5
- package/dist/corpus-watermark.js +5 -5
- package/dist/entity-retrieval.js +3 -3
- package/dist/external-wiki-access.js +13 -13
- package/dist/extraction-error-classification.d.ts +15 -0
- package/dist/extraction-error-classification.d.ts.map +1 -1
- package/dist/extraction-error-classification.js +7 -3
- package/dist/extraction.js +5 -5
- package/dist/harmonic-retrieval.js +3 -3
- package/dist/index.js +50 -50
- package/dist/location/index.js +5 -5
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection-runner.js +5 -5
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/memory-browse-operations.js +13 -13
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/search.d.ts +1 -0
- package/dist/namespaces/search.d.ts.map +1 -1
- package/dist/namespaces/search.js +5 -3
- package/dist/namespaces/storage.js +3 -3
- package/dist/operator-doctor-corpus.js +6 -6
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/maintenance.js +13 -13
- package/dist/orchestration/qmd-result-resolver.d.ts +5 -0
- package/dist/orchestration/qmd-result-resolver.d.ts.map +1 -1
- package/dist/orchestration/recall-search-pipeline.d.ts.map +1 -1
- package/dist/orchestrator.js +50 -50
- package/dist/recall-navigation-operations.js +13 -13
- package/dist/recall-navigation.js +12 -12
- package/dist/resume-bundles.js +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/source-agent-qualifier.js +3 -3
- package/dist/standup/build.js +3 -3
- package/dist/storage.js +2 -2
- package/dist/support-passport/index.js +15 -15
- package/dist/transfer/export-okf.js +3 -3
- package/dist/verified-recall.js +3 -3
- package/dist/who-knows-cli.js +4 -4
- package/dist/who-knows.js +3 -3
- package/package.json +2 -2
- package/src/access-entity-principal.test.ts +190 -0
- package/src/access-http.ts +2 -2
- package/src/access-operations-batch.ts +2 -2
- package/src/access-service.ts +7 -6
- package/src/chat/chat-executor.ts +1 -1
- package/src/extraction-error-classification.ts +23 -0
- package/src/extraction-local-failure-class.test.ts +55 -0
- package/src/extraction.ts +9 -9
- package/src/namespaces/search.ts +1 -1
- package/src/orchestration/extraction-run.test.ts +83 -2
- package/src/orchestration/qmd-result-resolver.ts +26 -1
- package/src/orchestration/recall-search-pipeline.ts +11 -12
- package/dist/chunk-7IANFJ24.js.map +0 -1
- package/dist/chunk-RWW5KPIY.js.map +0 -1
- package/dist/chunk-SJHFU52W.js.map +0 -1
- package/dist/chunk-VIS23B6O.js.map +0 -1
- /package/dist/{chunk-NJ2DZYEK.js.map → chunk-2T6KEOUL.js.map} +0 -0
- /package/dist/{chunk-BUKZ7MTN.js.map → chunk-5TRU6QQC.js.map} +0 -0
- /package/dist/{chunk-SRPGA6WN.js.map → chunk-7BCYAJKP.js.map} +0 -0
- /package/dist/{chunk-JRTKYFFY.js.map → chunk-AY6LO7GD.js.map} +0 -0
- /package/dist/{chunk-GPVGAHXL.js.map → chunk-CNAL35D5.js.map} +0 -0
- /package/dist/{chunk-U66CTIF5.js.map → chunk-F2RDRE7M.js.map} +0 -0
- /package/dist/{chunk-B7VKRCAG.js.map → chunk-FNEYSTB6.js.map} +0 -0
- /package/dist/{chunk-GSBSGT43.js.map → chunk-FPHU6KVI.js.map} +0 -0
- /package/dist/{chunk-RO2NNWR5.js.map → chunk-GAUS4XGN.js.map} +0 -0
- /package/dist/{chunk-4HJ2QK32.js.map → chunk-GDOI4U4D.js.map} +0 -0
- /package/dist/{chunk-IZRNMXZC.js.map → chunk-GRN4BVPM.js.map} +0 -0
- /package/dist/{chunk-VCOCOBUS.js.map → chunk-GZMHBRIR.js.map} +0 -0
- /package/dist/{chunk-TTQYX7VU.js.map → chunk-HN35OH2C.js.map} +0 -0
- /package/dist/{chunk-F2IU6A2L.js.map → chunk-HSNV4CSW.js.map} +0 -0
- /package/dist/{chunk-EKR6OO4P.js.map → chunk-I7CWAJHX.js.map} +0 -0
- /package/dist/{chunk-LJXBFVI2.js.map → chunk-ICTJOOWZ.js.map} +0 -0
- /package/dist/{chunk-IAOW2L6K.js.map → chunk-IJJWM2ZA.js.map} +0 -0
- /package/dist/{chunk-6Z2ZWBOV.js.map → chunk-IWDFHVPJ.js.map} +0 -0
- /package/dist/{chunk-GCW7UT5I.js.map → chunk-JJSMSS45.js.map} +0 -0
- /package/dist/{chunk-O2O4FDAH.js.map → chunk-JXQTECMU.js.map} +0 -0
- /package/dist/{chunk-ZXFKG7VZ.js.map → chunk-LB6HIXQC.js.map} +0 -0
- /package/dist/{chunk-B3I2QQU7.js.map → chunk-LWIU5BMA.js.map} +0 -0
- /package/dist/{chunk-WQYS47G4.js.map → chunk-N3PUGD7E.js.map} +0 -0
- /package/dist/{chunk-JORSMFL6.js.map → chunk-NBEM5QEH.js.map} +0 -0
- /package/dist/{chunk-JQCP5QW3.js.map → chunk-O67H7OXJ.js.map} +0 -0
- /package/dist/{chunk-4LLV2N3R.js.map → chunk-ONIVKGNC.js.map} +0 -0
- /package/dist/{chunk-WT2VVYBM.js.map → chunk-PJXSBXEC.js.map} +0 -0
- /package/dist/{chunk-ANV373S5.js.map → chunk-PW63SXFM.js.map} +0 -0
- /package/dist/{chunk-RIAKNXZB.js.map → chunk-Q77SLBWT.js.map} +0 -0
- /package/dist/{chunk-22YJQTPN.js.map → chunk-QGNZ5QPV.js.map} +0 -0
- /package/dist/{chunk-GE5ZNDLE.js.map → chunk-R42VUN5V.js.map} +0 -0
- /package/dist/{chunk-LPD6I2U6.js.map → chunk-SLVR3U4E.js.map} +0 -0
- /package/dist/{chunk-JZFJZLJY.js.map → chunk-UGV256H3.js.map} +0 -0
- /package/dist/{chunk-L74NWAD4.js.map → chunk-UKIIAEJF.js.map} +0 -0
- /package/dist/{chunk-5Q6CR65T.js.map → chunk-VTZSIG6O.js.map} +0 -0
- /package/dist/{chunk-4UT2NUAC.js.map → chunk-WJMAWDAU.js.map} +0 -0
- /package/dist/{chunk-JT3IXJIL.js.map → chunk-XBHUMPIQ.js.map} +0 -0
- /package/dist/{chunk-JM6U3SAE.js.map → chunk-XJ77IOAD.js.map} +0 -0
- /package/dist/{chunk-ODJ2HRFW.js.map → chunk-XXBCUIYQ.js.map} +0 -0
- /package/dist/{chunk-JOOGPZJE.js.map → chunk-XXW3P3RX.js.map} +0 -0
- /package/dist/{chunk-P3YUEPSQ.js.map → chunk-Y473XFTD.js.map} +0 -0
package/src/extraction.ts
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
import { applyGroundingWithConnector, headerConnector, renderExtractionConversation, resolveSourceConnector, type ExtractionGroundingContext } from "./source-agent-qualifier.js";
|
|
39
39
|
import { isMemoryCategory } from "./write-envelope.js";
|
|
40
40
|
export { classifyExtractionThrownError, classifyFallbackParseFailure, formatExtractionParseFailureLog } from "./extraction-error-classification.js";
|
|
41
|
-
import { classifyExtractionThrownError, classifyFallbackParseFailure, formatExtractionParseFailureLog } from "./extraction-error-classification.js";
|
|
41
|
+
import { LocalLlmRejectedError, classifyExtractionThrownError, classifyFallbackParseFailure, formatExtractionParseFailureLog, localRejectionStatus, type LocalFailureDiag } from "./extraction-error-classification.js";
|
|
42
42
|
import { AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT, clampAmbientCaptureConfidence } from "./ambient-provenance.js";
|
|
43
43
|
import {
|
|
44
44
|
CONSOLIDATION_RESPONSE_SCHEMA,
|
|
@@ -1244,7 +1244,7 @@ export class ExtractionEngine {
|
|
|
1244
1244
|
entities: [],
|
|
1245
1245
|
questions: [],
|
|
1246
1246
|
extractionFailure: "local_llm_error",
|
|
1247
|
-
extractionFailureClass: "
|
|
1247
|
+
extractionFailureClass: err instanceof LocalLlmRejectedError ? "parse_empty" : classifyExtractionThrownError(err),
|
|
1248
1248
|
};
|
|
1249
1249
|
}
|
|
1250
1250
|
log.info("extraction: local LLM error, falling back to gateway default AI:", err);
|
|
@@ -1494,9 +1494,8 @@ ${extractionResponseShape(this.config.extraction?.spanMode ?? "off")}
|
|
|
1494
1494
|
Conversation:
|
|
1495
1495
|
${truncatedConversation}`;
|
|
1496
1496
|
|
|
1497
|
-
log.debug(
|
|
1498
|
-
|
|
1499
|
-
);
|
|
1497
|
+
log.debug(`extractWithLocalLlm: calling localLlm.chatCompletion with prompt length ${localPrompt.length}...`);
|
|
1498
|
+
const failureDiag: LocalFailureDiag = {};
|
|
1500
1499
|
const response = await this.localLlm.chatCompletion(
|
|
1501
1500
|
[
|
|
1502
1501
|
{ role: "system", content: "You are a memory extraction system. Output valid JSON only." },
|
|
@@ -1512,9 +1511,12 @@ ${truncatedConversation}`;
|
|
|
1512
1511
|
: undefined,
|
|
1513
1512
|
priority: "background",
|
|
1514
1513
|
signal,
|
|
1514
|
+
failureDiag,
|
|
1515
1515
|
},
|
|
1516
1516
|
);
|
|
1517
1517
|
if (!response?.content) {
|
|
1518
|
+
const rejected = localRejectionStatus(failureDiag);
|
|
1519
|
+
if (rejected !== undefined) throw new LocalLlmRejectedError(rejected); // the endpoint is up and refuses this input
|
|
1518
1520
|
log.debug("extractWithLocalLlm: chatCompletion returned null or empty content");
|
|
1519
1521
|
return null;
|
|
1520
1522
|
}
|
|
@@ -1547,12 +1549,10 @@ ${truncatedConversation}`;
|
|
|
1547
1549
|
log.debug("extractWithLocalLlm: JSON parse failed, attempting partial extraction...");
|
|
1548
1550
|
const partial = this.extractPartialFacts(content);
|
|
1549
1551
|
if (partial.facts.length > 0 || partial.entities.length > 0) {
|
|
1550
|
-
log.debug(
|
|
1551
|
-
`extractWithLocalLlm: extracted ${partial.facts.length} partial facts from truncated JSON`,
|
|
1552
|
-
);
|
|
1552
|
+
log.debug(`extractWithLocalLlm: extracted ${partial.facts.length} partial facts from truncated JSON`);
|
|
1553
1553
|
return partial;
|
|
1554
1554
|
}
|
|
1555
|
-
|
|
1555
|
+
throw new LocalLlmRejectedError(); // the endpoint answered and nothing in the answer is usable
|
|
1556
1556
|
}
|
|
1557
1557
|
|
|
1558
1558
|
/**
|
package/src/namespaces/search.ts
CHANGED
|
@@ -700,7 +700,7 @@ export function normalizeQmdResultPath(resultPath: string, collection: string):
|
|
|
700
700
|
}
|
|
701
701
|
return value;
|
|
702
702
|
}
|
|
703
|
-
function resolveNamespaceResultPath(
|
|
703
|
+
export function resolveNamespaceResultPath(
|
|
704
704
|
memoryDir: string,
|
|
705
705
|
collection: string,
|
|
706
706
|
resultPath: string,
|
|
@@ -88,6 +88,7 @@ const migrationSummary: TierMigrationCycleSummary = {
|
|
|
88
88
|
|
|
89
89
|
interface Harness {
|
|
90
90
|
config: PluginConfig;
|
|
91
|
+
buffer: SmartBuffer;
|
|
91
92
|
storageForNs: (ns: string) => Promise<StorageManager>;
|
|
92
93
|
setStorageForDelay: (delayMs: number) => void;
|
|
93
94
|
newCoordinator: () => ExtractionRunCoordinator;
|
|
@@ -105,7 +106,7 @@ interface Harness {
|
|
|
105
106
|
coord: ExtractionRunCoordinator,
|
|
106
107
|
content: string,
|
|
107
108
|
opts?: { force?: boolean; failClosed?: boolean; writeNamespaceOverride?: string },
|
|
108
|
-
) => Promise<{ status: string; reason?: string }>;
|
|
109
|
+
) => Promise<{ status: string; reason?: string; failureClass?: string; retainedBuffer?: boolean }>;
|
|
109
110
|
cleanup: () => Promise<void>;
|
|
110
111
|
passiveCapture: () => { principal?: string; namespace?: string } | null;
|
|
111
112
|
setThreadingBlock: (blocked: boolean) => void;
|
|
@@ -201,6 +202,7 @@ async function makeHarness(overrides: Record<string, unknown> = {}): Promise<Har
|
|
|
201
202
|
|
|
202
203
|
return {
|
|
203
204
|
config,
|
|
205
|
+
buffer,
|
|
204
206
|
storageForNs,
|
|
205
207
|
setStorageForDelay: (delayMs) => {
|
|
206
208
|
storageForDelayMs = delayMs;
|
|
@@ -243,7 +245,7 @@ async function makeHarness(overrides: Record<string, unknown> = {}): Promise<Har
|
|
|
243
245
|
forceExtractionAttempt: opts.force === true,
|
|
244
246
|
writeNamespaceOverride: opts.writeNamespaceOverride,
|
|
245
247
|
});
|
|
246
|
-
return { status: result.status, reason: result.reason };
|
|
248
|
+
return { status: result.status, reason: result.reason, failureClass: result.failureClass, retainedBuffer: result.retainedBuffer };
|
|
247
249
|
},
|
|
248
250
|
cleanup: async () => {
|
|
249
251
|
StorageManager.clearAllStaticCaches();
|
|
@@ -1336,3 +1338,82 @@ test("#3140: a successful flush heals the recorded LLM health", async () => {
|
|
|
1336
1338
|
await h.cleanup();
|
|
1337
1339
|
}
|
|
1338
1340
|
});
|
|
1341
|
+
|
|
1342
|
+
// ---------------------------------------------------------------------------
|
|
1343
|
+
// Wiring the trigger drain depends on (#3266): what a real run hands back, and what it asks of the buffer
|
|
1344
|
+
// ---------------------------------------------------------------------------
|
|
1345
|
+
|
|
1346
|
+
test("a retained failure carries the extraction's failure class, so the drain can tell an outage from a bad chunk", async () => {
|
|
1347
|
+
for (const cls of ["provider_retryable", "auth_config", "parse_empty"] as const) {
|
|
1348
|
+
const h = await makeHarness({ extractionRetryScheduleMs: [3_600_000], extractionBreakerFailureThreshold: 100 });
|
|
1349
|
+
try {
|
|
1350
|
+
h.setRespond(() => failureResult(cls));
|
|
1351
|
+
const result = await h.run(h.newCoordinator(), `class-${cls}`);
|
|
1352
|
+
assert.equal(result.retainedBuffer, true, `${cls}: the window is kept for a retry`);
|
|
1353
|
+
assert.equal(result.failureClass, cls, `${cls}: the class reaches the run result`);
|
|
1354
|
+
} finally {
|
|
1355
|
+
await h.cleanup();
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
test("a failure with no class defaults to provider_retryable on the run result, like the retry bookkeeping", async () => {
|
|
1361
|
+
const h = await makeHarness({ extractionRetryScheduleMs: [3_600_000], extractionBreakerFailureThreshold: 100 });
|
|
1362
|
+
try {
|
|
1363
|
+
h.setRespond(() => ({ ...failureResult("parse_empty"), extractionFailureClass: undefined }));
|
|
1364
|
+
const result = await h.run(h.newCoordinator(), "class-default");
|
|
1365
|
+
assert.equal(result.failureClass, "provider_retryable");
|
|
1366
|
+
} finally {
|
|
1367
|
+
await h.cleanup();
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
|
|
1371
|
+
test("a run without a failure reports no failure class", async () => {
|
|
1372
|
+
const h = await makeHarness();
|
|
1373
|
+
try {
|
|
1374
|
+
h.setRespond(() => ({ ...successResult(), facts: [] }));
|
|
1375
|
+
const result = await h.run(h.newCoordinator(), "class-none");
|
|
1376
|
+
assert.equal(result.failureClass, undefined);
|
|
1377
|
+
} finally {
|
|
1378
|
+
await h.cleanup();
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
|
|
1382
|
+
test("the retention window a chunk run is given reaches the buffer as the processed snapshot (#3266)", async () => {
|
|
1383
|
+
const h = await makeHarness();
|
|
1384
|
+
try {
|
|
1385
|
+
const seen: Array<readonly BufferTurn[] | undefined> = [];
|
|
1386
|
+
const original = h.buffer.retainDeferredTurns.bind(h.buffer);
|
|
1387
|
+
h.buffer.retainDeferredTurns = async (key, turns, max, processed) => {
|
|
1388
|
+
seen.push(processed);
|
|
1389
|
+
await original(key, turns, max, processed);
|
|
1390
|
+
};
|
|
1391
|
+
const chunk = makeTurns("chunk-turns");
|
|
1392
|
+
const window = [...makeTurns("earlier-turns"), ...chunk];
|
|
1393
|
+
h.setRespond(() => successResult());
|
|
1394
|
+
await h.newCoordinator().runExtraction(chunk, {
|
|
1395
|
+
skipCharThreshold: true,
|
|
1396
|
+
skipUserTurnThreshold: true,
|
|
1397
|
+
clearBufferAfterExtraction: true,
|
|
1398
|
+
bufferKey: "window",
|
|
1399
|
+
failOnExtractionFailure: false,
|
|
1400
|
+
forceExtractionAttempt: false,
|
|
1401
|
+
retentionWindow: window,
|
|
1402
|
+
});
|
|
1403
|
+
assert.equal(seen.length, 1, "the run asked the buffer to update its retention slot once");
|
|
1404
|
+
assert.deepEqual(seen[0], window, "with the window it was given, not just its own chunk");
|
|
1405
|
+
|
|
1406
|
+
seen.length = 0;
|
|
1407
|
+
await h.newCoordinator().runExtraction(chunk, {
|
|
1408
|
+
skipCharThreshold: true,
|
|
1409
|
+
skipUserTurnThreshold: true,
|
|
1410
|
+
clearBufferAfterExtraction: true,
|
|
1411
|
+
bufferKey: "window",
|
|
1412
|
+
failOnExtractionFailure: false,
|
|
1413
|
+
forceExtractionAttempt: false,
|
|
1414
|
+
});
|
|
1415
|
+
assert.deepEqual(seen[0], chunk, "without a window the run keeps naming its own turns");
|
|
1416
|
+
} finally {
|
|
1417
|
+
await h.cleanup();
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
@@ -26,12 +26,13 @@
|
|
|
26
26
|
* RecallRerankCoordinator / ConversationIndexCoordinator accessor pattern.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
import { existsSync } from "node:fs";
|
|
29
30
|
import path from "node:path";
|
|
30
31
|
import { resolveNamespaceCapabilities } from "../capabilities.js";
|
|
31
32
|
import type { StorageManager } from "../index.js";
|
|
32
33
|
import { log } from "../logger.js";
|
|
33
34
|
import { namespaceIdentityFromToken } from "../namespaces/identity.js";
|
|
34
|
-
import { normalizeQmdResultPath } from "../namespaces/search.js";
|
|
35
|
+
import { normalizeQmdResultPath, resolveNamespaceResultPath } from "../namespaces/search.js";
|
|
35
36
|
import { SecureStoreLockedError } from "../secure-store/index.js";
|
|
36
37
|
import { isPathInsideStorageRoot } from "../storage-paths.js";
|
|
37
38
|
import { isSupportPassportPrivateMemory } from "../support-passport/card-projection.js";
|
|
@@ -136,6 +137,30 @@ export function qmdResultPathCandidates(storageDir: string, resultPath: string):
|
|
|
136
137
|
return [...candidates];
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
/** Canonicalize flat hot-memory identities before merging with native hits (#3194).
|
|
141
|
+
* This is a path-only map: no candidates, collections or namespace scopes are removed.
|
|
142
|
+
* Cold/explicit foreign collections keep their existing owner-resolution path.
|
|
143
|
+
*/
|
|
144
|
+
export function normalizeFlatQmdResults(
|
|
145
|
+
results: QmdSearchResult[],
|
|
146
|
+
config: PluginConfig,
|
|
147
|
+
collection = config.qmdCollection,
|
|
148
|
+
): QmdSearchResult[] {
|
|
149
|
+
if (!collection || resolveNamespaceCapabilities(config).namespaces || collection !== config.qmdCollection) return results;
|
|
150
|
+
return results.map((result) => ({
|
|
151
|
+
...result,
|
|
152
|
+
path: withHotFactsPath(config.memoryDir, resolveNamespaceResultPath(config.memoryDir, collection, result.path)),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** A hot-facts collection registered at the facts/ subtree returns date-relative paths (#2111); meet the loaded memory's path. */
|
|
157
|
+
function withHotFactsPath(memoryDir: string, resolved: string): string {
|
|
158
|
+
const relative = path.relative(path.resolve(memoryDir), resolved).split(path.sep).join("/");
|
|
159
|
+
if (!/^\d{4}-\d{2}-\d{2}\//.test(relative) || existsSync(resolved)) return resolved;
|
|
160
|
+
const hot = path.join(path.resolve(memoryDir), "facts", relative);
|
|
161
|
+
return existsSync(hot) ? hot : resolved;
|
|
162
|
+
}
|
|
163
|
+
|
|
139
164
|
/**
|
|
140
165
|
* Extract a non-empty `dir` from a storage, returning `null` when the
|
|
141
166
|
* property is absent or not a non-empty string at runtime. Proxy-backed
|
|
@@ -27,7 +27,7 @@ import { inferIntentFromText, intentCompatibilityScore } from "../intent.js";
|
|
|
27
27
|
import { log } from "../logger.js";
|
|
28
28
|
import { NamespaceStorageRouter } from "../namespaces/storage.js";
|
|
29
29
|
import { NegativeExampleStore } from "../negative.js";
|
|
30
|
-
import { qmdCollectionPathParts } from "./qmd-result-resolver.js";
|
|
30
|
+
import { normalizeFlatQmdResults, qmdCollectionPathParts } from "./qmd-result-resolver.js";
|
|
31
31
|
import type { RecallRerankCoordinator, RecallResultPartitionSink } from "./recall-rerank-coordinator.js";
|
|
32
32
|
import type { GraphRecallExpansionOptions, GraphRecallExpansionResult } from "./graph-recall-coordinator.js";
|
|
33
33
|
import { RelevanceStore } from "../relevance.js";
|
|
@@ -394,7 +394,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
394
394
|
break;
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
-
|
|
397
|
+
let primaryResults = options.collection
|
|
398
398
|
? options.abortSignal
|
|
399
399
|
? await this.deps.qmd.search(
|
|
400
400
|
prompt,
|
|
@@ -426,6 +426,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
426
426
|
onDegradation: options.onDegradation,
|
|
427
427
|
},
|
|
428
428
|
});
|
|
429
|
+
primaryResults = normalizeFlatQmdResults(primaryResults, this.deps.config, options.collection);
|
|
429
430
|
lastPrimaryResultCount = primaryResults.length;
|
|
430
431
|
lastHybridResultCount = 0;
|
|
431
432
|
lastHybridTopUpUsed = false;
|
|
@@ -452,7 +453,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
452
453
|
// uniform across primary + top-up (gotcha #39). Issue #1335 (codex review #1422).
|
|
453
454
|
lastHybridTopUpSkippedReason = "lex_strategy";
|
|
454
455
|
} else {
|
|
455
|
-
|
|
456
|
+
let hybridResults = options.collection
|
|
456
457
|
? await this.deps.qmd.hybridSearch(
|
|
457
458
|
prompt,
|
|
458
459
|
options.collection,
|
|
@@ -474,6 +475,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
474
475
|
onDegradation: options.onDegradation,
|
|
475
476
|
},
|
|
476
477
|
});
|
|
478
|
+
hybridResults = normalizeFlatQmdResults(hybridResults, this.deps.config, options.collection);
|
|
477
479
|
lastHybridResultCount = hybridResults.length;
|
|
478
480
|
lastHybridTopUpUsed = hybridResults.length > 0;
|
|
479
481
|
if (hybridResults.length > 0) {
|
|
@@ -740,9 +742,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
740
742
|
// limps home later cannot mutate a recorded recall's collector.
|
|
741
743
|
coldQmdObserverActive = false;
|
|
742
744
|
if (longTerm.length > 0) {
|
|
743
|
-
log.debug(
|
|
744
|
-
`cold-tier recall source=cold-qmd collection=${coldCollection} hits=${longTerm.length}`,
|
|
745
|
-
);
|
|
745
|
+
log.debug(`cold-tier recall source=cold-qmd collection=${coldCollection} hits=${longTerm.length}`);
|
|
746
746
|
}
|
|
747
747
|
}
|
|
748
748
|
}
|
|
@@ -940,9 +940,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
942
|
if (caps.rerank && this.deps.config.rerankProvider === "cloud") {
|
|
943
|
-
log.debug(
|
|
944
|
-
"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank",
|
|
945
|
-
);
|
|
943
|
+
log.debug("rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank");
|
|
946
944
|
}
|
|
947
945
|
|
|
948
946
|
if (caps.recallTrustScore && results.length > 0) {
|
|
@@ -1149,6 +1147,9 @@ export class RecallSearchPipelineCoordinator {
|
|
|
1149
1147
|
: null;
|
|
1150
1148
|
const buildRecallRow = (r: QmdSearchResult, memory: MemoryFile | undefined): QmdSearchResult => ({
|
|
1151
1149
|
...r,
|
|
1150
|
+
// Render loaded flat memories, not QMD's front-matter/chunk preview (#3194).
|
|
1151
|
+
snippet: memory && !resolveNamespaceCapabilities(this.deps.config).namespaces ? memory.content : r.snippet,
|
|
1152
|
+
line: memory && !resolveNamespaceCapabilities(this.deps.config).namespaces ? undefined : r.line,
|
|
1152
1153
|
sourceConnector: memory ? memory.frontmatter.sourceConnector : undefined,
|
|
1153
1154
|
origin: memory ? memory.frontmatter.origin : undefined,
|
|
1154
1155
|
// #1952: an active state view carries the chain fields the inject
|
|
@@ -1358,9 +1359,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
1358
1359
|
}
|
|
1359
1360
|
}
|
|
1360
1361
|
if (connectorPartitionFilteredCount > 0) {
|
|
1361
|
-
log.debug(
|
|
1362
|
-
`connector partition filter removed ${connectorPartitionFilteredCount} tool-scoped candidates from recall`,
|
|
1363
|
-
);
|
|
1362
|
+
log.debug(`connector partition filter removed ${connectorPartitionFilteredCount} tool-scoped candidates from recall`);
|
|
1364
1363
|
}
|
|
1365
1364
|
if (supportPassportFilteredCount > 0) {
|
|
1366
1365
|
log.debug(
|