@remnic/core 9.3.624 → 9.3.626
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-7TPH6UZL.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-FG76RDVI.js → chunk-Y3TMFC6I.js} +136 -4
- 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 +10 -10
- 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/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 +167 -0
- 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-7TPH6UZL.js.map +0 -1
- package/dist/chunk-FG76RDVI.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-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
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wearable sync-state ledger — per-source bookkeeping for incremental
|
|
3
|
+
* syncs, stored at `state/wearables/sync.json`.
|
|
4
|
+
*
|
|
5
|
+
* State is written only AFTER a source's transcripts (and any memories)
|
|
6
|
+
* were persisted successfully, so a failed sync never advances the
|
|
7
|
+
* watermark past data that didn't land.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { promises as fsPromises } from "node:fs";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
|
|
13
|
+
export interface WearableSourceSyncState {
|
|
14
|
+
/** ISO timestamp of the last successful sync run. */
|
|
15
|
+
lastSyncAt: string;
|
|
16
|
+
/** Most recent day (YYYY-MM-DD) that was synced. */
|
|
17
|
+
lastDateSynced: string;
|
|
18
|
+
/** Body hashes of the last-written day files, keyed by date. */
|
|
19
|
+
dayHashes: Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* Body hashes of days whose memory-extraction pass completed without
|
|
22
|
+
* warnings, keyed by date. A day whose entry is missing or stale
|
|
23
|
+
* re-extracts on the next sync even when its transcript is unchanged
|
|
24
|
+
* — this is how a memory pass that failed mid-run (transcript stored,
|
|
25
|
+
* memories incomplete) self-heals. Absent on records written before
|
|
26
|
+
* this field existed.
|
|
27
|
+
*/
|
|
28
|
+
memoryDayHashes?: Record<string, string>;
|
|
29
|
+
/** Native-memory ids already imported (bounded, newest kept). */
|
|
30
|
+
importedNativeMemoryIds: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface WearableSyncStateFile {
|
|
34
|
+
version: 1;
|
|
35
|
+
sources: Record<string, WearableSourceSyncState>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Cap on remembered native-memory ids per source. */
|
|
39
|
+
const MAX_TRACKED_NATIVE_IDS = 5_000;
|
|
40
|
+
/** Cap on remembered day hashes per source (~2 years of days). */
|
|
41
|
+
const MAX_TRACKED_DAY_HASHES = 800;
|
|
42
|
+
|
|
43
|
+
export function syncStateFilePath(memoryDir: string): string {
|
|
44
|
+
return path.join(memoryDir, "state", "wearables", "sync.json");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function emptySyncState(): WearableSyncStateFile {
|
|
48
|
+
return { version: 1, sources: {} };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function loadSyncState(
|
|
52
|
+
memoryDir: string,
|
|
53
|
+
): Promise<WearableSyncStateFile> {
|
|
54
|
+
const filePath = syncStateFilePath(memoryDir);
|
|
55
|
+
let raw: string;
|
|
56
|
+
try {
|
|
57
|
+
raw = await fsPromises.readFile(filePath, "utf-8");
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
60
|
+
return emptySyncState();
|
|
61
|
+
}
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
let parsed: unknown;
|
|
65
|
+
try {
|
|
66
|
+
parsed = JSON.parse(raw);
|
|
67
|
+
} catch {
|
|
68
|
+
// A corrupt state file should not brick syncing forever; treat it
|
|
69
|
+
// as a cold start (the worst case is re-syncing days we already
|
|
70
|
+
// have, which the day-hash skip makes cheap and idempotent).
|
|
71
|
+
return emptySyncState();
|
|
72
|
+
}
|
|
73
|
+
if (
|
|
74
|
+
typeof parsed !== "object" ||
|
|
75
|
+
parsed === null ||
|
|
76
|
+
Array.isArray(parsed) ||
|
|
77
|
+
typeof (parsed as WearableSyncStateFile).sources !== "object" ||
|
|
78
|
+
(parsed as WearableSyncStateFile).sources === null
|
|
79
|
+
) {
|
|
80
|
+
return emptySyncState();
|
|
81
|
+
}
|
|
82
|
+
return { version: 1, sources: (parsed as WearableSyncStateFile).sources };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function saveSyncState(
|
|
86
|
+
memoryDir: string,
|
|
87
|
+
state: WearableSyncStateFile,
|
|
88
|
+
): Promise<void> {
|
|
89
|
+
const filePath = syncStateFilePath(memoryDir);
|
|
90
|
+
await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
|
|
91
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
|
|
92
|
+
await fsPromises.writeFile(
|
|
93
|
+
tmpPath,
|
|
94
|
+
`${JSON.stringify(state, null, 2)}\n`,
|
|
95
|
+
"utf-8",
|
|
96
|
+
);
|
|
97
|
+
try {
|
|
98
|
+
await fsPromises.rename(tmpPath, filePath);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
await fsPromises.unlink(tmpPath).catch(() => undefined);
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Merge a completed source sync into the state file shape. */
|
|
106
|
+
export function updateSourceSyncState(
|
|
107
|
+
state: WearableSyncStateFile,
|
|
108
|
+
sourceId: string,
|
|
109
|
+
update: {
|
|
110
|
+
syncedAt: string;
|
|
111
|
+
days: string[];
|
|
112
|
+
dayHashes: Record<string, string>;
|
|
113
|
+
/** Days whose memory pass completed cleanly this run. */
|
|
114
|
+
memoryDayHashes?: Record<string, string>;
|
|
115
|
+
/**
|
|
116
|
+
* Days whose memory pass ran this sync but did NOT complete
|
|
117
|
+
* cleanly. Their previous completion records are removed so a
|
|
118
|
+
* stale hash from an earlier clean pass can never mask the
|
|
119
|
+
* failure on the next sync.
|
|
120
|
+
*/
|
|
121
|
+
clearMemoryDays?: string[];
|
|
122
|
+
importedNativeMemoryIds?: string[];
|
|
123
|
+
},
|
|
124
|
+
): WearableSyncStateFile {
|
|
125
|
+
const previous = state.sources[sourceId];
|
|
126
|
+
const mergedHashes: Record<string, string> = {
|
|
127
|
+
...(previous?.dayHashes ?? {}),
|
|
128
|
+
...update.dayHashes,
|
|
129
|
+
};
|
|
130
|
+
// Bound the hash map: keep the lexicographically-largest (most
|
|
131
|
+
// recent) dates, which sort naturally for YYYY-MM-DD keys.
|
|
132
|
+
const hashKeys = Object.keys(mergedHashes).sort();
|
|
133
|
+
while (hashKeys.length > MAX_TRACKED_DAY_HASHES) {
|
|
134
|
+
const oldest = hashKeys.shift();
|
|
135
|
+
if (oldest === undefined) break;
|
|
136
|
+
delete mergedHashes[oldest];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const mergedMemoryHashes: Record<string, string> = {
|
|
140
|
+
...(previous?.memoryDayHashes ?? {}),
|
|
141
|
+
...(update.memoryDayHashes ?? {}),
|
|
142
|
+
};
|
|
143
|
+
for (const day of update.clearMemoryDays ?? []) {
|
|
144
|
+
if (!(day in (update.memoryDayHashes ?? {}))) {
|
|
145
|
+
delete mergedMemoryHashes[day];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const memoryHashKeys = Object.keys(mergedMemoryHashes).sort();
|
|
149
|
+
while (memoryHashKeys.length > MAX_TRACKED_DAY_HASHES) {
|
|
150
|
+
const oldest = memoryHashKeys.shift();
|
|
151
|
+
if (oldest === undefined) break;
|
|
152
|
+
delete mergedMemoryHashes[oldest];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const mergedNativeIds = [
|
|
156
|
+
...(previous?.importedNativeMemoryIds ?? []),
|
|
157
|
+
...(update.importedNativeMemoryIds ?? []),
|
|
158
|
+
];
|
|
159
|
+
const dedupedNativeIds = [...new Set(mergedNativeIds)];
|
|
160
|
+
const boundedNativeIds =
|
|
161
|
+
dedupedNativeIds.length > MAX_TRACKED_NATIVE_IDS
|
|
162
|
+
? dedupedNativeIds.slice(dedupedNativeIds.length - MAX_TRACKED_NATIVE_IDS)
|
|
163
|
+
: dedupedNativeIds;
|
|
164
|
+
|
|
165
|
+
const sortedDays = [...update.days].sort();
|
|
166
|
+
const latestDay = sortedDays[sortedDays.length - 1];
|
|
167
|
+
const lastDateSynced =
|
|
168
|
+
latestDay !== undefined &&
|
|
169
|
+
(!previous || previous.lastDateSynced < latestDay)
|
|
170
|
+
? latestDay
|
|
171
|
+
: previous?.lastDateSynced ?? latestDay ?? "";
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
version: 1,
|
|
175
|
+
sources: {
|
|
176
|
+
...state.sources,
|
|
177
|
+
[sourceId]: {
|
|
178
|
+
lastSyncAt: update.syncedAt,
|
|
179
|
+
lastDateSynced,
|
|
180
|
+
dayHashes: mergedHashes,
|
|
181
|
+
memoryDayHashes: mergedMemoryHashes,
|
|
182
|
+
importedNativeMemoryIds: boundedNativeIds,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wearable transcript subsystem — shared types (issue: wearable connectors).
|
|
3
|
+
*
|
|
4
|
+
* A "wearable source" is an always-on recording device with a cloud or
|
|
5
|
+
* local API that exposes diarized conversation transcripts (Limitless
|
|
6
|
+
* Pendant, Bee, Omi, ...). Connectors for concrete providers live in
|
|
7
|
+
* optional à-la-carte packages (`@remnic/connector-limitless`,
|
|
8
|
+
* `@remnic/connector-bee`, `@remnic/connector-omi`) and implement
|
|
9
|
+
* `WearableSourceConnector`; everything provider-agnostic — cleanup,
|
|
10
|
+
* speaker labeling, user corrections, day-transcript storage, and
|
|
11
|
+
* trust-gated memory creation — lives in this core subsystem.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { ImportanceLevel } from "../types.js";
|
|
15
|
+
|
|
16
|
+
/** One diarized utterance from a wearable transcript. */
|
|
17
|
+
export interface WearableTranscriptSegment {
|
|
18
|
+
/** Utterance text as supplied by the provider (pre-cleanup). */
|
|
19
|
+
text: string;
|
|
20
|
+
/**
|
|
21
|
+
* Stable per-source speaker key. Connectors derive this from whatever
|
|
22
|
+
* the provider exposes (a name, a diarization label like "SPEAKER_00"
|
|
23
|
+
* or "0", or a person id). Used to look up overrides in the speaker
|
|
24
|
+
* registry as `<sourceId>:<speakerKey>`.
|
|
25
|
+
*/
|
|
26
|
+
speakerKey: string;
|
|
27
|
+
/** Provider-supplied display name, when available. */
|
|
28
|
+
speakerName?: string;
|
|
29
|
+
/** True when the provider identified this utterance as the wearer. */
|
|
30
|
+
isWearer?: boolean;
|
|
31
|
+
/** ISO 8601 start of the utterance, when the provider supplies one. */
|
|
32
|
+
startIso?: string;
|
|
33
|
+
/** ISO 8601 end of the utterance, when the provider supplies one. */
|
|
34
|
+
endIso?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** One conversation (recording session) from a wearable source. */
|
|
38
|
+
export interface WearableConversation {
|
|
39
|
+
/** Provider-stable conversation id (string form). */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Connector id this conversation came from (e.g. "limitless"). */
|
|
42
|
+
source: string;
|
|
43
|
+
/** Provider title / one-line summary, when available. */
|
|
44
|
+
title?: string;
|
|
45
|
+
/** Provider-generated long summary, when available. */
|
|
46
|
+
summary?: string;
|
|
47
|
+
/** ISO 8601 conversation start. */
|
|
48
|
+
startIso: string;
|
|
49
|
+
/** ISO 8601 conversation end, when known. */
|
|
50
|
+
endIso?: string;
|
|
51
|
+
/** Human-readable location, when the provider supplies one. */
|
|
52
|
+
location?: string;
|
|
53
|
+
/** Ordered diarized segments. */
|
|
54
|
+
segments: WearableTranscriptSegment[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Options for a single conversations fetch (one day window). */
|
|
58
|
+
export interface WearableFetchOptions {
|
|
59
|
+
/** Day to fetch, formatted YYYY-MM-DD in `timezone`. */
|
|
60
|
+
date: string;
|
|
61
|
+
/** IANA timezone the date is interpreted in. */
|
|
62
|
+
timezone: string;
|
|
63
|
+
/** Opaque pagination cursor from a previous page, when paging. */
|
|
64
|
+
cursor?: string | null;
|
|
65
|
+
/** Abort signal for the underlying HTTP requests. */
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** One page of conversations from a connector. */
|
|
70
|
+
export interface WearableFetchPage {
|
|
71
|
+
conversations: WearableConversation[];
|
|
72
|
+
/** Cursor for the next page, or null when exhausted. */
|
|
73
|
+
nextCursor: string | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A "native memory" is a fact the provider's own pipeline extracted
|
|
78
|
+
* (Bee facts, Omi memories). Importing these is optional and always
|
|
79
|
+
* lands them in the review queue — provider extraction quality is
|
|
80
|
+
* outside Remnic's control.
|
|
81
|
+
*/
|
|
82
|
+
export interface WearableNativeMemory {
|
|
83
|
+
id: string;
|
|
84
|
+
content: string;
|
|
85
|
+
createdIso?: string;
|
|
86
|
+
tags?: string[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface WearableNativeMemoryPage {
|
|
90
|
+
memories: WearableNativeMemory[];
|
|
91
|
+
nextCursor: string | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Result of a connector auth probe. */
|
|
95
|
+
export interface WearableAuthCheck {
|
|
96
|
+
ok: boolean;
|
|
97
|
+
/** Short human-readable detail (never includes credentials). */
|
|
98
|
+
detail?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Contract implemented by provider connector packages.
|
|
103
|
+
*
|
|
104
|
+
* Connectors are pure API clients + normalizers: no file IO, no memory
|
|
105
|
+
* writes, no config parsing beyond their own settings object. All
|
|
106
|
+
* pipeline behavior stays in core so every source benefits from the
|
|
107
|
+
* same cleanup, corrections, and trust gating.
|
|
108
|
+
*/
|
|
109
|
+
export interface WearableSourceConnector {
|
|
110
|
+
/** Stable connector id ("limitless" | "bee" | "omi" | custom). */
|
|
111
|
+
id: string;
|
|
112
|
+
/** Human-readable provider name for status output. */
|
|
113
|
+
displayName: string;
|
|
114
|
+
/** Probe credentials/connectivity without mutating anything. */
|
|
115
|
+
verifyAuth(signal?: AbortSignal): Promise<WearableAuthCheck>;
|
|
116
|
+
/** Fetch one page of conversations for a single day window. */
|
|
117
|
+
fetchConversations(opts: WearableFetchOptions): Promise<WearableFetchPage>;
|
|
118
|
+
/**
|
|
119
|
+
* Fetch one page of provider-extracted memories. Optional — only
|
|
120
|
+
* connectors whose provider exposes such a surface implement it.
|
|
121
|
+
*/
|
|
122
|
+
fetchNativeMemories?(opts: {
|
|
123
|
+
cursor?: string | null;
|
|
124
|
+
signal?: AbortSignal;
|
|
125
|
+
}): Promise<WearableNativeMemoryPage>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Per-source settings handed to a connector factory (parsed config). */
|
|
129
|
+
export interface WearableSourceSettings {
|
|
130
|
+
/** Master gate for this source. */
|
|
131
|
+
enabled: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Credential for the provider API. Prefer the per-connector
|
|
134
|
+
* environment variable (see each connector's README); the config
|
|
135
|
+
* value takes precedence when both are set.
|
|
136
|
+
*/
|
|
137
|
+
apiKey?: string;
|
|
138
|
+
/** Override the provider base URL (self-hosted / proxy setups). */
|
|
139
|
+
baseUrl?: string;
|
|
140
|
+
/** Omi: integration app id (the `{app_id}` path component). */
|
|
141
|
+
appId?: string;
|
|
142
|
+
/** Omi: target user id (`uid` query parameter). */
|
|
143
|
+
userId?: string;
|
|
144
|
+
/**
|
|
145
|
+
* Memory creation mode (trust gate):
|
|
146
|
+
* - "off": transcripts only; never create memories.
|
|
147
|
+
* - "review": extract candidate memories but write every one with
|
|
148
|
+
* status "pending_review" so nothing enters active
|
|
149
|
+
* recall without operator approval. Default.
|
|
150
|
+
* - "auto": extracted memories that pass the quality gates are
|
|
151
|
+
* written active, like live-conversation extraction.
|
|
152
|
+
*/
|
|
153
|
+
memoryMode: WearableMemoryMode;
|
|
154
|
+
/** Drop extracted facts below this confidence (0–1). */
|
|
155
|
+
minConfidence: number;
|
|
156
|
+
/** Drop extracted facts scored below this importance level. */
|
|
157
|
+
minImportance: ImportanceLevel;
|
|
158
|
+
/**
|
|
159
|
+
* Cap on memories created per source per day. 0 disables the cap.
|
|
160
|
+
*/
|
|
161
|
+
maxMemoriesPerDay: number;
|
|
162
|
+
/**
|
|
163
|
+
* Import provider-extracted memories (Bee facts / Omi memories).
|
|
164
|
+
* "review" lands them in the review queue; "off" (default) skips.
|
|
165
|
+
*/
|
|
166
|
+
importNativeMemories: "off" | "review";
|
|
167
|
+
/** Transcript cleanup toggles. */
|
|
168
|
+
cleanup: WearableCleanupSettings;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export type WearableMemoryMode = "off" | "review" | "auto";
|
|
172
|
+
|
|
173
|
+
export interface WearableCleanupSettings {
|
|
174
|
+
/** Merge consecutive segments from the same speaker. */
|
|
175
|
+
mergeSameSpeaker: boolean;
|
|
176
|
+
/** Strip standalone filler tokens (um, uh, ...). */
|
|
177
|
+
stripFillers: boolean;
|
|
178
|
+
/** Collapse immediately repeated phrases (ASR stutter). */
|
|
179
|
+
collapseRepeats: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Drop segments that look like ASR garbage (very low word ratio,
|
|
182
|
+
* long single-character runs). Dropped segments are counted in the
|
|
183
|
+
* sync summary and excluded from memory extraction.
|
|
184
|
+
*/
|
|
185
|
+
dropLowQuality: boolean;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** A single user-specific transcript correction rule. */
|
|
189
|
+
export interface WearableCorrectionRule {
|
|
190
|
+
/** Text (or regex when `regex` is true) to match. */
|
|
191
|
+
match: string;
|
|
192
|
+
/** Replacement text. */
|
|
193
|
+
replace: string;
|
|
194
|
+
/** Treat `match` as a regular expression. Default false (literal). */
|
|
195
|
+
regex?: boolean;
|
|
196
|
+
/** Case-insensitive matching. Default true. */
|
|
197
|
+
caseInsensitive?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Restrict the rule to specific source ids. Omit to apply to all
|
|
200
|
+
* sources.
|
|
201
|
+
*/
|
|
202
|
+
sources?: string[];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Top-level wearables configuration (parsed). */
|
|
206
|
+
export interface WearablesConfig {
|
|
207
|
+
/** Master gate for the whole subsystem. Default false. */
|
|
208
|
+
enabled: boolean;
|
|
209
|
+
/**
|
|
210
|
+
* IANA timezone used to bucket transcripts into days. Defaults to
|
|
211
|
+
* the host timezone at runtime when unset.
|
|
212
|
+
*/
|
|
213
|
+
timezone?: string;
|
|
214
|
+
/** Built-in PII redaction (SSN / payment-card patterns). Default true. */
|
|
215
|
+
redactionEnabled: boolean;
|
|
216
|
+
/** Additional user-supplied redaction regexes (validated at parse). */
|
|
217
|
+
redactionPatterns: string[];
|
|
218
|
+
/**
|
|
219
|
+
* Honor a spoken "off the record" marker by dropping segments until
|
|
220
|
+
* "back on the record" (or conversation end). Default false.
|
|
221
|
+
*/
|
|
222
|
+
offTheRecordEnabled: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Write one compact daily-digest memory per synced source/day.
|
|
225
|
+
* Default false.
|
|
226
|
+
*/
|
|
227
|
+
digestEnabled: boolean;
|
|
228
|
+
/** Correction rules from config (merged with CLI-managed rules). */
|
|
229
|
+
corrections: WearableCorrectionRule[];
|
|
230
|
+
/** Per-source settings, keyed by connector id. */
|
|
231
|
+
sources: Record<string, WearableSourceSettings>;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Summary returned by a sync run (one source). */
|
|
235
|
+
export interface WearableSyncSummary {
|
|
236
|
+
source: string;
|
|
237
|
+
/** Days that were synced (YYYY-MM-DD). */
|
|
238
|
+
days: string[];
|
|
239
|
+
conversations: number;
|
|
240
|
+
segmentsKept: number;
|
|
241
|
+
segmentsDropped: number;
|
|
242
|
+
redactions: number;
|
|
243
|
+
correctionsApplied: number;
|
|
244
|
+
/** Day files written (skipped-unchanged days are not listed). */
|
|
245
|
+
transcriptsWritten: string[];
|
|
246
|
+
memoriesCreated: number;
|
|
247
|
+
memoriesSkipped: number;
|
|
248
|
+
nativeMemoriesImported: number;
|
|
249
|
+
/** Non-fatal warnings surfaced to the operator. */
|
|
250
|
+
warnings: string[];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Frontmatter persisted on a day-transcript file. */
|
|
254
|
+
export interface WearableDayTranscriptMeta {
|
|
255
|
+
kind: "wearable-transcript";
|
|
256
|
+
source: string;
|
|
257
|
+
date: string;
|
|
258
|
+
timezone: string;
|
|
259
|
+
conversationCount: number;
|
|
260
|
+
segmentCount: number;
|
|
261
|
+
speakers: string[];
|
|
262
|
+
durationMinutes: number;
|
|
263
|
+
/** SHA-256 of the body — used to skip unchanged rewrites. */
|
|
264
|
+
contentHash: string;
|
|
265
|
+
syncedAt: string;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** A parsed day-transcript file. */
|
|
269
|
+
export interface WearableDayTranscript {
|
|
270
|
+
meta: WearableDayTranscriptMeta;
|
|
271
|
+
body: string;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Status snapshot for one configured source. */
|
|
275
|
+
export interface WearableSourceStatus {
|
|
276
|
+
source: string;
|
|
277
|
+
displayName: string;
|
|
278
|
+
enabled: boolean;
|
|
279
|
+
connectorInstalled: boolean;
|
|
280
|
+
memoryMode: WearableMemoryMode;
|
|
281
|
+
lastSyncAt: string | null;
|
|
282
|
+
lastDateSynced: string | null;
|
|
283
|
+
transcriptDays: number;
|
|
284
|
+
}
|
|
285
|
+
|