@remnic/core 9.3.623 → 9.3.625
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 +18 -16
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +12 -5
- package/dist/access-http.js +10 -9
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +8 -8
- package/dist/access-schema.d.ts +5 -5
- package/dist/{access-service-CBNEKjzN.d.ts → access-service-C_sfOHsX.d.ts} +26 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +7 -7
- 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 +2 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.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/{chunk-C4PZTWTG.js → chunk-2RHI3FGV.js} +540 -17
- package/dist/chunk-2RHI3FGV.js.map +1 -0
- package/dist/{chunk-GYTVOLNX.js → chunk-3MNBW7R7.js} +2 -2
- package/dist/{chunk-QFQQFX2H.js → chunk-3R2UZV3U.js} +2 -2
- package/dist/{chunk-O4UNM6OR.js → chunk-532VCWYW.js} +2 -2
- package/dist/{chunk-2UFQYU5F.js → chunk-57QXN2CS.js} +2 -2
- package/dist/chunk-7WV3F5DQ.js +22 -0
- package/dist/chunk-7WV3F5DQ.js.map +1 -0
- package/dist/{chunk-RKW6QR7W.js → chunk-AZ4RI3QD.js} +1461 -78
- package/dist/chunk-AZ4RI3QD.js.map +1 -0
- package/dist/{chunk-KQFQ3IS5.js → chunk-F3FY3D3S.js} +43 -7
- package/dist/chunk-F3FY3D3S.js.map +1 -0
- package/dist/{chunk-4R4KTDIE.js → chunk-FPNQF475.js} +1 -1
- package/dist/chunk-FPNQF475.js.map +1 -0
- package/dist/{chunk-UGEBPVNI.js → chunk-GE7Q7KXP.js} +2 -2
- package/dist/{chunk-GLWW3EJQ.js → chunk-KB4MFBF5.js} +3 -3
- package/dist/{chunk-5GOMXHLC.js → chunk-KKTXCFD7.js} +255 -1
- package/dist/chunk-KKTXCFD7.js.map +1 -0
- package/dist/{chunk-FH3PPO42.js → chunk-KVFYTRMV.js} +2 -2
- package/dist/{chunk-BNW5NJJH.js → chunk-LQYTQCXM.js} +2 -2
- package/dist/{chunk-AYHXQR53.js → chunk-MVQN73GT.js} +2 -2
- package/dist/{chunk-ZZPIJPPD.js → chunk-N5RGXWLQ.js} +2 -2
- package/dist/chunk-NDAH7BJ5.js +213 -0
- package/dist/chunk-NDAH7BJ5.js.map +1 -0
- package/dist/{chunk-R3OQGYOU.js → chunk-P2D2MM47.js} +2 -2
- package/dist/{chunk-PSUB67YB.js → chunk-PW6GURU3.js} +2 -2
- package/dist/{chunk-W3BKVM64.js → chunk-QDV6VAD4.js} +2 -2
- package/dist/{chunk-3QSU4NFF.js → chunk-QHXW3LZV.js} +3 -3
- package/dist/{chunk-I6UCUHLK.js → chunk-SHV5Y2WU.js} +182 -3
- package/dist/chunk-SHV5Y2WU.js.map +1 -0
- package/dist/{chunk-OZXVGYGZ.js → chunk-STDAAGH7.js} +2 -2
- package/dist/{chunk-FMGWXIES.js → chunk-TZDSNIRO.js} +5 -5
- package/dist/{chunk-2L54V4ZO.js → chunk-UELS6WWF.js} +2 -2
- package/dist/{chunk-PJGB7XRR.js → chunk-UGHUNQ74.js} +502 -134
- package/dist/chunk-UGHUNQ74.js.map +1 -0
- package/dist/{chunk-ZJSZNTEI.js → chunk-Y3TMFC6I.js} +140 -10
- package/dist/chunk-Y3TMFC6I.js.map +1 -0
- package/dist/{chunk-BPSGLMQ4.js → chunk-YQNADJCT.js} +2 -2
- package/dist/{cli-Cw729yLf.d.ts → cli-EZv6YE6_.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +23 -21
- package/dist/compounding/engine.d.ts +1 -1
- 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 +2 -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 +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- 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 +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- 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/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +307 -9
- package/dist/index.js +155 -29
- package/dist/index.js.map +1 -1
- 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/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 +5 -5
- 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 +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- 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 +1 -1
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +8 -7
- package/dist/{orchestrator-CqWOjfgl.d.ts → orchestrator-CEycaY3M.d.ts} +361 -4
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +13 -11
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- 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-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/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +3 -2
- package/dist/retrieval-agents.d.ts +1 -1
- 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/schemas.d.ts +32 -32
- 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-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
- package/dist/{semantic-consolidation-4HkHWgeI.d.ts → semantic-consolidation-FbhPeJjB.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 +5 -5
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +19 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.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 +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/types-D5VRAI04.d.ts +3134 -0
- package/dist/types.d.ts +3 -2862
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +1 -1
- package/src/access-http.ts +182 -8
- package/src/access-mcp.ts +198 -0
- package/src/access-service.ts +65 -0
- package/src/cli.ts +187 -0
- package/src/config.ts +7 -0
- package/src/index.ts +7 -0
- package/src/orchestrator.ts +42 -0
- package/src/storage.ts +106 -0
- package/src/types.ts +5 -0
- package/src/wearables/cleanup.test.ts +134 -0
- package/src/wearables/cleanup.ts +188 -0
- package/src/wearables/cli.test.ts +170 -0
- package/src/wearables/cli.ts +441 -0
- package/src/wearables/config.test.ts +143 -0
- package/src/wearables/config.ts +332 -0
- package/src/wearables/corrections.test.ts +118 -0
- package/src/wearables/corrections.ts +211 -0
- package/src/wearables/day-store.test.ts +143 -0
- package/src/wearables/day-store.ts +238 -0
- package/src/wearables/errors.test.ts +32 -0
- package/src/wearables/errors.ts +29 -0
- package/src/wearables/index.ts +114 -0
- package/src/wearables/memory-gen.test.ts +342 -0
- package/src/wearables/memory-gen.ts +413 -0
- package/src/wearables/pipeline.test.ts +608 -0
- package/src/wearables/pipeline.ts +519 -0
- package/src/wearables/redaction.test.ts +94 -0
- package/src/wearables/redaction.ts +156 -0
- package/src/wearables/registry.test.ts +62 -0
- package/src/wearables/registry.ts +133 -0
- package/src/wearables/service.test.ts +425 -0
- package/src/wearables/service.ts +691 -0
- package/src/wearables/speakers.test.ts +110 -0
- package/src/wearables/speakers.ts +174 -0
- package/src/wearables/storage-io.test.ts +105 -0
- package/src/wearables/sync-state.test.ts +134 -0
- package/src/wearables/sync-state.ts +186 -0
- package/src/wearables/types.ts +285 -0
- package/dist/chunk-4R4KTDIE.js.map +0 -1
- package/dist/chunk-5GOMXHLC.js.map +0 -1
- package/dist/chunk-C4PZTWTG.js.map +0 -1
- package/dist/chunk-I6UCUHLK.js.map +0 -1
- package/dist/chunk-KQFQ3IS5.js.map +0 -1
- package/dist/chunk-PJGB7XRR.js.map +0 -1
- package/dist/chunk-RKW6QR7W.js.map +0 -1
- package/dist/chunk-ZJSZNTEI.js.map +0 -1
- /package/dist/{chunk-GYTVOLNX.js.map → chunk-3MNBW7R7.js.map} +0 -0
- /package/dist/{chunk-QFQQFX2H.js.map → chunk-3R2UZV3U.js.map} +0 -0
- /package/dist/{chunk-O4UNM6OR.js.map → chunk-532VCWYW.js.map} +0 -0
- /package/dist/{chunk-2UFQYU5F.js.map → chunk-57QXN2CS.js.map} +0 -0
- /package/dist/{chunk-UGEBPVNI.js.map → chunk-GE7Q7KXP.js.map} +0 -0
- /package/dist/{chunk-GLWW3EJQ.js.map → chunk-KB4MFBF5.js.map} +0 -0
- /package/dist/{chunk-FH3PPO42.js.map → chunk-KVFYTRMV.js.map} +0 -0
- /package/dist/{chunk-BNW5NJJH.js.map → chunk-LQYTQCXM.js.map} +0 -0
- /package/dist/{chunk-AYHXQR53.js.map → chunk-MVQN73GT.js.map} +0 -0
- /package/dist/{chunk-ZZPIJPPD.js.map → chunk-N5RGXWLQ.js.map} +0 -0
- /package/dist/{chunk-R3OQGYOU.js.map → chunk-P2D2MM47.js.map} +0 -0
- /package/dist/{chunk-PSUB67YB.js.map → chunk-PW6GURU3.js.map} +0 -0
- /package/dist/{chunk-W3BKVM64.js.map → chunk-QDV6VAD4.js.map} +0 -0
- /package/dist/{chunk-3QSU4NFF.js.map → chunk-QHXW3LZV.js.map} +0 -0
- /package/dist/{chunk-OZXVGYGZ.js.map → chunk-STDAAGH7.js.map} +0 -0
- /package/dist/{chunk-FMGWXIES.js.map → chunk-TZDSNIRO.js.map} +0 -0
- /package/dist/{chunk-2L54V4ZO.js.map → chunk-UELS6WWF.js.map} +0 -0
- /package/dist/{chunk-BPSGLMQ4.js.map → chunk-YQNADJCT.js.map} +0 -0
package/dist/types.js
CHANGED
package/dist/verified-recall.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
searchVerifiedEpisodes
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-P2D2MM47.js";
|
|
4
4
|
import "./chunk-HQ6NIBL6.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-UGHUNQ74.js";
|
|
6
6
|
import "./chunk-5UZXUTVO.js";
|
|
7
7
|
import "./chunk-J6A3CX5N.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-FPNQF475.js";
|
|
9
9
|
import "./chunk-RULE4VG5.js";
|
|
10
10
|
import "./chunk-SCU65EZI.js";
|
|
11
11
|
import "./chunk-MB5RSUW6.js";
|
package/package.json
CHANGED
package/src/access-http.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath, URL } from "node:url";
|
|
|
8
8
|
import { gunzipSync } from "node:zlib";
|
|
9
9
|
import { log } from "./logger.js";
|
|
10
10
|
import { EngramAccessInputError, type EngramAccessService } from "./access-service.js";
|
|
11
|
+
import { WearablesInputError } from "./wearables/errors.js";
|
|
11
12
|
import { EngramMcpServer } from "./access-mcp.js";
|
|
12
13
|
import { validateRequest, type SchemaName, type SchemaTypeFor } from "./access-schema.js";
|
|
13
14
|
import {
|
|
@@ -984,23 +985,149 @@ export class EngramAccessHttpServer {
|
|
|
984
985
|
...(disclosure !== undefined ? { disclosure } : {}),
|
|
985
986
|
});
|
|
986
987
|
} catch (err) {
|
|
987
|
-
|
|
988
|
-
|
|
988
|
+
// Only surface the message for the deliberately-prefixed recallXray
|
|
989
|
+
// input-validation errors, and only when it is a real Error.message —
|
|
990
|
+
// never String(err) of an arbitrary throw, which CodeQL flags as
|
|
991
|
+
// stack-trace exposure (js/stack-trace-exposure). Validation errors are
|
|
992
|
+
// always thrown as Error instances (see access-service.ts), so this is
|
|
993
|
+
// behavior-preserving; anything else is a server-side fault and is
|
|
994
|
+
// rethrown so the outer `handle()` catch returns 500 + logs it.
|
|
995
|
+
if (err instanceof Error && err.message.startsWith("recallXray:")) {
|
|
989
996
|
this.respondJson(res, 400, {
|
|
990
997
|
error: "invalid_request",
|
|
991
998
|
code: "invalid_request",
|
|
992
|
-
message,
|
|
999
|
+
message: err.message,
|
|
993
1000
|
});
|
|
994
1001
|
return;
|
|
995
1002
|
}
|
|
996
|
-
// Anything else is a server-side fault; rethrow so the
|
|
997
|
-
// outer `handle()` catch returns 500 + logs the error.
|
|
998
1003
|
throw err;
|
|
999
1004
|
}
|
|
1000
1005
|
this.respondJson(res, 200, payload);
|
|
1001
1006
|
return;
|
|
1002
1007
|
}
|
|
1003
1008
|
|
|
1009
|
+
// -- Wearables (Limitless / Bee / Omi transcript ingestion). All
|
|
1010
|
+
// behavior + validation lives in WearablesService; these routes
|
|
1011
|
+
// translate transport shape only. Service validation errors map
|
|
1012
|
+
// to 400 via respondWearablesError; backend faults bubble to the
|
|
1013
|
+
// global 500 handler.
|
|
1014
|
+
if (
|
|
1015
|
+
req.method === "GET" &&
|
|
1016
|
+
(pathname === "/engram/v1/wearables/status" || pathname === "/remnic/v1/wearables/status")
|
|
1017
|
+
) {
|
|
1018
|
+
this.respondJson(res, 200, await this.service.wearablesStatus());
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
if (
|
|
1023
|
+
req.method === "POST" &&
|
|
1024
|
+
(pathname === "/engram/v1/wearables/sync" || pathname === "/remnic/v1/wearables/sync")
|
|
1025
|
+
) {
|
|
1026
|
+
const body = (await this.readJsonBody(req)) as Record<string, unknown>;
|
|
1027
|
+
const source = optionalQueryString(body.source, "source");
|
|
1028
|
+
const date = optionalQueryString(body.date, "date");
|
|
1029
|
+
let days: number | undefined;
|
|
1030
|
+
if (body.days !== undefined && body.days !== null) {
|
|
1031
|
+
if (
|
|
1032
|
+
typeof body.days !== "number" ||
|
|
1033
|
+
!Number.isInteger(body.days) ||
|
|
1034
|
+
body.days < 1
|
|
1035
|
+
) {
|
|
1036
|
+
throw new EngramAccessInputError(
|
|
1037
|
+
`days must be a positive integer (got ${JSON.stringify(body.days)})`,
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
days = body.days;
|
|
1041
|
+
}
|
|
1042
|
+
if (body.forceMemories !== undefined && typeof body.forceMemories !== "boolean") {
|
|
1043
|
+
throw new EngramAccessInputError(
|
|
1044
|
+
`forceMemories must be a boolean (got ${JSON.stringify(body.forceMemories)})`,
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
try {
|
|
1048
|
+
const summaries = await this.service.wearablesSync({
|
|
1049
|
+
source,
|
|
1050
|
+
date,
|
|
1051
|
+
days,
|
|
1052
|
+
forceMemories: body.forceMemories === true,
|
|
1053
|
+
});
|
|
1054
|
+
this.respondJson(res, 200, { summaries });
|
|
1055
|
+
} catch (err) {
|
|
1056
|
+
if (this.respondWearablesError(res, err)) return;
|
|
1057
|
+
throw err;
|
|
1058
|
+
}
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
if (
|
|
1063
|
+
req.method === "GET" &&
|
|
1064
|
+
(pathname === "/engram/v1/wearables/transcript" || pathname === "/remnic/v1/wearables/transcript")
|
|
1065
|
+
) {
|
|
1066
|
+
const date = parsed.searchParams.get("date");
|
|
1067
|
+
if (!date || date.trim().length === 0) {
|
|
1068
|
+
throw new EngramAccessInputError(
|
|
1069
|
+
"date query parameter is required (YYYY-MM-DD)",
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
const sourceParam = parsed.searchParams.get("source");
|
|
1073
|
+
try {
|
|
1074
|
+
const transcripts = await this.service.wearablesTranscriptDay({
|
|
1075
|
+
date,
|
|
1076
|
+
source: sourceParam && sourceParam.length > 0 ? sourceParam : undefined,
|
|
1077
|
+
});
|
|
1078
|
+
this.respondJson(res, 200, { transcripts });
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
if (this.respondWearablesError(res, err)) return;
|
|
1081
|
+
throw err;
|
|
1082
|
+
}
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (
|
|
1087
|
+
req.method === "GET" &&
|
|
1088
|
+
(pathname === "/engram/v1/wearables/transcripts/search" ||
|
|
1089
|
+
pathname === "/remnic/v1/wearables/transcripts/search")
|
|
1090
|
+
) {
|
|
1091
|
+
const queryParam = parsed.searchParams.get("q");
|
|
1092
|
+
if (!queryParam || queryParam.trim().length === 0) {
|
|
1093
|
+
throw new EngramAccessInputError(
|
|
1094
|
+
"q query parameter is required and must be non-empty",
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
try {
|
|
1098
|
+
const results = await this.service.wearablesTranscriptSearch({
|
|
1099
|
+
query: queryParam,
|
|
1100
|
+
source: nonEmptyQueryParam(parsed.searchParams.get("source")),
|
|
1101
|
+
from: nonEmptyQueryParam(parsed.searchParams.get("from")),
|
|
1102
|
+
to: nonEmptyQueryParam(parsed.searchParams.get("to")),
|
|
1103
|
+
limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"),
|
|
1104
|
+
});
|
|
1105
|
+
this.respondJson(res, 200, { results });
|
|
1106
|
+
} catch (err) {
|
|
1107
|
+
if (this.respondWearablesError(res, err)) return;
|
|
1108
|
+
throw err;
|
|
1109
|
+
}
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
if (
|
|
1114
|
+
req.method === "GET" &&
|
|
1115
|
+
(pathname === "/engram/v1/wearables/memories" || pathname === "/remnic/v1/wearables/memories")
|
|
1116
|
+
) {
|
|
1117
|
+
try {
|
|
1118
|
+
const memories = await this.service.wearablesTranscriptMemories({
|
|
1119
|
+
source: nonEmptyQueryParam(parsed.searchParams.get("source")),
|
|
1120
|
+
date: nonEmptyQueryParam(parsed.searchParams.get("date")),
|
|
1121
|
+
limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"),
|
|
1122
|
+
});
|
|
1123
|
+
this.respondJson(res, 200, { memories });
|
|
1124
|
+
} catch (err) {
|
|
1125
|
+
if (this.respondWearablesError(res, err)) return;
|
|
1126
|
+
throw err;
|
|
1127
|
+
}
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1004
1131
|
if (req.method === "POST" && pathname === "/engram/v1/observe") {
|
|
1005
1132
|
const body = await this.readValidatedBody(req, "observe");
|
|
1006
1133
|
this.ensureWriteRateLimitAvailable();
|
|
@@ -1558,12 +1685,15 @@ export class EngramAccessHttpServer {
|
|
|
1558
1685
|
);
|
|
1559
1686
|
this.respondJson(res, 200, snapshot);
|
|
1560
1687
|
} catch (err) {
|
|
1561
|
-
|
|
1562
|
-
|
|
1688
|
+
// As with recallXray above: surface only the deliberately-prefixed
|
|
1689
|
+
// graphSnapshot validation Error.message, never String(err) of an
|
|
1690
|
+
// arbitrary throw (CodeQL js/stack-trace-exposure). Validation errors are
|
|
1691
|
+
// always Error instances; anything else is rethrown as a 500.
|
|
1692
|
+
if (err instanceof Error && err.message.startsWith("graphSnapshot:")) {
|
|
1563
1693
|
this.respondJson(res, 400, {
|
|
1564
1694
|
error: "invalid_request",
|
|
1565
1695
|
code: "invalid_request",
|
|
1566
|
-
message,
|
|
1696
|
+
message: err.message,
|
|
1567
1697
|
});
|
|
1568
1698
|
return;
|
|
1569
1699
|
}
|
|
@@ -2365,4 +2495,48 @@ export class EngramAccessHttpServer {
|
|
|
2365
2495
|
private shouldCountWriteRateLimit(response: { dryRun?: boolean; idempotencyReplay?: boolean }): boolean {
|
|
2366
2496
|
return response.dryRun !== true && response.idempotencyReplay !== true;
|
|
2367
2497
|
}
|
|
2498
|
+
|
|
2499
|
+
/**
|
|
2500
|
+
* Map wearables validation errors (WearablesInputError — invalid
|
|
2501
|
+
* params, unknown/disabled sources, missing connector packages) to a
|
|
2502
|
+
* 400 response. Returns false for everything else so backend faults
|
|
2503
|
+
* keep flowing to the global 500 handler.
|
|
2504
|
+
*/
|
|
2505
|
+
private respondWearablesError(res: ServerResponse, err: unknown): boolean {
|
|
2506
|
+
if (err instanceof WearablesInputError) {
|
|
2507
|
+
this.respondJson(res, 400, {
|
|
2508
|
+
error: "invalid_request",
|
|
2509
|
+
code: "invalid_request",
|
|
2510
|
+
message: err.message,
|
|
2511
|
+
});
|
|
2512
|
+
return true;
|
|
2513
|
+
}
|
|
2514
|
+
return false;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
/** Optional string field from a JSON body: absent/null/"" → undefined. */
|
|
2519
|
+
function optionalQueryString(value: unknown, label: string): string | undefined {
|
|
2520
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
2521
|
+
if (typeof value !== "string") {
|
|
2522
|
+
throw new EngramAccessInputError(
|
|
2523
|
+
`${label} must be a string (got ${JSON.stringify(value)})`,
|
|
2524
|
+
);
|
|
2525
|
+
}
|
|
2526
|
+
return value;
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
/** Optional non-empty query param: null/"" → undefined. */
|
|
2530
|
+
function nonEmptyQueryParam(value: string | null): string | undefined {
|
|
2531
|
+
return value !== null && value.length > 0 ? value : undefined;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
/** Optional positive-integer query param; rejects invalid values. */
|
|
2535
|
+
function positiveIntQueryParam(value: string | null, label: string): number | undefined {
|
|
2536
|
+
if (value === null || value.length === 0) return undefined;
|
|
2537
|
+
const parsed = Number(value);
|
|
2538
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
2539
|
+
throw new EngramAccessInputError(`${label} expects a positive integer`);
|
|
2540
|
+
}
|
|
2541
|
+
return parsed;
|
|
2368
2542
|
}
|
package/src/access-mcp.ts
CHANGED
|
@@ -204,6 +204,36 @@ function parseMcpRequest<N extends SchemaName>(
|
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Strict optional-string MCP argument: absent/null/"" → undefined,
|
|
209
|
+
* non-string → loud error (CLAUDE.md rule 51 — no silent coercion).
|
|
210
|
+
*/
|
|
211
|
+
function optionalNonEmptyString(value: unknown, label: string): string | undefined {
|
|
212
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
213
|
+
if (typeof value !== "string") {
|
|
214
|
+
throw new Error(`${label} expects a string; got ${JSON.stringify(value)}`);
|
|
215
|
+
}
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Strict optional positive-integer MCP argument. Accepts JSON numbers
|
|
221
|
+
* and numeric strings (loosely-typed MCP clients send both); rejects
|
|
222
|
+
* everything else including booleans, which `Number()` would silently
|
|
223
|
+
* coerce.
|
|
224
|
+
*/
|
|
225
|
+
function optionalPositiveInteger(value: unknown, label: string): number | undefined {
|
|
226
|
+
if (value === undefined || value === null || value === "") return undefined;
|
|
227
|
+
if (typeof value !== "number" && typeof value !== "string") {
|
|
228
|
+
throw new Error(`${label} expects a positive integer; got ${JSON.stringify(value)}`);
|
|
229
|
+
}
|
|
230
|
+
const parsed = typeof value === "number" ? value : Number(value);
|
|
231
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
232
|
+
throw new Error(`${label} expects a positive integer; got ${JSON.stringify(value)}`);
|
|
233
|
+
}
|
|
234
|
+
return parsed;
|
|
235
|
+
}
|
|
236
|
+
|
|
207
237
|
function getObjectProperties(value: unknown): Record<string, unknown> | undefined {
|
|
208
238
|
return value && typeof value === "object" && !Array.isArray(value)
|
|
209
239
|
? (value as Record<string, unknown>)
|
|
@@ -452,6 +482,124 @@ export class EngramMcpServer {
|
|
|
452
482
|
additionalProperties: false,
|
|
453
483
|
},
|
|
454
484
|
},
|
|
485
|
+
{
|
|
486
|
+
name: "engram.wearables_status",
|
|
487
|
+
description:
|
|
488
|
+
"Status of wearable transcript sources (Limitless / Bee / Omi): configured sources, connector availability, last sync, stored transcript days.",
|
|
489
|
+
inputSchema: {
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {},
|
|
492
|
+
additionalProperties: false,
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: "engram.wearables_sync",
|
|
497
|
+
description:
|
|
498
|
+
"Pull, clean, and store wearable transcripts for one source or all enabled sources; optionally creates trust-gated memories per the source's memoryMode.",
|
|
499
|
+
inputSchema: {
|
|
500
|
+
type: "object",
|
|
501
|
+
properties: {
|
|
502
|
+
source: {
|
|
503
|
+
type: "string",
|
|
504
|
+
description: "Source id (e.g. limitless, bee, omi). Omit to sync every enabled source.",
|
|
505
|
+
},
|
|
506
|
+
date: {
|
|
507
|
+
type: "string",
|
|
508
|
+
description: "Sync exactly this day (YYYY-MM-DD). Overrides days.",
|
|
509
|
+
},
|
|
510
|
+
days: {
|
|
511
|
+
type: "integer",
|
|
512
|
+
minimum: 1,
|
|
513
|
+
maximum: 90,
|
|
514
|
+
description: "Lookback window in days ending today (default 2).",
|
|
515
|
+
},
|
|
516
|
+
forceMemories: {
|
|
517
|
+
type: "boolean",
|
|
518
|
+
description: "Re-run memory extraction even for unchanged days.",
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
additionalProperties: false,
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: "engram.transcript_day",
|
|
526
|
+
description:
|
|
527
|
+
"Return the full stored wearable transcript(s) for a day, across all sources or one source, with cross-source overlap hints.",
|
|
528
|
+
inputSchema: {
|
|
529
|
+
type: "object",
|
|
530
|
+
properties: {
|
|
531
|
+
date: {
|
|
532
|
+
type: "string",
|
|
533
|
+
description: "Day to read (YYYY-MM-DD). Required.",
|
|
534
|
+
},
|
|
535
|
+
source: {
|
|
536
|
+
type: "string",
|
|
537
|
+
description: "Optional source id to scope to (e.g. limitless).",
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
required: ["date"],
|
|
541
|
+
additionalProperties: false,
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
name: "engram.transcript_search",
|
|
546
|
+
description:
|
|
547
|
+
"Search stored wearable transcripts. Results carry source + date so callers can pull the full day via engram.transcript_day.",
|
|
548
|
+
inputSchema: {
|
|
549
|
+
type: "object",
|
|
550
|
+
properties: {
|
|
551
|
+
query: {
|
|
552
|
+
type: "string",
|
|
553
|
+
description: "Search query. Required; non-empty.",
|
|
554
|
+
},
|
|
555
|
+
source: {
|
|
556
|
+
type: "string",
|
|
557
|
+
description: "Optional source id filter.",
|
|
558
|
+
},
|
|
559
|
+
from: {
|
|
560
|
+
type: "string",
|
|
561
|
+
description: "Optional inclusive start date (YYYY-MM-DD).",
|
|
562
|
+
},
|
|
563
|
+
to: {
|
|
564
|
+
type: "string",
|
|
565
|
+
description: "Optional inclusive end date (YYYY-MM-DD).",
|
|
566
|
+
},
|
|
567
|
+
limit: {
|
|
568
|
+
type: "integer",
|
|
569
|
+
minimum: 1,
|
|
570
|
+
maximum: 50,
|
|
571
|
+
description: "Maximum results (default 10).",
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
required: ["query"],
|
|
575
|
+
additionalProperties: false,
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
name: "engram.transcript_memories",
|
|
580
|
+
description:
|
|
581
|
+
"List memories created from wearable transcripts, filterable by source and/or day. Includes pending_review candidates awaiting approval.",
|
|
582
|
+
inputSchema: {
|
|
583
|
+
type: "object",
|
|
584
|
+
properties: {
|
|
585
|
+
source: {
|
|
586
|
+
type: "string",
|
|
587
|
+
description: "Optional source id filter (e.g. limitless).",
|
|
588
|
+
},
|
|
589
|
+
date: {
|
|
590
|
+
type: "string",
|
|
591
|
+
description: "Optional transcript day filter (YYYY-MM-DD).",
|
|
592
|
+
},
|
|
593
|
+
limit: {
|
|
594
|
+
type: "integer",
|
|
595
|
+
minimum: 1,
|
|
596
|
+
maximum: 200,
|
|
597
|
+
description: "Maximum results (default 50).",
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
additionalProperties: false,
|
|
601
|
+
},
|
|
602
|
+
},
|
|
455
603
|
{
|
|
456
604
|
name: "engram.action_confidence",
|
|
457
605
|
description:
|
|
@@ -2348,6 +2496,56 @@ export class EngramMcpServer {
|
|
|
2348
2496
|
: {}),
|
|
2349
2497
|
});
|
|
2350
2498
|
}
|
|
2499
|
+
case "engram.wearables_status":
|
|
2500
|
+
return this.service.wearablesStatus();
|
|
2501
|
+
case "engram.wearables_sync": {
|
|
2502
|
+
const source = optionalNonEmptyString(args.source, "engram.wearables_sync: source");
|
|
2503
|
+
const date = optionalNonEmptyString(args.date, "engram.wearables_sync: date");
|
|
2504
|
+
const days = optionalPositiveInteger(args.days, "engram.wearables_sync: days");
|
|
2505
|
+
let forceMemories: boolean | undefined;
|
|
2506
|
+
if (args.forceMemories !== undefined && args.forceMemories !== null) {
|
|
2507
|
+
if (typeof args.forceMemories !== "boolean") {
|
|
2508
|
+
throw new Error(
|
|
2509
|
+
`engram.wearables_sync: forceMemories expects a boolean; got ${JSON.stringify(args.forceMemories)}`,
|
|
2510
|
+
);
|
|
2511
|
+
}
|
|
2512
|
+
forceMemories = args.forceMemories;
|
|
2513
|
+
}
|
|
2514
|
+
// Date/days/source validation beyond shape lives in the shared
|
|
2515
|
+
// WearablesService so CLI/HTTP/MCP reject identically.
|
|
2516
|
+
return this.service.wearablesSync({ source, date, days, forceMemories });
|
|
2517
|
+
}
|
|
2518
|
+
case "engram.transcript_day": {
|
|
2519
|
+
const date = typeof args.date === "string" ? args.date : "";
|
|
2520
|
+
if (date.trim().length === 0) {
|
|
2521
|
+
throw new Error(
|
|
2522
|
+
"engram.transcript_day: date is required and must be YYYY-MM-DD",
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
const source = optionalNonEmptyString(args.source, "engram.transcript_day: source");
|
|
2526
|
+
return this.service.wearablesTranscriptDay({ date, source });
|
|
2527
|
+
}
|
|
2528
|
+
case "engram.transcript_search": {
|
|
2529
|
+
const query = typeof args.query === "string" ? args.query : "";
|
|
2530
|
+
if (query.trim().length === 0) {
|
|
2531
|
+
throw new Error(
|
|
2532
|
+
"engram.transcript_search: query is required and must be non-empty",
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
return this.service.wearablesTranscriptSearch({
|
|
2536
|
+
query,
|
|
2537
|
+
source: optionalNonEmptyString(args.source, "engram.transcript_search: source"),
|
|
2538
|
+
from: optionalNonEmptyString(args.from, "engram.transcript_search: from"),
|
|
2539
|
+
to: optionalNonEmptyString(args.to, "engram.transcript_search: to"),
|
|
2540
|
+
limit: optionalPositiveInteger(args.limit, "engram.transcript_search: limit"),
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
case "engram.transcript_memories":
|
|
2544
|
+
return this.service.wearablesTranscriptMemories({
|
|
2545
|
+
source: optionalNonEmptyString(args.source, "engram.transcript_memories: source"),
|
|
2546
|
+
date: optionalNonEmptyString(args.date, "engram.transcript_memories: date"),
|
|
2547
|
+
limit: optionalPositiveInteger(args.limit, "engram.transcript_memories: limit"),
|
|
2548
|
+
});
|
|
2351
2549
|
case "engram.action_confidence": {
|
|
2352
2550
|
const body: ActionConfidenceRequest = parseMcpRequest("actionConfidence", args);
|
|
2353
2551
|
return this.service.actionConfidence(body);
|
package/src/access-service.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
import { runProcedureMining } from "./procedural/procedure-miner.js";
|
|
40
40
|
import type { PatternReinforcementResult } from "./maintenance/pattern-reinforcement.js";
|
|
41
41
|
import type { LiveConnectorsRunSummary } from "./live-connectors-runner.js";
|
|
42
|
+
import type { WearablesService } from "./wearables/service.js";
|
|
42
43
|
import {
|
|
43
44
|
computeProcedureStats,
|
|
44
45
|
type ProcedureStatsReport,
|
|
@@ -6154,4 +6155,68 @@ export class EngramAccessService {
|
|
|
6154
6155
|
notes: result.notes,
|
|
6155
6156
|
};
|
|
6156
6157
|
}
|
|
6158
|
+
|
|
6159
|
+
// ---------------------------------------------------------------------------
|
|
6160
|
+
// Wearables (Limitless / Bee / Omi transcript ingestion)
|
|
6161
|
+
//
|
|
6162
|
+
// Thin delegations to the orchestrator-owned WearablesService — the
|
|
6163
|
+
// same instance behind the CLI, so HTTP/MCP callers observe identical
|
|
6164
|
+
// behavior and validation (renderer-sharing rule).
|
|
6165
|
+
// ---------------------------------------------------------------------------
|
|
6166
|
+
|
|
6167
|
+
async wearablesStatus(): Promise<
|
|
6168
|
+
Awaited<ReturnType<WearablesService["status"]>>
|
|
6169
|
+
> {
|
|
6170
|
+
return this.orchestrator.getWearablesService().status();
|
|
6171
|
+
}
|
|
6172
|
+
|
|
6173
|
+
async wearablesSync(request: {
|
|
6174
|
+
source?: string;
|
|
6175
|
+
date?: string;
|
|
6176
|
+
days?: number;
|
|
6177
|
+
forceMemories?: boolean;
|
|
6178
|
+
}): Promise<Awaited<ReturnType<WearablesService["sync"]>>> {
|
|
6179
|
+
return this.orchestrator.getWearablesService().sync({
|
|
6180
|
+
source: request.source,
|
|
6181
|
+
date: request.date,
|
|
6182
|
+
days: request.days,
|
|
6183
|
+
forceMemories: request.forceMemories,
|
|
6184
|
+
});
|
|
6185
|
+
}
|
|
6186
|
+
|
|
6187
|
+
async wearablesTranscriptDay(request: {
|
|
6188
|
+
date: string;
|
|
6189
|
+
source?: string;
|
|
6190
|
+
}): Promise<Awaited<ReturnType<WearablesService["dayTranscript"]>>> {
|
|
6191
|
+
return this.orchestrator
|
|
6192
|
+
.getWearablesService()
|
|
6193
|
+
.dayTranscript(request.date, request.source);
|
|
6194
|
+
}
|
|
6195
|
+
|
|
6196
|
+
async wearablesTranscriptSearch(request: {
|
|
6197
|
+
query: string;
|
|
6198
|
+
source?: string;
|
|
6199
|
+
from?: string;
|
|
6200
|
+
to?: string;
|
|
6201
|
+
limit?: number;
|
|
6202
|
+
}): Promise<Awaited<ReturnType<WearablesService["searchTranscripts"]>>> {
|
|
6203
|
+
return this.orchestrator.getWearablesService().searchTranscripts(request.query, {
|
|
6204
|
+
source: request.source,
|
|
6205
|
+
from: request.from,
|
|
6206
|
+
to: request.to,
|
|
6207
|
+
limit: request.limit,
|
|
6208
|
+
});
|
|
6209
|
+
}
|
|
6210
|
+
|
|
6211
|
+
async wearablesTranscriptMemories(request: {
|
|
6212
|
+
source?: string;
|
|
6213
|
+
date?: string;
|
|
6214
|
+
limit?: number;
|
|
6215
|
+
}): Promise<Awaited<ReturnType<WearablesService["transcriptMemories"]>>> {
|
|
6216
|
+
return this.orchestrator.getWearablesService().transcriptMemories({
|
|
6217
|
+
source: request.source,
|
|
6218
|
+
date: request.date,
|
|
6219
|
+
limit: request.limit,
|
|
6220
|
+
});
|
|
6221
|
+
}
|
|
6157
6222
|
}
|