@remnic/core 9.3.630 → 9.3.631
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 +15 -13
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +4 -4
- package/dist/access-http.js +7 -6
- package/dist/access-mcp.d.ts +4 -4
- package/dist/access-mcp.js +6 -5
- package/dist/{access-service-C4v-eFjB.d.ts → access-service-C9_EpVHd.d.ts} +2 -2
- package/dist/access-service.d.ts +4 -4
- package/dist/access-service.js +5 -4
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/auto-sync-RFADEHIQ.js +75 -0
- package/dist/auto-sync-RFADEHIQ.js.map +1 -0
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -2
- 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 -3
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-BWK5EEKS.js → chunk-242XFZ36.js} +2 -2
- package/dist/{chunk-K3BTOW7N.js → chunk-32U3N7H5.js} +3 -3
- package/dist/{chunk-5S6IREG3.js → chunk-3RDYU3JS.js} +3 -3
- package/dist/{chunk-SACS6KE6.js → chunk-4S3N6HFG.js} +2 -2
- package/dist/{chunk-VUTPRX7K.js → chunk-5PT5I6JQ.js} +14 -14
- package/dist/{chunk-2VJ7AJFX.js → chunk-7A2QKUUA.js} +2 -2
- package/dist/{chunk-EORL2IDM.js → chunk-7H5WCPBS.js} +58 -5
- package/dist/{chunk-EORL2IDM.js.map → chunk-7H5WCPBS.js.map} +1 -1
- package/dist/{chunk-NRQJBK36.js → chunk-C4KKM62E.js} +2 -2
- package/dist/{chunk-GXWFZYSR.js → chunk-CMN5AWAZ.js} +2 -2
- package/dist/{chunk-F6USGHMO.js → chunk-DOBJH4I6.js} +4 -4
- package/dist/{chunk-ADOD7PJC.js → chunk-IFVFQRZ2.js} +5 -5
- package/dist/{chunk-6LBQL5US.js → chunk-JCLECECB.js} +2 -2
- package/dist/chunk-KVDUDYEN.js +1164 -0
- package/dist/chunk-KVDUDYEN.js.map +1 -0
- package/dist/{chunk-S5W37FPX.js → chunk-LEG7XWS2.js} +2 -2
- package/dist/chunk-M7XQSUBB.js +280 -0
- package/dist/chunk-M7XQSUBB.js.map +1 -0
- package/dist/{chunk-MQ24KOOR.js → chunk-PUEAEQSN.js} +2 -2
- package/dist/{chunk-RSKUUEBA.js → chunk-QYGIQ5NM.js} +140 -417
- package/dist/chunk-QYGIQ5NM.js.map +1 -0
- package/dist/{chunk-UE57H4MA.js → chunk-UXFOGILU.js} +2 -2
- package/dist/{chunk-OQMR2SDZ.js → chunk-VTR3MNYF.js} +2 -2
- package/dist/{chunk-4QEUKASL.js → chunk-W25I7G6U.js} +2 -2
- package/dist/{chunk-YJOWWRRS.js → chunk-WLZBVYC6.js} +125 -1206
- package/dist/chunk-WLZBVYC6.js.map +1 -0
- package/dist/{chunk-OOFBE62K.js → chunk-X7EJF46S.js} +2 -2
- package/dist/{chunk-BL33LBTN.js → chunk-XG4NAWAV.js} +3 -3
- package/dist/{chunk-ZZSXUZF3.js → chunk-YROCXMCK.js} +2 -2
- package/dist/{cli-B_6EMiQc.d.ts → cli-CuVEQWKr.d.ts} +3 -3
- package/dist/cli.d.ts +5 -5
- package/dist/cli.js +18 -17
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -2
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -2
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -2
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/contradiction/index.js +4 -4
- 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 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +3 -3
- 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 +8 -8
- package/dist/index.js +49 -45
- 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 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
- package/dist/maintenance/rebuild-memory-projection.js +4 -3
- package/dist/mcp-memory-inspector-app.d.ts +4 -4
- 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 -3
- 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 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +7 -6
- package/dist/{orchestrator-Dlw3ae4B.d.ts → orchestrator-CoqytbK_.d.ts} +3 -2
- package/dist/orchestrator.d.ts +3 -3
- package/dist/orchestrator.js +12 -10
- 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-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-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +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 +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-C4sefXEI.d.ts → semantic-consolidation-BPs6BURk.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -3
- package/dist/semantic-rule-promotion.js +3 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -1
- 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-2vqxmO0j.d.ts → types-CpMPD8xl.d.ts} +20 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -2
- package/package.json +1 -1
- package/src/orchestrator.ts +58 -0
- package/src/wearables/auto-sync.test.ts +181 -0
- package/src/wearables/auto-sync.ts +129 -0
- package/src/wearables/config.test.ts +58 -8
- package/src/wearables/config.ts +75 -5
- package/src/wearables/pipeline.test.ts +87 -4
- package/src/wearables/pipeline.ts +43 -13
- package/src/wearables/types.ts +20 -1
- package/dist/chunk-RSKUUEBA.js.map +0 -1
- package/dist/chunk-YJOWWRRS.js.map +0 -1
- /package/dist/{chunk-BWK5EEKS.js.map → chunk-242XFZ36.js.map} +0 -0
- /package/dist/{chunk-K3BTOW7N.js.map → chunk-32U3N7H5.js.map} +0 -0
- /package/dist/{chunk-5S6IREG3.js.map → chunk-3RDYU3JS.js.map} +0 -0
- /package/dist/{chunk-SACS6KE6.js.map → chunk-4S3N6HFG.js.map} +0 -0
- /package/dist/{chunk-VUTPRX7K.js.map → chunk-5PT5I6JQ.js.map} +0 -0
- /package/dist/{chunk-2VJ7AJFX.js.map → chunk-7A2QKUUA.js.map} +0 -0
- /package/dist/{chunk-NRQJBK36.js.map → chunk-C4KKM62E.js.map} +0 -0
- /package/dist/{chunk-GXWFZYSR.js.map → chunk-CMN5AWAZ.js.map} +0 -0
- /package/dist/{chunk-F6USGHMO.js.map → chunk-DOBJH4I6.js.map} +0 -0
- /package/dist/{chunk-ADOD7PJC.js.map → chunk-IFVFQRZ2.js.map} +0 -0
- /package/dist/{chunk-6LBQL5US.js.map → chunk-JCLECECB.js.map} +0 -0
- /package/dist/{chunk-S5W37FPX.js.map → chunk-LEG7XWS2.js.map} +0 -0
- /package/dist/{chunk-MQ24KOOR.js.map → chunk-PUEAEQSN.js.map} +0 -0
- /package/dist/{chunk-UE57H4MA.js.map → chunk-UXFOGILU.js.map} +0 -0
- /package/dist/{chunk-OQMR2SDZ.js.map → chunk-VTR3MNYF.js.map} +0 -0
- /package/dist/{chunk-4QEUKASL.js.map → chunk-W25I7G6U.js.map} +0 -0
- /package/dist/{chunk-OOFBE62K.js.map → chunk-X7EJF46S.js.map} +0 -0
- /package/dist/{chunk-BL33LBTN.js.map → chunk-XG4NAWAV.js.map} +0 -0
- /package/dist/{chunk-ZZSXUZF3.js.map → chunk-YROCXMCK.js.map} +0 -0
|
@@ -544,14 +544,15 @@ test("zero provider conversations never clobber an existing transcript", async (
|
|
|
544
544
|
}
|
|
545
545
|
});
|
|
546
546
|
|
|
547
|
-
test("
|
|
547
|
+
test("looping pagination cursors stop with a partial marker and keep warning", async () => {
|
|
548
548
|
const memoryDir = mkdtempSync(path.join(tmpdir(), "remnic-pipeline-"));
|
|
549
549
|
try {
|
|
550
550
|
const conversation = makeConversation("c1", "2026-06-11", [
|
|
551
551
|
{ speaker: "user", isWearer: true, text: "First chunk of a very long recorded day of conversations." },
|
|
552
552
|
{ speaker: "Speaker 2", text: "Indeed, the recordings just keep going on and on today." },
|
|
553
553
|
]);
|
|
554
|
-
// A connector
|
|
554
|
+
// A connector whose cursor loops forever (pathological) — cycle
|
|
555
|
+
// detection must stop it; no page-count cap truncates real data.
|
|
555
556
|
const endlessConnector = {
|
|
556
557
|
id: "testsource",
|
|
557
558
|
displayName: "Test Source",
|
|
@@ -567,14 +568,96 @@ test("page-capped days carry a visible partial marker and keep warning", async (
|
|
|
567
568
|
};
|
|
568
569
|
const { deps, written } = makeDeps(memoryDir);
|
|
569
570
|
const first = await syncWearableSource(endlessConnector, settings(), config(), { days: 1 }, deps);
|
|
570
|
-
assert.ok(first.warnings.some((warning) => warning.includes("
|
|
571
|
+
assert.ok(first.warnings.some((warning) => warning.includes("repeated cursor")));
|
|
571
572
|
assert.equal(written.length, 1);
|
|
572
573
|
assert.match(written[0].serialized, /pagination safety cap reached/);
|
|
573
574
|
|
|
574
575
|
// Identical second sync: file unchanged (no rewrite), warning persists.
|
|
575
576
|
const second = await syncWearableSource(endlessConnector, settings(), config(), { days: 1 }, deps);
|
|
576
577
|
assert.equal(second.transcriptsWritten.length, 0);
|
|
577
|
-
assert.ok(second.warnings.some((warning) => warning.includes("
|
|
578
|
+
assert.ok(second.warnings.some((warning) => warning.includes("repeated cursor")));
|
|
579
|
+
} finally {
|
|
580
|
+
rmSync(memoryDir, { recursive: true, force: true });
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test("looping providers that re-serve rows never duplicate conversations", async () => {
|
|
585
|
+
const memoryDir = mkdtempSync(path.join(tmpdir(), "remnic-pipeline-"));
|
|
586
|
+
try {
|
|
587
|
+
const conversation = makeConversation("c1", "2026-06-11", [
|
|
588
|
+
{ speaker: "user", isWearer: true, text: "A conversation the provider keeps re-serving on every page." },
|
|
589
|
+
{ speaker: "Speaker 2", text: "The looping pagination should still store this exactly once." },
|
|
590
|
+
]);
|
|
591
|
+
// Pathological: every page returns the SAME row and loops the cursor.
|
|
592
|
+
const reServingConnector = {
|
|
593
|
+
id: "testsource",
|
|
594
|
+
displayName: "Test Source",
|
|
595
|
+
async verifyAuth() {
|
|
596
|
+
return { ok: true };
|
|
597
|
+
},
|
|
598
|
+
async fetchConversations() {
|
|
599
|
+
return { conversations: [conversation], nextCursor: "loop" };
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
const { deps, written } = makeDeps(memoryDir);
|
|
603
|
+
const summary = await syncWearableSource(
|
|
604
|
+
reServingConnector,
|
|
605
|
+
settings(),
|
|
606
|
+
config(),
|
|
607
|
+
{ days: 1 },
|
|
608
|
+
deps,
|
|
609
|
+
);
|
|
610
|
+
assert.equal(summary.conversations, 1, "re-served rows collapse by conversation id");
|
|
611
|
+
assert.ok(summary.warnings.some((warning) => warning.includes("repeated cursor")));
|
|
612
|
+
assert.equal(written.length, 1);
|
|
613
|
+
const occurrences = written[0].serialized.split("conversation c1").length - 1;
|
|
614
|
+
assert.equal(occurrences, 1, "day file stores the conversation exactly once");
|
|
615
|
+
} finally {
|
|
616
|
+
rmSync(memoryDir, { recursive: true, force: true });
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("long provider days paginate fully — no page-count truncation", async () => {
|
|
621
|
+
const memoryDir = mkdtempSync(path.join(tmpdir(), "remnic-pipeline-"));
|
|
622
|
+
try {
|
|
623
|
+
// 60 pages (beyond the old 50-page cap), each with one conversation.
|
|
624
|
+
const PAGES = 60;
|
|
625
|
+
const longDayConnector = {
|
|
626
|
+
id: "testsource",
|
|
627
|
+
displayName: "Test Source",
|
|
628
|
+
async verifyAuth() {
|
|
629
|
+
return { ok: true };
|
|
630
|
+
},
|
|
631
|
+
async fetchConversations(opts: { cursor?: string | null }) {
|
|
632
|
+
const page = opts.cursor ? Number(opts.cursor) : 0;
|
|
633
|
+
return {
|
|
634
|
+
conversations: [
|
|
635
|
+
makeConversation(`c${page + 1}`, "2026-06-11", [
|
|
636
|
+
{ speaker: "user", isWearer: true, text: `Recorded conversation segment number ${page + 1} from the long day.` },
|
|
637
|
+
{ speaker: "Speaker 2", text: "Acknowledged, that part of the day was captured as well." },
|
|
638
|
+
]),
|
|
639
|
+
],
|
|
640
|
+
nextCursor: page + 1 < PAGES ? String(page + 1) : null,
|
|
641
|
+
};
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
const { deps } = makeDeps(memoryDir);
|
|
645
|
+
const summary = await syncWearableSource(
|
|
646
|
+
longDayConnector,
|
|
647
|
+
settings(),
|
|
648
|
+
config(),
|
|
649
|
+
{ days: 1 },
|
|
650
|
+
deps,
|
|
651
|
+
);
|
|
652
|
+
assert.equal(summary.conversations, PAGES, "every page's conversation synced");
|
|
653
|
+
assert.equal(
|
|
654
|
+
summary.warnings.filter(
|
|
655
|
+
(warning) =>
|
|
656
|
+
warning.includes("stopped paginating") || warning.includes("repeated cursor"),
|
|
657
|
+
).length,
|
|
658
|
+
0,
|
|
659
|
+
"a real long day is never truncated or warned",
|
|
660
|
+
);
|
|
578
661
|
} finally {
|
|
579
662
|
rmSync(memoryDir, { recursive: true, force: true });
|
|
580
663
|
}
|
|
@@ -52,10 +52,13 @@ import type {
|
|
|
52
52
|
WearablesConfig,
|
|
53
53
|
} from "./types.js";
|
|
54
54
|
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Pathological-provider backstop on pagination loops. Day fetches are
|
|
57
|
+
* intentionally UNLIMITED for real data — a full day must never be
|
|
58
|
+
* truncated — so runaway protection comes from cursor-cycle detection
|
|
59
|
+
* plus this far-out-of-band ceiling, not from a content-sized cap.
|
|
60
|
+
*/
|
|
61
|
+
const PAGE_SAFETY_CEILING = 10_000;
|
|
59
62
|
/** Default lookback window (today + yesterday) for unscoped syncs. */
|
|
60
63
|
const DEFAULT_SYNC_DAYS = 2;
|
|
61
64
|
const MAX_SYNC_DAYS = 90;
|
|
@@ -186,23 +189,42 @@ async function fetchAllConversationsForDate(
|
|
|
186
189
|
signal: AbortSignal | undefined,
|
|
187
190
|
warnings: string[],
|
|
188
191
|
): Promise<{ conversations: WearableConversation[]; partial: boolean }> {
|
|
189
|
-
|
|
192
|
+
// Keyed by conversation id: a looping or overlapping provider can
|
|
193
|
+
// re-serve rows it already returned, and appending blindly would
|
|
194
|
+
// store the same conversation twice in the day file (Cursor review
|
|
195
|
+
// on PR #1464). Map keeps first-seen order; a re-served id replaces
|
|
196
|
+
// its entry in place, so the provider's LATEST version of a
|
|
197
|
+
// conversation wins — exactly what the current-day refresh wants.
|
|
198
|
+
const byId = new Map<string, WearableConversation>();
|
|
190
199
|
let cursor: string | null | undefined = undefined;
|
|
191
|
-
|
|
200
|
+
const seenCursors = new Set<string>();
|
|
201
|
+
const collect = () => [...byId.values()];
|
|
202
|
+
for (let page = 0; page < PAGE_SAFETY_CEILING; page++) {
|
|
192
203
|
const result = await connector.fetchConversations({
|
|
193
204
|
date,
|
|
194
205
|
timezone,
|
|
195
206
|
cursor,
|
|
196
207
|
signal,
|
|
197
208
|
});
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
for (const conversation of result.conversations) {
|
|
210
|
+
byId.set(conversation.id, conversation);
|
|
211
|
+
}
|
|
212
|
+
if (!result.nextCursor) return { conversations: collect(), partial: false };
|
|
213
|
+
// A repeated cursor means the provider's pagination is looping —
|
|
214
|
+
// following it again would refetch the same page forever.
|
|
215
|
+
if (seenCursors.has(result.nextCursor)) {
|
|
216
|
+
warnings.push(
|
|
217
|
+
`${connector.id}: provider pagination repeated cursor on ${date} — stopped to avoid an infinite loop; day may be partially synced (every sync refetches and re-warns while the provider misbehaves)`,
|
|
218
|
+
);
|
|
219
|
+
return { conversations: collect(), partial: true };
|
|
220
|
+
}
|
|
221
|
+
seenCursors.add(result.nextCursor);
|
|
200
222
|
cursor = result.nextCursor;
|
|
201
223
|
}
|
|
202
224
|
warnings.push(
|
|
203
|
-
`${connector.id}: stopped paginating ${date} after ${
|
|
225
|
+
`${connector.id}: stopped paginating ${date} after the ${PAGE_SAFETY_CEILING}-page safety ceiling — day may be partially synced (every sync refetches and re-warns while this persists)`,
|
|
204
226
|
);
|
|
205
|
-
return { conversations, partial: true };
|
|
227
|
+
return { conversations: collect(), partial: true };
|
|
206
228
|
}
|
|
207
229
|
|
|
208
230
|
/** Visible marker appended to day files whose fetch hit the page cap. */
|
|
@@ -521,7 +543,8 @@ export async function syncWearableSource(
|
|
|
521
543
|
: {}),
|
|
522
544
|
};
|
|
523
545
|
let cursor: string | null | undefined = undefined;
|
|
524
|
-
|
|
546
|
+
const seenNativeCursors = new Set<string>();
|
|
547
|
+
for (let page = 0; page < PAGE_SAFETY_CEILING; page++) {
|
|
525
548
|
const result = await connector.fetchNativeMemories({
|
|
526
549
|
cursor,
|
|
527
550
|
signal: options.signal,
|
|
@@ -538,10 +561,17 @@ export async function syncWearableSource(
|
|
|
538
561
|
importedNativeIds.push(...imported.importedIds);
|
|
539
562
|
for (const id of imported.importedIds) alreadyImported.add(id);
|
|
540
563
|
if (!result.nextCursor) break;
|
|
564
|
+
if (seenNativeCursors.has(result.nextCursor)) {
|
|
565
|
+
summary.warnings.push(
|
|
566
|
+
`${connector.id}: provider pagination repeated cursor during native-memory import — stopped to avoid an infinite loop; remaining items import on the next sync`,
|
|
567
|
+
);
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
seenNativeCursors.add(result.nextCursor);
|
|
541
571
|
cursor = result.nextCursor;
|
|
542
|
-
if (page ===
|
|
572
|
+
if (page === PAGE_SAFETY_CEILING - 1) {
|
|
543
573
|
summary.warnings.push(
|
|
544
|
-
`${connector.id}: stopped native-memory import
|
|
574
|
+
`${connector.id}: stopped native-memory import at the ${PAGE_SAFETY_CEILING}-page safety ceiling — remaining items import on the next sync`,
|
|
545
575
|
);
|
|
546
576
|
}
|
|
547
577
|
}
|
package/src/wearables/types.ts
CHANGED
|
@@ -176,7 +176,9 @@ export interface WearableSourceSettings {
|
|
|
176
176
|
/** Drop extracted facts scored below this importance level. */
|
|
177
177
|
minImportance: ImportanceLevel;
|
|
178
178
|
/**
|
|
179
|
-
* Cap on memories created per source per day. 0
|
|
179
|
+
* Cap on memories created per source per day. 0 (the default)
|
|
180
|
+
* disables the cap — the smart trust pipeline is the quality gate,
|
|
181
|
+
* and a count cap would drop real memories on busy days.
|
|
180
182
|
*/
|
|
181
183
|
maxMemoriesPerDay: number;
|
|
182
184
|
/**
|
|
@@ -250,6 +252,23 @@ export interface WearablesConfig {
|
|
|
250
252
|
* Default false.
|
|
251
253
|
*/
|
|
252
254
|
digestEnabled: boolean;
|
|
255
|
+
/**
|
|
256
|
+
* Periodically refresh transcripts in-process (long-lived hosts).
|
|
257
|
+
* Every tick re-syncs `autoSyncDays` ending today — existing day
|
|
258
|
+
* files included, so the current day keeps growing while the
|
|
259
|
+
* wearable records. Default true.
|
|
260
|
+
*/
|
|
261
|
+
autoSyncEnabled: boolean;
|
|
262
|
+
/** Minutes between auto-sync ticks (1-1440). Default 15. */
|
|
263
|
+
autoSyncIntervalMinutes: number;
|
|
264
|
+
/** Rolling window (days ending today) per tick (1-90). Default 2. */
|
|
265
|
+
autoSyncDays: number;
|
|
266
|
+
/**
|
|
267
|
+
* Once-per-local-day deep pass window (days, 0-90) picking up late
|
|
268
|
+
* uploads and provider re-processing. 0 disables; otherwise must be
|
|
269
|
+
* >= autoSyncDays. Default 7.
|
|
270
|
+
*/
|
|
271
|
+
autoSyncDeepDays: number;
|
|
253
272
|
/** Correction rules from config (merged with CLI-managed rules). */
|
|
254
273
|
corrections: WearableCorrectionRule[];
|
|
255
274
|
/** Per-source settings, keyed by connector id. */
|