@remnic/core 9.25.3 → 9.25.5
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.d.ts +3 -2
- package/dist/access-admin-ops-surface.js +9 -8
- package/dist/access-authorization-probe.d.ts +10 -3
- package/dist/access-authorization-probe.js +12 -9
- package/dist/access-boundary.d.ts +6 -3
- package/dist/access-boundary.js +13 -10
- package/dist/access-cli.js +42 -41
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +3 -2
- package/dist/access-http.js +16 -15
- package/dist/access-identity-continuity-surface.d.ts +2 -1
- package/dist/access-identity-continuity-surface.js +9 -8
- package/dist/access-lcm-surface.d.ts +3 -2
- package/dist/access-lcm-surface.js +9 -8
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +3 -2
- package/dist/access-mcp.js +13 -12
- package/dist/access-namespace-preflight.js +9 -8
- package/dist/access-observe-write-surface.d.ts +3 -2
- package/dist/access-observe-write-surface.js +9 -8
- package/dist/access-operations-batch.js +10 -9
- package/dist/access-operations.d.ts +6 -5
- package/dist/access-operations.js +11 -10
- package/dist/access-recall-concurrency.d.ts +3 -2
- package/dist/access-recall-concurrency.js +9 -8
- package/dist/access-recall-response.d.ts +4 -2
- package/dist/access-recall-response.js +9 -8
- package/dist/access-recall-surface.d.ts +3 -2
- package/dist/access-recall-surface.js +9 -8
- package/dist/access-schema.d.ts +76 -76
- package/dist/{access-service-BlNKWBC9.d.ts → access-service-BJQ22URi.d.ts} +4 -1
- package/dist/access-service.d.ts +3 -2
- package/dist/access-service.js +9 -8
- package/dist/access-surface-catalog.d.ts +3 -2
- package/dist/bootstrap.d.ts +2 -1
- package/dist/briefing.js +3 -3
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-GF22HWS2.js → chunk-2PHX3I5C.js} +7 -7
- package/dist/{chunk-3I35RLJW.js → chunk-32XTXKIA.js} +14 -13
- package/dist/chunk-32XTXKIA.js.map +1 -0
- package/dist/{chunk-LXKJNUND.js → chunk-37VPMR4E.js} +2 -2
- package/dist/{chunk-3CDMIR3C.js → chunk-3CHQZVAL.js} +2 -2
- package/dist/{chunk-U37RGPJT.js → chunk-5J7HJ7RT.js} +2 -2
- package/dist/{chunk-AGR7MGUX.js → chunk-7IGWPXVC.js} +2 -2
- package/dist/{chunk-FIGDB2HR.js → chunk-7KXQ44PA.js} +2 -2
- package/dist/chunk-AHVEHR6K.js +82 -0
- package/dist/chunk-AHVEHR6K.js.map +1 -0
- package/dist/{chunk-MNLZGCM2.js → chunk-AQ2ZQYDI.js} +3 -3
- package/dist/{chunk-TWCOYET2.js → chunk-B6JDYXL7.js} +2 -1
- package/dist/chunk-B6JDYXL7.js.map +1 -0
- package/dist/{chunk-RROMWDDC.js → chunk-BL4JHZSO.js} +49 -12
- package/dist/chunk-BL4JHZSO.js.map +1 -0
- package/dist/{chunk-PXJ4A6IK.js → chunk-BUK2FXOL.js} +133 -105
- package/dist/chunk-BUK2FXOL.js.map +1 -0
- package/dist/{chunk-JMDZDT24.js → chunk-D7MAWMMK.js} +18 -4
- package/dist/chunk-D7MAWMMK.js.map +1 -0
- package/dist/{chunk-TG2DJFH7.js → chunk-E5A6C4A5.js} +20 -20
- package/dist/{chunk-NBT7O25Z.js → chunk-FR75B4UU.js} +82 -56
- package/dist/chunk-FR75B4UU.js.map +1 -0
- package/dist/{chunk-DPYYSG6F.js → chunk-G6MGAE36.js} +7 -7
- package/dist/{chunk-GNFZFJBJ.js → chunk-IR4LGIH6.js} +2 -2
- package/dist/{chunk-MPDX5QMH.js → chunk-JA4HEXV7.js} +2 -2
- package/dist/{chunk-XTAAG4SQ.js → chunk-K4DP5KZA.js} +6 -6
- package/dist/{chunk-AT6DNUCM.js → chunk-NY6W6CJW.js} +2 -2
- package/dist/{chunk-NMGO2HAZ.js → chunk-OIE242WM.js} +2 -2
- package/dist/{chunk-SZN6XVFC.js → chunk-PS5OG75R.js} +2 -2
- package/dist/{chunk-VY6SDKWZ.js → chunk-SSYBI43M.js} +2 -2
- package/dist/{chunk-IE4HB6O5.js → chunk-TPYZ727G.js} +3 -3
- package/dist/{chunk-5ZGWA4AG.js → chunk-UMFLAACL.js} +6 -6
- package/dist/{chunk-THHPDPMS.js → chunk-UOURUMBN.js} +2 -2
- package/dist/{chunk-6LRTGCRV.js → chunk-VPSAVXHM.js} +3 -3
- package/dist/{chunk-AL4TZWI3.js → chunk-W33DEUKR.js} +2 -2
- package/dist/{chunk-W4ZDTHWZ.js → chunk-WIGBTWXA.js} +2 -2
- package/dist/{chunk-NVYCTASB.js → chunk-WSEA52RI.js} +2 -2
- package/dist/{chunk-LARPWF3S.js → chunk-ZPUFQGUF.js} +4 -4
- package/dist/{cli-Zc6UclD1.d.ts → cli-1W7cNjJJ.d.ts} +2 -2
- package/dist/cli.d.ts +4 -3
- package/dist/cli.js +28 -27
- package/dist/compounding/engine.js +3 -3
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/index.js +3 -3
- package/dist/corpus-watermark.js +5 -5
- package/dist/entity-retrieval.js +3 -3
- package/dist/explicit-capture.d.ts +2 -1
- package/dist/extraction.js +5 -1
- package/dist/{first-start-migration-LEXL3XYL.js → first-start-migration-BKNGOFED.js} +4 -4
- package/dist/index.d.ts +391 -390
- package/dist/index.js +74 -54
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.js +8 -8
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +3 -2
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/storage.js +3 -3
- package/dist/operator-doctor-corpus.js +6 -6
- package/dist/operator-toolkit.js +9 -9
- package/dist/orchestration/maintenance.js +8 -8
- package/dist/{orchestrator-BTGgoKli.d.ts → orchestrator-BtA1wC5K.d.ts} +2 -0
- package/dist/orchestrator.d.ts +2 -1
- package/dist/orchestrator.js +42 -41
- package/dist/recall-context-composition.d.ts +30 -0
- package/dist/recall-context-composition.js +24 -0
- package/dist/recall-context-composition.js.map +1 -0
- package/dist/schemas.d.ts +54 -54
- 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/shared-context/manager.d.ts +8 -8
- package/dist/storage.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/verified-recall.js +3 -3
- package/package.json +2 -2
- package/src/access-authorization-probe.ts +30 -1
- package/src/access-boundary.ts +21 -0
- package/src/access-http.test.ts +86 -1
- package/src/access-http.ts +6 -6
- package/src/access-mcp-output-schemas.ts +1 -0
- package/src/access-recall-response.ts +18 -13
- package/src/access-recall-surface.ts +11 -1
- package/src/access-service.ts +3 -0
- package/src/extraction-prompt-safety.test.ts +179 -0
- package/src/extraction.ts +186 -205
- package/src/index.ts +1 -1
- package/src/orchestration/orchestrator-helpers.ts +2 -0
- package/src/orchestration/recall-internal.ts +49 -49
- package/src/recall-context-composition.test.ts +90 -0
- package/src/recall-context-composition.ts +104 -0
- package/src/recall-curiosity-composition.test.ts +301 -0
- package/dist/chunk-3I35RLJW.js.map +0 -1
- package/dist/chunk-JMDZDT24.js.map +0 -1
- package/dist/chunk-NBT7O25Z.js.map +0 -1
- package/dist/chunk-PXJ4A6IK.js.map +0 -1
- package/dist/chunk-RROMWDDC.js.map +0 -1
- package/dist/chunk-TWCOYET2.js.map +0 -1
- /package/dist/{chunk-GF22HWS2.js.map → chunk-2PHX3I5C.js.map} +0 -0
- /package/dist/{chunk-LXKJNUND.js.map → chunk-37VPMR4E.js.map} +0 -0
- /package/dist/{chunk-3CDMIR3C.js.map → chunk-3CHQZVAL.js.map} +0 -0
- /package/dist/{chunk-U37RGPJT.js.map → chunk-5J7HJ7RT.js.map} +0 -0
- /package/dist/{chunk-AGR7MGUX.js.map → chunk-7IGWPXVC.js.map} +0 -0
- /package/dist/{chunk-FIGDB2HR.js.map → chunk-7KXQ44PA.js.map} +0 -0
- /package/dist/{chunk-MNLZGCM2.js.map → chunk-AQ2ZQYDI.js.map} +0 -0
- /package/dist/{chunk-TG2DJFH7.js.map → chunk-E5A6C4A5.js.map} +0 -0
- /package/dist/{chunk-DPYYSG6F.js.map → chunk-G6MGAE36.js.map} +0 -0
- /package/dist/{chunk-GNFZFJBJ.js.map → chunk-IR4LGIH6.js.map} +0 -0
- /package/dist/{chunk-MPDX5QMH.js.map → chunk-JA4HEXV7.js.map} +0 -0
- /package/dist/{chunk-XTAAG4SQ.js.map → chunk-K4DP5KZA.js.map} +0 -0
- /package/dist/{chunk-AT6DNUCM.js.map → chunk-NY6W6CJW.js.map} +0 -0
- /package/dist/{chunk-NMGO2HAZ.js.map → chunk-OIE242WM.js.map} +0 -0
- /package/dist/{chunk-SZN6XVFC.js.map → chunk-PS5OG75R.js.map} +0 -0
- /package/dist/{chunk-VY6SDKWZ.js.map → chunk-SSYBI43M.js.map} +0 -0
- /package/dist/{chunk-IE4HB6O5.js.map → chunk-TPYZ727G.js.map} +0 -0
- /package/dist/{chunk-5ZGWA4AG.js.map → chunk-UMFLAACL.js.map} +0 -0
- /package/dist/{chunk-THHPDPMS.js.map → chunk-UOURUMBN.js.map} +0 -0
- /package/dist/{chunk-6LRTGCRV.js.map → chunk-VPSAVXHM.js.map} +0 -0
- /package/dist/{chunk-AL4TZWI3.js.map → chunk-W33DEUKR.js.map} +0 -0
- /package/dist/{chunk-W4ZDTHWZ.js.map → chunk-WIGBTWXA.js.map} +0 -0
- /package/dist/{chunk-NVYCTASB.js.map → chunk-WSEA52RI.js.map} +0 -0
- /package/dist/{chunk-LARPWF3S.js.map → chunk-ZPUFQGUF.js.map} +0 -0
- /package/dist/{first-start-migration-LEXL3XYL.js.map → first-start-migration-BKNGOFED.js.map} +0 -0
|
@@ -16,6 +16,11 @@ import { decideDisclosureEscalation } from "./recall-disclosure-escalation.js";
|
|
|
16
16
|
import { type TagMatchMode, applyTagFilter, normalizeTags, parseTagMatch } from "./recall-tag-filter.js";
|
|
17
17
|
import type { RecallDisclosure, RecallPlanMode } from "./types.js";
|
|
18
18
|
import { displaySafeBudgetsApplied, displaySafeRecallSnapshot } from "./orchestration/recall-result-formatter.js";
|
|
19
|
+
import {
|
|
20
|
+
boundRecallContextComposition,
|
|
21
|
+
composeRecallContext,
|
|
22
|
+
type RecallContextComposition,
|
|
23
|
+
} from "./recall-context-composition.js";
|
|
19
24
|
|
|
20
25
|
/**
|
|
21
26
|
* Build the recall response from the completed pipeline (issue #1906 review
|
|
@@ -29,6 +34,7 @@ export async function assembleRecallResponse(
|
|
|
29
34
|
params: {
|
|
30
35
|
request: EngramAccessRecallRequest;
|
|
31
36
|
context: string;
|
|
37
|
+
contextComposition?: RecallContextComposition;
|
|
32
38
|
query: string;
|
|
33
39
|
mode: RecallPlanMode | undefined;
|
|
34
40
|
namespace: string;
|
|
@@ -47,6 +53,7 @@ export async function assembleRecallResponse(
|
|
|
47
53
|
const {
|
|
48
54
|
request,
|
|
49
55
|
context,
|
|
56
|
+
contextComposition,
|
|
50
57
|
query,
|
|
51
58
|
mode,
|
|
52
59
|
namespace,
|
|
@@ -191,7 +198,8 @@ export async function assembleRecallResponse(
|
|
|
191
198
|
err instanceof Error ? err.message : String(err),
|
|
192
199
|
);
|
|
193
200
|
}
|
|
194
|
-
let
|
|
201
|
+
let effectiveComposition: RecallContextComposition = contextComposition ?? { context };
|
|
202
|
+
let effectiveContext = composeRecallContext(effectiveComposition);
|
|
195
203
|
if (filterTags && filterTags.length > 0) {
|
|
196
204
|
const beforeIds = results.map((r) => r.id);
|
|
197
205
|
const { results: admitted } = applyTagFilter(results, {
|
|
@@ -213,20 +221,16 @@ export async function assembleRecallResponse(
|
|
|
213
221
|
const admittedIds = new Set(results.map((r) => r.id));
|
|
214
222
|
const droppedAny = beforeIds.some((id) => !admittedIds.has(id));
|
|
215
223
|
if (droppedAny) {
|
|
216
|
-
|
|
217
|
-
.map((
|
|
218
|
-
const content =
|
|
219
|
-
typeof (r as { content?: unknown }).content === "string"
|
|
220
|
-
? ((r as { content?: string }).content ?? "")
|
|
221
|
-
: "";
|
|
222
|
-
const preview =
|
|
223
|
-
typeof (r as { preview?: unknown }).preview === "string"
|
|
224
|
-
? ((r as { preview?: string }).preview ?? "")
|
|
225
|
-
: "";
|
|
226
|
-
return content || preview;
|
|
227
|
-
})
|
|
224
|
+
const filteredContext = results
|
|
225
|
+
.map((result) => result.content || result.preview)
|
|
228
226
|
.filter((s) => s.length > 0)
|
|
229
227
|
.join("\n\n");
|
|
228
|
+
effectiveComposition = boundRecallContextComposition({
|
|
229
|
+
context: filteredContext,
|
|
230
|
+
footer: effectiveComposition.footer,
|
|
231
|
+
maxChars: deps.orchestrator.config.recallBudgetChars,
|
|
232
|
+
});
|
|
233
|
+
effectiveContext = composeRecallContext(effectiveComposition);
|
|
230
234
|
}
|
|
231
235
|
}
|
|
232
236
|
const filteredMemoryIds = filterTags && filterTags.length > 0
|
|
@@ -289,6 +293,7 @@ export async function assembleRecallResponse(
|
|
|
289
293
|
sessionKey: request.sessionKey,
|
|
290
294
|
namespace: effectiveNamespace,
|
|
291
295
|
context: effectiveContext,
|
|
296
|
+
contextComposition: effectiveComposition,
|
|
292
297
|
count: filterTags && filterTags.length > 0
|
|
293
298
|
? results.length
|
|
294
299
|
: (snapshot?.memoryIds.length ?? results.length),
|
|
@@ -27,6 +27,7 @@ import type { Orchestrator, RecallInvocationOptions } from "./orchestrator.js";
|
|
|
27
27
|
import { decideDisclosureEscalation } from "./recall-disclosure-escalation.js";
|
|
28
28
|
import { assembleRecallResponse } from "./access-recall-response.js";
|
|
29
29
|
import type { LastRecallSnapshot } from "./recall-state.js";
|
|
30
|
+
import type { RecallContextComposition } from "./recall-context-composition.js";
|
|
30
31
|
import { type TagMatchMode, applyTagFilter, normalizeTags, parseTagMatch } from "./recall-tag-filter.js";
|
|
31
32
|
import { type RecallXraySnapshot, estimateRecallTokens } from "./recall-xray.js";
|
|
32
33
|
import { SecureStoreLockedError } from "./secure-store/index.js";
|
|
@@ -852,10 +853,14 @@ export class AccessRecallSurface {
|
|
|
852
853
|
}
|
|
853
854
|
asOf = request.asOf;
|
|
854
855
|
}
|
|
856
|
+
let contextComposition: RecallContextComposition | undefined;
|
|
855
857
|
const recallOptions: RecallInvocationOptions = {
|
|
856
858
|
namespace: namespaceOverride,
|
|
857
859
|
topK,
|
|
858
860
|
mode,
|
|
861
|
+
onContextComposition: (composition) => {
|
|
862
|
+
contextComposition = composition;
|
|
863
|
+
},
|
|
859
864
|
...(authenticatedPrincipal ? { principalOverride: authenticatedPrincipal } : {}),
|
|
860
865
|
...(asOf !== undefined ? { asOf } : {}),
|
|
861
866
|
...(request.includeLowConfidence === true ? { includeLowConfidence: true } : {}),
|
|
@@ -892,10 +897,15 @@ export class AccessRecallSurface {
|
|
|
892
897
|
// construction — so ANY failure after the reserve releases the exact
|
|
893
898
|
// budget entry (by token, review #4) instead of leaking it.
|
|
894
899
|
try {
|
|
895
|
-
const context = await this.deps.orchestrator.recall(
|
|
900
|
+
const context = await this.deps.orchestrator.recall(
|
|
901
|
+
query,
|
|
902
|
+
request.sessionKey,
|
|
903
|
+
recallOptions,
|
|
904
|
+
);
|
|
896
905
|
const assembled = await assembleRecallResponse(this.deps, {
|
|
897
906
|
request,
|
|
898
907
|
context,
|
|
908
|
+
contextComposition,
|
|
899
909
|
query,
|
|
900
910
|
mode,
|
|
901
911
|
namespace,
|
package/src/access-service.ts
CHANGED
|
@@ -170,6 +170,7 @@ import {
|
|
|
170
170
|
type ScopeInspection,
|
|
171
171
|
} from "./admin/admin-surfaces.js";
|
|
172
172
|
import type { LastRecallSnapshot } from "./recall-state.js";
|
|
173
|
+
import type { RecallContextComposition } from "./recall-context-composition.js";
|
|
173
174
|
import type {
|
|
174
175
|
GraphRecallSnapshot,
|
|
175
176
|
IntentDebugSnapshot,
|
|
@@ -453,6 +454,8 @@ export interface EngramAccessRecallResponse {
|
|
|
453
454
|
sessionKey?: string;
|
|
454
455
|
namespace: string;
|
|
455
456
|
context: string;
|
|
457
|
+
/** Request-local split used by adapters that must re-render a tighter prompt budget. */
|
|
458
|
+
contextComposition?: RecallContextComposition;
|
|
456
459
|
count: number;
|
|
457
460
|
memoryIds: string[];
|
|
458
461
|
results: EngramAccessMemorySummary[];
|
|
@@ -12,6 +12,11 @@ const SOURCE_TURN: BufferTurn = {
|
|
|
12
12
|
timestamp: "2026-07-25T12:00:00.000Z",
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const TAG_SOURCE_TURN: BufferTurn = {
|
|
16
|
+
...SOURCE_TURN,
|
|
17
|
+
content: "The page uses <main> as the primary landmark.",
|
|
18
|
+
};
|
|
19
|
+
|
|
15
20
|
const SOURCE_GROUNDED_EXTRACTION = {
|
|
16
21
|
facts: [{
|
|
17
22
|
category: "fact",
|
|
@@ -23,6 +28,81 @@ const SOURCE_GROUNDED_EXTRACTION = {
|
|
|
23
28
|
entities: [],
|
|
24
29
|
questions: [],
|
|
25
30
|
};
|
|
31
|
+
const STRUCTURAL_PLACEHOLDER_EXTRACTION = {
|
|
32
|
+
facts: [{
|
|
33
|
+
category: "<category>",
|
|
34
|
+
content: "<source-grounded statement>",
|
|
35
|
+
confidence: 0,
|
|
36
|
+
tags: ["<tag>"],
|
|
37
|
+
entityRef: "<optional normalized-name>",
|
|
38
|
+
promptedByQuestion: "<optional source-grounded question>",
|
|
39
|
+
quote: "<optional exact contiguous source span>",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
category: "<category>",
|
|
43
|
+
content: SOURCE_TURN.content,
|
|
44
|
+
confidence: 0.95,
|
|
45
|
+
tags: ["theme"],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
category: "procedure",
|
|
49
|
+
content: SOURCE_TURN.content,
|
|
50
|
+
confidence: 0.95,
|
|
51
|
+
tags: ["theme"],
|
|
52
|
+
procedureSteps: [
|
|
53
|
+
{ order: 1, intent: "<step>" },
|
|
54
|
+
{ order: 2, intent: "<step>" },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
category: "reasoning_trace",
|
|
59
|
+
content: SOURCE_TURN.content,
|
|
60
|
+
confidence: 0.95,
|
|
61
|
+
tags: ["theme"],
|
|
62
|
+
reasoningTrace: {
|
|
63
|
+
steps: [
|
|
64
|
+
{ order: 1, description: "<step>" },
|
|
65
|
+
{ order: 2, description: "<step>" },
|
|
66
|
+
],
|
|
67
|
+
finalAnswer: "<answer>",
|
|
68
|
+
},
|
|
69
|
+
}],
|
|
70
|
+
profileUpdates: ["<source-grounded profile update>"],
|
|
71
|
+
entities: [{
|
|
72
|
+
name: "<normalized-name>",
|
|
73
|
+
type: "<entity-type>",
|
|
74
|
+
facts: ["<source-grounded statement>"],
|
|
75
|
+
promptedByQuestion: "<optional source-grounded question>",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "Moonlight",
|
|
79
|
+
type: "<entity-type>",
|
|
80
|
+
facts: [SOURCE_TURN.content],
|
|
81
|
+
}],
|
|
82
|
+
questions: [{
|
|
83
|
+
question: "<source-grounded unresolved question>",
|
|
84
|
+
context: "<source-grounded context>",
|
|
85
|
+
priority: 0,
|
|
86
|
+
}],
|
|
87
|
+
identityReflection: "<conversation-grounded agent reflection>",
|
|
88
|
+
relationships: [{
|
|
89
|
+
source: "<normalized-name>",
|
|
90
|
+
target: "<normalized-name>",
|
|
91
|
+
label: "<source-grounded relationship>",
|
|
92
|
+
}],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const GATEWAY_PLACEHOLDER_EXTRACTION = {
|
|
96
|
+
...STRUCTURAL_PLACEHOLDER_EXTRACTION,
|
|
97
|
+
facts: [{
|
|
98
|
+
...STRUCTURAL_PLACEHOLDER_EXTRACTION.facts[0],
|
|
99
|
+
category: "fact",
|
|
100
|
+
}],
|
|
101
|
+
entities: [{
|
|
102
|
+
...STRUCTURAL_PLACEHOLDER_EXTRACTION.entities[0],
|
|
103
|
+
type: "other",
|
|
104
|
+
}],
|
|
105
|
+
};
|
|
26
106
|
|
|
27
107
|
type ChatMessage = { role: string; content: string };
|
|
28
108
|
|
|
@@ -100,6 +180,105 @@ test("local extraction prompt uses placeholders and accepts an empty question li
|
|
|
100
180
|
assert.doesNotMatch(prompt, /^- rule:/m);
|
|
101
181
|
});
|
|
102
182
|
|
|
183
|
+
test("local extraction discards literal structural placeholders", async () => {
|
|
184
|
+
const engine = new ExtractionEngine(parseConfig({
|
|
185
|
+
localLlmEnabled: true,
|
|
186
|
+
localLlmModel: "fixture-local",
|
|
187
|
+
localLlmFallback: false,
|
|
188
|
+
}));
|
|
189
|
+
const localLlm: LocalLlmFixture = {
|
|
190
|
+
async chatCompletion() {
|
|
191
|
+
return { content: JSON.stringify(STRUCTURAL_PLACEHOLDER_EXTRACTION) };
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
const modelRegistry = {
|
|
195
|
+
calculateContextSizes: () => ({ maxInputChars: 8_000, maxOutputTokens: 1_000, description: "fixture" }),
|
|
196
|
+
};
|
|
197
|
+
assert.equal(Reflect.set(engine, "localLlm", localLlm), true);
|
|
198
|
+
assert.equal(Reflect.set(engine, "modelRegistry", modelRegistry), true);
|
|
199
|
+
|
|
200
|
+
const result = await engine.extract([SOURCE_TURN]);
|
|
201
|
+
|
|
202
|
+
assert.deepEqual(result.facts, []);
|
|
203
|
+
assert.deepEqual(result.profileUpdates, []);
|
|
204
|
+
assert.deepEqual(result.entities, []);
|
|
205
|
+
assert.deepEqual(result.questions, []);
|
|
206
|
+
assert.deepEqual(result.relationships, []);
|
|
207
|
+
assert.equal(result.identityReflection, undefined);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("local extraction preserves source text that looks like a tag", async () => {
|
|
211
|
+
const engine = new ExtractionEngine(parseConfig({
|
|
212
|
+
localLlmEnabled: true,
|
|
213
|
+
localLlmModel: "fixture-local",
|
|
214
|
+
localLlmFallback: false,
|
|
215
|
+
}));
|
|
216
|
+
const localLlm: LocalLlmFixture = {
|
|
217
|
+
async chatCompletion() {
|
|
218
|
+
return {
|
|
219
|
+
content: JSON.stringify({
|
|
220
|
+
facts: [{ category: "fact", content: "<main>", confidence: 0.95, tags: [] }],
|
|
221
|
+
profileUpdates: [],
|
|
222
|
+
entities: [],
|
|
223
|
+
questions: [],
|
|
224
|
+
}),
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
const modelRegistry = {
|
|
229
|
+
calculateContextSizes: () => ({ maxInputChars: 8_000, maxOutputTokens: 1_000, description: "fixture" }),
|
|
230
|
+
};
|
|
231
|
+
assert.equal(Reflect.set(engine, "localLlm", localLlm), true);
|
|
232
|
+
assert.equal(Reflect.set(engine, "modelRegistry", modelRegistry), true);
|
|
233
|
+
|
|
234
|
+
const result = await engine.extract([TAG_SOURCE_TURN]);
|
|
235
|
+
|
|
236
|
+
assert.equal(result.facts[0]?.content, "<main>");
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("local truncated recovery discards literal structural placeholders", async () => {
|
|
240
|
+
const engine = new ExtractionEngine(parseConfig({
|
|
241
|
+
localLlmEnabled: true,
|
|
242
|
+
localLlmModel: "fixture-local",
|
|
243
|
+
localLlmFallback: false,
|
|
244
|
+
}));
|
|
245
|
+
const localLlm: LocalLlmFixture = {
|
|
246
|
+
async chatCompletion() {
|
|
247
|
+
return {
|
|
248
|
+
content: "{\"facts\":[{\"category\":\"<category>\",\"content\":\"<source-grounded statement>\",\"confidence\":0.7}",
|
|
249
|
+
};
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
const modelRegistry = {
|
|
253
|
+
calculateContextSizes: () => ({ maxInputChars: 8_000, maxOutputTokens: 1_000, description: "fixture" }),
|
|
254
|
+
};
|
|
255
|
+
assert.equal(Reflect.set(engine, "localLlm", localLlm), true);
|
|
256
|
+
assert.equal(Reflect.set(engine, "modelRegistry", modelRegistry), true);
|
|
257
|
+
|
|
258
|
+
const result = await engine.extract([SOURCE_TURN]);
|
|
259
|
+
|
|
260
|
+
assert.deepEqual(result.facts, []);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("gateway extraction discards literal structural placeholders", async () => {
|
|
264
|
+
const engine = new ExtractionEngine(parseConfig({ modelSource: "gateway" }));
|
|
265
|
+
const fallbackLlm: GatewayFixture = {
|
|
266
|
+
async parseWithSchemaDetailed() {
|
|
267
|
+
return { modelUsed: "fixture-gateway", result: GATEWAY_PLACEHOLDER_EXTRACTION };
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
assert.equal(Reflect.set(engine, "fallbackLlm", fallbackLlm), true);
|
|
271
|
+
|
|
272
|
+
const result = await engine.extract([SOURCE_TURN]);
|
|
273
|
+
|
|
274
|
+
assert.deepEqual(result.facts, []);
|
|
275
|
+
assert.deepEqual(result.profileUpdates, []);
|
|
276
|
+
assert.deepEqual(result.entities, []);
|
|
277
|
+
assert.deepEqual(result.questions, []);
|
|
278
|
+
assert.deepEqual(result.relationships, []);
|
|
279
|
+
assert.equal(result.identityReflection, undefined);
|
|
280
|
+
});
|
|
281
|
+
|
|
103
282
|
test("gateway extraction prompt uses placeholders and accepts an empty question list", async () => {
|
|
104
283
|
const engine = new ExtractionEngine(parseConfig({ modelSource: "gateway" }));
|
|
105
284
|
let calls = 0;
|