@remnic/core 9.3.629 → 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 +5 -4
- package/dist/access-http.js +7 -6
- package/dist/access-mcp.d.ts +5 -4
- package/dist/access-mcp.js +6 -5
- package/dist/{access-service-BdThkfIE.d.ts → access-service-C9_EpVHd.d.ts} +2 -2
- package/dist/access-service.d.ts +5 -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 +4 -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-532VCWYW.js → chunk-242XFZ36.js} +2 -2
- package/dist/{chunk-XXO5TI3B.js → chunk-32U3N7H5.js} +3 -3
- package/dist/{chunk-KB4MFBF5.js → chunk-3RDYU3JS.js} +3 -3
- package/dist/{chunk-57QXN2CS.js → chunk-4S3N6HFG.js} +2 -2
- package/dist/{chunk-OLNNOHBC.js → chunk-5PT5I6JQ.js} +20 -14
- package/dist/{chunk-OLNNOHBC.js.map → chunk-5PT5I6JQ.js.map} +1 -1
- package/dist/{chunk-GE7Q7KXP.js → chunk-7A2QKUUA.js} +2 -2
- package/dist/{chunk-KKTXCFD7.js → chunk-7H5WCPBS.js} +95 -11
- package/dist/{chunk-KKTXCFD7.js.map → chunk-7H5WCPBS.js.map} +1 -1
- package/dist/{chunk-3MNBW7R7.js → chunk-C4KKM62E.js} +2 -2
- package/dist/{chunk-NKCW223V.js → chunk-CMN5AWAZ.js} +2 -2
- package/dist/{chunk-JXHMAQYT.js → chunk-DOBJH4I6.js} +4 -4
- package/dist/{chunk-TZDSNIRO.js → chunk-IFVFQRZ2.js} +5 -5
- package/dist/{chunk-LQYTQCXM.js → chunk-JCLECECB.js} +2 -2
- package/dist/chunk-KVDUDYEN.js +1164 -0
- package/dist/chunk-KVDUDYEN.js.map +1 -0
- package/dist/{chunk-QDV6VAD4.js → chunk-LEG7XWS2.js} +2 -2
- package/dist/chunk-M7XQSUBB.js +280 -0
- package/dist/chunk-M7XQSUBB.js.map +1 -0
- package/dist/{chunk-N5RGXWLQ.js → chunk-PUEAEQSN.js} +2 -2
- package/dist/{chunk-UGHUNQ74.js → chunk-QYGIQ5NM.js} +212 -417
- package/dist/chunk-QYGIQ5NM.js.map +1 -0
- package/dist/{chunk-JKCDQBDW.js → chunk-UXFOGILU.js} +2 -2
- package/dist/{chunk-MVQN73GT.js → chunk-VTR3MNYF.js} +2 -2
- package/dist/{chunk-KVFYTRMV.js → chunk-W25I7G6U.js} +2 -2
- package/dist/{chunk-3GLCUPXP.js → chunk-WLZBVYC6.js} +192 -889
- package/dist/chunk-WLZBVYC6.js.map +1 -0
- package/dist/{chunk-3R2UZV3U.js → chunk-X7EJF46S.js} +2 -2
- package/dist/{chunk-54KDA6UK.js → chunk-XG4NAWAV.js} +3 -3
- package/dist/{chunk-P2D2MM47.js → chunk-YROCXMCK.js} +2 -2
- package/dist/{cli-DAsHklrf.d.ts → cli-CuVEQWKr.d.ts} +3 -3
- package/dist/cli.d.ts +6 -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 +4 -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 +5 -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-BexeSJ2j.d.ts → orchestrator-CoqytbK_.d.ts} +102 -10
- package/dist/orchestrator.d.ts +4 -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/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-PwkzNfdK.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 +38 -2
- package/dist/storage.js +6 -3
- 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-BCF2wqKa.d.ts → types-CpMPD8xl.d.ts} +59 -11
- 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 +74 -0
- package/src/storage.ts +100 -0
- package/src/wearables/auto-sync.test.ts +181 -0
- package/src/wearables/auto-sync.ts +129 -0
- package/src/wearables/cli.ts +6 -0
- package/src/wearables/config.test.ts +90 -11
- package/src/wearables/config.ts +113 -11
- package/src/wearables/memory-gen.test.ts +416 -1
- package/src/wearables/memory-gen.ts +381 -23
- package/src/wearables/pipeline.test.ts +396 -5
- package/src/wearables/pipeline.ts +174 -22
- package/src/wearables/service.test.ts +172 -0
- package/src/wearables/service.ts +84 -3
- package/src/wearables/storage-io.test.ts +81 -0
- package/src/wearables/trust.test.ts +123 -0
- package/src/wearables/trust.ts +168 -0
- package/src/wearables/types.ts +57 -9
- package/dist/chunk-3GLCUPXP.js.map +0 -1
- package/dist/chunk-UGHUNQ74.js.map +0 -1
- /package/dist/{chunk-532VCWYW.js.map → chunk-242XFZ36.js.map} +0 -0
- /package/dist/{chunk-XXO5TI3B.js.map → chunk-32U3N7H5.js.map} +0 -0
- /package/dist/{chunk-KB4MFBF5.js.map → chunk-3RDYU3JS.js.map} +0 -0
- /package/dist/{chunk-57QXN2CS.js.map → chunk-4S3N6HFG.js.map} +0 -0
- /package/dist/{chunk-GE7Q7KXP.js.map → chunk-7A2QKUUA.js.map} +0 -0
- /package/dist/{chunk-3MNBW7R7.js.map → chunk-C4KKM62E.js.map} +0 -0
- /package/dist/{chunk-NKCW223V.js.map → chunk-CMN5AWAZ.js.map} +0 -0
- /package/dist/{chunk-JXHMAQYT.js.map → chunk-DOBJH4I6.js.map} +0 -0
- /package/dist/{chunk-TZDSNIRO.js.map → chunk-IFVFQRZ2.js.map} +0 -0
- /package/dist/{chunk-LQYTQCXM.js.map → chunk-JCLECECB.js.map} +0 -0
- /package/dist/{chunk-QDV6VAD4.js.map → chunk-LEG7XWS2.js.map} +0 -0
- /package/dist/{chunk-N5RGXWLQ.js.map → chunk-PUEAEQSN.js.map} +0 -0
- /package/dist/{chunk-JKCDQBDW.js.map → chunk-UXFOGILU.js.map} +0 -0
- /package/dist/{chunk-MVQN73GT.js.map → chunk-VTR3MNYF.js.map} +0 -0
- /package/dist/{chunk-KVFYTRMV.js.map → chunk-W25I7G6U.js.map} +0 -0
- /package/dist/{chunk-3R2UZV3U.js.map → chunk-X7EJF46S.js.map} +0 -0
- /package/dist/{chunk-54KDA6UK.js.map → chunk-XG4NAWAV.js.map} +0 -0
- /package/dist/{chunk-P2D2MM47.js.map → chunk-YROCXMCK.js.map} +0 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WEARABLE_SOURCE_PREFIX,
|
|
3
|
+
defaultTimezone,
|
|
4
|
+
loadSyncState,
|
|
5
|
+
syncWearableSource,
|
|
6
|
+
wearableSourceLabel
|
|
7
|
+
} from "./chunk-KVDUDYEN.js";
|
|
1
8
|
import {
|
|
2
9
|
migrateFromEngram
|
|
3
10
|
} from "./chunk-4HFJQCJZ.js";
|
|
@@ -22,7 +29,7 @@ import {
|
|
|
22
29
|
import {
|
|
23
30
|
CompoundingEngine,
|
|
24
31
|
defaultTierMigrationCycleBudget
|
|
25
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-UXFOGILU.js";
|
|
26
33
|
import {
|
|
27
34
|
SharedContextManager
|
|
28
35
|
} from "./chunk-DRD2Q7HQ.js";
|
|
@@ -168,7 +175,7 @@ import {
|
|
|
168
175
|
buildEntityRecallSection,
|
|
169
176
|
entityRecentTranscriptLookbackHours,
|
|
170
177
|
readRecentEntityTranscriptEntries
|
|
171
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-JCLECECB.js";
|
|
172
179
|
import {
|
|
173
180
|
buildEventOrderRecallSection,
|
|
174
181
|
shouldRecallEventOrderEvidence
|
|
@@ -203,7 +210,7 @@ import {
|
|
|
203
210
|
materializeAfterSemanticConsolidation,
|
|
204
211
|
parseConsolidationResponse,
|
|
205
212
|
parseOperatorAwareConsolidationResponse
|
|
206
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-X7EJF46S.js";
|
|
207
214
|
import {
|
|
208
215
|
normalizeReplaySessionKey
|
|
209
216
|
} from "./chunk-2PRQG7PV.js";
|
|
@@ -212,13 +219,13 @@ import {
|
|
|
212
219
|
} from "./chunk-X6IRLNOO.js";
|
|
213
220
|
import {
|
|
214
221
|
searchVerifiedEpisodes
|
|
215
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-YROCXMCK.js";
|
|
216
223
|
import {
|
|
217
224
|
ThreadingManager
|
|
218
225
|
} from "./chunk-W4RVMTHR.js";
|
|
219
226
|
import {
|
|
220
227
|
searchVerifiedSemanticRules
|
|
221
|
-
} from "./chunk-
|
|
228
|
+
} from "./chunk-4S3N6HFG.js";
|
|
222
229
|
import {
|
|
223
230
|
searchWorkProductLedgerEntries
|
|
224
231
|
} from "./chunk-ZRWB5D4H.js";
|
|
@@ -237,7 +244,7 @@ import {
|
|
|
237
244
|
} from "./chunk-CYEPCZN5.js";
|
|
238
245
|
import {
|
|
239
246
|
NamespaceStorageRouter
|
|
240
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-LEG7XWS2.js";
|
|
241
248
|
import {
|
|
242
249
|
namespaceIdentityFromToken
|
|
243
250
|
} from "./chunk-ZFXCQPNO.js";
|
|
@@ -286,14 +293,9 @@ import {
|
|
|
286
293
|
fallbackLlmRuntimeContextFromConfig
|
|
287
294
|
} from "./chunk-723OMPUI.js";
|
|
288
295
|
import {
|
|
289
|
-
applyCorrections,
|
|
290
|
-
applyOffTheRecord,
|
|
291
296
|
compileCorrectionRule,
|
|
292
|
-
compileCorrectionRules,
|
|
293
|
-
compileRedactionPatterns,
|
|
294
297
|
correctionsFilePath,
|
|
295
298
|
loadCorrectionsFile,
|
|
296
|
-
redactText,
|
|
297
299
|
saveCorrectionsFile
|
|
298
300
|
} from "./chunk-NDAH7BJ5.js";
|
|
299
301
|
import {
|
|
@@ -351,26 +353,24 @@ import {
|
|
|
351
353
|
} from "./chunk-XL7FK7PJ.js";
|
|
352
354
|
import {
|
|
353
355
|
buildChainFollowupGenerator
|
|
354
|
-
} from "./chunk-
|
|
356
|
+
} from "./chunk-CMN5AWAZ.js";
|
|
355
357
|
import {
|
|
356
358
|
ContentHashIndex,
|
|
357
359
|
StorageManager,
|
|
358
360
|
compareEntityTimestamps,
|
|
359
|
-
composeDayTranscriptBody,
|
|
360
|
-
composeDayTranscriptMeta,
|
|
361
361
|
fingerprintEntityStructuredFacts,
|
|
362
|
-
hashTranscriptBody,
|
|
363
|
-
isValidTranscriptDate,
|
|
364
|
-
loadSpeakerRegistry,
|
|
365
362
|
normalizeAttributePairs,
|
|
366
363
|
normalizeEntityName,
|
|
367
|
-
parseDayTranscript,
|
|
368
364
|
parseEntityFile,
|
|
369
|
-
|
|
365
|
+
stripAttributesSuffix
|
|
366
|
+
} from "./chunk-QYGIQ5NM.js";
|
|
367
|
+
import {
|
|
368
|
+
isValidTranscriptDate,
|
|
369
|
+
loadSpeakerRegistry,
|
|
370
|
+
parseDayTranscript,
|
|
370
371
|
saveSpeakerRegistry,
|
|
371
|
-
serializeDayTranscript,
|
|
372
372
|
speakerRegistryKey
|
|
373
|
-
} from "./chunk-
|
|
373
|
+
} from "./chunk-M7XQSUBB.js";
|
|
374
374
|
import {
|
|
375
375
|
attachCitation,
|
|
376
376
|
hasCitationForTemplate,
|
|
@@ -380,6 +380,7 @@ import {
|
|
|
380
380
|
confidenceTier
|
|
381
381
|
} from "./chunk-FPNQF475.js";
|
|
382
382
|
import {
|
|
383
|
+
inferMemoryStatus,
|
|
383
384
|
isActiveMemoryStatus
|
|
384
385
|
} from "./chunk-RULE4VG5.js";
|
|
385
386
|
import {
|
|
@@ -423,7 +424,7 @@ import {
|
|
|
423
424
|
} from "./chunk-AC5LO7IU.js";
|
|
424
425
|
|
|
425
426
|
// src/orchestrator.ts
|
|
426
|
-
import
|
|
427
|
+
import path2 from "path";
|
|
427
428
|
import os from "os";
|
|
428
429
|
import { createHash, randomBytes } from "crypto";
|
|
429
430
|
import { existsSync } from "fs";
|
|
@@ -965,780 +966,6 @@ function getTaxonomyFilePath(memoryDir) {
|
|
|
965
966
|
return path.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
966
967
|
}
|
|
967
968
|
|
|
968
|
-
// src/wearables/memory-gen.ts
|
|
969
|
-
function memoryStatusForMode(mode) {
|
|
970
|
-
return mode === "auto" ? "active" : "pending_review";
|
|
971
|
-
}
|
|
972
|
-
var WEARABLE_SOURCE_PREFIX = "wearable";
|
|
973
|
-
function wearableSourceLabel(sourceId) {
|
|
974
|
-
return `${WEARABLE_SOURCE_PREFIX}:${sourceId}`;
|
|
975
|
-
}
|
|
976
|
-
function wearableDayTag(date) {
|
|
977
|
-
return `wearable-day:${date}`;
|
|
978
|
-
}
|
|
979
|
-
var IMPORTANCE_RANK = {
|
|
980
|
-
trivial: 0,
|
|
981
|
-
low: 1,
|
|
982
|
-
normal: 2,
|
|
983
|
-
high: 3,
|
|
984
|
-
critical: 4
|
|
985
|
-
};
|
|
986
|
-
var MAX_EXTRACTION_CHUNK_CHARS = 6e3;
|
|
987
|
-
var MIN_CONVERSATION_CHARS = 80;
|
|
988
|
-
function buildExtractionTurns(sourceId, date, conversation, registry) {
|
|
989
|
-
const headerParts = [
|
|
990
|
-
`Wearable transcript (${sourceId}) \u2014 ${date}`,
|
|
991
|
-
conversation.title ? `"${conversation.title}"` : void 0,
|
|
992
|
-
conversation.location ? `at ${conversation.location}` : void 0
|
|
993
|
-
].filter((part) => typeof part === "string");
|
|
994
|
-
const header = `[${headerParts.join(" \u2014 ")}]`;
|
|
995
|
-
const lines = [];
|
|
996
|
-
for (const segment of conversation.segments) {
|
|
997
|
-
const { label } = resolveSpeaker(sourceId, segment, registry);
|
|
998
|
-
lines.push(`${label}: ${segment.text}`);
|
|
999
|
-
}
|
|
1000
|
-
const transcript = lines.join("\n");
|
|
1001
|
-
if (transcript.trim().length < MIN_CONVERSATION_CHARS) return [];
|
|
1002
|
-
const sessionKey = `wearables:${sourceId}:${date}:${conversation.id}`;
|
|
1003
|
-
const timestamp = conversation.startIso;
|
|
1004
|
-
const turns = [];
|
|
1005
|
-
let chunkLines = [];
|
|
1006
|
-
let chunkChars = 0;
|
|
1007
|
-
const flush = () => {
|
|
1008
|
-
if (chunkLines.length === 0) return;
|
|
1009
|
-
turns.push({
|
|
1010
|
-
role: "user",
|
|
1011
|
-
content: `${header}
|
|
1012
|
-
${chunkLines.join("\n")}`,
|
|
1013
|
-
timestamp,
|
|
1014
|
-
sourceValidAt: timestamp,
|
|
1015
|
-
sessionKey
|
|
1016
|
-
});
|
|
1017
|
-
chunkLines = [];
|
|
1018
|
-
chunkChars = 0;
|
|
1019
|
-
};
|
|
1020
|
-
for (const line of transcript.split("\n")) {
|
|
1021
|
-
if (chunkChars + line.length + 1 > MAX_EXTRACTION_CHUNK_CHARS) flush();
|
|
1022
|
-
chunkLines.push(line);
|
|
1023
|
-
chunkChars += line.length + 1;
|
|
1024
|
-
}
|
|
1025
|
-
flush();
|
|
1026
|
-
return turns;
|
|
1027
|
-
}
|
|
1028
|
-
async function generateWearableMemories(sourceId, date, conversations, settings, registry, deps) {
|
|
1029
|
-
const result = {
|
|
1030
|
-
created: 0,
|
|
1031
|
-
skipped: 0,
|
|
1032
|
-
skippedByReason: {},
|
|
1033
|
-
warnings: []
|
|
1034
|
-
};
|
|
1035
|
-
if (settings.memoryMode === "off") return result;
|
|
1036
|
-
const skip = (reason, count = 1) => {
|
|
1037
|
-
result.skipped += count;
|
|
1038
|
-
result.skippedByReason[reason] = (result.skippedByReason[reason] ?? 0) + count;
|
|
1039
|
-
};
|
|
1040
|
-
const candidates = [];
|
|
1041
|
-
const seenContent = /* @__PURE__ */ new Set();
|
|
1042
|
-
for (const conversation of conversations) {
|
|
1043
|
-
const turns = buildExtractionTurns(sourceId, date, conversation, registry);
|
|
1044
|
-
if (turns.length === 0) continue;
|
|
1045
|
-
let extraction;
|
|
1046
|
-
try {
|
|
1047
|
-
extraction = await deps.extract(turns);
|
|
1048
|
-
} catch (err) {
|
|
1049
|
-
result.warnings.push(
|
|
1050
|
-
`extraction failed for ${sourceId}/${date} (conversation ${conversation.id}): ${describeErrorForOperator(err)} \u2014 the memory pass for this day retries on the next sync`
|
|
1051
|
-
);
|
|
1052
|
-
break;
|
|
1053
|
-
}
|
|
1054
|
-
for (const fact of extraction.facts) {
|
|
1055
|
-
const content = fact.content?.trim();
|
|
1056
|
-
if (!content) {
|
|
1057
|
-
skip("empty");
|
|
1058
|
-
continue;
|
|
1059
|
-
}
|
|
1060
|
-
if (fact.category === "procedure" || fact.category === "reasoning_trace") {
|
|
1061
|
-
skip("unsupported-category");
|
|
1062
|
-
continue;
|
|
1063
|
-
}
|
|
1064
|
-
if (typeof fact.confidence === "number" && fact.confidence < settings.minConfidence) {
|
|
1065
|
-
skip("below-confidence");
|
|
1066
|
-
continue;
|
|
1067
|
-
}
|
|
1068
|
-
const importance = scoreImportance(content, fact.category, fact.tags ?? []);
|
|
1069
|
-
if (IMPORTANCE_RANK[importance.level] < IMPORTANCE_RANK[settings.minImportance]) {
|
|
1070
|
-
skip("below-importance");
|
|
1071
|
-
continue;
|
|
1072
|
-
}
|
|
1073
|
-
const dedupKey = content.toLowerCase();
|
|
1074
|
-
if (seenContent.has(dedupKey)) {
|
|
1075
|
-
skip("duplicate-in-run");
|
|
1076
|
-
continue;
|
|
1077
|
-
}
|
|
1078
|
-
seenContent.add(dedupKey);
|
|
1079
|
-
candidates.push({ fact: { ...fact, content }, importance, conversation });
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
const novel = [];
|
|
1083
|
-
for (const candidate of candidates) {
|
|
1084
|
-
if (await deps.writer.hasFactContentHash(candidate.fact.content)) {
|
|
1085
|
-
skip("duplicate-existing");
|
|
1086
|
-
continue;
|
|
1087
|
-
}
|
|
1088
|
-
novel.push(candidate);
|
|
1089
|
-
}
|
|
1090
|
-
novel.sort((a, b) => {
|
|
1091
|
-
if (a.importance.score > b.importance.score) return -1;
|
|
1092
|
-
if (a.importance.score < b.importance.score) return 1;
|
|
1093
|
-
if (a.fact.content < b.fact.content) return -1;
|
|
1094
|
-
if (a.fact.content > b.fact.content) return 1;
|
|
1095
|
-
return 0;
|
|
1096
|
-
});
|
|
1097
|
-
const cap = settings.maxMemoriesPerDay;
|
|
1098
|
-
const kept = cap > 0 ? novel.slice(0, cap) : novel;
|
|
1099
|
-
if (novel.length > kept.length) {
|
|
1100
|
-
skip("over-day-cap", novel.length - kept.length);
|
|
1101
|
-
}
|
|
1102
|
-
const status = memoryStatusForMode(settings.memoryMode);
|
|
1103
|
-
for (const candidate of kept) {
|
|
1104
|
-
const tags = [
|
|
1105
|
-
.../* @__PURE__ */ new Set([
|
|
1106
|
-
...candidate.fact.tags ?? [],
|
|
1107
|
-
WEARABLE_SOURCE_PREFIX,
|
|
1108
|
-
wearableSourceLabel(sourceId),
|
|
1109
|
-
wearableDayTag(date)
|
|
1110
|
-
])
|
|
1111
|
-
];
|
|
1112
|
-
await deps.writer.writeMemory(candidate.fact.category, candidate.fact.content, {
|
|
1113
|
-
confidence: candidate.fact.confidence,
|
|
1114
|
-
tags,
|
|
1115
|
-
source: wearableSourceLabel(sourceId),
|
|
1116
|
-
importance: candidate.importance,
|
|
1117
|
-
validAt: candidate.conversation.startIso,
|
|
1118
|
-
structuredAttributes: {
|
|
1119
|
-
...candidate.fact.structuredAttributes ?? {},
|
|
1120
|
-
wearableSource: sourceId,
|
|
1121
|
-
wearableDate: date,
|
|
1122
|
-
wearableConversationId: candidate.conversation.id
|
|
1123
|
-
},
|
|
1124
|
-
contentHashSource: candidate.fact.content,
|
|
1125
|
-
status
|
|
1126
|
-
});
|
|
1127
|
-
result.created += 1;
|
|
1128
|
-
}
|
|
1129
|
-
return result;
|
|
1130
|
-
}
|
|
1131
|
-
async function writeDailyDigestMemory(sourceId, date, conversations, settings, registry, writer) {
|
|
1132
|
-
if (settings.memoryMode === "off") return false;
|
|
1133
|
-
if (conversations.length === 0) return false;
|
|
1134
|
-
const lines = conversations.map((conversation) => {
|
|
1135
|
-
const title = conversation.title?.trim() || "Untitled conversation";
|
|
1136
|
-
const speakers = new Set(
|
|
1137
|
-
conversation.segments.map(
|
|
1138
|
-
(segment) => resolveSpeaker(sourceId, segment, registry).label
|
|
1139
|
-
)
|
|
1140
|
-
);
|
|
1141
|
-
return `- ${title} (${speakers.size} speaker${speakers.size === 1 ? "" : "s"})`;
|
|
1142
|
-
});
|
|
1143
|
-
const content = `Wearable day digest \u2014 ${sourceId}, ${date}: ${conversations.length} recorded conversation${conversations.length === 1 ? "" : "s"}.
|
|
1144
|
-
` + lines.join("\n");
|
|
1145
|
-
if (await writer.hasFactContentHash(content)) return false;
|
|
1146
|
-
await writer.writeMemory("moment", content, {
|
|
1147
|
-
confidence: 0.9,
|
|
1148
|
-
tags: [
|
|
1149
|
-
WEARABLE_SOURCE_PREFIX,
|
|
1150
|
-
wearableSourceLabel(sourceId),
|
|
1151
|
-
wearableDayTag(date),
|
|
1152
|
-
"daily-digest"
|
|
1153
|
-
],
|
|
1154
|
-
source: wearableSourceLabel(sourceId),
|
|
1155
|
-
importance: scoreImportance(content, "moment", ["daily-digest"]),
|
|
1156
|
-
validAt: `${date}T00:00:00.000Z`,
|
|
1157
|
-
structuredAttributes: {
|
|
1158
|
-
wearableSource: sourceId,
|
|
1159
|
-
wearableDate: date
|
|
1160
|
-
},
|
|
1161
|
-
contentHashSource: content,
|
|
1162
|
-
status: memoryStatusForMode(settings.memoryMode),
|
|
1163
|
-
memoryKind: "episode"
|
|
1164
|
-
});
|
|
1165
|
-
return true;
|
|
1166
|
-
}
|
|
1167
|
-
async function importNativeMemories(sourceId, memories, alreadyImportedIds, writer) {
|
|
1168
|
-
let imported = 0;
|
|
1169
|
-
const importedIds = [];
|
|
1170
|
-
const seenContent = /* @__PURE__ */ new Set();
|
|
1171
|
-
for (const memory of memories) {
|
|
1172
|
-
const content = memory.content?.trim();
|
|
1173
|
-
if (!content) continue;
|
|
1174
|
-
if (alreadyImportedIds.has(memory.id)) continue;
|
|
1175
|
-
if (seenContent.has(content) || await writer.hasFactContentHash(content)) {
|
|
1176
|
-
importedIds.push(memory.id);
|
|
1177
|
-
continue;
|
|
1178
|
-
}
|
|
1179
|
-
seenContent.add(content);
|
|
1180
|
-
await writer.writeMemory("fact", content, {
|
|
1181
|
-
confidence: 0.6,
|
|
1182
|
-
tags: [
|
|
1183
|
-
.../* @__PURE__ */ new Set([
|
|
1184
|
-
...memory.tags ?? [],
|
|
1185
|
-
WEARABLE_SOURCE_PREFIX,
|
|
1186
|
-
wearableSourceLabel(sourceId),
|
|
1187
|
-
"native-import"
|
|
1188
|
-
])
|
|
1189
|
-
],
|
|
1190
|
-
source: `${wearableSourceLabel(sourceId)}:native`,
|
|
1191
|
-
importance: scoreImportance(content, "fact", memory.tags ?? []),
|
|
1192
|
-
validAt: memory.createdIso,
|
|
1193
|
-
structuredAttributes: {
|
|
1194
|
-
wearableSource: sourceId,
|
|
1195
|
-
wearableNativeId: memory.id
|
|
1196
|
-
},
|
|
1197
|
-
contentHashSource: content,
|
|
1198
|
-
status: "pending_review"
|
|
1199
|
-
});
|
|
1200
|
-
imported += 1;
|
|
1201
|
-
importedIds.push(memory.id);
|
|
1202
|
-
}
|
|
1203
|
-
return { imported, importedIds };
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
// src/wearables/cleanup.ts
|
|
1207
|
-
var MERGE_GAP_MS = 3e4;
|
|
1208
|
-
var FILLER_TOKENS = ["um", "uh", "uhm", "umm", "uhh", "erm", "hmm", "mhm"];
|
|
1209
|
-
var FILLER_PATTERN = new RegExp(
|
|
1210
|
-
// Leading/trailing punctuation around the filler collapses with it so
|
|
1211
|
-
// "Um, so we should" -> "so we should" rather than ", so we should".
|
|
1212
|
-
`(?:^|\\s)(?:${FILLER_TOKENS.join("|")})[,.]?(?=\\s|$)`,
|
|
1213
|
-
"gi"
|
|
1214
|
-
);
|
|
1215
|
-
function cleanConversation(conversation, settings) {
|
|
1216
|
-
let segments = conversation.segments.map((segment) => ({ ...segment }));
|
|
1217
|
-
let droppedSegments = 0;
|
|
1218
|
-
let mergedSegments = 0;
|
|
1219
|
-
if (settings.stripFillers) {
|
|
1220
|
-
for (const segment of segments) {
|
|
1221
|
-
segment.text = stripFillerTokens(segment.text);
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
if (settings.collapseRepeats) {
|
|
1225
|
-
for (const segment of segments) {
|
|
1226
|
-
segment.text = collapseImmediateRepeats(segment.text);
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
for (const segment of segments) {
|
|
1230
|
-
segment.text = normalizeWhitespace(segment.text);
|
|
1231
|
-
}
|
|
1232
|
-
if (settings.dropLowQuality) {
|
|
1233
|
-
const kept = [];
|
|
1234
|
-
for (const segment of segments) {
|
|
1235
|
-
if (isLowQualitySegment(segment.text)) {
|
|
1236
|
-
droppedSegments += 1;
|
|
1237
|
-
} else {
|
|
1238
|
-
kept.push(segment);
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
segments = kept;
|
|
1242
|
-
} else {
|
|
1243
|
-
const kept = segments.filter((segment) => segment.text.length > 0);
|
|
1244
|
-
droppedSegments += segments.length - kept.length;
|
|
1245
|
-
segments = kept;
|
|
1246
|
-
}
|
|
1247
|
-
if (settings.mergeSameSpeaker) {
|
|
1248
|
-
const merged = [];
|
|
1249
|
-
for (const segment of segments) {
|
|
1250
|
-
const previous = merged[merged.length - 1];
|
|
1251
|
-
if (previous && canMerge(previous, segment)) {
|
|
1252
|
-
previous.text = `${previous.text} ${segment.text}`.trim();
|
|
1253
|
-
if (segment.endIso) previous.endIso = segment.endIso;
|
|
1254
|
-
mergedSegments += 1;
|
|
1255
|
-
} else {
|
|
1256
|
-
merged.push(segment);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
segments = merged;
|
|
1260
|
-
}
|
|
1261
|
-
return {
|
|
1262
|
-
conversation: { ...conversation, segments },
|
|
1263
|
-
droppedSegments,
|
|
1264
|
-
mergedSegments
|
|
1265
|
-
};
|
|
1266
|
-
}
|
|
1267
|
-
function canMerge(previous, next) {
|
|
1268
|
-
if (previous.speakerKey !== next.speakerKey) return false;
|
|
1269
|
-
const previousEnd = previous.endIso ? Date.parse(previous.endIso) : NaN;
|
|
1270
|
-
const nextStart = next.startIso ? Date.parse(next.startIso) : NaN;
|
|
1271
|
-
if (Number.isNaN(previousEnd) || Number.isNaN(nextStart)) return true;
|
|
1272
|
-
return nextStart - previousEnd <= MERGE_GAP_MS;
|
|
1273
|
-
}
|
|
1274
|
-
function stripFillerTokens(text) {
|
|
1275
|
-
return normalizeWhitespace(text.replace(FILLER_PATTERN, " "));
|
|
1276
|
-
}
|
|
1277
|
-
function collapseImmediateRepeats(text) {
|
|
1278
|
-
const words = text.split(/\s+/).filter((word) => word.length > 0);
|
|
1279
|
-
if (words.length < 2) return text.trim();
|
|
1280
|
-
const out = [];
|
|
1281
|
-
let index = 0;
|
|
1282
|
-
while (index < words.length) {
|
|
1283
|
-
out.push(words[index]);
|
|
1284
|
-
index += 1;
|
|
1285
|
-
let matched = true;
|
|
1286
|
-
while (matched) {
|
|
1287
|
-
matched = false;
|
|
1288
|
-
for (let size = 4; size >= 1; size--) {
|
|
1289
|
-
if (out.length < size || index + size > words.length) continue;
|
|
1290
|
-
const tail = out.slice(-size).join(" ").toLowerCase();
|
|
1291
|
-
if (!/\p{L}/u.test(tail)) continue;
|
|
1292
|
-
const ahead = words.slice(index, index + size).join(" ").toLowerCase();
|
|
1293
|
-
if (tail === ahead) {
|
|
1294
|
-
index += size;
|
|
1295
|
-
matched = true;
|
|
1296
|
-
break;
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
return out.join(" ");
|
|
1302
|
-
}
|
|
1303
|
-
function isLowQualitySegment(text) {
|
|
1304
|
-
const trimmed = text.trim();
|
|
1305
|
-
if (trimmed.length === 0) return true;
|
|
1306
|
-
if (/^(.)\1{4,}$/.test(trimmed)) return true;
|
|
1307
|
-
const letters = trimmed.replace(/[^\p{L}\p{N}]/gu, "");
|
|
1308
|
-
if (letters.length === 0) return true;
|
|
1309
|
-
if (trimmed.length >= 12 && letters.length / trimmed.length < 0.3) {
|
|
1310
|
-
return true;
|
|
1311
|
-
}
|
|
1312
|
-
const words = trimmed.toLowerCase().split(/\s+/);
|
|
1313
|
-
if (words.length >= 5) {
|
|
1314
|
-
const unique = new Set(words);
|
|
1315
|
-
if (unique.size === 1) return true;
|
|
1316
|
-
}
|
|
1317
|
-
return false;
|
|
1318
|
-
}
|
|
1319
|
-
function normalizeWhitespace(text) {
|
|
1320
|
-
return text.replace(/\s+/g, " ").trim();
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
// src/wearables/sync-state.ts
|
|
1324
|
-
import { promises as fsPromises } from "fs";
|
|
1325
|
-
import * as path2 from "path";
|
|
1326
|
-
var MAX_TRACKED_NATIVE_IDS = 5e3;
|
|
1327
|
-
var MAX_TRACKED_DAY_HASHES = 800;
|
|
1328
|
-
function syncStateFilePath(memoryDir) {
|
|
1329
|
-
return path2.join(memoryDir, "state", "wearables", "sync.json");
|
|
1330
|
-
}
|
|
1331
|
-
function emptySyncState() {
|
|
1332
|
-
return { version: 1, sources: {} };
|
|
1333
|
-
}
|
|
1334
|
-
async function loadSyncState(memoryDir) {
|
|
1335
|
-
const filePath = syncStateFilePath(memoryDir);
|
|
1336
|
-
let raw;
|
|
1337
|
-
try {
|
|
1338
|
-
raw = await fsPromises.readFile(filePath, "utf-8");
|
|
1339
|
-
} catch (err) {
|
|
1340
|
-
if (err.code === "ENOENT") {
|
|
1341
|
-
return emptySyncState();
|
|
1342
|
-
}
|
|
1343
|
-
throw err;
|
|
1344
|
-
}
|
|
1345
|
-
let parsed;
|
|
1346
|
-
try {
|
|
1347
|
-
parsed = JSON.parse(raw);
|
|
1348
|
-
} catch {
|
|
1349
|
-
return emptySyncState();
|
|
1350
|
-
}
|
|
1351
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.sources !== "object" || parsed.sources === null) {
|
|
1352
|
-
return emptySyncState();
|
|
1353
|
-
}
|
|
1354
|
-
return { version: 1, sources: parsed.sources };
|
|
1355
|
-
}
|
|
1356
|
-
async function saveSyncState(memoryDir, state) {
|
|
1357
|
-
const filePath = syncStateFilePath(memoryDir);
|
|
1358
|
-
await fsPromises.mkdir(path2.dirname(filePath), { recursive: true });
|
|
1359
|
-
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
|
|
1360
|
-
await fsPromises.writeFile(
|
|
1361
|
-
tmpPath,
|
|
1362
|
-
`${JSON.stringify(state, null, 2)}
|
|
1363
|
-
`,
|
|
1364
|
-
"utf-8"
|
|
1365
|
-
);
|
|
1366
|
-
try {
|
|
1367
|
-
await fsPromises.rename(tmpPath, filePath);
|
|
1368
|
-
} catch (err) {
|
|
1369
|
-
await fsPromises.unlink(tmpPath).catch(() => void 0);
|
|
1370
|
-
throw err;
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
function updateSourceSyncState(state, sourceId, update) {
|
|
1374
|
-
const previous = state.sources[sourceId];
|
|
1375
|
-
const mergedHashes = {
|
|
1376
|
-
...previous?.dayHashes ?? {},
|
|
1377
|
-
...update.dayHashes
|
|
1378
|
-
};
|
|
1379
|
-
const hashKeys = Object.keys(mergedHashes).sort();
|
|
1380
|
-
while (hashKeys.length > MAX_TRACKED_DAY_HASHES) {
|
|
1381
|
-
const oldest = hashKeys.shift();
|
|
1382
|
-
if (oldest === void 0) break;
|
|
1383
|
-
delete mergedHashes[oldest];
|
|
1384
|
-
}
|
|
1385
|
-
const mergedMemoryHashes = {
|
|
1386
|
-
...previous?.memoryDayHashes ?? {},
|
|
1387
|
-
...update.memoryDayHashes ?? {}
|
|
1388
|
-
};
|
|
1389
|
-
for (const day of update.clearMemoryDays ?? []) {
|
|
1390
|
-
if (!(day in (update.memoryDayHashes ?? {}))) {
|
|
1391
|
-
delete mergedMemoryHashes[day];
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
const memoryHashKeys = Object.keys(mergedMemoryHashes).sort();
|
|
1395
|
-
while (memoryHashKeys.length > MAX_TRACKED_DAY_HASHES) {
|
|
1396
|
-
const oldest = memoryHashKeys.shift();
|
|
1397
|
-
if (oldest === void 0) break;
|
|
1398
|
-
delete mergedMemoryHashes[oldest];
|
|
1399
|
-
}
|
|
1400
|
-
const mergedNativeIds = [
|
|
1401
|
-
...previous?.importedNativeMemoryIds ?? [],
|
|
1402
|
-
...update.importedNativeMemoryIds ?? []
|
|
1403
|
-
];
|
|
1404
|
-
const dedupedNativeIds = [...new Set(mergedNativeIds)];
|
|
1405
|
-
const boundedNativeIds = dedupedNativeIds.length > MAX_TRACKED_NATIVE_IDS ? dedupedNativeIds.slice(dedupedNativeIds.length - MAX_TRACKED_NATIVE_IDS) : dedupedNativeIds;
|
|
1406
|
-
const sortedDays = [...update.days].sort();
|
|
1407
|
-
const latestDay = sortedDays[sortedDays.length - 1];
|
|
1408
|
-
const lastDateSynced = latestDay !== void 0 && (!previous || previous.lastDateSynced < latestDay) ? latestDay : previous?.lastDateSynced ?? latestDay ?? "";
|
|
1409
|
-
return {
|
|
1410
|
-
version: 1,
|
|
1411
|
-
sources: {
|
|
1412
|
-
...state.sources,
|
|
1413
|
-
[sourceId]: {
|
|
1414
|
-
lastSyncAt: update.syncedAt,
|
|
1415
|
-
lastDateSynced,
|
|
1416
|
-
dayHashes: mergedHashes,
|
|
1417
|
-
memoryDayHashes: mergedMemoryHashes,
|
|
1418
|
-
importedNativeMemoryIds: boundedNativeIds
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
// src/wearables/pipeline.ts
|
|
1425
|
-
var MAX_PAGES_PER_DAY = 50;
|
|
1426
|
-
var MAX_NATIVE_PAGES = 20;
|
|
1427
|
-
var DEFAULT_SYNC_DAYS = 2;
|
|
1428
|
-
var MAX_SYNC_DAYS = 90;
|
|
1429
|
-
function dateInTimezone(date, timezone) {
|
|
1430
|
-
try {
|
|
1431
|
-
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
1432
|
-
timeZone: timezone,
|
|
1433
|
-
year: "numeric",
|
|
1434
|
-
month: "2-digit",
|
|
1435
|
-
day: "2-digit"
|
|
1436
|
-
}).formatToParts(date);
|
|
1437
|
-
const get = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
1438
|
-
return `${get("year")}-${get("month")}-${get("day")}`;
|
|
1439
|
-
} catch {
|
|
1440
|
-
return date.toISOString().slice(0, 10);
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
function resolveSyncDates(options, timezone, now) {
|
|
1444
|
-
if (options.date !== void 0) {
|
|
1445
|
-
if (!isValidTranscriptDate(options.date)) {
|
|
1446
|
-
throw new WearablesInputError(
|
|
1447
|
-
`wearables sync: invalid date '${options.date}' \u2014 expected YYYY-MM-DD`
|
|
1448
|
-
);
|
|
1449
|
-
}
|
|
1450
|
-
return [options.date];
|
|
1451
|
-
}
|
|
1452
|
-
let days = DEFAULT_SYNC_DAYS;
|
|
1453
|
-
if (options.days !== void 0) {
|
|
1454
|
-
if (!Number.isFinite(options.days) || !Number.isInteger(options.days) || options.days < 1 || options.days > MAX_SYNC_DAYS) {
|
|
1455
|
-
throw new WearablesInputError(
|
|
1456
|
-
`wearables sync: invalid days '${options.days}' \u2014 expected an integer between 1 and ${MAX_SYNC_DAYS}`
|
|
1457
|
-
);
|
|
1458
|
-
}
|
|
1459
|
-
days = options.days;
|
|
1460
|
-
}
|
|
1461
|
-
const dates = [];
|
|
1462
|
-
let cursor = dateInTimezone(now, timezone);
|
|
1463
|
-
for (let count = 0; count < days; count++) {
|
|
1464
|
-
dates.unshift(cursor);
|
|
1465
|
-
cursor = previousIsoDate(cursor);
|
|
1466
|
-
}
|
|
1467
|
-
return dates;
|
|
1468
|
-
}
|
|
1469
|
-
function previousIsoDate(date) {
|
|
1470
|
-
const parsed = /* @__PURE__ */ new Date(`${date}T00:00:00Z`);
|
|
1471
|
-
parsed.setUTCDate(parsed.getUTCDate() - 1);
|
|
1472
|
-
return parsed.toISOString().slice(0, 10);
|
|
1473
|
-
}
|
|
1474
|
-
async function fetchAllConversationsForDate(connector, date, timezone, signal, warnings) {
|
|
1475
|
-
const conversations = [];
|
|
1476
|
-
let cursor = void 0;
|
|
1477
|
-
for (let page = 0; page < MAX_PAGES_PER_DAY; page++) {
|
|
1478
|
-
const result = await connector.fetchConversations({
|
|
1479
|
-
date,
|
|
1480
|
-
timezone,
|
|
1481
|
-
cursor,
|
|
1482
|
-
signal
|
|
1483
|
-
});
|
|
1484
|
-
conversations.push(...result.conversations);
|
|
1485
|
-
if (!result.nextCursor) return { conversations, partial: false };
|
|
1486
|
-
cursor = result.nextCursor;
|
|
1487
|
-
}
|
|
1488
|
-
warnings.push(
|
|
1489
|
-
`${connector.id}: stopped paginating ${date} after ${MAX_PAGES_PER_DAY} pages \u2014 day may be partially synced (every sync refetches and re-warns until the provider day fits the cap)`
|
|
1490
|
-
);
|
|
1491
|
-
return { conversations, partial: true };
|
|
1492
|
-
}
|
|
1493
|
-
var PARTIAL_DAY_MARKER = "\n*Note: pagination safety cap reached during sync \u2014 this day may be incomplete.*\n";
|
|
1494
|
-
function emptyDayBody(sourceId, date) {
|
|
1495
|
-
return `# ${sourceId} transcript \u2014 ${date}
|
|
1496
|
-
|
|
1497
|
-
_No storable conversation content for this day (all segments were elided or dropped)._
|
|
1498
|
-
`;
|
|
1499
|
-
}
|
|
1500
|
-
function cleanDay(raw, sourceId, settings, config, userRedaction, correctionRules) {
|
|
1501
|
-
const out = {
|
|
1502
|
-
conversations: [],
|
|
1503
|
-
segmentsKept: 0,
|
|
1504
|
-
segmentsDropped: 0,
|
|
1505
|
-
redactions: 0,
|
|
1506
|
-
correctionsApplied: 0
|
|
1507
|
-
};
|
|
1508
|
-
for (const conversation of raw) {
|
|
1509
|
-
let current = conversation;
|
|
1510
|
-
if (config.offTheRecordEnabled) {
|
|
1511
|
-
const otr = applyOffTheRecord(current);
|
|
1512
|
-
current = otr.conversation;
|
|
1513
|
-
out.segmentsDropped += otr.droppedSegments;
|
|
1514
|
-
}
|
|
1515
|
-
const cleaned = cleanConversation(current, settings.cleanup);
|
|
1516
|
-
current = cleaned.conversation;
|
|
1517
|
-
out.segmentsDropped += cleaned.droppedSegments;
|
|
1518
|
-
const segments = current.segments.map((segment) => {
|
|
1519
|
-
let text = segment.text;
|
|
1520
|
-
if (config.redactionEnabled) {
|
|
1521
|
-
const redacted = redactText(text, userRedaction);
|
|
1522
|
-
text = redacted.text;
|
|
1523
|
-
out.redactions += redacted.redactions;
|
|
1524
|
-
}
|
|
1525
|
-
const corrected = applyCorrections(text, correctionRules, sourceId);
|
|
1526
|
-
out.correctionsApplied += corrected.applied;
|
|
1527
|
-
return { ...segment, text: corrected.text };
|
|
1528
|
-
});
|
|
1529
|
-
current = { ...current, segments };
|
|
1530
|
-
if (current.segments.length > 0) {
|
|
1531
|
-
out.conversations.push(current);
|
|
1532
|
-
out.segmentsKept += current.segments.length;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
return out;
|
|
1536
|
-
}
|
|
1537
|
-
async function syncWearableSource(connector, settings, config, options, deps) {
|
|
1538
|
-
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
1539
|
-
const timezone = config.timezone ?? defaultTimezone();
|
|
1540
|
-
const dates = resolveSyncDates(options, timezone, now);
|
|
1541
|
-
const summary = {
|
|
1542
|
-
source: connector.id,
|
|
1543
|
-
days: dates,
|
|
1544
|
-
conversations: 0,
|
|
1545
|
-
segmentsKept: 0,
|
|
1546
|
-
segmentsDropped: 0,
|
|
1547
|
-
redactions: 0,
|
|
1548
|
-
correctionsApplied: 0,
|
|
1549
|
-
transcriptsWritten: [],
|
|
1550
|
-
memoriesCreated: 0,
|
|
1551
|
-
memoriesSkipped: 0,
|
|
1552
|
-
nativeMemoriesImported: 0,
|
|
1553
|
-
warnings: []
|
|
1554
|
-
};
|
|
1555
|
-
const registry = await loadSpeakerRegistry(deps.memoryDir);
|
|
1556
|
-
const stateRules = await loadCorrectionsFile(deps.memoryDir);
|
|
1557
|
-
const correctionRules = [
|
|
1558
|
-
...compileCorrectionRules(config.corrections, "wearables.corrections"),
|
|
1559
|
-
...compileCorrectionRules(stateRules, "state corrections")
|
|
1560
|
-
];
|
|
1561
|
-
const userRedaction = compileRedactionPatterns(config.redactionPatterns);
|
|
1562
|
-
let syncState = await loadSyncState(deps.memoryDir);
|
|
1563
|
-
const previousState = syncState.sources[connector.id];
|
|
1564
|
-
const dayHashes = {};
|
|
1565
|
-
const memoryDayHashes = {};
|
|
1566
|
-
const failedMemoryDays = [];
|
|
1567
|
-
const importedNativeIds = [];
|
|
1568
|
-
for (const date of dates) {
|
|
1569
|
-
const fetched = await fetchAllConversationsForDate(
|
|
1570
|
-
connector,
|
|
1571
|
-
date,
|
|
1572
|
-
timezone,
|
|
1573
|
-
options.signal,
|
|
1574
|
-
summary.warnings
|
|
1575
|
-
);
|
|
1576
|
-
const cleaned = cleanDay(
|
|
1577
|
-
fetched.conversations,
|
|
1578
|
-
connector.id,
|
|
1579
|
-
settings,
|
|
1580
|
-
config,
|
|
1581
|
-
userRedaction,
|
|
1582
|
-
correctionRules
|
|
1583
|
-
);
|
|
1584
|
-
summary.conversations += cleaned.conversations.length;
|
|
1585
|
-
summary.segmentsKept += cleaned.segmentsKept;
|
|
1586
|
-
summary.segmentsDropped += cleaned.segmentsDropped;
|
|
1587
|
-
summary.redactions += cleaned.redactions;
|
|
1588
|
-
summary.correctionsApplied += cleaned.correctionsApplied;
|
|
1589
|
-
if (fetched.conversations.length === 0) {
|
|
1590
|
-
const existing = await deps.readDayContentHash(connector.id, date);
|
|
1591
|
-
if (existing !== null) {
|
|
1592
|
-
summary.warnings.push(
|
|
1593
|
-
`${connector.id}: provider returned no conversations for ${date} but a stored transcript exists \u2014 leaving it in place; delete the day file manually if the recordings were intentionally removed upstream`
|
|
1594
|
-
);
|
|
1595
|
-
}
|
|
1596
|
-
continue;
|
|
1597
|
-
}
|
|
1598
|
-
const allElided = cleaned.conversations.length === 0;
|
|
1599
|
-
let body = allElided ? emptyDayBody(connector.id, date) : composeDayTranscriptBody(
|
|
1600
|
-
connector.id,
|
|
1601
|
-
date,
|
|
1602
|
-
timezone,
|
|
1603
|
-
cleaned.conversations,
|
|
1604
|
-
registry
|
|
1605
|
-
);
|
|
1606
|
-
if (fetched.partial && !allElided) {
|
|
1607
|
-
body += PARTIAL_DAY_MARKER;
|
|
1608
|
-
}
|
|
1609
|
-
const bodyHash = hashTranscriptBody(body);
|
|
1610
|
-
const existingHash = await deps.readDayContentHash(connector.id, date);
|
|
1611
|
-
const changed = existingHash !== bodyHash;
|
|
1612
|
-
const shouldWrite = changed && (!allElided || existingHash !== null);
|
|
1613
|
-
if (shouldWrite) {
|
|
1614
|
-
const meta = composeDayTranscriptMeta(
|
|
1615
|
-
connector.id,
|
|
1616
|
-
date,
|
|
1617
|
-
timezone,
|
|
1618
|
-
cleaned.conversations,
|
|
1619
|
-
registry,
|
|
1620
|
-
body,
|
|
1621
|
-
now.toISOString()
|
|
1622
|
-
);
|
|
1623
|
-
await deps.writeDayTranscript(
|
|
1624
|
-
connector.id,
|
|
1625
|
-
date,
|
|
1626
|
-
serializeDayTranscript(meta, body)
|
|
1627
|
-
);
|
|
1628
|
-
summary.transcriptsWritten.push(date);
|
|
1629
|
-
}
|
|
1630
|
-
dayHashes[date] = bodyHash;
|
|
1631
|
-
if (allElided) continue;
|
|
1632
|
-
const memoryPassComplete = previousState?.memoryDayHashes?.[date] === bodyHash;
|
|
1633
|
-
if (settings.memoryMode !== "off" && (changed || options.forceMemories === true || !memoryPassComplete)) {
|
|
1634
|
-
if (!deps.memoryGen) {
|
|
1635
|
-
summary.warnings.push(
|
|
1636
|
-
`${connector.id}: memoryMode is '${settings.memoryMode}' but no extraction engine is available in this context \u2014 transcripts synced, memories skipped`
|
|
1637
|
-
);
|
|
1638
|
-
} else {
|
|
1639
|
-
let passClean = false;
|
|
1640
|
-
try {
|
|
1641
|
-
const generated = await generateWearableMemories(
|
|
1642
|
-
connector.id,
|
|
1643
|
-
date,
|
|
1644
|
-
cleaned.conversations,
|
|
1645
|
-
settings,
|
|
1646
|
-
registry,
|
|
1647
|
-
deps.memoryGen
|
|
1648
|
-
);
|
|
1649
|
-
summary.memoriesCreated += generated.created;
|
|
1650
|
-
summary.memoriesSkipped += generated.skipped;
|
|
1651
|
-
summary.warnings.push(...generated.warnings);
|
|
1652
|
-
passClean = generated.warnings.length === 0;
|
|
1653
|
-
if (config.digestEnabled) {
|
|
1654
|
-
const wrote = await writeDailyDigestMemory(
|
|
1655
|
-
connector.id,
|
|
1656
|
-
date,
|
|
1657
|
-
cleaned.conversations,
|
|
1658
|
-
settings,
|
|
1659
|
-
registry,
|
|
1660
|
-
deps.memoryGen.writer
|
|
1661
|
-
);
|
|
1662
|
-
if (wrote) summary.memoriesCreated += 1;
|
|
1663
|
-
}
|
|
1664
|
-
} catch (err) {
|
|
1665
|
-
passClean = false;
|
|
1666
|
-
summary.warnings.push(
|
|
1667
|
-
`${connector.id}: memory pass failed for ${date}: ${describeErrorForOperator(err)} \u2014 retries on the next sync`
|
|
1668
|
-
);
|
|
1669
|
-
}
|
|
1670
|
-
if (passClean) {
|
|
1671
|
-
memoryDayHashes[date] = bodyHash;
|
|
1672
|
-
} else {
|
|
1673
|
-
failedMemoryDays.push(date);
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
} else if (settings.memoryMode !== "off" && memoryPassComplete) {
|
|
1677
|
-
memoryDayHashes[date] = bodyHash;
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
if (settings.importNativeMemories === "review" && typeof connector.fetchNativeMemories === "function") {
|
|
1681
|
-
if (!deps.memoryGen) {
|
|
1682
|
-
summary.warnings.push(
|
|
1683
|
-
`${connector.id}: importNativeMemories is enabled but no memory writer is available in this context`
|
|
1684
|
-
);
|
|
1685
|
-
} else {
|
|
1686
|
-
const alreadyImported = new Set(
|
|
1687
|
-
previousState?.importedNativeMemoryIds ?? []
|
|
1688
|
-
);
|
|
1689
|
-
let cursor = void 0;
|
|
1690
|
-
for (let page = 0; page < MAX_NATIVE_PAGES; page++) {
|
|
1691
|
-
const result = await connector.fetchNativeMemories({
|
|
1692
|
-
cursor,
|
|
1693
|
-
signal: options.signal
|
|
1694
|
-
});
|
|
1695
|
-
const imported = await importNativeMemories(
|
|
1696
|
-
connector.id,
|
|
1697
|
-
result.memories,
|
|
1698
|
-
alreadyImported,
|
|
1699
|
-
deps.memoryGen.writer
|
|
1700
|
-
);
|
|
1701
|
-
summary.nativeMemoriesImported += imported.imported;
|
|
1702
|
-
importedNativeIds.push(...imported.importedIds);
|
|
1703
|
-
for (const id of imported.importedIds) alreadyImported.add(id);
|
|
1704
|
-
if (!result.nextCursor) break;
|
|
1705
|
-
cursor = result.nextCursor;
|
|
1706
|
-
if (page === MAX_NATIVE_PAGES - 1) {
|
|
1707
|
-
summary.warnings.push(
|
|
1708
|
-
`${connector.id}: stopped native-memory import after ${MAX_NATIVE_PAGES} pages \u2014 remaining items import on the next sync`
|
|
1709
|
-
);
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
if (summary.transcriptsWritten.length > 0 && deps.afterTranscriptsWritten) {
|
|
1715
|
-
try {
|
|
1716
|
-
await deps.afterTranscriptsWritten();
|
|
1717
|
-
} catch (err) {
|
|
1718
|
-
summary.warnings.push(
|
|
1719
|
-
`search reindex failed (transcripts are stored and will index on the next update): ${describeErrorForOperator(err)}`
|
|
1720
|
-
);
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
syncState = updateSourceSyncState(syncState, connector.id, {
|
|
1724
|
-
syncedAt: now.toISOString(),
|
|
1725
|
-
days: dates,
|
|
1726
|
-
dayHashes,
|
|
1727
|
-
memoryDayHashes,
|
|
1728
|
-
clearMemoryDays: failedMemoryDays,
|
|
1729
|
-
importedNativeMemoryIds: importedNativeIds
|
|
1730
|
-
});
|
|
1731
|
-
await saveSyncState(deps.memoryDir, syncState);
|
|
1732
|
-
return summary;
|
|
1733
|
-
}
|
|
1734
|
-
function defaultTimezone() {
|
|
1735
|
-
try {
|
|
1736
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
1737
|
-
} catch {
|
|
1738
|
-
return "UTC";
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
969
|
// src/wearables/registry.ts
|
|
1743
970
|
var registrations = /* @__PURE__ */ new Map();
|
|
1744
971
|
function registerWearableConnector(registration) {
|
|
@@ -1816,12 +1043,15 @@ function isModuleNotFound(err, specifier) {
|
|
|
1816
1043
|
function createWearableMemoryWriter(storage) {
|
|
1817
1044
|
return {
|
|
1818
1045
|
writeMemory: storage.writeMemory.bind(storage),
|
|
1046
|
+
findWearableMemoryByContent: async (content) => await storage.findWearableMemoryByContent(content),
|
|
1047
|
+
promoteWearableMemory: storage.promoteWearableMemory.bind(storage),
|
|
1048
|
+
demoteWearableMemory: storage.demoteWearableMemory.bind(storage),
|
|
1819
1049
|
hasFactContentHash: async (content) => {
|
|
1820
1050
|
if (await storage.hasFactContentHash(content)) return true;
|
|
1821
|
-
const needle = content
|
|
1051
|
+
const needle = stripAttributesSuffix(content);
|
|
1822
1052
|
const memories = await storage.readAllMemories();
|
|
1823
1053
|
return memories.some(
|
|
1824
|
-
(memory) => typeof memory.frontmatter.source === "string" && memory.frontmatter.source.startsWith(`${WEARABLE_SOURCE_PREFIX}:`) && memory.content
|
|
1054
|
+
(memory) => typeof memory.frontmatter.source === "string" && memory.frontmatter.source.startsWith(`${WEARABLE_SOURCE_PREFIX}:`) && stripAttributesSuffix(memory.content) === needle
|
|
1825
1055
|
);
|
|
1826
1056
|
}
|
|
1827
1057
|
};
|
|
@@ -1919,7 +1149,8 @@ var WearablesService = class {
|
|
|
1919
1149
|
}
|
|
1920
1150
|
const memoryGen = this.deps.extract ? {
|
|
1921
1151
|
extract: this.deps.extract,
|
|
1922
|
-
writer: createWearableMemoryWriter(storage)
|
|
1152
|
+
writer: createWearableMemoryWriter(storage),
|
|
1153
|
+
...this.deps.judgeFacts !== void 0 ? { judgeFacts: this.deps.judgeFacts } : {}
|
|
1923
1154
|
} : null;
|
|
1924
1155
|
const summaries = [];
|
|
1925
1156
|
for (const [sourceId, settings] of targets) {
|
|
@@ -1948,8 +1179,51 @@ Install it alongside Remnic:
|
|
|
1948
1179
|
return parseDayTranscript(raw)?.meta.contentHash ?? null;
|
|
1949
1180
|
},
|
|
1950
1181
|
writeDayTranscript: (source, date, serialized) => storage.writeWearableDayTranscript(source, date, serialized),
|
|
1951
|
-
|
|
1952
|
-
memoryGen
|
|
1182
|
+
afterWrites: this.deps.reindexSearch,
|
|
1183
|
+
memoryGen,
|
|
1184
|
+
// Cross-device corroboration evidence (smart mode): other
|
|
1185
|
+
// sources' stored transcripts for the same day...
|
|
1186
|
+
readOtherSourceDayBodies: async (date, excludeSource) => {
|
|
1187
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
1188
|
+
const days = await storage.listWearableTranscriptDays();
|
|
1189
|
+
for (const entry of days) {
|
|
1190
|
+
if (entry.date !== date || entry.source === excludeSource) continue;
|
|
1191
|
+
if (bodies.size >= 4) break;
|
|
1192
|
+
const raw = await storage.readWearableDayTranscript(entry.source, entry.date);
|
|
1193
|
+
if (raw === null) continue;
|
|
1194
|
+
bodies.set(entry.source, parseDayTranscript(raw)?.body ?? raw);
|
|
1195
|
+
}
|
|
1196
|
+
return bodies;
|
|
1197
|
+
},
|
|
1198
|
+
// ...and existing memories for the support boost. Status
|
|
1199
|
+
// resolves through the canonical inferMemoryStatus so rows
|
|
1200
|
+
// archived via `archivedAt` (or an archive/ path) without an
|
|
1201
|
+
// explicit status never count. Explicit allow-list: active
|
|
1202
|
+
// rows AND pending_review rows — a borderline fact observed
|
|
1203
|
+
// again on a later day is repetition signal and the support
|
|
1204
|
+
// boost is how it earns promotion. Rejected/quarantined/
|
|
1205
|
+
// superseded/archived/forgotten rows never count (CLAUDE.md
|
|
1206
|
+
// rule 53). Bodies feed token matching with the
|
|
1207
|
+
// "[Attributes: ...]" enrichment suffix stripped — attribute
|
|
1208
|
+
// metadata must never grant corroboration.
|
|
1209
|
+
listSupportMemories: async () => {
|
|
1210
|
+
const memories = await storage.readAllMemories();
|
|
1211
|
+
const support = [];
|
|
1212
|
+
for (const memory of memories) {
|
|
1213
|
+
const status = inferMemoryStatus(
|
|
1214
|
+
memory.frontmatter,
|
|
1215
|
+
memory.path
|
|
1216
|
+
);
|
|
1217
|
+
if (status !== "active" && status !== "pending_review") {
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
support.push({
|
|
1221
|
+
id: memory.frontmatter.id,
|
|
1222
|
+
content: stripAttributesSuffix(memory.content)
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
return support;
|
|
1226
|
+
}
|
|
1953
1227
|
}
|
|
1954
1228
|
);
|
|
1955
1229
|
summaries.push(summary);
|
|
@@ -2394,7 +1668,7 @@ async function qmdStartupCollectionCheckWithTimeout(promise, controller, label)
|
|
|
2394
1668
|
return await Promise.race([checkedPromise, timeoutPromise]);
|
|
2395
1669
|
}
|
|
2396
1670
|
function defaultWorkspaceDir() {
|
|
2397
|
-
return
|
|
1671
|
+
return path2.join(os.homedir(), ".openclaw", "workspace");
|
|
2398
1672
|
}
|
|
2399
1673
|
function sanitizeSessionKeyForFilename(sessionKey) {
|
|
2400
1674
|
const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -2703,11 +1977,11 @@ function mergeGraphExpandedResults(primary, expanded) {
|
|
|
2703
1977
|
return Array.from(mergedByPath.values());
|
|
2704
1978
|
}
|
|
2705
1979
|
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
2706
|
-
const absolutePath =
|
|
2707
|
-
const rel =
|
|
1980
|
+
const absolutePath = path2.isAbsolute(candidatePath) ? candidatePath : path2.resolve(storageDir, candidatePath);
|
|
1981
|
+
const rel = path2.relative(storageDir, absolutePath);
|
|
2708
1982
|
if (!rel || rel === ".") return null;
|
|
2709
1983
|
if (rel.startsWith("..")) return null;
|
|
2710
|
-
return rel.split(
|
|
1984
|
+
return rel.split(path2.sep).join("/");
|
|
2711
1985
|
}
|
|
2712
1986
|
function normalizeGraphActivationScore(score) {
|
|
2713
1987
|
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
@@ -2849,7 +2123,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
|
|
|
2849
2123
|
for (const mem of allMemsForGraph ?? []) {
|
|
2850
2124
|
const id = mem.frontmatter.id;
|
|
2851
2125
|
if (!id) continue;
|
|
2852
|
-
pathById.set(id,
|
|
2126
|
+
pathById.set(id, path2.relative(storageDir, mem.path));
|
|
2853
2127
|
}
|
|
2854
2128
|
return pathById;
|
|
2855
2129
|
}
|
|
@@ -2857,7 +2131,7 @@ function appendMemoryToGraphContext(options) {
|
|
|
2857
2131
|
if (!Array.isArray(options.allMemsForGraph)) return;
|
|
2858
2132
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
2859
2133
|
options.allMemsForGraph.push({
|
|
2860
|
-
path:
|
|
2134
|
+
path: path2.join(options.storageDir, options.memoryRelPath),
|
|
2861
2135
|
content: options.content,
|
|
2862
2136
|
frontmatter: {
|
|
2863
2137
|
id: options.memoryId,
|
|
@@ -2877,16 +2151,16 @@ function resolvePersistedMemoryRelativePath(options) {
|
|
|
2877
2151
|
const persisted = options.pathById.get(options.memoryId);
|
|
2878
2152
|
if (persisted) return persisted;
|
|
2879
2153
|
if (options.category === "correction") {
|
|
2880
|
-
return
|
|
2154
|
+
return path2.join("corrections", `${options.memoryId}.md`);
|
|
2881
2155
|
}
|
|
2882
2156
|
const subtree = options.category === "procedure" ? "procedures" : options.category === "reasoning_trace" ? "reasoning-traces" : "facts";
|
|
2883
2157
|
const idParts = options.memoryId.split("-");
|
|
2884
2158
|
const maybeTimestamp = Number(idParts[1]);
|
|
2885
2159
|
if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
|
|
2886
2160
|
const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
|
|
2887
|
-
return
|
|
2161
|
+
return path2.join(subtree, day, `${options.memoryId}.md`);
|
|
2888
2162
|
}
|
|
2889
|
-
return
|
|
2163
|
+
return path2.join(subtree, `${options.memoryId}.md`);
|
|
2890
2164
|
}
|
|
2891
2165
|
var Orchestrator = class _Orchestrator {
|
|
2892
2166
|
storage;
|
|
@@ -3006,6 +2280,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3006
2280
|
consolidationObservers = /* @__PURE__ */ new Set();
|
|
3007
2281
|
qmdMaintenanceTimer = null;
|
|
3008
2282
|
wearablesServiceInstance = null;
|
|
2283
|
+
wearablesAutoSyncHandle = null;
|
|
3009
2284
|
qmdMaintenancePending = false;
|
|
3010
2285
|
qmdMaintenanceInFlight = false;
|
|
3011
2286
|
lastQmdEmbedAtMs = 0;
|
|
@@ -3080,6 +2355,10 @@ var Orchestrator = class _Orchestrator {
|
|
|
3080
2355
|
*/
|
|
3081
2356
|
async destroy() {
|
|
3082
2357
|
this.abortDeferredInit();
|
|
2358
|
+
if (this.wearablesAutoSyncHandle) {
|
|
2359
|
+
await this.wearablesAutoSyncHandle.stop();
|
|
2360
|
+
this.wearablesAutoSyncHandle = null;
|
|
2361
|
+
}
|
|
3083
2362
|
if (this.qmdMaintenanceTimer) {
|
|
3084
2363
|
clearTimeout(this.qmdMaintenanceTimer);
|
|
3085
2364
|
this.qmdMaintenanceTimer = null;
|
|
@@ -3324,7 +2603,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3324
2603
|
this.config = config;
|
|
3325
2604
|
this.profiler = new ProfilingCollector({
|
|
3326
2605
|
enabled: config.profilingEnabled,
|
|
3327
|
-
storageDir: config.profilingStorageDir ||
|
|
2606
|
+
storageDir: config.profilingStorageDir || path2.join(config.memoryDir, "profiling"),
|
|
3328
2607
|
maxTraces: config.profilingMaxTraces
|
|
3329
2608
|
});
|
|
3330
2609
|
this.storageRouter = new NamespaceStorageRouter(config);
|
|
@@ -3359,7 +2638,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3359
2638
|
this.compounding = config.compoundingEnabled ? new CompoundingEngine(config, this.storage) : void 0;
|
|
3360
2639
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
3361
2640
|
this.transcript = new TranscriptManager(config);
|
|
3362
|
-
this.conversationIndexDir =
|
|
2641
|
+
this.conversationIndexDir = path2.join(
|
|
3363
2642
|
config.memoryDir,
|
|
3364
2643
|
"conversation-index",
|
|
3365
2644
|
"chunks"
|
|
@@ -3416,7 +2695,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3416
2695
|
this.modelRegistry
|
|
3417
2696
|
);
|
|
3418
2697
|
this.threading = new ThreadingManager(
|
|
3419
|
-
|
|
2698
|
+
path2.join(config.memoryDir, "threads"),
|
|
3420
2699
|
config.threadingGapMinutes
|
|
3421
2700
|
);
|
|
3422
2701
|
this.tmtBuilder = new TmtBuilder(config.memoryDir, {
|
|
@@ -3714,7 +2993,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3714
2993
|
const files = await readdir(wsDir).catch(() => []);
|
|
3715
2994
|
for (const f of files) {
|
|
3716
2995
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
3717
|
-
const fp =
|
|
2996
|
+
const fp = path2.join(wsDir, f);
|
|
3718
2997
|
const s = await stat(fp).catch(() => null);
|
|
3719
2998
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
3720
2999
|
await unlink(fp).catch(() => {
|
|
@@ -3969,6 +3248,36 @@ var Orchestrator = class _Orchestrator {
|
|
|
3969
3248
|
log.warn(`first-start lifecycle migration failed (non-fatal): ${err}`);
|
|
3970
3249
|
}
|
|
3971
3250
|
}
|
|
3251
|
+
if (signal.aborted) return;
|
|
3252
|
+
if (!this.wearablesAutoSyncHandle && this.config.wearables.enabled && this.config.wearables.autoSyncEnabled && Object.values(this.config.wearables.sources).some((source) => source.enabled)) {
|
|
3253
|
+
try {
|
|
3254
|
+
const { startWearablesAutoSync } = await import("./auto-sync-RFADEHIQ.js");
|
|
3255
|
+
if (signal.aborted) return;
|
|
3256
|
+
this.wearablesAutoSyncHandle = startWearablesAutoSync(
|
|
3257
|
+
{
|
|
3258
|
+
intervalMinutes: this.config.wearables.autoSyncIntervalMinutes,
|
|
3259
|
+
days: this.config.wearables.autoSyncDays,
|
|
3260
|
+
deepDays: this.config.wearables.autoSyncDeepDays,
|
|
3261
|
+
...this.config.wearables.timezone !== void 0 ? { timezone: this.config.wearables.timezone } : {}
|
|
3262
|
+
},
|
|
3263
|
+
{
|
|
3264
|
+
sync: (options) => this.getWearablesService().sync(options),
|
|
3265
|
+
log: {
|
|
3266
|
+
info: (message) => log.info(message),
|
|
3267
|
+
warn: (message) => log.warn(message)
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
);
|
|
3271
|
+
log.info(
|
|
3272
|
+
`wearables auto-sync started: every ${this.config.wearables.autoSyncIntervalMinutes}m over ${this.config.wearables.autoSyncDays}d (deep ${this.config.wearables.autoSyncDeepDays}d daily)`
|
|
3273
|
+
);
|
|
3274
|
+
} catch (err) {
|
|
3275
|
+
const { displayErrorDetail } = await import("./runtime/better-sqlite.js");
|
|
3276
|
+
log.warn(
|
|
3277
|
+
`wearables auto-sync failed to start (non-fatal): ${displayErrorDetail(err)}`
|
|
3278
|
+
);
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3972
3281
|
log.info("orchestrator initialized (full \u2014 deferred steps complete)");
|
|
3973
3282
|
}
|
|
3974
3283
|
/**
|
|
@@ -4076,7 +3385,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4076
3385
|
*/
|
|
4077
3386
|
async autoRegisterDaySummaryCron() {
|
|
4078
3387
|
const home = resolveHomeDir();
|
|
4079
|
-
const jobsPath =
|
|
3388
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4080
3389
|
try {
|
|
4081
3390
|
if (!existsSync(jobsPath)) {
|
|
4082
3391
|
log.debug(
|
|
@@ -4100,7 +3409,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4100
3409
|
}
|
|
4101
3410
|
async autoRegisterNightlyGovernanceCron() {
|
|
4102
3411
|
const home = resolveHomeDir();
|
|
4103
|
-
const jobsPath =
|
|
3412
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4104
3413
|
try {
|
|
4105
3414
|
if (!existsSync(jobsPath)) {
|
|
4106
3415
|
log.debug("nightly governance cron: jobs.json not found, skipping auto-register");
|
|
@@ -4122,7 +3431,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4122
3431
|
}
|
|
4123
3432
|
async autoRegisterProceduralMiningCron() {
|
|
4124
3433
|
const home = resolveHomeDir();
|
|
4125
|
-
const jobsPath =
|
|
3434
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4126
3435
|
try {
|
|
4127
3436
|
if (!existsSync(jobsPath)) {
|
|
4128
3437
|
log.debug("procedural mining cron: jobs.json not found, skipping auto-register");
|
|
@@ -4142,7 +3451,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4142
3451
|
}
|
|
4143
3452
|
async autoRegisterContradictionScanCron() {
|
|
4144
3453
|
const home = resolveHomeDir();
|
|
4145
|
-
const jobsPath =
|
|
3454
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4146
3455
|
try {
|
|
4147
3456
|
if (!existsSync(jobsPath)) {
|
|
4148
3457
|
log.debug("contradiction scan cron: jobs.json not found, skipping auto-register");
|
|
@@ -4162,7 +3471,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4162
3471
|
}
|
|
4163
3472
|
async autoRegisterPatternReinforcementCron() {
|
|
4164
3473
|
const home = resolveHomeDir();
|
|
4165
|
-
const jobsPath =
|
|
3474
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4166
3475
|
try {
|
|
4167
3476
|
if (!existsSync(jobsPath)) {
|
|
4168
3477
|
log.debug("pattern reinforcement cron: jobs.json not found, skipping auto-register");
|
|
@@ -4224,7 +3533,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
4224
3533
|
}
|
|
4225
3534
|
async autoRegisterGraphEdgeDecayCron() {
|
|
4226
3535
|
const home = resolveHomeDir();
|
|
4227
|
-
const jobsPath =
|
|
3536
|
+
const jobsPath = path2.join(home, ".openclaw", "cron", "jobs.json");
|
|
4228
3537
|
try {
|
|
4229
3538
|
if (!existsSync(jobsPath)) {
|
|
4230
3539
|
log.debug("graph edge decay cron: jobs.json not found, skipping auto-register");
|
|
@@ -4281,15 +3590,15 @@ ${doc.content}` : doc.content,
|
|
|
4281
3590
|
this.lastFileHygieneRunAtMs = now;
|
|
4282
3591
|
if (hygiene.rotateEnabled) {
|
|
4283
3592
|
for (const rel of hygiene.rotatePaths) {
|
|
4284
|
-
const abs =
|
|
3593
|
+
const abs = path2.isAbsolute(rel) ? rel : path2.join(this.config.workspaceDir, rel);
|
|
4285
3594
|
try {
|
|
4286
3595
|
const raw = await readFile2(abs, "utf-8");
|
|
4287
3596
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
4288
|
-
const archiveDir =
|
|
3597
|
+
const archiveDir = path2.join(
|
|
4289
3598
|
this.config.workspaceDir,
|
|
4290
3599
|
hygiene.archiveDir
|
|
4291
3600
|
);
|
|
4292
|
-
const base =
|
|
3601
|
+
const base = path2.basename(abs);
|
|
4293
3602
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
4294
3603
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
4295
3604
|
filePath: abs,
|
|
@@ -4314,8 +3623,8 @@ ${doc.content}` : doc.content,
|
|
|
4314
3623
|
log.warn(w.message);
|
|
4315
3624
|
}
|
|
4316
3625
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
4317
|
-
const fp =
|
|
4318
|
-
await mkdir2(
|
|
3626
|
+
const fp = path2.join(this.config.memoryDir, hygiene.warningsLogPath);
|
|
3627
|
+
await mkdir2(path2.dirname(fp), { recursive: true });
|
|
4319
3628
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4320
3629
|
const block = `
|
|
4321
3630
|
|
|
@@ -4784,16 +4093,16 @@ ${evidenceText}`
|
|
|
4784
4093
|
const datesToScan = [yesterday, utcToday].filter(
|
|
4785
4094
|
(v, i, a) => a.indexOf(v) === i
|
|
4786
4095
|
);
|
|
4787
|
-
const factsBaseDir =
|
|
4096
|
+
const factsBaseDir = path2.join(storage.dir, "facts");
|
|
4788
4097
|
const MAX_CHARS = 1e5;
|
|
4789
4098
|
const facts = [];
|
|
4790
4099
|
for (const date of datesToScan) {
|
|
4791
|
-
const factsDir =
|
|
4100
|
+
const factsDir = path2.join(factsBaseDir, date);
|
|
4792
4101
|
try {
|
|
4793
4102
|
const entries = await readdir(factsDir, { withFileTypes: true });
|
|
4794
4103
|
for (const entry of entries) {
|
|
4795
4104
|
if (!entry.name.endsWith(".md")) continue;
|
|
4796
|
-
const fullPath =
|
|
4105
|
+
const fullPath = path2.join(factsDir, entry.name);
|
|
4797
4106
|
try {
|
|
4798
4107
|
const raw = await readFile2(fullPath, "utf-8");
|
|
4799
4108
|
const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
@@ -4809,7 +4118,7 @@ ${evidenceText}`
|
|
|
4809
4118
|
facts.push({
|
|
4810
4119
|
path: fullPath,
|
|
4811
4120
|
frontmatter: {
|
|
4812
|
-
id: fm.id ||
|
|
4121
|
+
id: fm.id || path2.basename(entry.name, ".md"),
|
|
4813
4122
|
category: fm.category || "fact",
|
|
4814
4123
|
created: fm.created || "unknown",
|
|
4815
4124
|
updated: fm.updated || fm.created || "unknown",
|
|
@@ -4830,13 +4139,13 @@ ${evidenceText}`
|
|
|
4830
4139
|
(a, b) => a.frontmatter.created < b.frontmatter.created ? -1 : 1
|
|
4831
4140
|
);
|
|
4832
4141
|
const hourlySummaries = [];
|
|
4833
|
-
const hourlyBaseDir =
|
|
4142
|
+
const hourlyBaseDir = path2.join(storage.dir, "summaries", "hourly");
|
|
4834
4143
|
try {
|
|
4835
4144
|
const sessionKeys = await readdir(hourlyBaseDir, { withFileTypes: true });
|
|
4836
4145
|
for (const sk of sessionKeys) {
|
|
4837
4146
|
if (!sk.isDirectory()) continue;
|
|
4838
4147
|
for (const date of datesToScan) {
|
|
4839
|
-
const summaryFile =
|
|
4148
|
+
const summaryFile = path2.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
4840
4149
|
try {
|
|
4841
4150
|
const raw = await readFile2(summaryFile, "utf-8");
|
|
4842
4151
|
if (raw.trim().length > 0) {
|
|
@@ -4934,7 +4243,7 @@ ${evidenceText}`
|
|
|
4934
4243
|
}
|
|
4935
4244
|
async getLastGraphRecallSnapshot(namespace) {
|
|
4936
4245
|
const storage = await this.getStorage(namespace);
|
|
4937
|
-
const snapshotPath =
|
|
4246
|
+
const snapshotPath = path2.join(
|
|
4938
4247
|
storage.dir,
|
|
4939
4248
|
"state",
|
|
4940
4249
|
"last_graph_recall.json"
|
|
@@ -4973,7 +4282,7 @@ ${evidenceText}`
|
|
|
4973
4282
|
}
|
|
4974
4283
|
async getLastIntentSnapshot(namespace) {
|
|
4975
4284
|
const storage = await this.getStorage(namespace);
|
|
4976
|
-
const snapshotPath =
|
|
4285
|
+
const snapshotPath = path2.join(storage.dir, "state", "last_intent.json");
|
|
4977
4286
|
try {
|
|
4978
4287
|
const raw = await readFile2(snapshotPath, "utf-8");
|
|
4979
4288
|
const parsed = JSON.parse(raw);
|
|
@@ -5006,7 +4315,7 @@ ${evidenceText}`
|
|
|
5006
4315
|
}
|
|
5007
4316
|
async getLastQmdRecallSnapshot(namespace) {
|
|
5008
4317
|
const storage = await this.getStorage(namespace);
|
|
5009
|
-
const snapshotPath =
|
|
4318
|
+
const snapshotPath = path2.join(
|
|
5010
4319
|
storage.dir,
|
|
5011
4320
|
"state",
|
|
5012
4321
|
"last_qmd_recall.json"
|
|
@@ -5159,7 +4468,7 @@ ${r.snippet.trim()}
|
|
|
5159
4468
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
5160
4469
|
let total = 0;
|
|
5161
4470
|
for (const entry of entries) {
|
|
5162
|
-
const fullPath =
|
|
4471
|
+
const fullPath = path2.join(dir, entry.name);
|
|
5163
4472
|
if (entry.isDirectory()) {
|
|
5164
4473
|
total += await this.countConversationChunkDocs(fullPath);
|
|
5165
4474
|
continue;
|
|
@@ -6055,7 +5364,7 @@ ${r.snippet.trim()}
|
|
|
6055
5364
|
0
|
|
6056
5365
|
);
|
|
6057
5366
|
seedPaths.push(
|
|
6058
|
-
...seedRelativePaths.map((rel) =>
|
|
5367
|
+
...seedRelativePaths.map((rel) => path2.join(storage.dir, rel))
|
|
6059
5368
|
);
|
|
6060
5369
|
const seedSet = new Set(seedRelativePaths);
|
|
6061
5370
|
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
@@ -6066,7 +5375,7 @@ ${r.snippet.trim()}
|
|
|
6066
5375
|
if (expanded.length === 0) continue;
|
|
6067
5376
|
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
6068
5377
|
if (seedSet.has(candidate.path)) continue;
|
|
6069
|
-
const memoryPath =
|
|
5378
|
+
const memoryPath = path2.resolve(storage.dir, candidate.path);
|
|
6070
5379
|
const memory = await storage.readMemoryByPath(memoryPath);
|
|
6071
5380
|
if (!memory) continue;
|
|
6072
5381
|
if (isArtifactMemoryPath(memory.path)) continue;
|
|
@@ -6090,7 +5399,7 @@ ${r.snippet.trim()}
|
|
|
6090
5399
|
path: memory.path,
|
|
6091
5400
|
score,
|
|
6092
5401
|
namespace,
|
|
6093
|
-
seed:
|
|
5402
|
+
seed: path2.resolve(storage.dir, candidate.seed),
|
|
6094
5403
|
hopDepth: candidate.hopDepth,
|
|
6095
5404
|
decayedWeight: candidate.decayedWeight,
|
|
6096
5405
|
graphType: candidate.graphType,
|
|
@@ -6111,12 +5420,12 @@ ${r.snippet.trim()}
|
|
|
6111
5420
|
}
|
|
6112
5421
|
async recordLastGraphRecallSnapshot(options) {
|
|
6113
5422
|
try {
|
|
6114
|
-
const snapshotPath =
|
|
5423
|
+
const snapshotPath = path2.join(
|
|
6115
5424
|
options.storage.dir,
|
|
6116
5425
|
"state",
|
|
6117
5426
|
"last_graph_recall.json"
|
|
6118
5427
|
);
|
|
6119
|
-
await mkdir2(
|
|
5428
|
+
await mkdir2(path2.dirname(snapshotPath), { recursive: true });
|
|
6120
5429
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6121
5430
|
const totalSeedCount = options.seedPaths.length;
|
|
6122
5431
|
const totalExpandedCount = options.expandedPaths.length;
|
|
@@ -6150,12 +5459,12 @@ ${r.snippet.trim()}
|
|
|
6150
5459
|
}
|
|
6151
5460
|
async recordLastIntentSnapshot(options) {
|
|
6152
5461
|
try {
|
|
6153
|
-
const snapshotPath =
|
|
5462
|
+
const snapshotPath = path2.join(
|
|
6154
5463
|
options.storage.dir,
|
|
6155
5464
|
"state",
|
|
6156
5465
|
"last_intent.json"
|
|
6157
5466
|
);
|
|
6158
|
-
await mkdir2(
|
|
5467
|
+
await mkdir2(path2.dirname(snapshotPath), { recursive: true });
|
|
6159
5468
|
await writeFile2(
|
|
6160
5469
|
snapshotPath,
|
|
6161
5470
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -6167,12 +5476,12 @@ ${r.snippet.trim()}
|
|
|
6167
5476
|
}
|
|
6168
5477
|
async recordLastQmdRecallSnapshot(options) {
|
|
6169
5478
|
try {
|
|
6170
|
-
const snapshotPath =
|
|
5479
|
+
const snapshotPath = path2.join(
|
|
6171
5480
|
options.storage.dir,
|
|
6172
5481
|
"state",
|
|
6173
5482
|
"last_qmd_recall.json"
|
|
6174
5483
|
);
|
|
6175
|
-
await mkdir2(
|
|
5484
|
+
await mkdir2(path2.dirname(snapshotPath), { recursive: true });
|
|
6176
5485
|
await writeFile2(
|
|
6177
5486
|
snapshotPath,
|
|
6178
5487
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -6187,8 +5496,8 @@ ${r.snippet.trim()}
|
|
|
6187
5496
|
const stateDir = await this.resolveStateDirForNamespace(
|
|
6188
5497
|
options.namespace
|
|
6189
5498
|
);
|
|
6190
|
-
const snapshotPath =
|
|
6191
|
-
await mkdir2(
|
|
5499
|
+
const snapshotPath = path2.join(stateDir, "last_intent.json");
|
|
5500
|
+
await mkdir2(path2.dirname(snapshotPath), { recursive: true });
|
|
6192
5501
|
await writeFile2(
|
|
6193
5502
|
snapshotPath,
|
|
6194
5503
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -6200,12 +5509,12 @@ ${r.snippet.trim()}
|
|
|
6200
5509
|
}
|
|
6201
5510
|
async resolveStateDirForNamespace(namespace) {
|
|
6202
5511
|
if (!this.config.namespacesEnabled) {
|
|
6203
|
-
return
|
|
5512
|
+
return path2.join(this.config.memoryDir, "state");
|
|
6204
5513
|
}
|
|
6205
5514
|
if (namespace !== this.config.defaultNamespace) {
|
|
6206
|
-
return
|
|
5515
|
+
return path2.join(this.config.memoryDir, "namespaces", namespace, "state");
|
|
6207
5516
|
}
|
|
6208
|
-
const candidate =
|
|
5517
|
+
const candidate = path2.join(
|
|
6209
5518
|
this.config.memoryDir,
|
|
6210
5519
|
"namespaces",
|
|
6211
5520
|
this.config.defaultNamespace
|
|
@@ -6213,11 +5522,11 @@ ${r.snippet.trim()}
|
|
|
6213
5522
|
try {
|
|
6214
5523
|
const candidateStat = await stat(candidate);
|
|
6215
5524
|
if (candidateStat.isDirectory()) {
|
|
6216
|
-
return
|
|
5525
|
+
return path2.join(candidate, "state");
|
|
6217
5526
|
}
|
|
6218
5527
|
} catch {
|
|
6219
5528
|
}
|
|
6220
|
-
return
|
|
5529
|
+
return path2.join(this.config.memoryDir, "state");
|
|
6221
5530
|
}
|
|
6222
5531
|
buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
|
|
6223
5532
|
return results.slice(0, limit).map((result) => ({
|
|
@@ -6603,7 +5912,7 @@ ${r.snippet.trim()}
|
|
|
6603
5912
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
6604
5913
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
6605
5914
|
const labels = [];
|
|
6606
|
-
const normalizedPath = resultPath.split(
|
|
5915
|
+
const normalizedPath = resultPath.split(path2.sep).join("/");
|
|
6607
5916
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
6608
5917
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
6609
5918
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -7918,11 +7227,11 @@ ${formatted}`;
|
|
|
7918
7227
|
if (!this.config.compactionResetEnabled) return null;
|
|
7919
7228
|
const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
|
|
7920
7229
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
7921
|
-
const signalPath =
|
|
7230
|
+
const signalPath = path2.join(
|
|
7922
7231
|
workspaceDir,
|
|
7923
7232
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
7924
7233
|
);
|
|
7925
|
-
const bootPath =
|
|
7234
|
+
const bootPath = path2.join(workspaceDir, "BOOT.md");
|
|
7926
7235
|
try {
|
|
7927
7236
|
const signalStat = await stat(signalPath).catch(() => null);
|
|
7928
7237
|
if (!signalStat) return null;
|
|
@@ -9798,6 +9107,21 @@ _Context: ${topQuestion.context}_`
|
|
|
9798
9107
|
config: this.config.wearables,
|
|
9799
9108
|
getStorage: async () => await this.getStorageForNamespace(this.bulkImportWriteNamespace()),
|
|
9800
9109
|
extract: (turns) => this.extraction.extract(turns),
|
|
9110
|
+
// Smart memoryMode runs candidates through the SAME extraction
|
|
9111
|
+
// judge (cache + defer counters included) the live extraction
|
|
9112
|
+
// pipeline uses, so wearable facts get identical LLM-as-judge
|
|
9113
|
+
// durability gating.
|
|
9114
|
+
judgeFacts: (candidates) => judgeFactDurability(
|
|
9115
|
+
candidates,
|
|
9116
|
+
this.config,
|
|
9117
|
+
this.localLlm,
|
|
9118
|
+
new FallbackLlmClient(
|
|
9119
|
+
this.config.gatewayConfig,
|
|
9120
|
+
fallbackLlmRuntimeContextFromConfig(this.config)
|
|
9121
|
+
),
|
|
9122
|
+
this.judgeVerdictCache,
|
|
9123
|
+
this.judgeDeferCounts
|
|
9124
|
+
),
|
|
9801
9125
|
searchBackend: {
|
|
9802
9126
|
search: async (query, maxResults) => {
|
|
9803
9127
|
if (!this.qmd.isAvailable()) return null;
|
|
@@ -10388,7 +9712,7 @@ ${normalized}`).digest("hex");
|
|
|
10388
9712
|
);
|
|
10389
9713
|
this.tierMigrationInFlight = true;
|
|
10390
9714
|
try {
|
|
10391
|
-
const coldStorage = new StorageManager(
|
|
9715
|
+
const coldStorage = new StorageManager(path2.join(storage.dir, "cold"));
|
|
10392
9716
|
const [hotMemories, coldMemories] = await Promise.all([
|
|
10393
9717
|
storage.readAllMemories(),
|
|
10394
9718
|
coldStorage.readAllMemories()
|
|
@@ -11591,7 +10915,7 @@ ${normalized}`).digest("hex");
|
|
|
11591
10915
|
const allMems = allMemsForGraph ?? [];
|
|
11592
10916
|
for (const m of allMems) {
|
|
11593
10917
|
if (m.frontmatter.entityRef === entityRef) {
|
|
11594
|
-
const rel =
|
|
10918
|
+
const rel = path2.relative(storage.dir, m.path);
|
|
11595
10919
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
11596
10920
|
}
|
|
11597
10921
|
}
|
|
@@ -11891,7 +11215,7 @@ ${normalized}`).digest("hex");
|
|
|
11891
11215
|
}
|
|
11892
11216
|
if (this.config.semanticConsolidationEnabled) {
|
|
11893
11217
|
try {
|
|
11894
|
-
const stateFilePath =
|
|
11218
|
+
const stateFilePath = path2.join(
|
|
11895
11219
|
this.config.memoryDir,
|
|
11896
11220
|
"state",
|
|
11897
11221
|
"semantic-consolidation-last-run.json"
|
|
@@ -11939,7 +11263,7 @@ ${normalized}`).digest("hex");
|
|
|
11939
11263
|
);
|
|
11940
11264
|
}
|
|
11941
11265
|
if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
|
|
11942
|
-
const stateDir =
|
|
11266
|
+
const stateDir = path2.join(this.config.memoryDir, "state");
|
|
11943
11267
|
await mkdir2(stateDir, { recursive: true });
|
|
11944
11268
|
await writeFile2(
|
|
11945
11269
|
stateFilePath,
|
|
@@ -12434,12 +11758,12 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
12434
11758
|
protectedCategories: this.config.lifecycleProtectedCategories
|
|
12435
11759
|
}
|
|
12436
11760
|
};
|
|
12437
|
-
const metricsPath =
|
|
11761
|
+
const metricsPath = path2.join(
|
|
12438
11762
|
storage.dir,
|
|
12439
11763
|
"state",
|
|
12440
11764
|
"lifecycle-metrics.json"
|
|
12441
11765
|
);
|
|
12442
|
-
await mkdir2(
|
|
11766
|
+
await mkdir2(path2.dirname(metricsPath), { recursive: true });
|
|
12443
11767
|
await writeFile2(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
|
|
12444
11768
|
}
|
|
12445
11769
|
/**
|
|
@@ -12967,7 +12291,7 @@ ${lines.join("\n\n")}`;
|
|
|
12967
12291
|
nsMap = buildMemoryWorthCounterMap(memories);
|
|
12968
12292
|
this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
|
|
12969
12293
|
}
|
|
12970
|
-
for (const [
|
|
12294
|
+
for (const [path3, c] of nsMap) counters.set(path3, c);
|
|
12971
12295
|
} catch (err) {
|
|
12972
12296
|
log.debug("memory-worth: failed to read namespace, skipping", {
|
|
12973
12297
|
namespace: ns,
|
|
@@ -13138,12 +12462,12 @@ ${lines.join("\n\n")}`;
|
|
|
13138
12462
|
*/
|
|
13139
12463
|
semanticDedupScopeFor(targetStorage) {
|
|
13140
12464
|
if (!this.config.namespacesEnabled) return {};
|
|
13141
|
-
const memoryDir =
|
|
13142
|
-
const storageDir =
|
|
12465
|
+
const memoryDir = path2.resolve(this.config.memoryDir);
|
|
12466
|
+
const storageDir = path2.resolve(targetStorage.dir);
|
|
13143
12467
|
if (storageDir === memoryDir) {
|
|
13144
12468
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
13145
12469
|
}
|
|
13146
|
-
let rel =
|
|
12470
|
+
let rel = path2.relative(memoryDir, storageDir);
|
|
13147
12471
|
if (!rel || rel.startsWith("..")) {
|
|
13148
12472
|
log.debug(
|
|
13149
12473
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -13162,7 +12486,7 @@ ${lines.join("\n\n")}`;
|
|
|
13162
12486
|
if (hits.length === 0) return [];
|
|
13163
12487
|
const results = [];
|
|
13164
12488
|
for (const hit of hits) {
|
|
13165
|
-
const fullPath =
|
|
12489
|
+
const fullPath = path2.isAbsolute(hit.path) ? hit.path : path2.join(this.config.memoryDir, hit.path);
|
|
13166
12490
|
const memory = await this.storage.readMemoryByPath(fullPath);
|
|
13167
12491
|
if (!memory) continue;
|
|
13168
12492
|
results.push({
|
|
@@ -13805,8 +13129,8 @@ ${lines.join("\n\n")}`;
|
|
|
13805
13129
|
}
|
|
13806
13130
|
namespaceFromStorageDir(storageDir) {
|
|
13807
13131
|
if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
|
|
13808
|
-
const resolvedStorageDir =
|
|
13809
|
-
const resolvedMemoryDir =
|
|
13132
|
+
const resolvedStorageDir = path2.resolve(storageDir);
|
|
13133
|
+
const resolvedMemoryDir = path2.resolve(this.config.memoryDir);
|
|
13810
13134
|
if (resolvedStorageDir === resolvedMemoryDir)
|
|
13811
13135
|
return this.config.defaultNamespace;
|
|
13812
13136
|
const m = resolvedStorageDir.match(/[\\/]namespaces[\\/]([^\\/]+)$/);
|
|
@@ -13846,27 +13170,6 @@ export {
|
|
|
13846
13170
|
saveTaxonomy,
|
|
13847
13171
|
getTaxonomyDir,
|
|
13848
13172
|
getTaxonomyFilePath,
|
|
13849
|
-
memoryStatusForMode,
|
|
13850
|
-
WEARABLE_SOURCE_PREFIX,
|
|
13851
|
-
wearableSourceLabel,
|
|
13852
|
-
wearableDayTag,
|
|
13853
|
-
buildExtractionTurns,
|
|
13854
|
-
generateWearableMemories,
|
|
13855
|
-
writeDailyDigestMemory,
|
|
13856
|
-
importNativeMemories,
|
|
13857
|
-
cleanConversation,
|
|
13858
|
-
stripFillerTokens,
|
|
13859
|
-
collapseImmediateRepeats,
|
|
13860
|
-
isLowQualitySegment,
|
|
13861
|
-
syncStateFilePath,
|
|
13862
|
-
emptySyncState,
|
|
13863
|
-
loadSyncState,
|
|
13864
|
-
saveSyncState,
|
|
13865
|
-
updateSourceSyncState,
|
|
13866
|
-
dateInTimezone,
|
|
13867
|
-
resolveSyncDates,
|
|
13868
|
-
syncWearableSource,
|
|
13869
|
-
defaultTimezone,
|
|
13870
13173
|
registerWearableConnector,
|
|
13871
13174
|
getWearableConnector,
|
|
13872
13175
|
listWearableConnectors,
|
|
@@ -13903,4 +13206,4 @@ export {
|
|
|
13903
13206
|
resolvePersistedMemoryRelativePath,
|
|
13904
13207
|
Orchestrator
|
|
13905
13208
|
};
|
|
13906
|
-
//# sourceMappingURL=chunk-
|
|
13209
|
+
//# sourceMappingURL=chunk-WLZBVYC6.js.map
|