@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.
Files changed (261) hide show
  1. package/dist/access-cli.js +18 -16
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +12 -5
  4. package/dist/access-http.js +10 -9
  5. package/dist/access-mcp.d.ts +5 -5
  6. package/dist/access-mcp.js +8 -8
  7. package/dist/access-schema.d.ts +5 -5
  8. package/dist/{access-service-CBNEKjzN.d.ts → access-service-C_sfOHsX.d.ts} +26 -3
  9. package/dist/access-service.d.ts +5 -5
  10. package/dist/access-service.js +7 -7
  11. package/dist/action-confidence.d.ts +1 -1
  12. package/dist/active-memory-bridge.d.ts +1 -1
  13. package/dist/active-recall.d.ts +1 -1
  14. package/dist/active-recall.js +2 -1
  15. package/dist/active-recall.js.map +1 -1
  16. package/dist/behavior-learner.d.ts +1 -1
  17. package/dist/behavior-signals.d.ts +1 -1
  18. package/dist/bootstrap.d.ts +4 -4
  19. package/dist/briefing.d.ts +1 -1
  20. package/dist/briefing.js +3 -3
  21. package/dist/buffer-surprise-report.d.ts +1 -1
  22. package/dist/buffer.d.ts +1 -1
  23. package/dist/calibration.d.ts +1 -1
  24. package/dist/causal-behavior.d.ts +1 -1
  25. package/dist/causal-consolidation.d.ts +1 -1
  26. package/dist/causal-consolidation.js +4 -4
  27. package/dist/{chunk-7TPH6UZL.js → chunk-2RHI3FGV.js} +540 -17
  28. package/dist/chunk-2RHI3FGV.js.map +1 -0
  29. package/dist/{chunk-GYTVOLNX.js → chunk-3MNBW7R7.js} +2 -2
  30. package/dist/{chunk-QFQQFX2H.js → chunk-3R2UZV3U.js} +2 -2
  31. package/dist/{chunk-O4UNM6OR.js → chunk-532VCWYW.js} +2 -2
  32. package/dist/{chunk-2UFQYU5F.js → chunk-57QXN2CS.js} +2 -2
  33. package/dist/chunk-7WV3F5DQ.js +22 -0
  34. package/dist/chunk-7WV3F5DQ.js.map +1 -0
  35. package/dist/{chunk-RKW6QR7W.js → chunk-AZ4RI3QD.js} +1461 -78
  36. package/dist/chunk-AZ4RI3QD.js.map +1 -0
  37. package/dist/{chunk-KQFQ3IS5.js → chunk-F3FY3D3S.js} +43 -7
  38. package/dist/chunk-F3FY3D3S.js.map +1 -0
  39. package/dist/{chunk-4R4KTDIE.js → chunk-FPNQF475.js} +1 -1
  40. package/dist/chunk-FPNQF475.js.map +1 -0
  41. package/dist/{chunk-UGEBPVNI.js → chunk-GE7Q7KXP.js} +2 -2
  42. package/dist/{chunk-GLWW3EJQ.js → chunk-KB4MFBF5.js} +3 -3
  43. package/dist/{chunk-5GOMXHLC.js → chunk-KKTXCFD7.js} +255 -1
  44. package/dist/chunk-KKTXCFD7.js.map +1 -0
  45. package/dist/{chunk-FH3PPO42.js → chunk-KVFYTRMV.js} +2 -2
  46. package/dist/{chunk-BNW5NJJH.js → chunk-LQYTQCXM.js} +2 -2
  47. package/dist/{chunk-AYHXQR53.js → chunk-MVQN73GT.js} +2 -2
  48. package/dist/{chunk-ZZPIJPPD.js → chunk-N5RGXWLQ.js} +2 -2
  49. package/dist/chunk-NDAH7BJ5.js +213 -0
  50. package/dist/chunk-NDAH7BJ5.js.map +1 -0
  51. package/dist/{chunk-R3OQGYOU.js → chunk-P2D2MM47.js} +2 -2
  52. package/dist/{chunk-PSUB67YB.js → chunk-PW6GURU3.js} +2 -2
  53. package/dist/{chunk-W3BKVM64.js → chunk-QDV6VAD4.js} +2 -2
  54. package/dist/{chunk-3QSU4NFF.js → chunk-QHXW3LZV.js} +3 -3
  55. package/dist/{chunk-I6UCUHLK.js → chunk-SHV5Y2WU.js} +182 -3
  56. package/dist/chunk-SHV5Y2WU.js.map +1 -0
  57. package/dist/{chunk-OZXVGYGZ.js → chunk-STDAAGH7.js} +2 -2
  58. package/dist/{chunk-FMGWXIES.js → chunk-TZDSNIRO.js} +5 -5
  59. package/dist/{chunk-2L54V4ZO.js → chunk-UELS6WWF.js} +2 -2
  60. package/dist/{chunk-PJGB7XRR.js → chunk-UGHUNQ74.js} +502 -134
  61. package/dist/chunk-UGHUNQ74.js.map +1 -0
  62. package/dist/{chunk-FG76RDVI.js → chunk-Y3TMFC6I.js} +136 -4
  63. package/dist/chunk-Y3TMFC6I.js.map +1 -0
  64. package/dist/{chunk-BPSGLMQ4.js → chunk-YQNADJCT.js} +2 -2
  65. package/dist/{cli-Cw729yLf.d.ts → cli-EZv6YE6_.d.ts} +3 -3
  66. package/dist/cli.d.ts +6 -6
  67. package/dist/cli.js +23 -21
  68. package/dist/compounding/engine.d.ts +1 -1
  69. package/dist/compounding/engine.js +3 -3
  70. package/dist/compounding/preference-consolidator.d.ts +1 -1
  71. package/dist/compression-optimizer.d.ts +1 -1
  72. package/dist/config.d.ts +1 -1
  73. package/dist/config.js +2 -1
  74. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  75. package/dist/connectors/codex-materialize-runner.js +3 -3
  76. package/dist/connectors/codex-materialize.d.ts +1 -1
  77. package/dist/connectors/index.d.ts +1 -1
  78. package/dist/connectors/index.js +3 -3
  79. package/dist/consolidation-provenance-check.d.ts +1 -1
  80. package/dist/consolidation-undo.d.ts +1 -1
  81. package/dist/contradiction/index.d.ts +2 -2
  82. package/dist/conversation-index/backend.d.ts +1 -1
  83. package/dist/conversation-index/chunker.d.ts +1 -1
  84. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  85. package/dist/conversation-index/indexer.d.ts +1 -1
  86. package/dist/conversation-index/search.d.ts +1 -1
  87. package/dist/day-summary.d.ts +1 -1
  88. package/dist/delinearize.d.ts +1 -1
  89. package/dist/direct-answer-wiring.d.ts +1 -1
  90. package/dist/direct-answer.d.ts +1 -1
  91. package/dist/embedding-fallback.d.ts +1 -1
  92. package/dist/enrichment/index.d.ts +1 -1
  93. package/dist/entity-retrieval.d.ts +1 -1
  94. package/dist/entity-retrieval.js +3 -3
  95. package/dist/entity-schema.d.ts +1 -1
  96. package/dist/explicit-capture.d.ts +4 -4
  97. package/dist/extraction-judge-telemetry.d.ts +1 -1
  98. package/dist/extraction-judge-training.d.ts +1 -1
  99. package/dist/extraction-judge.d.ts +1 -1
  100. package/dist/extraction.d.ts +1 -1
  101. package/dist/fallback-llm.d.ts +1 -1
  102. package/dist/identity-continuity.d.ts +1 -1
  103. package/dist/importance.d.ts +1 -1
  104. package/dist/index.d.ts +307 -9
  105. package/dist/index.js +155 -29
  106. package/dist/index.js.map +1 -1
  107. package/dist/intent.d.ts +1 -1
  108. package/dist/lcm/engine.d.ts +1 -1
  109. package/dist/lcm/index.d.ts +1 -1
  110. package/dist/lcm/tools.d.ts +1 -1
  111. package/dist/lifecycle.d.ts +1 -1
  112. package/dist/live-connectors-runner.d.ts +1 -1
  113. package/dist/local-llm.d.ts +1 -1
  114. package/dist/maintenance/memory-governance.d.ts +1 -1
  115. package/dist/maintenance/memory-governance.js +3 -3
  116. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  117. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  118. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  119. package/dist/memory-action-policy.d.ts +1 -1
  120. package/dist/memory-cache.d.ts +1 -1
  121. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  122. package/dist/memory-projection-store.d.ts +1 -1
  123. package/dist/memory-provenance.d.ts +1 -1
  124. package/dist/memory-worth-outcomes.d.ts +1 -1
  125. package/dist/models-json.d.ts +1 -1
  126. package/dist/namespaces/migrate.d.ts +1 -1
  127. package/dist/namespaces/migrate.js +4 -4
  128. package/dist/namespaces/principal.d.ts +1 -1
  129. package/dist/namespaces/search.d.ts +1 -1
  130. package/dist/namespaces/storage.d.ts +1 -1
  131. package/dist/namespaces/storage.js +3 -3
  132. package/dist/native-knowledge.d.ts +1 -1
  133. package/dist/operator-toolkit.d.ts +1 -1
  134. package/dist/operator-toolkit.js +8 -7
  135. package/dist/{orchestrator-CqWOjfgl.d.ts → orchestrator-CEycaY3M.d.ts} +361 -4
  136. package/dist/orchestrator.d.ts +4 -4
  137. package/dist/orchestrator.js +13 -11
  138. package/dist/patterns-cli.d.ts +1 -1
  139. package/dist/policy-runtime.d.ts +1 -1
  140. package/dist/qmd-recall-cache.d.ts +1 -1
  141. package/dist/qmd.d.ts +1 -1
  142. package/dist/recall-disclosure-escalation.d.ts +1 -1
  143. package/dist/recall-explain-renderer.d.ts +1 -1
  144. package/dist/recall-explain-renderer.js +3 -3
  145. package/dist/recall-planner-llm.d.ts +1 -1
  146. package/dist/recall-state.d.ts +1 -1
  147. package/dist/recall-tag-filter.d.ts +1 -1
  148. package/dist/recall-xray-cli.d.ts +1 -1
  149. package/dist/recall-xray-cli.js +4 -4
  150. package/dist/recall-xray-renderer.d.ts +1 -1
  151. package/dist/recall-xray-renderer.js +3 -3
  152. package/dist/recall-xray.d.ts +1 -1
  153. package/dist/recall-xray.js +2 -2
  154. package/dist/resolve-auth-token.d.ts +1 -1
  155. package/dist/resume-bundles.js +3 -2
  156. package/dist/retrieval-agents.d.ts +1 -1
  157. package/dist/retrieval-tiers.d.ts +1 -1
  158. package/dist/routing/engine.d.ts +1 -1
  159. package/dist/routing/store.d.ts +1 -1
  160. package/dist/schemas.d.ts +10 -10
  161. package/dist/search/embed-helper.d.ts +1 -1
  162. package/dist/search/factory.d.ts +1 -1
  163. package/dist/search/index.d.ts +1 -1
  164. package/dist/search/lancedb-backend.d.ts +1 -1
  165. package/dist/search/meilisearch-backend.d.ts +1 -1
  166. package/dist/search/noop-backend.d.ts +1 -1
  167. package/dist/search/orama-backend.d.ts +1 -1
  168. package/dist/search/port.d.ts +1 -1
  169. package/dist/search/remote-backend.d.ts +1 -1
  170. package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
  171. package/dist/{semantic-consolidation-4HkHWgeI.d.ts → semantic-consolidation-FbhPeJjB.d.ts} +1 -1
  172. package/dist/semantic-consolidation.d.ts +2 -2
  173. package/dist/semantic-consolidation.js +4 -4
  174. package/dist/semantic-rule-promotion.js +3 -3
  175. package/dist/semantic-rule-verifier.d.ts +1 -1
  176. package/dist/semantic-rule-verifier.js +3 -3
  177. package/dist/session-observer-bands.d.ts +1 -1
  178. package/dist/session-observer-state.d.ts +1 -1
  179. package/dist/shared-context/manager.d.ts +5 -5
  180. package/dist/signal.d.ts +1 -1
  181. package/dist/storage.d.ts +19 -1
  182. package/dist/storage.js +2 -2
  183. package/dist/summarizer.d.ts +1 -1
  184. package/dist/summary-snapshot.d.ts +1 -1
  185. package/dist/temporal-supersession.d.ts +1 -1
  186. package/dist/temporal-validity.d.ts +1 -1
  187. package/dist/threading.d.ts +1 -1
  188. package/dist/tier-migration.d.ts +1 -1
  189. package/dist/tier-routing.d.ts +1 -1
  190. package/dist/topics.d.ts +1 -1
  191. package/dist/transcript.d.ts +1 -1
  192. package/dist/types-D5VRAI04.d.ts +3134 -0
  193. package/dist/types.d.ts +3 -2862
  194. package/dist/types.js +1 -1
  195. package/dist/utility-runtime.d.ts +1 -1
  196. package/dist/verified-recall.js +3 -3
  197. package/package.json +1 -1
  198. package/src/access-http.ts +167 -0
  199. package/src/access-mcp.ts +198 -0
  200. package/src/access-service.ts +65 -0
  201. package/src/cli.ts +187 -0
  202. package/src/config.ts +7 -0
  203. package/src/index.ts +7 -0
  204. package/src/orchestrator.ts +42 -0
  205. package/src/storage.ts +106 -0
  206. package/src/types.ts +5 -0
  207. package/src/wearables/cleanup.test.ts +134 -0
  208. package/src/wearables/cleanup.ts +188 -0
  209. package/src/wearables/cli.test.ts +170 -0
  210. package/src/wearables/cli.ts +441 -0
  211. package/src/wearables/config.test.ts +143 -0
  212. package/src/wearables/config.ts +332 -0
  213. package/src/wearables/corrections.test.ts +118 -0
  214. package/src/wearables/corrections.ts +211 -0
  215. package/src/wearables/day-store.test.ts +143 -0
  216. package/src/wearables/day-store.ts +238 -0
  217. package/src/wearables/errors.test.ts +32 -0
  218. package/src/wearables/errors.ts +29 -0
  219. package/src/wearables/index.ts +114 -0
  220. package/src/wearables/memory-gen.test.ts +342 -0
  221. package/src/wearables/memory-gen.ts +413 -0
  222. package/src/wearables/pipeline.test.ts +608 -0
  223. package/src/wearables/pipeline.ts +519 -0
  224. package/src/wearables/redaction.test.ts +94 -0
  225. package/src/wearables/redaction.ts +156 -0
  226. package/src/wearables/registry.test.ts +62 -0
  227. package/src/wearables/registry.ts +133 -0
  228. package/src/wearables/service.test.ts +425 -0
  229. package/src/wearables/service.ts +691 -0
  230. package/src/wearables/speakers.test.ts +110 -0
  231. package/src/wearables/speakers.ts +174 -0
  232. package/src/wearables/storage-io.test.ts +105 -0
  233. package/src/wearables/sync-state.test.ts +134 -0
  234. package/src/wearables/sync-state.ts +186 -0
  235. package/src/wearables/types.ts +285 -0
  236. package/dist/chunk-4R4KTDIE.js.map +0 -1
  237. package/dist/chunk-5GOMXHLC.js.map +0 -1
  238. package/dist/chunk-7TPH6UZL.js.map +0 -1
  239. package/dist/chunk-FG76RDVI.js.map +0 -1
  240. package/dist/chunk-I6UCUHLK.js.map +0 -1
  241. package/dist/chunk-KQFQ3IS5.js.map +0 -1
  242. package/dist/chunk-PJGB7XRR.js.map +0 -1
  243. package/dist/chunk-RKW6QR7W.js.map +0 -1
  244. /package/dist/{chunk-GYTVOLNX.js.map → chunk-3MNBW7R7.js.map} +0 -0
  245. /package/dist/{chunk-QFQQFX2H.js.map → chunk-3R2UZV3U.js.map} +0 -0
  246. /package/dist/{chunk-O4UNM6OR.js.map → chunk-532VCWYW.js.map} +0 -0
  247. /package/dist/{chunk-2UFQYU5F.js.map → chunk-57QXN2CS.js.map} +0 -0
  248. /package/dist/{chunk-UGEBPVNI.js.map → chunk-GE7Q7KXP.js.map} +0 -0
  249. /package/dist/{chunk-GLWW3EJQ.js.map → chunk-KB4MFBF5.js.map} +0 -0
  250. /package/dist/{chunk-FH3PPO42.js.map → chunk-KVFYTRMV.js.map} +0 -0
  251. /package/dist/{chunk-BNW5NJJH.js.map → chunk-LQYTQCXM.js.map} +0 -0
  252. /package/dist/{chunk-AYHXQR53.js.map → chunk-MVQN73GT.js.map} +0 -0
  253. /package/dist/{chunk-ZZPIJPPD.js.map → chunk-N5RGXWLQ.js.map} +0 -0
  254. /package/dist/{chunk-R3OQGYOU.js.map → chunk-P2D2MM47.js.map} +0 -0
  255. /package/dist/{chunk-PSUB67YB.js.map → chunk-PW6GURU3.js.map} +0 -0
  256. /package/dist/{chunk-W3BKVM64.js.map → chunk-QDV6VAD4.js.map} +0 -0
  257. /package/dist/{chunk-3QSU4NFF.js.map → chunk-QHXW3LZV.js.map} +0 -0
  258. /package/dist/{chunk-OZXVGYGZ.js.map → chunk-STDAAGH7.js.map} +0 -0
  259. /package/dist/{chunk-FMGWXIES.js.map → chunk-TZDSNIRO.js.map} +0 -0
  260. /package/dist/{chunk-2L54V4ZO.js.map → chunk-UELS6WWF.js.map} +0 -0
  261. /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
+