@remnic/core 9.7.12 → 9.7.14
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 +6 -6
- package/dist/access-admin-ops-surface.js +7 -7
- package/dist/access-boundary.d.ts +6 -6
- package/dist/access-boundary.js +8 -8
- package/dist/access-cli.js +34 -34
- package/dist/access-http.d.ts +6 -6
- package/dist/access-http.js +12 -12
- package/dist/access-identity-continuity-surface.d.ts +5 -5
- package/dist/access-identity-continuity-surface.js +7 -7
- package/dist/access-lcm-surface.d.ts +6 -6
- package/dist/access-lcm-surface.js +7 -7
- package/dist/access-mcp.d.ts +6 -6
- package/dist/access-mcp.js +11 -11
- package/dist/access-observe-write-surface.d.ts +6 -6
- package/dist/access-observe-write-surface.js +7 -7
- package/dist/access-operations-batch.js +9 -9
- package/dist/access-operations.d.ts +6 -6
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-surface.d.ts +6 -6
- package/dist/access-recall-surface.js +7 -7
- package/dist/{access-service-tHd3eQpd.d.ts → access-service-CPhSnLOH.d.ts} +4 -4
- package/dist/access-service.d.ts +6 -6
- package/dist/access-service.js +7 -7
- package/dist/access-surface-catalog.d.ts +6 -6
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +5 -5
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-DEMiw6HZ.d.ts → catalog-uX9sT9ws.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-2RSL6YRA.js → chunk-2E6G7FCE.js} +2 -2
- package/dist/{chunk-JKLJ6A7W.js → chunk-3D6AFGQR.js} +2 -2
- package/dist/{chunk-BQTSGK5Y.js → chunk-4B4MUS5D.js} +2 -2
- package/dist/{chunk-NVXQTRBL.js → chunk-4LEF6XWJ.js} +2 -2
- package/dist/{chunk-TMGK6YE7.js → chunk-5UNWK7KU.js} +2 -2
- package/dist/{chunk-OIFZII6J.js → chunk-67ZCJLJY.js} +2 -2
- package/dist/{chunk-ZRXSHGXT.js → chunk-6CALL5VN.js} +2 -2
- package/dist/{chunk-TRH533CA.js → chunk-7ICYQUOL.js} +2 -2
- package/dist/{chunk-I3GKTDM2.js → chunk-7LFXDGLH.js} +3 -3
- package/dist/{chunk-OCY3CRPG.js → chunk-A7B4RMQG.js} +3 -3
- package/dist/{chunk-2ZPQUTMW.js → chunk-AD6AMF2N.js} +4 -4
- package/dist/{chunk-TITSEN2M.js → chunk-ANADNYWK.js} +19 -5
- package/dist/chunk-ANADNYWK.js.map +1 -0
- package/dist/{chunk-YI7XUXLX.js → chunk-ASKEM4AR.js} +18 -18
- package/dist/{chunk-G5PVJJRA.js → chunk-B3F4CWQR.js} +1 -1
- package/dist/chunk-B3F4CWQR.js.map +1 -0
- package/dist/{chunk-675YU5IK.js → chunk-DDGV7NAX.js} +2 -2
- package/dist/{chunk-CE3GMHT4.js → chunk-EEARRVZ2.js} +2 -2
- package/dist/{chunk-AOWPZ7TM.js → chunk-F7AU34FC.js} +17 -17
- package/dist/{chunk-T6U7HDIY.js → chunk-FBNWOMCE.js} +2 -2
- package/dist/{chunk-QPZCAVDC.js → chunk-GMSDQUCR.js} +7 -7
- package/dist/{chunk-6N7R7TR2.js → chunk-IFJ23BHU.js} +6 -1
- package/dist/chunk-IFJ23BHU.js.map +1 -0
- package/dist/{chunk-IQULRIZM.js → chunk-IKSELOIV.js} +2 -2
- package/dist/{chunk-ZC3HG22I.js → chunk-JMBVCAR4.js} +2 -2
- package/dist/{chunk-CLFY35ED.js → chunk-KGWXHWAH.js} +3 -3
- package/dist/{chunk-RT7IP3D3.js → chunk-KSNVDPDF.js} +2 -2
- package/dist/{chunk-TWGGNUWJ.js → chunk-MKDRQAA3.js} +2 -2
- package/dist/{chunk-ZASJ53ML.js → chunk-ND5M64JJ.js} +41 -9
- package/dist/chunk-ND5M64JJ.js.map +1 -0
- package/dist/{chunk-XUQUBZ7O.js → chunk-NUWYOKS6.js} +2 -2
- package/dist/{chunk-VY6LKKVN.js → chunk-NWTGD4AN.js} +6 -1
- package/dist/chunk-NWTGD4AN.js.map +1 -0
- package/dist/{chunk-D4TLWDYR.js → chunk-PK5XBDA6.js} +2 -2
- package/dist/{chunk-2AL7N3BH.js → chunk-RBQLJSJ7.js} +2 -2
- package/dist/{chunk-FUUF7FMX.js → chunk-TXVD7PLT.js} +2 -2
- package/dist/{chunk-UTZW3X2R.js → chunk-UN3CH3CO.js} +2 -2
- package/dist/{chunk-PA6DMYEK.js → chunk-VYOFVVNK.js} +6 -6
- package/dist/{chunk-3SIC3E65.js → chunk-W5NKDU24.js} +2 -2
- package/dist/{cli-D8Tsa4Sh.d.ts → cli-_Y2Bmt6A.d.ts} +5 -5
- package/dist/cli.d.ts +8 -8
- package/dist/cli.js +25 -25
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +5 -5
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +2 -2
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.js +34 -34
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- 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 +6 -6
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +8 -8
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +5 -5
- package/dist/{orchestrator-B_WXBmuE.d.ts → orchestrator-BbZ_dQSU.d.ts} +4 -4
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +34 -34
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-Dvtvt141.d.ts → pipeline-FRMDb1fn.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/{qmd-DwBLh_hl.d.ts → qmd-xJRrHFbA.d.ts} +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-Dia_6FOn.d.ts → semantic-consolidation-fvdZRa5Z.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-RshM7i8-.d.ts → storage-CrvzaM9C.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +2 -2
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CHSXOq7s.d.ts → types-Bl4BWDM8.d.ts} +6 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +2 -2
- package/src/access-http.ts +40 -2
- package/src/config.ts +9 -0
- package/src/local-llm-thinking.test.ts +55 -1
- package/src/local-llm.ts +14 -0
- package/src/relay/mission-access.test.ts +58 -3
- package/src/relay/mission-access.ts +17 -3
- package/src/relay/mission-ui.test.ts +90 -0
- package/src/types.ts +6 -0
- package/dist/chunk-6N7R7TR2.js.map +0 -1
- package/dist/chunk-G5PVJJRA.js.map +0 -1
- package/dist/chunk-TITSEN2M.js.map +0 -1
- package/dist/chunk-VY6LKKVN.js.map +0 -1
- package/dist/chunk-ZASJ53ML.js.map +0 -1
- /package/dist/{chunk-2RSL6YRA.js.map → chunk-2E6G7FCE.js.map} +0 -0
- /package/dist/{chunk-JKLJ6A7W.js.map → chunk-3D6AFGQR.js.map} +0 -0
- /package/dist/{chunk-BQTSGK5Y.js.map → chunk-4B4MUS5D.js.map} +0 -0
- /package/dist/{chunk-NVXQTRBL.js.map → chunk-4LEF6XWJ.js.map} +0 -0
- /package/dist/{chunk-TMGK6YE7.js.map → chunk-5UNWK7KU.js.map} +0 -0
- /package/dist/{chunk-OIFZII6J.js.map → chunk-67ZCJLJY.js.map} +0 -0
- /package/dist/{chunk-ZRXSHGXT.js.map → chunk-6CALL5VN.js.map} +0 -0
- /package/dist/{chunk-TRH533CA.js.map → chunk-7ICYQUOL.js.map} +0 -0
- /package/dist/{chunk-I3GKTDM2.js.map → chunk-7LFXDGLH.js.map} +0 -0
- /package/dist/{chunk-OCY3CRPG.js.map → chunk-A7B4RMQG.js.map} +0 -0
- /package/dist/{chunk-2ZPQUTMW.js.map → chunk-AD6AMF2N.js.map} +0 -0
- /package/dist/{chunk-YI7XUXLX.js.map → chunk-ASKEM4AR.js.map} +0 -0
- /package/dist/{chunk-675YU5IK.js.map → chunk-DDGV7NAX.js.map} +0 -0
- /package/dist/{chunk-CE3GMHT4.js.map → chunk-EEARRVZ2.js.map} +0 -0
- /package/dist/{chunk-AOWPZ7TM.js.map → chunk-F7AU34FC.js.map} +0 -0
- /package/dist/{chunk-T6U7HDIY.js.map → chunk-FBNWOMCE.js.map} +0 -0
- /package/dist/{chunk-QPZCAVDC.js.map → chunk-GMSDQUCR.js.map} +0 -0
- /package/dist/{chunk-IQULRIZM.js.map → chunk-IKSELOIV.js.map} +0 -0
- /package/dist/{chunk-ZC3HG22I.js.map → chunk-JMBVCAR4.js.map} +0 -0
- /package/dist/{chunk-CLFY35ED.js.map → chunk-KGWXHWAH.js.map} +0 -0
- /package/dist/{chunk-RT7IP3D3.js.map → chunk-KSNVDPDF.js.map} +0 -0
- /package/dist/{chunk-TWGGNUWJ.js.map → chunk-MKDRQAA3.js.map} +0 -0
- /package/dist/{chunk-XUQUBZ7O.js.map → chunk-NUWYOKS6.js.map} +0 -0
- /package/dist/{chunk-D4TLWDYR.js.map → chunk-PK5XBDA6.js.map} +0 -0
- /package/dist/{chunk-2AL7N3BH.js.map → chunk-RBQLJSJ7.js.map} +0 -0
- /package/dist/{chunk-FUUF7FMX.js.map → chunk-TXVD7PLT.js.map} +0 -0
- /package/dist/{chunk-UTZW3X2R.js.map → chunk-UN3CH3CO.js.map} +0 -0
- /package/dist/{chunk-PA6DMYEK.js.map → chunk-VYOFVVNK.js.map} +0 -0
- /package/dist/{chunk-3SIC3E65.js.map → chunk-W5NKDU24.js.map} +0 -0
package/src/local-llm.ts
CHANGED
|
@@ -999,6 +999,20 @@ export class LocalLlmClient {
|
|
|
999
999
|
THINKING_COMPATIBLE_BACKENDS.has(this.detectedType)
|
|
1000
1000
|
) {
|
|
1001
1001
|
requestBody.chat_template_kwargs = { enable_thinking: false };
|
|
1002
|
+
} else if (shouldSuppressThinking && this.detectedType === "ollama") {
|
|
1003
|
+
// Ollama's /v1 endpoint silently drops `chat_template_kwargs` AND
|
|
1004
|
+
// `enable_thinking` — the ONLY field it maps to think-off is
|
|
1005
|
+
// `reasoning_effort` ("none" → ThinkValue{false} in openai.go;
|
|
1006
|
+
// verified against Ollama 0.32.0 source and live probes,
|
|
1007
|
+
// issue #1996). Without this, thinking-capable models (Gemma 4,
|
|
1008
|
+
// Qwen 3.5+) burn 1,700-2,000 reasoning tokens per extraction on
|
|
1009
|
+
// Ollama, exceed the client timeout, and retry forever. The effort
|
|
1010
|
+
// is configurable via `localLlmReasoningEffort` (default "none");
|
|
1011
|
+
// an empty value disables injection (pre-#1996 behavior).
|
|
1012
|
+
const effort = this.config.localLlmReasoningEffort;
|
|
1013
|
+
if (effort) {
|
|
1014
|
+
requestBody.reasoning_effort = effort;
|
|
1015
|
+
}
|
|
1002
1016
|
}
|
|
1003
1017
|
|
|
1004
1018
|
// Normalize URL (use 127.0.0.1 instead of localhost)
|
|
@@ -60,13 +60,33 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
|
|
|
60
60
|
service: fakeService(root, calls),
|
|
61
61
|
port: 0,
|
|
62
62
|
authToken: "relay-token",
|
|
63
|
-
principal: "
|
|
63
|
+
principal: "operator-build-week",
|
|
64
64
|
adminConsoleEnabled: false,
|
|
65
65
|
});
|
|
66
66
|
const status = await server.start();
|
|
67
67
|
const base = `http://127.0.0.1:${status.port}/engram/v1/relay/missions/${RELAY_DEMO_MISSION_ID}`;
|
|
68
68
|
try {
|
|
69
69
|
const fixture = createRelayMissionFixture();
|
|
70
|
+
const approval = fixture.find((event) => event.payload.kind === "correction_approved");
|
|
71
|
+
assert.ok(approval && approval.payload.kind === "correction_approved");
|
|
72
|
+
const mismatchedApproval = await fetch(`${base}/events`, {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: authHeaders(),
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
namespace: RELAY_DEMO_NAMESPACE,
|
|
77
|
+
event: {
|
|
78
|
+
...approval,
|
|
79
|
+
idempotencyKey: "mismatched-human-approval",
|
|
80
|
+
payload: {
|
|
81
|
+
...approval.payload,
|
|
82
|
+
approvedBy: { ...approval.payload.approvedBy, id: "different-operator" },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
assert.equal(mismatchedApproval.status, 400);
|
|
88
|
+
assert.equal(((await mismatchedApproval.json()) as { code: string }).code, "input_error");
|
|
89
|
+
|
|
70
90
|
const blankNamespace = await fetch(`${base}/events`, {
|
|
71
91
|
method: "POST",
|
|
72
92
|
headers: authHeaders(),
|
|
@@ -91,7 +111,7 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
|
|
|
91
111
|
assert.equal(response.status, 201, responseBody);
|
|
92
112
|
assert.equal(
|
|
93
113
|
(JSON.parse(responseBody) as { event: { authenticatedPrincipal?: string } }).event.authenticatedPrincipal,
|
|
94
|
-
"
|
|
114
|
+
"operator-build-week"
|
|
95
115
|
);
|
|
96
116
|
}
|
|
97
117
|
|
|
@@ -108,6 +128,7 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
|
|
|
108
128
|
});
|
|
109
129
|
assert.equal(response.status, 200);
|
|
110
130
|
assert.equal(response.headers.get("cache-control"), "no-store");
|
|
131
|
+
assert.equal(response.headers.get("x-remnic-authenticated-principal"), "operator-build-week");
|
|
111
132
|
const snapshot = (await response.json()) as RelayMissionSnapshot;
|
|
112
133
|
assert.equal(snapshot.receipt.complete, true);
|
|
113
134
|
assert.deepEqual(snapshot.receipt.activeDecisionIds, ["decision-refresh-after-expiry"]);
|
|
@@ -115,7 +136,40 @@ test("HTTP fixture endpoint returns one complete, namespace-authorized Relay rec
|
|
|
115
136
|
assert.equal(snapshot.agents.length, 3);
|
|
116
137
|
assert.equal(snapshot.tests.at(-1)?.status, "passed");
|
|
117
138
|
assert.ok(calls.every((call) => call.namespace === RELAY_DEMO_NAMESPACE));
|
|
118
|
-
assert.ok(calls.every((call) => call.principal === "
|
|
139
|
+
assert.ok(calls.every((call) => call.principal === "operator-build-week"));
|
|
140
|
+
} finally {
|
|
141
|
+
await server.stop();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("HTTP Relay rejects human approval without a server-resolved principal before persistence", async () => {
|
|
147
|
+
await withTempRoot(async (root) => {
|
|
148
|
+
const server = new EngramAccessHttpServer({
|
|
149
|
+
service: fakeService(root, []),
|
|
150
|
+
port: 0,
|
|
151
|
+
authToken: "relay-token",
|
|
152
|
+
adminConsoleEnabled: false,
|
|
153
|
+
});
|
|
154
|
+
const status = await server.start();
|
|
155
|
+
const base = `http://127.0.0.1:${status.port}/engram/v1/relay/missions/${RELAY_DEMO_MISSION_ID}`;
|
|
156
|
+
try {
|
|
157
|
+
const approval = createRelayMissionFixture().find((event) => event.payload.kind === "correction_approved");
|
|
158
|
+
assert.ok(approval);
|
|
159
|
+
const rejected = await fetch(`${base}/events`, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: authHeaders(),
|
|
162
|
+
body: JSON.stringify({ namespace: RELAY_DEMO_NAMESPACE, event: approval }),
|
|
163
|
+
});
|
|
164
|
+
assert.equal(rejected.status, 400);
|
|
165
|
+
assert.equal(((await rejected.json()) as { code: string }).code, "input_error");
|
|
166
|
+
|
|
167
|
+
const snapshotResponse = await fetch(`${base}?namespace=${RELAY_DEMO_NAMESPACE}`, {
|
|
168
|
+
headers: authHeaders(),
|
|
169
|
+
});
|
|
170
|
+
assert.equal(snapshotResponse.status, 200);
|
|
171
|
+
assert.equal(snapshotResponse.headers.get("x-remnic-authenticated-principal"), null);
|
|
172
|
+
assert.equal(((await snapshotResponse.json()) as RelayMissionSnapshot).found, false);
|
|
119
173
|
} finally {
|
|
120
174
|
await server.stop();
|
|
121
175
|
}
|
|
@@ -150,6 +204,7 @@ test("HTTP Relay surface distinguishes empty, invalid, unauthorized, and backend
|
|
|
150
204
|
|
|
151
205
|
const empty = await fetch(emptyUrl, { headers: authHeaders("read-token") });
|
|
152
206
|
assert.equal(empty.status, 200);
|
|
207
|
+
assert.equal(empty.headers.get("x-remnic-authenticated-principal"), null);
|
|
153
208
|
assert.deepEqual(await empty.json(), assertEmptyMissionShape());
|
|
154
209
|
|
|
155
210
|
const badLimit = await fetch(`${emptyUrl}&limit=501`, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
import { type OperationContext, defineOperation } from "../access-boundary.js";
|
|
4
|
-
import type
|
|
4
|
+
import { EngramAccessInputError, type EngramAccessService } from "../access-service.js";
|
|
5
5
|
import {
|
|
6
6
|
RELAY_MISSION_MAX_EVENT_LIMIT,
|
|
7
7
|
RelayIsoDateTimeSchema,
|
|
@@ -76,12 +76,26 @@ export async function appendRelayMissionEvent(
|
|
|
76
76
|
authenticatedPrincipal?: string,
|
|
77
77
|
beforeAppend?: () => void | Promise<void>
|
|
78
78
|
): Promise<RelayMissionAppendResult> {
|
|
79
|
-
const
|
|
79
|
+
const event = RelayMissionEventInputSchema.parse(input.event);
|
|
80
|
+
const approvalPrincipal = authenticatedPrincipal?.trim() || undefined;
|
|
81
|
+
if (event.payload.kind === "correction_approved" && event.payload.approvedBy.kind === "human") {
|
|
82
|
+
if (!approvalPrincipal) {
|
|
83
|
+
throw new EngramAccessInputError(
|
|
84
|
+
"Relay human approval requires a server-resolved authenticated principal"
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (event.payload.approvedBy.id !== approvalPrincipal) {
|
|
88
|
+
throw new EngramAccessInputError(
|
|
89
|
+
"Relay human approval identity must match the server-resolved authenticated principal"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const resolved = await service.getWritableStorageForNamespace(input.namespace ?? undefined, approvalPrincipal);
|
|
80
94
|
const store = new RelayMissionStore({
|
|
81
95
|
rootDir: resolved.storage.dir,
|
|
82
96
|
namespace: resolved.namespace,
|
|
83
97
|
});
|
|
84
|
-
return store.append(input.missionId,
|
|
98
|
+
return store.append(input.missionId, event, { authenticatedPrincipal: approvalPrincipal, beforeAppend });
|
|
85
99
|
}
|
|
86
100
|
|
|
87
101
|
/** Namespace-authorized, bounded Relay snapshot read shared by HTTP and UI. */
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
import { EngramAccessHttpServer } from "../access-http.js";
|
|
9
|
+
import type { EngramAccessService } from "../access-service.js";
|
|
10
|
+
import type { StorageManager } from "../storage.js";
|
|
11
|
+
|
|
12
|
+
const adminConsolePublicDir = path.resolve(
|
|
13
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
14
|
+
"../../../../admin-console/public"
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
async function withTempRoot(run: (root: string) => Promise<void>): Promise<void> {
|
|
18
|
+
const root = await mkdtemp(path.join(os.tmpdir(), "remnic-relay-ui-"));
|
|
19
|
+
try {
|
|
20
|
+
await run(root);
|
|
21
|
+
} finally {
|
|
22
|
+
await rm(root, { recursive: true, force: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function fakeService(root: string): EngramAccessService {
|
|
27
|
+
const storage = { dir: root } as StorageManager;
|
|
28
|
+
return {
|
|
29
|
+
configRef: { defaultNamespace: "relay-build-week", namespacesEnabled: true },
|
|
30
|
+
getReadableStorageForNamespace: async (namespace?: string) => ({ namespace: namespace ?? "relay-build-week", storage }),
|
|
31
|
+
getWritableStorageForNamespace: async (namespace?: string) => ({ namespace: namespace ?? "relay-build-week", storage }),
|
|
32
|
+
} as unknown as EngramAccessService;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test("Relay Mission Control serves both aliases from one exact static allow-list", async () => {
|
|
36
|
+
await withTempRoot(async (root) => {
|
|
37
|
+
const server = new EngramAccessHttpServer({
|
|
38
|
+
service: fakeService(root),
|
|
39
|
+
host: "127.0.0.1",
|
|
40
|
+
port: 0,
|
|
41
|
+
authToken: "relay-token",
|
|
42
|
+
principal: "relay-operator",
|
|
43
|
+
adminConsoleEnabled: true,
|
|
44
|
+
adminConsolePublicDir,
|
|
45
|
+
adminConsolePrefillToken: true,
|
|
46
|
+
});
|
|
47
|
+
const status = await server.start();
|
|
48
|
+
const origin = `http://127.0.0.1:${status.port}`;
|
|
49
|
+
try {
|
|
50
|
+
for (const prefix of ["remnic", "engram"]) {
|
|
51
|
+
const redirect = await fetch(`${origin}/${prefix}/ui/relay`, { redirect: "manual" });
|
|
52
|
+
assert.equal(redirect.status, 301);
|
|
53
|
+
assert.equal(redirect.headers.get("location"), `/${prefix}/ui/relay/`);
|
|
54
|
+
|
|
55
|
+
const shell = await fetch(`${origin}/${prefix}/ui/relay/`);
|
|
56
|
+
assert.equal(shell.status, 200);
|
|
57
|
+
assert.match(shell.headers.get("content-type") ?? "", /^text\/html/);
|
|
58
|
+
assert.doesNotMatch(await shell.text(), /__REMNIC_ADMIN_CONSOLE_PREFILL_TOKEN__/);
|
|
59
|
+
|
|
60
|
+
const authorizedShell = await fetch(`${origin}/${prefix}/ui/relay/`, {
|
|
61
|
+
headers: { authorization: "Bearer relay-token" },
|
|
62
|
+
});
|
|
63
|
+
assert.equal(authorizedShell.status, 200);
|
|
64
|
+
assert.equal(authorizedShell.headers.get("cache-control"), "private, no-store");
|
|
65
|
+
assert.match(await authorizedShell.text(), /__REMNIC_ADMIN_CONSOLE_PREFILL_TOKEN__="relay-token"/);
|
|
66
|
+
|
|
67
|
+
const expectedAssets = new Map([
|
|
68
|
+
["relay.css", /^text\/css/],
|
|
69
|
+
["relay-model.js", /^application\/javascript/],
|
|
70
|
+
["relay.js", /^application\/javascript/],
|
|
71
|
+
["replay.json", /^application\/json/],
|
|
72
|
+
]);
|
|
73
|
+
for (const [fileName, contentType] of expectedAssets) {
|
|
74
|
+
const asset = await fetch(`${origin}/${prefix}/ui/relay/${fileName}`);
|
|
75
|
+
assert.equal(asset.status, 200, `${prefix}/${fileName}`);
|
|
76
|
+
assert.match(asset.headers.get("content-type") ?? "", contentType);
|
|
77
|
+
assert.ok((await asset.text()).length > 100);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const auth = { authorization: "Bearer relay-token" };
|
|
81
|
+
const unknown = await fetch(`${origin}/${prefix}/ui/relay/not-allowed.js`, { headers: auth });
|
|
82
|
+
assert.equal(unknown.status, 404);
|
|
83
|
+
const nested = await fetch(`${origin}/${prefix}/ui/relay/relay.js/extra`, { headers: auth });
|
|
84
|
+
assert.equal(nested.status, 404);
|
|
85
|
+
}
|
|
86
|
+
} finally {
|
|
87
|
+
await server.stop();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/types.ts
CHANGED
|
@@ -1595,6 +1595,12 @@ export interface PluginConfig {
|
|
|
1595
1595
|
localLlmRetryBackoffMs: number;
|
|
1596
1596
|
localLlm400TripThreshold: number;
|
|
1597
1597
|
localLlm400CooldownMs: number;
|
|
1598
|
+
/** Ollama-backend thinking suppression: `reasoning_effort` value injected on
|
|
1599
|
+
* `/v1/chat/completions` for THINKING_SUPPRESSED_OPERATIONS ("none" | "low" |
|
|
1600
|
+
* "medium" | "high" | "max"; "" disables injection). Ollama ignores
|
|
1601
|
+
* `chat_template_kwargs`, so this is the only think-off dialect it honors.
|
|
1602
|
+
* Issue #1996. */
|
|
1603
|
+
localLlmReasoningEffort: string;
|
|
1598
1604
|
// Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)
|
|
1599
1605
|
/** Master gate. When false, restores pre-change behavior (extractor called on every triggered observe; no gate). */
|
|
1600
1606
|
extractionRetryEnabled: boolean;
|