@remnic/core 9.3.624 → 9.3.625
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +18 -16
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +12 -5
- package/dist/access-http.js +10 -9
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +8 -8
- package/dist/access-schema.d.ts +5 -5
- package/dist/{access-service-CBNEKjzN.d.ts → access-service-C_sfOHsX.d.ts} +26 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +7 -7
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +2 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-7TPH6UZL.js → chunk-2RHI3FGV.js} +540 -17
- package/dist/chunk-2RHI3FGV.js.map +1 -0
- package/dist/{chunk-GYTVOLNX.js → chunk-3MNBW7R7.js} +2 -2
- package/dist/{chunk-QFQQFX2H.js → chunk-3R2UZV3U.js} +2 -2
- package/dist/{chunk-O4UNM6OR.js → chunk-532VCWYW.js} +2 -2
- package/dist/{chunk-2UFQYU5F.js → chunk-57QXN2CS.js} +2 -2
- package/dist/chunk-7WV3F5DQ.js +22 -0
- package/dist/chunk-7WV3F5DQ.js.map +1 -0
- package/dist/{chunk-RKW6QR7W.js → chunk-AZ4RI3QD.js} +1461 -78
- package/dist/chunk-AZ4RI3QD.js.map +1 -0
- package/dist/{chunk-KQFQ3IS5.js → chunk-F3FY3D3S.js} +43 -7
- package/dist/chunk-F3FY3D3S.js.map +1 -0
- package/dist/{chunk-4R4KTDIE.js → chunk-FPNQF475.js} +1 -1
- package/dist/chunk-FPNQF475.js.map +1 -0
- package/dist/{chunk-UGEBPVNI.js → chunk-GE7Q7KXP.js} +2 -2
- package/dist/{chunk-GLWW3EJQ.js → chunk-KB4MFBF5.js} +3 -3
- package/dist/{chunk-5GOMXHLC.js → chunk-KKTXCFD7.js} +255 -1
- package/dist/chunk-KKTXCFD7.js.map +1 -0
- package/dist/{chunk-FH3PPO42.js → chunk-KVFYTRMV.js} +2 -2
- package/dist/{chunk-BNW5NJJH.js → chunk-LQYTQCXM.js} +2 -2
- package/dist/{chunk-AYHXQR53.js → chunk-MVQN73GT.js} +2 -2
- package/dist/{chunk-ZZPIJPPD.js → chunk-N5RGXWLQ.js} +2 -2
- package/dist/chunk-NDAH7BJ5.js +213 -0
- package/dist/chunk-NDAH7BJ5.js.map +1 -0
- package/dist/{chunk-R3OQGYOU.js → chunk-P2D2MM47.js} +2 -2
- package/dist/{chunk-PSUB67YB.js → chunk-PW6GURU3.js} +2 -2
- package/dist/{chunk-W3BKVM64.js → chunk-QDV6VAD4.js} +2 -2
- package/dist/{chunk-3QSU4NFF.js → chunk-QHXW3LZV.js} +3 -3
- package/dist/{chunk-I6UCUHLK.js → chunk-SHV5Y2WU.js} +182 -3
- package/dist/chunk-SHV5Y2WU.js.map +1 -0
- package/dist/{chunk-OZXVGYGZ.js → chunk-STDAAGH7.js} +2 -2
- package/dist/{chunk-FMGWXIES.js → chunk-TZDSNIRO.js} +5 -5
- package/dist/{chunk-2L54V4ZO.js → chunk-UELS6WWF.js} +2 -2
- package/dist/{chunk-PJGB7XRR.js → chunk-UGHUNQ74.js} +502 -134
- package/dist/chunk-UGHUNQ74.js.map +1 -0
- package/dist/{chunk-FG76RDVI.js → chunk-Y3TMFC6I.js} +136 -4
- package/dist/chunk-Y3TMFC6I.js.map +1 -0
- package/dist/{chunk-BPSGLMQ4.js → chunk-YQNADJCT.js} +2 -2
- package/dist/{cli-Cw729yLf.d.ts → cli-EZv6YE6_.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +23 -21
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +307 -9
- package/dist/index.js +155 -29
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +8 -7
- package/dist/{orchestrator-CqWOjfgl.d.ts → orchestrator-CEycaY3M.d.ts} +361 -4
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +13 -11
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +3 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +10 -10
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
- package/dist/{semantic-consolidation-4HkHWgeI.d.ts → semantic-consolidation-FbhPeJjB.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +5 -5
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +19 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/types-D5VRAI04.d.ts +3134 -0
- package/dist/types.d.ts +3 -2862
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +1 -1
- package/src/access-http.ts +167 -0
- package/src/access-mcp.ts +198 -0
- package/src/access-service.ts +65 -0
- package/src/cli.ts +187 -0
- package/src/config.ts +7 -0
- package/src/index.ts +7 -0
- package/src/orchestrator.ts +42 -0
- package/src/storage.ts +106 -0
- package/src/types.ts +5 -0
- package/src/wearables/cleanup.test.ts +134 -0
- package/src/wearables/cleanup.ts +188 -0
- package/src/wearables/cli.test.ts +170 -0
- package/src/wearables/cli.ts +441 -0
- package/src/wearables/config.test.ts +143 -0
- package/src/wearables/config.ts +332 -0
- package/src/wearables/corrections.test.ts +118 -0
- package/src/wearables/corrections.ts +211 -0
- package/src/wearables/day-store.test.ts +143 -0
- package/src/wearables/day-store.ts +238 -0
- package/src/wearables/errors.test.ts +32 -0
- package/src/wearables/errors.ts +29 -0
- package/src/wearables/index.ts +114 -0
- package/src/wearables/memory-gen.test.ts +342 -0
- package/src/wearables/memory-gen.ts +413 -0
- package/src/wearables/pipeline.test.ts +608 -0
- package/src/wearables/pipeline.ts +519 -0
- package/src/wearables/redaction.test.ts +94 -0
- package/src/wearables/redaction.ts +156 -0
- package/src/wearables/registry.test.ts +62 -0
- package/src/wearables/registry.ts +133 -0
- package/src/wearables/service.test.ts +425 -0
- package/src/wearables/service.ts +691 -0
- package/src/wearables/speakers.test.ts +110 -0
- package/src/wearables/speakers.ts +174 -0
- package/src/wearables/storage-io.test.ts +105 -0
- package/src/wearables/sync-state.test.ts +134 -0
- package/src/wearables/sync-state.ts +186 -0
- package/src/wearables/types.ts +285 -0
- package/dist/chunk-4R4KTDIE.js.map +0 -1
- package/dist/chunk-5GOMXHLC.js.map +0 -1
- package/dist/chunk-7TPH6UZL.js.map +0 -1
- package/dist/chunk-FG76RDVI.js.map +0 -1
- package/dist/chunk-I6UCUHLK.js.map +0 -1
- package/dist/chunk-KQFQ3IS5.js.map +0 -1
- package/dist/chunk-PJGB7XRR.js.map +0 -1
- package/dist/chunk-RKW6QR7W.js.map +0 -1
- /package/dist/{chunk-GYTVOLNX.js.map → chunk-3MNBW7R7.js.map} +0 -0
- /package/dist/{chunk-QFQQFX2H.js.map → chunk-3R2UZV3U.js.map} +0 -0
- /package/dist/{chunk-O4UNM6OR.js.map → chunk-532VCWYW.js.map} +0 -0
- /package/dist/{chunk-2UFQYU5F.js.map → chunk-57QXN2CS.js.map} +0 -0
- /package/dist/{chunk-UGEBPVNI.js.map → chunk-GE7Q7KXP.js.map} +0 -0
- /package/dist/{chunk-GLWW3EJQ.js.map → chunk-KB4MFBF5.js.map} +0 -0
- /package/dist/{chunk-FH3PPO42.js.map → chunk-KVFYTRMV.js.map} +0 -0
- /package/dist/{chunk-BNW5NJJH.js.map → chunk-LQYTQCXM.js.map} +0 -0
- /package/dist/{chunk-AYHXQR53.js.map → chunk-MVQN73GT.js.map} +0 -0
- /package/dist/{chunk-ZZPIJPPD.js.map → chunk-N5RGXWLQ.js.map} +0 -0
- /package/dist/{chunk-R3OQGYOU.js.map → chunk-P2D2MM47.js.map} +0 -0
- /package/dist/{chunk-PSUB67YB.js.map → chunk-PW6GURU3.js.map} +0 -0
- /package/dist/{chunk-W3BKVM64.js.map → chunk-QDV6VAD4.js.map} +0 -0
- /package/dist/{chunk-3QSU4NFF.js.map → chunk-QHXW3LZV.js.map} +0 -0
- /package/dist/{chunk-OZXVGYGZ.js.map → chunk-STDAAGH7.js.map} +0 -0
- /package/dist/{chunk-FMGWXIES.js.map → chunk-TZDSNIRO.js.map} +0 -0
- /package/dist/{chunk-2L54V4ZO.js.map → chunk-UELS6WWF.js.map} +0 -0
- /package/dist/{chunk-BPSGLMQ4.js.map → chunk-YQNADJCT.js.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
SPECULATIVE_TTL_DAYS,
|
|
11
11
|
confidenceTier
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-FPNQF475.js";
|
|
13
13
|
import {
|
|
14
14
|
inferMemoryStatus,
|
|
15
15
|
isArchivedMemoryPath,
|
|
@@ -77,8 +77,274 @@ import {
|
|
|
77
77
|
// src/storage.ts
|
|
78
78
|
import { access, readdir, readFile, stat, writeFile, mkdir, unlink, appendFile, open } from "fs/promises";
|
|
79
79
|
import { appendFileSync, createReadStream, mkdirSync, statSync } from "fs";
|
|
80
|
+
import { createHash as createHash2 } from "crypto";
|
|
81
|
+
import path2 from "path";
|
|
82
|
+
|
|
83
|
+
// src/wearables/day-store.ts
|
|
80
84
|
import { createHash } from "crypto";
|
|
81
|
-
|
|
85
|
+
|
|
86
|
+
// src/wearables/speakers.ts
|
|
87
|
+
import { promises as fsPromises } from "fs";
|
|
88
|
+
import * as path from "path";
|
|
89
|
+
var DEFAULT_SELF_NAME = "Me";
|
|
90
|
+
function emptySpeakerRegistry() {
|
|
91
|
+
return { version: 1, selfName: DEFAULT_SELF_NAME, speakers: {} };
|
|
92
|
+
}
|
|
93
|
+
function speakersFilePath(memoryDir) {
|
|
94
|
+
return path.join(memoryDir, "state", "wearables", "speakers.json");
|
|
95
|
+
}
|
|
96
|
+
async function loadSpeakerRegistry(memoryDir) {
|
|
97
|
+
const filePath = speakersFilePath(memoryDir);
|
|
98
|
+
let raw;
|
|
99
|
+
try {
|
|
100
|
+
raw = await fsPromises.readFile(filePath, "utf-8");
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err.code === "ENOENT") {
|
|
103
|
+
return emptySpeakerRegistry();
|
|
104
|
+
}
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
let parsed;
|
|
108
|
+
try {
|
|
109
|
+
parsed = JSON.parse(raw);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`wearables speakers file is not valid JSON (state/wearables/speakers.json): ${err instanceof Error ? err.message : String(err)}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.speakers !== "object" || parsed.speakers === null) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
'wearables speakers file has an unexpected shape (state/wearables/speakers.json); expected {"version":1,"selfName":"...","speakers":{}}'
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const registry = parsed;
|
|
121
|
+
return {
|
|
122
|
+
version: 1,
|
|
123
|
+
selfName: typeof registry.selfName === "string" && registry.selfName.trim().length > 0 ? registry.selfName.trim() : DEFAULT_SELF_NAME,
|
|
124
|
+
speakers: registry.speakers
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async function saveSpeakerRegistry(memoryDir, registry) {
|
|
128
|
+
const filePath = speakersFilePath(memoryDir);
|
|
129
|
+
await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
|
|
130
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
|
|
131
|
+
await fsPromises.writeFile(
|
|
132
|
+
tmpPath,
|
|
133
|
+
`${JSON.stringify(registry, null, 2)}
|
|
134
|
+
`,
|
|
135
|
+
"utf-8"
|
|
136
|
+
);
|
|
137
|
+
try {
|
|
138
|
+
await fsPromises.rename(tmpPath, filePath);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
await fsPromises.unlink(tmpPath).catch(() => void 0);
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function speakerRegistryKey(sourceId, speakerKey) {
|
|
145
|
+
return `${sourceId}:${speakerKey}`;
|
|
146
|
+
}
|
|
147
|
+
function resolveSpeaker(sourceId, segment, registry) {
|
|
148
|
+
const override = registry.speakers[speakerRegistryKey(sourceId, segment.speakerKey)];
|
|
149
|
+
if (override) {
|
|
150
|
+
const isSelf = override.isSelf === true;
|
|
151
|
+
return {
|
|
152
|
+
label: isSelf ? `${override.name} (you)` : override.name,
|
|
153
|
+
isSelf
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (segment.isWearer === true) {
|
|
157
|
+
return { label: `${registry.selfName} (you)`, isSelf: true };
|
|
158
|
+
}
|
|
159
|
+
if (typeof segment.speakerName === "string" && segment.speakerName.trim().length > 0) {
|
|
160
|
+
return { label: segment.speakerName.trim(), isSelf: false };
|
|
161
|
+
}
|
|
162
|
+
const key = segment.speakerKey.trim();
|
|
163
|
+
if (/^\d+$/.test(key)) {
|
|
164
|
+
return { label: `Speaker ${key}`, isSelf: false };
|
|
165
|
+
}
|
|
166
|
+
return { label: key.length > 0 ? key : "Unknown speaker", isSelf: false };
|
|
167
|
+
}
|
|
168
|
+
function distinctSpeakerLabels(sourceId, segments, registry) {
|
|
169
|
+
const labels = [];
|
|
170
|
+
const seen = /* @__PURE__ */ new Set();
|
|
171
|
+
for (const segment of segments) {
|
|
172
|
+
const { label } = resolveSpeaker(sourceId, segment, registry);
|
|
173
|
+
if (!seen.has(label)) {
|
|
174
|
+
seen.add(label);
|
|
175
|
+
labels.push(label);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return labels;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/wearables/day-store.ts
|
|
182
|
+
var WEARABLES_DIR_NAME = "wearables";
|
|
183
|
+
var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
184
|
+
function isValidTranscriptDate(date) {
|
|
185
|
+
if (!DATE_PATTERN.test(date)) return false;
|
|
186
|
+
const parsed = /* @__PURE__ */ new Date(`${date}T00:00:00Z`);
|
|
187
|
+
return !Number.isNaN(parsed.getTime()) && parsed.toISOString().slice(0, 10) === date;
|
|
188
|
+
}
|
|
189
|
+
function hashTranscriptBody(body) {
|
|
190
|
+
return createHash("sha256").update(body, "utf-8").digest("hex");
|
|
191
|
+
}
|
|
192
|
+
function formatClockTime(iso, timezone) {
|
|
193
|
+
if (!iso) return "--:--";
|
|
194
|
+
const ms = Date.parse(iso);
|
|
195
|
+
if (Number.isNaN(ms)) return "--:--";
|
|
196
|
+
try {
|
|
197
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
198
|
+
timeZone: timezone,
|
|
199
|
+
hour12: false,
|
|
200
|
+
hour: "2-digit",
|
|
201
|
+
minute: "2-digit"
|
|
202
|
+
}).format(new Date(ms));
|
|
203
|
+
} catch {
|
|
204
|
+
return new Date(ms).toISOString().slice(11, 16);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function conversationDurationMinutes(conversation) {
|
|
208
|
+
const start = Date.parse(conversation.startIso);
|
|
209
|
+
const end = conversation.endIso ? Date.parse(conversation.endIso) : NaN;
|
|
210
|
+
if (Number.isNaN(start) || Number.isNaN(end) || end <= start) return 0;
|
|
211
|
+
return (end - start) / 6e4;
|
|
212
|
+
}
|
|
213
|
+
function composeDayTranscriptBody(sourceId, date, timezone, conversations, registry) {
|
|
214
|
+
const lines = [];
|
|
215
|
+
lines.push(`# ${sourceId} transcript \u2014 ${date}`);
|
|
216
|
+
lines.push("");
|
|
217
|
+
const ordered = [...conversations].sort((a, b) => {
|
|
218
|
+
const aMs = Date.parse(a.startIso);
|
|
219
|
+
const bMs = Date.parse(b.startIso);
|
|
220
|
+
if (aMs < bMs) return -1;
|
|
221
|
+
if (aMs > bMs) return 1;
|
|
222
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
223
|
+
});
|
|
224
|
+
for (const conversation of ordered) {
|
|
225
|
+
const start = formatClockTime(conversation.startIso, timezone);
|
|
226
|
+
const end = formatClockTime(conversation.endIso, timezone);
|
|
227
|
+
const title = conversation.title?.trim();
|
|
228
|
+
const heading = title && title.length > 0 ? ` \xB7 ${title}` : "";
|
|
229
|
+
lines.push(`## ${start}\u2013${end}${heading} (conversation ${conversation.id})`);
|
|
230
|
+
if (conversation.location) {
|
|
231
|
+
lines.push(`*Location: ${conversation.location}*`);
|
|
232
|
+
}
|
|
233
|
+
lines.push("");
|
|
234
|
+
for (const segment of conversation.segments) {
|
|
235
|
+
const { label } = resolveSpeaker(sourceId, segment, registry);
|
|
236
|
+
const at = formatClockTime(segment.startIso, timezone);
|
|
237
|
+
lines.push(`**${label}** [${at}]: ${segment.text}`);
|
|
238
|
+
}
|
|
239
|
+
lines.push("");
|
|
240
|
+
}
|
|
241
|
+
return `${lines.join("\n").trimEnd()}
|
|
242
|
+
`;
|
|
243
|
+
}
|
|
244
|
+
function composeDayTranscriptMeta(sourceId, date, timezone, conversations, registry, body, syncedAt) {
|
|
245
|
+
const allSegments = conversations.flatMap((c) => c.segments);
|
|
246
|
+
const durationMinutes = Math.round(
|
|
247
|
+
conversations.reduce((sum, c) => sum + conversationDurationMinutes(c), 0)
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
kind: "wearable-transcript",
|
|
251
|
+
source: sourceId,
|
|
252
|
+
date,
|
|
253
|
+
timezone,
|
|
254
|
+
conversationCount: conversations.length,
|
|
255
|
+
segmentCount: allSegments.length,
|
|
256
|
+
speakers: distinctSpeakerLabels(sourceId, allSegments, registry),
|
|
257
|
+
durationMinutes,
|
|
258
|
+
contentHash: hashTranscriptBody(body),
|
|
259
|
+
syncedAt
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function serializeDayTranscript(meta, body) {
|
|
263
|
+
const lines = ["---"];
|
|
264
|
+
lines.push(`kind: ${meta.kind}`);
|
|
265
|
+
lines.push(`source: ${JSON.stringify(meta.source)}`);
|
|
266
|
+
lines.push(`date: ${JSON.stringify(meta.date)}`);
|
|
267
|
+
lines.push(`timezone: ${JSON.stringify(meta.timezone)}`);
|
|
268
|
+
lines.push(`conversationCount: ${meta.conversationCount}`);
|
|
269
|
+
lines.push(`segmentCount: ${meta.segmentCount}`);
|
|
270
|
+
if (meta.speakers.length === 0) {
|
|
271
|
+
lines.push("speakers: []");
|
|
272
|
+
} else {
|
|
273
|
+
lines.push("speakers:");
|
|
274
|
+
for (const speaker of meta.speakers) {
|
|
275
|
+
lines.push(` - ${JSON.stringify(speaker)}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
lines.push(`durationMinutes: ${meta.durationMinutes}`);
|
|
279
|
+
lines.push(`contentHash: ${JSON.stringify(meta.contentHash)}`);
|
|
280
|
+
lines.push(`syncedAt: ${JSON.stringify(meta.syncedAt)}`);
|
|
281
|
+
lines.push("---");
|
|
282
|
+
lines.push("");
|
|
283
|
+
return `${lines.join("\n")}${body}`;
|
|
284
|
+
}
|
|
285
|
+
function parseDayTranscript(raw) {
|
|
286
|
+
if (!raw.startsWith("---\n")) return null;
|
|
287
|
+
const closeIndex = raw.indexOf("\n---\n", 4);
|
|
288
|
+
if (closeIndex === -1) return null;
|
|
289
|
+
const header = raw.slice(4, closeIndex);
|
|
290
|
+
const body = raw.slice(closeIndex + 5).replace(/^\n/, "");
|
|
291
|
+
const scalars = /* @__PURE__ */ new Map();
|
|
292
|
+
const speakers = [];
|
|
293
|
+
let inSpeakers = false;
|
|
294
|
+
for (const line of header.split("\n")) {
|
|
295
|
+
if (inSpeakers) {
|
|
296
|
+
const item = line.match(/^ {2}- (.*)$/);
|
|
297
|
+
if (item) {
|
|
298
|
+
speakers.push(parseYamlScalar(item[1]));
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
inSpeakers = false;
|
|
302
|
+
}
|
|
303
|
+
if (line === "speakers:") {
|
|
304
|
+
inSpeakers = true;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
if (line === "speakers: []") continue;
|
|
308
|
+
const match = line.match(/^([A-Za-z][A-Za-z0-9]*): (.*)$/);
|
|
309
|
+
if (match) scalars.set(match[1], parseYamlScalar(match[2]));
|
|
310
|
+
}
|
|
311
|
+
if (scalars.get("kind") !== "wearable-transcript") return null;
|
|
312
|
+
const source = scalars.get("source");
|
|
313
|
+
const date = scalars.get("date");
|
|
314
|
+
if (!source || !date) return null;
|
|
315
|
+
const meta = {
|
|
316
|
+
kind: "wearable-transcript",
|
|
317
|
+
source,
|
|
318
|
+
date,
|
|
319
|
+
timezone: scalars.get("timezone") ?? "UTC",
|
|
320
|
+
conversationCount: parseNonNegativeInt(scalars.get("conversationCount")),
|
|
321
|
+
segmentCount: parseNonNegativeInt(scalars.get("segmentCount")),
|
|
322
|
+
speakers,
|
|
323
|
+
durationMinutes: parseNonNegativeInt(scalars.get("durationMinutes")),
|
|
324
|
+
contentHash: scalars.get("contentHash") ?? "",
|
|
325
|
+
syncedAt: scalars.get("syncedAt") ?? ""
|
|
326
|
+
};
|
|
327
|
+
return { meta, body };
|
|
328
|
+
}
|
|
329
|
+
function parseYamlScalar(value) {
|
|
330
|
+
const trimmed = value.trim();
|
|
331
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length >= 2) {
|
|
332
|
+
try {
|
|
333
|
+
const parsed = JSON.parse(trimmed);
|
|
334
|
+
if (typeof parsed === "string") return parsed;
|
|
335
|
+
} catch {
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return trimmed;
|
|
339
|
+
}
|
|
340
|
+
function parseNonNegativeInt(value) {
|
|
341
|
+
if (value === void 0) return 0;
|
|
342
|
+
const parsed = Number(value);
|
|
343
|
+
if (!Number.isFinite(parsed) || parsed < 0) return 0;
|
|
344
|
+
return Math.floor(parsed);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/storage.ts
|
|
82
348
|
var ARTIFACT_SEARCH_STOPWORDS = /* @__PURE__ */ new Set([
|
|
83
349
|
"a",
|
|
84
350
|
"an",
|
|
@@ -662,17 +928,17 @@ var KNOWN_ENTITY_FILENAME_PREFIXES = /* @__PURE__ */ new Set([
|
|
|
662
928
|
"topic"
|
|
663
929
|
]);
|
|
664
930
|
function inferEntityTypeFromFilename(pathRel) {
|
|
665
|
-
const basename =
|
|
931
|
+
const basename = path2.basename(pathRel, ".md").toLowerCase();
|
|
666
932
|
const separator = basename.indexOf("-");
|
|
667
933
|
if (separator <= 0) return void 0;
|
|
668
934
|
const candidate = basename.slice(0, separator);
|
|
669
935
|
return KNOWN_ENTITY_FILENAME_PREFIXES.has(candidate) ? candidate : void 0;
|
|
670
936
|
}
|
|
671
937
|
function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
|
|
672
|
-
const normalizedPath = pathRel.split(
|
|
938
|
+
const normalizedPath = pathRel.split(path2.sep).join("/");
|
|
673
939
|
let normalizedFrontmatter = frontmatter;
|
|
674
940
|
if (normalizedPath === "entities" || normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/")) {
|
|
675
|
-
const basename =
|
|
941
|
+
const basename = path2.basename(pathRel, ".md");
|
|
676
942
|
const inferredType = inferEntityTypeFromContent(content) || inferEntityTypeFromFilename(pathRel) || "entity";
|
|
677
943
|
const existingTags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
|
|
678
944
|
normalizedFrontmatter = {
|
|
@@ -739,8 +1005,8 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
739
1005
|
secureStoreKeyProvider;
|
|
740
1006
|
secureStoreWriteKeyProvider;
|
|
741
1007
|
memoryDir;
|
|
742
|
-
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir =
|
|
743
|
-
this.filePath =
|
|
1008
|
+
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path2.dirname(stateDir)) {
|
|
1009
|
+
this.filePath = path2.join(stateDir, "fact-hashes.txt");
|
|
744
1010
|
this.secureStoreKeyProvider = secureStoreKeyProvider;
|
|
745
1011
|
this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
|
|
746
1012
|
this.memoryDir = memoryDir;
|
|
@@ -787,7 +1053,7 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
787
1053
|
/** Persist index to disk if changed. */
|
|
788
1054
|
async save() {
|
|
789
1055
|
if (!this.dirty) return;
|
|
790
|
-
await mkdir(
|
|
1056
|
+
await mkdir(path2.dirname(this.filePath), { recursive: true });
|
|
791
1057
|
await writeMaybeEncryptedFile(
|
|
792
1058
|
this.filePath,
|
|
793
1059
|
[...this.hashes].join("\n") + "\n",
|
|
@@ -839,7 +1105,7 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
839
1105
|
/** Normalize content and compute SHA-256 hash. */
|
|
840
1106
|
static computeHash(content) {
|
|
841
1107
|
const normalized = _ContentHashIndex.normalizeContent(content);
|
|
842
|
-
return
|
|
1108
|
+
return createHash2("sha256").update(normalized).digest("hex");
|
|
843
1109
|
}
|
|
844
1110
|
};
|
|
845
1111
|
function normalizeAttributePairs(pairs) {
|
|
@@ -1330,7 +1596,7 @@ function fingerprintEntityStructuredFacts(entity) {
|
|
|
1330
1596
|
facts: normalizeStructuredSectionFacts(section.facts).slice().sort((left, right) => left.localeCompare(right))
|
|
1331
1597
|
})).filter((section) => section.facts.length > 0).sort((left, right) => left.key.localeCompare(right.key) || left.title.localeCompare(right.title) || left.facts.join("\n").localeCompare(right.facts.join("\n")));
|
|
1332
1598
|
if (normalizedSections.length === 0) return void 0;
|
|
1333
|
-
return
|
|
1599
|
+
return createHash2("sha256").update(JSON.stringify(normalizedSections)).digest("hex");
|
|
1334
1600
|
}
|
|
1335
1601
|
function isEntitySynthesisStale(entity) {
|
|
1336
1602
|
const structuredFactCount = countEntityStructuredFacts(entity);
|
|
@@ -1844,7 +2110,7 @@ var StorageManager = class _StorageManager {
|
|
|
1844
2110
|
void 0,
|
|
1845
2111
|
this.baseDir
|
|
1846
2112
|
);
|
|
1847
|
-
const rel =
|
|
2113
|
+
const rel = path2.relative(this.baseDir, filePath).split(path2.sep).join("/");
|
|
1848
2114
|
return `${rel}:${version.versionId}`;
|
|
1849
2115
|
} catch (err) {
|
|
1850
2116
|
log.warn(
|
|
@@ -1859,13 +2125,13 @@ var StorageManager = class _StorageManager {
|
|
|
1859
2125
|
}
|
|
1860
2126
|
identityFilePath(workspaceDir, namespace) {
|
|
1861
2127
|
const rawNamespace = typeof namespace === "string" ? namespace.trim() : "";
|
|
1862
|
-
if (!rawNamespace) return
|
|
2128
|
+
if (!rawNamespace) return path2.join(workspaceDir, "IDENTITY.md");
|
|
1863
2129
|
const safeNamespace = rawNamespace.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
1864
|
-
return
|
|
2130
|
+
return path2.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
|
|
1865
2131
|
}
|
|
1866
2132
|
versionFilePath(kind) {
|
|
1867
2133
|
const fileName = kind === "memory-status" ? ".memory-status-version.log" : kind === "artifact-write" ? ".artifact-write-version.log" : ".cold-write-version.log";
|
|
1868
|
-
return
|
|
2134
|
+
return path2.join(this.stateDir, fileName);
|
|
1869
2135
|
}
|
|
1870
2136
|
bumpSharedVersion(kind, fallbackMap) {
|
|
1871
2137
|
const filePath = this.versionFilePath(kind);
|
|
@@ -1901,26 +2167,113 @@ var StorageManager = class _StorageManager {
|
|
|
1901
2167
|
getArtifactWriteVersion() {
|
|
1902
2168
|
return this.readSharedVersion("artifact-write", _StorageManager.artifactWriteVersionByDir);
|
|
1903
2169
|
}
|
|
2170
|
+
// -------------------------------------------------------------------------
|
|
2171
|
+
// Wearable day transcripts
|
|
2172
|
+
//
|
|
2173
|
+
// Stored under `<baseDir>/wearables/<source>/<YYYY-MM-DD>.md` — outside
|
|
2174
|
+
// the memory scan roots (never surfaces as a memory) but inside the QMD
|
|
2175
|
+
// collection root (full-text searchable). IO lives here so transcripts
|
|
2176
|
+
// inherit the same encrypted-at-rest + atomic-write semantics as
|
|
2177
|
+
// memories.
|
|
2178
|
+
// -------------------------------------------------------------------------
|
|
2179
|
+
get wearablesDir() {
|
|
2180
|
+
return path2.join(this.baseDir, WEARABLES_DIR_NAME);
|
|
2181
|
+
}
|
|
2182
|
+
/**
|
|
2183
|
+
* Resolve the on-disk path for a source/day transcript. Throws on
|
|
2184
|
+
* malformed inputs — source ids and dates reach this from CLI/MCP/HTTP
|
|
2185
|
+
* surfaces and must never become path traversal.
|
|
2186
|
+
*/
|
|
2187
|
+
wearableTranscriptPath(sourceId, date) {
|
|
2188
|
+
if (typeof sourceId !== "string" || !/^[a-z][a-z0-9-]{0,63}$/.test(sourceId)) {
|
|
2189
|
+
throw new Error(
|
|
2190
|
+
`invalid wearable source id '${String(sourceId)}' \u2014 expected lowercase letters, digits, and dashes`
|
|
2191
|
+
);
|
|
2192
|
+
}
|
|
2193
|
+
if (!isValidTranscriptDate(date)) {
|
|
2194
|
+
throw new Error(
|
|
2195
|
+
`invalid wearable transcript date '${String(date)}' \u2014 expected YYYY-MM-DD`
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
return path2.join(this.wearablesDir, sourceId, `${date}.md`);
|
|
2199
|
+
}
|
|
2200
|
+
async writeWearableDayTranscript(sourceId, date, serialized) {
|
|
2201
|
+
const targetPath = this.wearableTranscriptPath(sourceId, date);
|
|
2202
|
+
await writeMaybeEncryptedFile(targetPath, serialized, this.resolveWriteKey(), {}, this.baseDir);
|
|
2203
|
+
}
|
|
2204
|
+
/** Read a stored day transcript; null when the day has no file. */
|
|
2205
|
+
async readWearableDayTranscript(sourceId, date) {
|
|
2206
|
+
const targetPath = this.wearableTranscriptPath(sourceId, date);
|
|
2207
|
+
try {
|
|
2208
|
+
return await readMaybeEncryptedFile(targetPath, this._secureStoreKey, this.baseDir);
|
|
2209
|
+
} catch (err) {
|
|
2210
|
+
if (err.code === "ENOENT") return null;
|
|
2211
|
+
throw err;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
/**
|
|
2215
|
+
* List stored transcript days, newest first, optionally scoped to one
|
|
2216
|
+
* source. Non-transcript files in the tree are ignored.
|
|
2217
|
+
*/
|
|
2218
|
+
async listWearableTranscriptDays(sourceId) {
|
|
2219
|
+
const days = [];
|
|
2220
|
+
let sources;
|
|
2221
|
+
if (sourceId !== void 0) {
|
|
2222
|
+
sources = [sourceId];
|
|
2223
|
+
} else {
|
|
2224
|
+
try {
|
|
2225
|
+
const entries = await readdir(this.wearablesDir, { withFileTypes: true });
|
|
2226
|
+
sources = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
2227
|
+
} catch (err) {
|
|
2228
|
+
if (err.code === "ENOENT") return [];
|
|
2229
|
+
throw err;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
for (const source of sources) {
|
|
2233
|
+
if (!/^[a-z][a-z0-9-]{0,63}$/.test(source)) continue;
|
|
2234
|
+
let entries;
|
|
2235
|
+
try {
|
|
2236
|
+
entries = await readdir(path2.join(this.wearablesDir, source));
|
|
2237
|
+
} catch (err) {
|
|
2238
|
+
if (err.code === "ENOENT") continue;
|
|
2239
|
+
throw err;
|
|
2240
|
+
}
|
|
2241
|
+
for (const entry of entries) {
|
|
2242
|
+
if (!entry.endsWith(".md")) continue;
|
|
2243
|
+
const date = entry.slice(0, -3);
|
|
2244
|
+
if (!isValidTranscriptDate(date)) continue;
|
|
2245
|
+
days.push({ source, date });
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
days.sort((a, b) => {
|
|
2249
|
+
if (a.date > b.date) return -1;
|
|
2250
|
+
if (a.date < b.date) return 1;
|
|
2251
|
+
if (a.source < b.source) return -1;
|
|
2252
|
+
if (a.source > b.source) return 1;
|
|
2253
|
+
return 0;
|
|
2254
|
+
});
|
|
2255
|
+
return days;
|
|
2256
|
+
}
|
|
1904
2257
|
get factsDir() {
|
|
1905
|
-
return
|
|
2258
|
+
return path2.join(this.baseDir, "facts");
|
|
1906
2259
|
}
|
|
1907
2260
|
get correctionsDir() {
|
|
1908
|
-
return
|
|
2261
|
+
return path2.join(this.baseDir, "corrections");
|
|
1909
2262
|
}
|
|
1910
2263
|
get proceduresDir() {
|
|
1911
|
-
return
|
|
2264
|
+
return path2.join(this.baseDir, "procedures");
|
|
1912
2265
|
}
|
|
1913
2266
|
get reasoningTracesDir() {
|
|
1914
|
-
return
|
|
2267
|
+
return path2.join(this.baseDir, "reasoning-traces");
|
|
1915
2268
|
}
|
|
1916
2269
|
get entitiesDir() {
|
|
1917
|
-
return
|
|
2270
|
+
return path2.join(this.baseDir, "entities");
|
|
1918
2271
|
}
|
|
1919
2272
|
resolveEntityFilePath(name) {
|
|
1920
2273
|
if (typeof name !== "string") return null;
|
|
1921
|
-
const filePath =
|
|
1922
|
-
const relative =
|
|
1923
|
-
if (relative === "" || relative.startsWith("..") ||
|
|
2274
|
+
const filePath = path2.resolve(this.entitiesDir, `${name}.md`);
|
|
2275
|
+
const relative = path2.relative(this.entitiesDir, filePath);
|
|
2276
|
+
if (relative === "" || relative.startsWith("..") || path2.isAbsolute(relative)) {
|
|
1924
2277
|
return null;
|
|
1925
2278
|
}
|
|
1926
2279
|
return filePath;
|
|
@@ -1932,10 +2285,10 @@ var StorageManager = class _StorageManager {
|
|
|
1932
2285
|
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir);
|
|
1933
2286
|
}
|
|
1934
2287
|
assertManagedStoragePath(filePath, method) {
|
|
1935
|
-
const resolved =
|
|
1936
|
-
const base =
|
|
1937
|
-
const rel =
|
|
1938
|
-
if (rel === "" || rel === ".." || rel.startsWith(`..${
|
|
2288
|
+
const resolved = path2.resolve(filePath);
|
|
2289
|
+
const base = path2.resolve(this.baseDir);
|
|
2290
|
+
const rel = path2.relative(base, resolved);
|
|
2291
|
+
if (rel === "" || rel === ".." || rel.startsWith(`..${path2.sep}`) || path2.isAbsolute(rel)) {
|
|
1939
2292
|
throw new Error(`${method}: file path escapes memory dir`);
|
|
1940
2293
|
}
|
|
1941
2294
|
return resolved;
|
|
@@ -1947,7 +2300,7 @@ var StorageManager = class _StorageManager {
|
|
|
1947
2300
|
async digestOfflineSyncFile(filePath) {
|
|
1948
2301
|
const target = this.assertManagedStoragePath(filePath, "storage.digestOfflineSyncFile");
|
|
1949
2302
|
const st = await stat(target);
|
|
1950
|
-
const relPath =
|
|
2303
|
+
const relPath = path2.relative(this.baseDir, target).split(path2.sep).join("/");
|
|
1951
2304
|
const cache = await this.loadOfflineSyncDigestCache();
|
|
1952
2305
|
const cached = cache.get(relPath);
|
|
1953
2306
|
if (cached && cached.statBytes === st.size && cached.mtimeMs === st.mtimeMs && cached.ctimeMs === st.ctimeMs && !cached.encrypted) {
|
|
@@ -1961,11 +2314,11 @@ var StorageManager = class _StorageManager {
|
|
|
1961
2314
|
if (encrypted) {
|
|
1962
2315
|
const content = await readMaybeEncryptedFileBuffer(target, this._secureStoreKey, this.baseDir);
|
|
1963
2316
|
digest = {
|
|
1964
|
-
sha256:
|
|
2317
|
+
sha256: createHash2("sha256").update(content).digest("hex"),
|
|
1965
2318
|
bytes: content.byteLength
|
|
1966
2319
|
};
|
|
1967
2320
|
} else {
|
|
1968
|
-
const hash =
|
|
2321
|
+
const hash = createHash2("sha256");
|
|
1969
2322
|
let bytes = 0;
|
|
1970
2323
|
for await (const rawChunk of createReadStream(target)) {
|
|
1971
2324
|
const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk);
|
|
@@ -2008,7 +2361,7 @@ var StorageManager = class _StorageManager {
|
|
|
2008
2361
|
const bytes = typeof record.bytes === "number" ? record.bytes : NaN;
|
|
2009
2362
|
const sha256 = typeof record.sha256 === "string" ? record.sha256 : "";
|
|
2010
2363
|
const encrypted = record.encrypted === true;
|
|
2011
|
-
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") ||
|
|
2364
|
+
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") || path2.isAbsolute(cachePath) || !Number.isFinite(statBytes) || !Number.isFinite(mtimeMs) || !Number.isFinite(ctimeMs) || !Number.isFinite(bytes) || !/^[a-f0-9]{64}$/i.test(sha256)) {
|
|
2012
2365
|
continue;
|
|
2013
2366
|
}
|
|
2014
2367
|
cache.set(cachePath, { statBytes, mtimeMs, ctimeMs, encrypted, sha256, bytes });
|
|
@@ -2050,7 +2403,7 @@ var StorageManager = class _StorageManager {
|
|
|
2050
2403
|
const cache = this.offlineSyncDigestCache;
|
|
2051
2404
|
if (!cache) return;
|
|
2052
2405
|
const entries = [...cache.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([entryPath, entry]) => ({ path: entryPath, ...entry }));
|
|
2053
|
-
await mkdir(
|
|
2406
|
+
await mkdir(path2.dirname(this.offlineSyncDigestCachePath), { recursive: true });
|
|
2054
2407
|
await writeFile(
|
|
2055
2408
|
this.offlineSyncDigestCachePath,
|
|
2056
2409
|
`${JSON.stringify({ version: 1, entries })}
|
|
@@ -2104,10 +2457,10 @@ var StorageManager = class _StorageManager {
|
|
|
2104
2457
|
if (isErrnoCode(error, "ENOENT")) return;
|
|
2105
2458
|
throw error;
|
|
2106
2459
|
});
|
|
2107
|
-
if (filePath.includes(`${
|
|
2460
|
+
if (filePath.includes(`${path2.sep}cold${path2.sep}`)) {
|
|
2108
2461
|
this.invalidateColdMemoriesCache();
|
|
2109
2462
|
}
|
|
2110
|
-
if (filePath.includes(`${
|
|
2463
|
+
if (filePath.includes(`${path2.sep}artifacts${path2.sep}`)) {
|
|
2111
2464
|
this.bumpArtifactWriteVersion();
|
|
2112
2465
|
}
|
|
2113
2466
|
this.bumpMemoryStatusVersion();
|
|
@@ -2135,7 +2488,7 @@ var StorageManager = class _StorageManager {
|
|
|
2135
2488
|
}
|
|
2136
2489
|
async appendStorageSecureFileUnlocked(filePath, content) {
|
|
2137
2490
|
const writeKey = this.resolveWriteKey();
|
|
2138
|
-
await mkdir(
|
|
2491
|
+
await mkdir(path2.dirname(filePath), { recursive: true });
|
|
2139
2492
|
if (writeKey === null) {
|
|
2140
2493
|
try {
|
|
2141
2494
|
if (isEncryptedFile(await readFile(filePath))) {
|
|
@@ -2158,16 +2511,16 @@ var StorageManager = class _StorageManager {
|
|
|
2158
2511
|
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, writeKey, {}, this.baseDir);
|
|
2159
2512
|
}
|
|
2160
2513
|
get stateDir() {
|
|
2161
|
-
return
|
|
2514
|
+
return path2.join(this.baseDir, "state");
|
|
2162
2515
|
}
|
|
2163
2516
|
get offlineSyncDigestCachePath() {
|
|
2164
|
-
return
|
|
2517
|
+
return path2.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
|
|
2165
2518
|
}
|
|
2166
2519
|
get entitySynthesisQueuePath() {
|
|
2167
|
-
return
|
|
2520
|
+
return path2.join(this.stateDir, "entity-synthesis-queue.json");
|
|
2168
2521
|
}
|
|
2169
2522
|
get factHashIndexReadyPath() {
|
|
2170
|
-
return
|
|
2523
|
+
return path2.join(this.stateDir, "fact-hashes.ready");
|
|
2171
2524
|
}
|
|
2172
2525
|
async getFactHashIndex() {
|
|
2173
2526
|
if (this.factHashIndex) {
|
|
@@ -2234,7 +2587,7 @@ var StorageManager = class _StorageManager {
|
|
|
2234
2587
|
);
|
|
2235
2588
|
}
|
|
2236
2589
|
await factHashIndex.save();
|
|
2237
|
-
await mkdir(
|
|
2590
|
+
await mkdir(path2.dirname(this.factHashIndexReadyPath), { recursive: true });
|
|
2238
2591
|
await writeFile(this.factHashIndexReadyPath, "v1\n", "utf-8");
|
|
2239
2592
|
this.factHashIndexAuthoritative = true;
|
|
2240
2593
|
})().finally(() => {
|
|
@@ -2243,55 +2596,55 @@ var StorageManager = class _StorageManager {
|
|
|
2243
2596
|
await this.factHashIndexAuthoritativePromise;
|
|
2244
2597
|
}
|
|
2245
2598
|
get questionsDir() {
|
|
2246
|
-
return
|
|
2599
|
+
return path2.join(this.baseDir, "questions");
|
|
2247
2600
|
}
|
|
2248
2601
|
get artifactsDir() {
|
|
2249
|
-
return
|
|
2602
|
+
return path2.join(this.baseDir, "artifacts");
|
|
2250
2603
|
}
|
|
2251
2604
|
get identityDir() {
|
|
2252
|
-
return
|
|
2605
|
+
return path2.join(this.baseDir, "identity");
|
|
2253
2606
|
}
|
|
2254
2607
|
get identityAnchorPath() {
|
|
2255
|
-
return
|
|
2608
|
+
return path2.join(this.identityDir, "identity-anchor.md");
|
|
2256
2609
|
}
|
|
2257
2610
|
get identityIncidentsDir() {
|
|
2258
|
-
return
|
|
2611
|
+
return path2.join(this.identityDir, "incidents");
|
|
2259
2612
|
}
|
|
2260
2613
|
get identityAuditsWeeklyDir() {
|
|
2261
|
-
return
|
|
2614
|
+
return path2.join(this.identityDir, "audits", "weekly");
|
|
2262
2615
|
}
|
|
2263
2616
|
get identityAuditsMonthlyDir() {
|
|
2264
|
-
return
|
|
2617
|
+
return path2.join(this.identityDir, "audits", "monthly");
|
|
2265
2618
|
}
|
|
2266
2619
|
get identityImprovementLoopsPath() {
|
|
2267
|
-
return
|
|
2620
|
+
return path2.join(this.identityDir, "improvement-loops.md");
|
|
2268
2621
|
}
|
|
2269
2622
|
get identityReflectionsPath() {
|
|
2270
|
-
return
|
|
2623
|
+
return path2.join(this.identityDir, "reflections.md");
|
|
2271
2624
|
}
|
|
2272
2625
|
get profilePath() {
|
|
2273
|
-
return
|
|
2626
|
+
return path2.join(this.baseDir, "profile.md");
|
|
2274
2627
|
}
|
|
2275
2628
|
get memoryActionsPath() {
|
|
2276
|
-
return
|
|
2629
|
+
return path2.join(this.stateDir, "memory-actions.jsonl");
|
|
2277
2630
|
}
|
|
2278
2631
|
get memoryLifecycleLedgerPath() {
|
|
2279
|
-
return
|
|
2632
|
+
return path2.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
|
|
2280
2633
|
}
|
|
2281
2634
|
get compressionGuidelinesPath() {
|
|
2282
|
-
return
|
|
2635
|
+
return path2.join(this.stateDir, "compression-guidelines.md");
|
|
2283
2636
|
}
|
|
2284
2637
|
get compressionGuidelineDraftPath() {
|
|
2285
|
-
return
|
|
2638
|
+
return path2.join(this.stateDir, "compression-guidelines.draft.md");
|
|
2286
2639
|
}
|
|
2287
2640
|
get compressionGuidelineStatePath() {
|
|
2288
|
-
return
|
|
2641
|
+
return path2.join(this.stateDir, "compression-guideline-state.json");
|
|
2289
2642
|
}
|
|
2290
2643
|
get compressionGuidelineDraftStatePath() {
|
|
2291
|
-
return
|
|
2644
|
+
return path2.join(this.stateDir, "compression-guideline-draft-state.json");
|
|
2292
2645
|
}
|
|
2293
2646
|
get behaviorSignalsPath() {
|
|
2294
|
-
return
|
|
2647
|
+
return path2.join(this.stateDir, "behavior-signals.jsonl");
|
|
2295
2648
|
}
|
|
2296
2649
|
/**
|
|
2297
2650
|
* Buffer surprise telemetry ledger (issue #563 PR 3).
|
|
@@ -2304,7 +2657,7 @@ var StorageManager = class _StorageManager {
|
|
|
2304
2657
|
* governance sweeps can treat it uniformly.
|
|
2305
2658
|
*/
|
|
2306
2659
|
get bufferSurpriseLedgerPath() {
|
|
2307
|
-
return
|
|
2660
|
+
return path2.join(this.stateDir, "buffer-surprise-ledger.jsonl");
|
|
2308
2661
|
}
|
|
2309
2662
|
/**
|
|
2310
2663
|
* Load user-defined entity aliases from config/aliases.json in the memory store.
|
|
@@ -2312,7 +2665,7 @@ var StorageManager = class _StorageManager {
|
|
|
2312
2665
|
* Call this once at startup (e.g. from orchestrator.initialize()).
|
|
2313
2666
|
*/
|
|
2314
2667
|
async loadAliases() {
|
|
2315
|
-
const aliasPath =
|
|
2668
|
+
const aliasPath = path2.join(this.baseDir, "config", "aliases.json");
|
|
2316
2669
|
try {
|
|
2317
2670
|
const raw = await readFile(aliasPath, "utf-8");
|
|
2318
2671
|
const parsed = JSON.parse(raw);
|
|
@@ -2326,9 +2679,9 @@ var StorageManager = class _StorageManager {
|
|
|
2326
2679
|
}
|
|
2327
2680
|
async ensureDirectories() {
|
|
2328
2681
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2329
|
-
await mkdir(
|
|
2330
|
-
await mkdir(
|
|
2331
|
-
await mkdir(
|
|
2682
|
+
await mkdir(path2.join(this.factsDir, today), { recursive: true });
|
|
2683
|
+
await mkdir(path2.join(this.proceduresDir, today), { recursive: true });
|
|
2684
|
+
await mkdir(path2.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2332
2685
|
await mkdir(this.correctionsDir, { recursive: true });
|
|
2333
2686
|
await mkdir(this.entitiesDir, { recursive: true });
|
|
2334
2687
|
await mkdir(this.stateDir, { recursive: true });
|
|
@@ -2338,7 +2691,7 @@ var StorageManager = class _StorageManager {
|
|
|
2338
2691
|
await mkdir(this.identityIncidentsDir, { recursive: true });
|
|
2339
2692
|
await mkdir(this.identityAuditsWeeklyDir, { recursive: true });
|
|
2340
2693
|
await mkdir(this.identityAuditsMonthlyDir, { recursive: true });
|
|
2341
|
-
await mkdir(
|
|
2694
|
+
await mkdir(path2.join(this.baseDir, "config"), { recursive: true });
|
|
2342
2695
|
}
|
|
2343
2696
|
async writeMemory(category, content, options = {}) {
|
|
2344
2697
|
await this.ensureDirectories();
|
|
@@ -2408,15 +2761,15 @@ ${sanitized.text}
|
|
|
2408
2761
|
`;
|
|
2409
2762
|
let filePath;
|
|
2410
2763
|
if (category === "correction") {
|
|
2411
|
-
filePath =
|
|
2764
|
+
filePath = path2.join(this.correctionsDir, `${id}.md`);
|
|
2412
2765
|
} else if (category === "procedure") {
|
|
2413
|
-
await mkdir(
|
|
2414
|
-
filePath =
|
|
2766
|
+
await mkdir(path2.join(this.proceduresDir, today), { recursive: true });
|
|
2767
|
+
filePath = path2.join(this.proceduresDir, today, `${id}.md`);
|
|
2415
2768
|
} else if (category === "reasoning_trace") {
|
|
2416
|
-
await mkdir(
|
|
2417
|
-
filePath =
|
|
2769
|
+
await mkdir(path2.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2770
|
+
filePath = path2.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
2418
2771
|
} else {
|
|
2419
|
-
filePath =
|
|
2772
|
+
filePath = path2.join(this.factsDir, today, `${id}.md`);
|
|
2420
2773
|
}
|
|
2421
2774
|
await this.snapshotBeforeWrite(filePath, "write");
|
|
2422
2775
|
await writeMaybeEncryptedFile(filePath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
@@ -2531,7 +2884,7 @@ ${sanitized.text}
|
|
|
2531
2884
|
await this.ensureDirectories();
|
|
2532
2885
|
const now = /* @__PURE__ */ new Date();
|
|
2533
2886
|
const day = now.toISOString().slice(0, 10);
|
|
2534
|
-
const dir =
|
|
2887
|
+
const dir = path2.join(this.artifactsDir, day);
|
|
2535
2888
|
await mkdir(dir, { recursive: true });
|
|
2536
2889
|
const id = `artifact-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
2537
2890
|
const fm = {
|
|
@@ -2555,7 +2908,7 @@ ${sanitized.text}
|
|
|
2555
2908
|
log.warn(`artifact content rejected for ${id}; violations=${sanitized.violations.join(", ")}`);
|
|
2556
2909
|
return "";
|
|
2557
2910
|
}
|
|
2558
|
-
const filePath =
|
|
2911
|
+
const filePath = path2.join(dir, `${id}.md`);
|
|
2559
2912
|
await writeMaybeEncryptedFile(filePath, `${serializeFrontmatter(fm)}
|
|
2560
2913
|
|
|
2561
2914
|
${sanitized.text}
|
|
@@ -2583,7 +2936,7 @@ ${sanitized.text}
|
|
|
2583
2936
|
try {
|
|
2584
2937
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
2585
2938
|
for (const entry of entries) {
|
|
2586
|
-
const fullPath =
|
|
2939
|
+
const fullPath = path2.join(dir, entry.name);
|
|
2587
2940
|
if (entry.isDirectory()) {
|
|
2588
2941
|
await readDir(fullPath);
|
|
2589
2942
|
continue;
|
|
@@ -2649,7 +3002,7 @@ ${sanitized.text}
|
|
|
2649
3002
|
log.debug(`fuzzy match: "${normalized}" \u2192 existing "${match}"`);
|
|
2650
3003
|
normalized = match;
|
|
2651
3004
|
}
|
|
2652
|
-
const filePath =
|
|
3005
|
+
const filePath = path2.join(this.entitiesDir, `${normalized}.md`);
|
|
2653
3006
|
let entity = {
|
|
2654
3007
|
name,
|
|
2655
3008
|
type,
|
|
@@ -2884,7 +3237,7 @@ ${sanitized.text}
|
|
|
2884
3237
|
* per-process in-memory cache safe across process boundaries.
|
|
2885
3238
|
*/
|
|
2886
3239
|
invalidateColdMemoriesCache() {
|
|
2887
|
-
const coldRoot =
|
|
3240
|
+
const coldRoot = path2.join(this.baseDir, "cold");
|
|
2888
3241
|
_StorageManager.coldMemoriesCache.delete(coldRoot);
|
|
2889
3242
|
this.bumpColdWriteVersion();
|
|
2890
3243
|
}
|
|
@@ -2912,7 +3265,7 @@ ${sanitized.text}
|
|
|
2912
3265
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
2913
3266
|
const subdirs = [];
|
|
2914
3267
|
for (const entry of entries) {
|
|
2915
|
-
const fullPath =
|
|
3268
|
+
const fullPath = path2.join(dir, entry.name);
|
|
2916
3269
|
if (entry.isDirectory()) {
|
|
2917
3270
|
subdirs.push(fullPath);
|
|
2918
3271
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -2996,7 +3349,7 @@ ${sanitized.text}
|
|
|
2996
3349
|
const correctionPaths = [];
|
|
2997
3350
|
const factPaths = [];
|
|
2998
3351
|
for (const filePath of filePaths) {
|
|
2999
|
-
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${
|
|
3352
|
+
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path2.sep}`)) {
|
|
3000
3353
|
correctionPaths.push(filePath);
|
|
3001
3354
|
} else {
|
|
3002
3355
|
factPaths.push(filePath);
|
|
@@ -3116,7 +3469,7 @@ ${sanitized.text}
|
|
|
3116
3469
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3117
3470
|
const subdirs = [];
|
|
3118
3471
|
for (const entry of entries) {
|
|
3119
|
-
const fullPath =
|
|
3472
|
+
const fullPath = path2.join(dir, entry.name);
|
|
3120
3473
|
if (entry.isDirectory()) {
|
|
3121
3474
|
subdirs.push(fullPath);
|
|
3122
3475
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3145,7 +3498,7 @@ ${sanitized.text}
|
|
|
3145
3498
|
try {
|
|
3146
3499
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3147
3500
|
for (const entry of entries) {
|
|
3148
|
-
const fullPath =
|
|
3501
|
+
const fullPath = path2.join(dir, entry.name);
|
|
3149
3502
|
if (entry.isDirectory()) {
|
|
3150
3503
|
await readDir(fullPath);
|
|
3151
3504
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3190,11 +3543,11 @@ ${sanitized.text}
|
|
|
3190
3543
|
content: parsed.content
|
|
3191
3544
|
};
|
|
3192
3545
|
}
|
|
3193
|
-
const normalizedPath = filePath.split(
|
|
3546
|
+
const normalizedPath = filePath.split(path2.sep).join("/");
|
|
3194
3547
|
if (normalizedPath.includes("/entities/") && filePath.endsWith(".md")) {
|
|
3195
3548
|
const entity = parseEntityFile(raw, this.entitySchemas);
|
|
3196
3549
|
if (!entity.name) return null;
|
|
3197
|
-
const nameWithoutExt =
|
|
3550
|
+
const nameWithoutExt = path2.basename(filePath, ".md");
|
|
3198
3551
|
const fileMtime = entity.updated || await stat(filePath).then((s) => s.mtime.toISOString()).catch(() => (/* @__PURE__ */ new Date(0)).toISOString());
|
|
3199
3552
|
return {
|
|
3200
3553
|
path: filePath,
|
|
@@ -3218,7 +3571,7 @@ ${sanitized.text}
|
|
|
3218
3571
|
}
|
|
3219
3572
|
}
|
|
3220
3573
|
resolveTierRootDir(tier) {
|
|
3221
|
-
return tier === "cold" ?
|
|
3574
|
+
return tier === "cold" ? path2.join(this.baseDir, "cold") : this.baseDir;
|
|
3222
3575
|
}
|
|
3223
3576
|
resolveMemoryDateDir(memory) {
|
|
3224
3577
|
const preferred = memory.frontmatter.created || memory.frontmatter.updated;
|
|
@@ -3233,18 +3586,18 @@ ${sanitized.text}
|
|
|
3233
3586
|
buildTierMemoryPath(memory, tier) {
|
|
3234
3587
|
const root = this.resolveTierRootDir(tier);
|
|
3235
3588
|
if (this.isArtifactMemory(memory)) {
|
|
3236
|
-
return
|
|
3589
|
+
return path2.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3237
3590
|
}
|
|
3238
3591
|
if (memory.frontmatter.category === "correction") {
|
|
3239
|
-
return
|
|
3592
|
+
return path2.join(root, "corrections", `${memory.frontmatter.id}.md`);
|
|
3240
3593
|
}
|
|
3241
3594
|
if (memory.frontmatter.category === "procedure") {
|
|
3242
|
-
return
|
|
3595
|
+
return path2.join(root, "procedures", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3243
3596
|
}
|
|
3244
3597
|
if (memory.frontmatter.category === "reasoning_trace") {
|
|
3245
|
-
return
|
|
3598
|
+
return path2.join(root, "reasoning-traces", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3246
3599
|
}
|
|
3247
|
-
return
|
|
3600
|
+
return path2.join(root, "facts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3248
3601
|
}
|
|
3249
3602
|
async writeMemoryFileAtomic(targetPath, memory) {
|
|
3250
3603
|
const fileContent = `${serializeFrontmatter(memory.frontmatter)}
|
|
@@ -3256,8 +3609,8 @@ ${memory.content}
|
|
|
3256
3609
|
}
|
|
3257
3610
|
async moveMemoryToPath(memory, targetPath) {
|
|
3258
3611
|
await this.writeMemoryFileAtomic(targetPath, memory);
|
|
3259
|
-
const sourcePath =
|
|
3260
|
-
const destPath =
|
|
3612
|
+
const sourcePath = path2.resolve(memory.path);
|
|
3613
|
+
const destPath = path2.resolve(targetPath);
|
|
3261
3614
|
if (sourcePath !== destPath) {
|
|
3262
3615
|
try {
|
|
3263
3616
|
await unlink(memory.path);
|
|
@@ -3272,8 +3625,8 @@ ${memory.content}
|
|
|
3272
3625
|
}
|
|
3273
3626
|
async migrateMemoryToTier(memory, targetTier) {
|
|
3274
3627
|
const targetPath = this.buildTierMemoryPath(memory, targetTier);
|
|
3275
|
-
const sourcePath =
|
|
3276
|
-
const destPath =
|
|
3628
|
+
const sourcePath = path2.resolve(memory.path);
|
|
3629
|
+
const destPath = path2.resolve(targetPath);
|
|
3277
3630
|
if (sourcePath === destPath) {
|
|
3278
3631
|
return { changed: false, targetPath };
|
|
3279
3632
|
}
|
|
@@ -3299,7 +3652,7 @@ ${memory.content}
|
|
|
3299
3652
|
return { changed: true, targetPath };
|
|
3300
3653
|
}
|
|
3301
3654
|
get archiveDir() {
|
|
3302
|
-
return
|
|
3655
|
+
return path2.join(this.baseDir, "archive");
|
|
3303
3656
|
}
|
|
3304
3657
|
/**
|
|
3305
3658
|
* Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
|
|
@@ -3310,7 +3663,7 @@ ${memory.content}
|
|
|
3310
3663
|
try {
|
|
3311
3664
|
const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
|
|
3312
3665
|
const today = now.toISOString().slice(0, 10);
|
|
3313
|
-
const destDir =
|
|
3666
|
+
const destDir = path2.join(this.archiveDir, today);
|
|
3314
3667
|
await mkdir(destDir, { recursive: true });
|
|
3315
3668
|
const updatedFm = {
|
|
3316
3669
|
...memory.frontmatter,
|
|
@@ -3322,7 +3675,7 @@ ${memory.content}
|
|
|
3322
3675
|
|
|
3323
3676
|
${memory.content}
|
|
3324
3677
|
`;
|
|
3325
|
-
const destPath =
|
|
3678
|
+
const destPath = path2.join(destDir, path2.basename(memory.path));
|
|
3326
3679
|
await writeMaybeEncryptedFile(destPath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3327
3680
|
await unlink(memory.path);
|
|
3328
3681
|
this.invalidateAllMemoriesCache();
|
|
@@ -3484,7 +3837,7 @@ ${memory.content}
|
|
|
3484
3837
|
`;
|
|
3485
3838
|
await writeMaybeEncryptedFile(memory.path, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3486
3839
|
this.invalidateAllMemoriesCache();
|
|
3487
|
-
if (memory.path.includes(`${
|
|
3840
|
+
if (memory.path.includes(`${path2.sep}cold${path2.sep}`)) {
|
|
3488
3841
|
this.invalidateColdMemoriesCache();
|
|
3489
3842
|
}
|
|
3490
3843
|
try {
|
|
@@ -3556,7 +3909,7 @@ ${memory.content}
|
|
|
3556
3909
|
return deleted;
|
|
3557
3910
|
}
|
|
3558
3911
|
async loadBuffer() {
|
|
3559
|
-
const bufferPath =
|
|
3912
|
+
const bufferPath = path2.join(this.stateDir, "buffer.json");
|
|
3560
3913
|
try {
|
|
3561
3914
|
const raw = await this.readStorageSecureFile(bufferPath);
|
|
3562
3915
|
return JSON.parse(raw);
|
|
@@ -3568,11 +3921,11 @@ ${memory.content}
|
|
|
3568
3921
|
}
|
|
3569
3922
|
async saveBuffer(state) {
|
|
3570
3923
|
await this.ensureDirectories();
|
|
3571
|
-
const bufferPath =
|
|
3924
|
+
const bufferPath = path2.join(this.stateDir, "buffer.json");
|
|
3572
3925
|
await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
|
|
3573
3926
|
}
|
|
3574
3927
|
async loadMeta() {
|
|
3575
|
-
const metaPath =
|
|
3928
|
+
const metaPath = path2.join(this.stateDir, "meta.json");
|
|
3576
3929
|
try {
|
|
3577
3930
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
3578
3931
|
const parsed = JSON.parse(raw);
|
|
@@ -3606,7 +3959,7 @@ ${memory.content}
|
|
|
3606
3959
|
}
|
|
3607
3960
|
async saveMeta(state) {
|
|
3608
3961
|
await this.ensureDirectories();
|
|
3609
|
-
const metaPath =
|
|
3962
|
+
const metaPath = path2.join(this.stateDir, "meta.json");
|
|
3610
3963
|
await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
|
|
3611
3964
|
}
|
|
3612
3965
|
async appendMemoryActionEvents(events) {
|
|
@@ -3776,7 +4129,7 @@ ${memory.content}
|
|
|
3776
4129
|
async appendReextractJobs(events) {
|
|
3777
4130
|
if (events.length === 0) return 0;
|
|
3778
4131
|
await this.ensureDirectories();
|
|
3779
|
-
const filePath =
|
|
4132
|
+
const filePath = path2.join(this.stateDir, "reextract-jobs.jsonl");
|
|
3780
4133
|
const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
|
|
3781
4134
|
try {
|
|
3782
4135
|
await this.appendStorageSecureFile(filePath, lines);
|
|
@@ -3789,7 +4142,7 @@ ${memory.content}
|
|
|
3789
4142
|
}
|
|
3790
4143
|
async readReextractJobs(limit = 200) {
|
|
3791
4144
|
const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
|
|
3792
|
-
const filePath =
|
|
4145
|
+
const filePath = path2.join(this.stateDir, "reextract-jobs.jsonl");
|
|
3793
4146
|
try {
|
|
3794
4147
|
const raw = await this.readStorageSecureFile(filePath);
|
|
3795
4148
|
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
@@ -3961,7 +4314,7 @@ ${memory.content}
|
|
|
3961
4314
|
return false;
|
|
3962
4315
|
}
|
|
3963
4316
|
if (draftState.contentHash) {
|
|
3964
|
-
const contentHash =
|
|
4317
|
+
const contentHash = createHash2("sha256").update(draftContent).digest("hex");
|
|
3965
4318
|
if (contentHash !== draftState.contentHash) return false;
|
|
3966
4319
|
}
|
|
3967
4320
|
await this.writeCompressionGuidelines(draftContent);
|
|
@@ -4043,7 +4396,7 @@ ${memory.content}
|
|
|
4043
4396
|
const date = nowIso.slice(0, 10);
|
|
4044
4397
|
const id = this.generateId("incident");
|
|
4045
4398
|
const incident = createContinuityIncidentRecord(id, input, nowIso);
|
|
4046
|
-
const filePath =
|
|
4399
|
+
const filePath = path2.join(this.identityIncidentsDir, `${date}-${id}.md`);
|
|
4047
4400
|
await this.writeStorageSecureFile(filePath, serializeContinuityIncident(incident));
|
|
4048
4401
|
return { ...incident, filePath };
|
|
4049
4402
|
}
|
|
@@ -4056,7 +4409,7 @@ ${memory.content}
|
|
|
4056
4409
|
const incidents = [];
|
|
4057
4410
|
for (const file of candidates) {
|
|
4058
4411
|
if (incidents.length >= cappedLimit) break;
|
|
4059
|
-
const filePath =
|
|
4412
|
+
const filePath = path2.join(this.identityIncidentsDir, file);
|
|
4060
4413
|
try {
|
|
4061
4414
|
const raw = await this.readStorageSecureFile(filePath);
|
|
4062
4415
|
const parsed = parseContinuityIncident(raw);
|
|
@@ -4087,7 +4440,7 @@ ${memory.content}
|
|
|
4087
4440
|
await this.ensureDirectories();
|
|
4088
4441
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4089
4442
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4090
|
-
const filePath =
|
|
4443
|
+
const filePath = path2.join(dir, `${safeKey}.md`);
|
|
4091
4444
|
await this.writeStorageSecureFile(filePath, content);
|
|
4092
4445
|
return filePath;
|
|
4093
4446
|
}
|
|
@@ -4095,7 +4448,7 @@ ${memory.content}
|
|
|
4095
4448
|
try {
|
|
4096
4449
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4097
4450
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4098
|
-
return await this.readStorageSecureFile(
|
|
4451
|
+
return await this.readStorageSecureFile(path2.join(dir, `${safeKey}.md`));
|
|
4099
4452
|
} catch (err) {
|
|
4100
4453
|
if (err instanceof Error && err.message === "Invalid identity audit key") return null;
|
|
4101
4454
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -4159,12 +4512,12 @@ ${memory.content}
|
|
|
4159
4512
|
const fileNames = await this.readContinuityIncidentFileNames();
|
|
4160
4513
|
const directMatch = fileNames.find((name) => name.endsWith(`-${id}.md`));
|
|
4161
4514
|
if (directMatch) {
|
|
4162
|
-
const directPath =
|
|
4515
|
+
const directPath = path2.join(this.identityIncidentsDir, directMatch);
|
|
4163
4516
|
const parsed = await this.readContinuityIncidentFile(directPath);
|
|
4164
4517
|
if (parsed?.id === id) return directPath;
|
|
4165
4518
|
}
|
|
4166
4519
|
for (const fileName of fileNames) {
|
|
4167
|
-
const filePath =
|
|
4520
|
+
const filePath = path2.join(this.identityIncidentsDir, fileName);
|
|
4168
4521
|
const parsed = await this.readContinuityIncidentFile(filePath);
|
|
4169
4522
|
if (parsed?.id === id) return filePath;
|
|
4170
4523
|
}
|
|
@@ -4194,7 +4547,7 @@ ${question}
|
|
|
4194
4547
|
|
|
4195
4548
|
**Context:** ${context}
|
|
4196
4549
|
`;
|
|
4197
|
-
const filePath =
|
|
4550
|
+
const filePath = path2.join(this.questionsDir, `${id}.md`);
|
|
4198
4551
|
await writeFile(filePath, content, "utf-8");
|
|
4199
4552
|
log.debug(`wrote question ${id} to ${filePath}`);
|
|
4200
4553
|
this.invalidateQuestionsCache();
|
|
@@ -4218,7 +4571,7 @@ ${question}
|
|
|
4218
4571
|
const questions = [];
|
|
4219
4572
|
for (const file of files) {
|
|
4220
4573
|
if (!file.endsWith(".md")) continue;
|
|
4221
|
-
const filePath =
|
|
4574
|
+
const filePath = path2.join(this.questionsDir, file);
|
|
4222
4575
|
const raw = await readMaybeEncryptedFile(filePath, this._secureStoreKey, this.baseDir);
|
|
4223
4576
|
const parsed = this.parseQuestionFile(raw, filePath);
|
|
4224
4577
|
if (parsed) {
|
|
@@ -4241,7 +4594,7 @@ ${question}
|
|
|
4241
4594
|
if (!match) return null;
|
|
4242
4595
|
const frontmatterStr = match[1];
|
|
4243
4596
|
const body = match[2].trim();
|
|
4244
|
-
const id = this.extractFrontmatterValue(frontmatterStr, "id") ??
|
|
4597
|
+
const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path2.basename(filePath, ".md");
|
|
4245
4598
|
const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
|
|
4246
4599
|
const priority = parseFloat(
|
|
4247
4600
|
this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5"
|
|
@@ -4303,11 +4656,11 @@ ${question}
|
|
|
4303
4656
|
} catch {
|
|
4304
4657
|
}
|
|
4305
4658
|
const hygiene = opts?.hygiene;
|
|
4306
|
-
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(
|
|
4659
|
+
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path2.basename(identityPath));
|
|
4307
4660
|
if (rotateEnabled) {
|
|
4308
4661
|
const maxBytes = hygiene.rotateMaxBytes;
|
|
4309
4662
|
if (existing.length > maxBytes) {
|
|
4310
|
-
const archiveDir =
|
|
4663
|
+
const archiveDir = path2.join(workspaceDir, hygiene.archiveDir);
|
|
4311
4664
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
4312
4665
|
filePath: identityPath,
|
|
4313
4666
|
archiveDir,
|
|
@@ -4401,7 +4754,7 @@ ${reflection}
|
|
|
4401
4754
|
* Deduplicates by target+label.
|
|
4402
4755
|
*/
|
|
4403
4756
|
async addEntityRelationship(name, rel) {
|
|
4404
|
-
const filePath =
|
|
4757
|
+
const filePath = path2.join(this.entitiesDir, `${name}.md`);
|
|
4405
4758
|
let entity;
|
|
4406
4759
|
try {
|
|
4407
4760
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4426,7 +4779,7 @@ ${reflection}
|
|
|
4426
4779
|
* Prepends to the beginning, prunes oldest entries beyond maxEntries.
|
|
4427
4780
|
*/
|
|
4428
4781
|
async addEntityActivity(name, entry, maxEntries) {
|
|
4429
|
-
const filePath =
|
|
4782
|
+
const filePath = path2.join(this.entitiesDir, `${name}.md`);
|
|
4430
4783
|
let entity;
|
|
4431
4784
|
try {
|
|
4432
4785
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4449,7 +4802,7 @@ ${reflection}
|
|
|
4449
4802
|
* Add an alias to an entity file. Deduplicates.
|
|
4450
4803
|
*/
|
|
4451
4804
|
async addEntityAlias(name, alias) {
|
|
4452
|
-
const filePath =
|
|
4805
|
+
const filePath = path2.join(this.entitiesDir, `${name}.md`);
|
|
4453
4806
|
let entity;
|
|
4454
4807
|
try {
|
|
4455
4808
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4470,7 +4823,7 @@ ${reflection}
|
|
|
4470
4823
|
* Set or rewrite the synthesis layer of an entity file.
|
|
4471
4824
|
*/
|
|
4472
4825
|
async updateEntitySynthesis(name, synthesis, options = {}) {
|
|
4473
|
-
const filePath =
|
|
4826
|
+
const filePath = path2.join(this.entitiesDir, `${name}.md`);
|
|
4474
4827
|
let entity;
|
|
4475
4828
|
try {
|
|
4476
4829
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4508,7 +4861,7 @@ ${reflection}
|
|
|
4508
4861
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4509
4862
|
let synthesisTimelineCount;
|
|
4510
4863
|
try {
|
|
4511
|
-
const filePath =
|
|
4864
|
+
const filePath = path2.join(this.entitiesDir, `${name}.md`);
|
|
4512
4865
|
const content = await this.readStorageSecureFile(filePath);
|
|
4513
4866
|
synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
|
|
4514
4867
|
} catch (err) {
|
|
@@ -4591,7 +4944,7 @@ ${reflection}
|
|
|
4591
4944
|
if (!raw) continue;
|
|
4592
4945
|
const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
|
|
4593
4946
|
if (raw.trimEnd() === serialized.trimEnd()) continue;
|
|
4594
|
-
await this.writeStorageSecureFile(
|
|
4947
|
+
await this.writeStorageSecureFile(path2.join(this.entitiesDir, `${entityName}.md`), serialized);
|
|
4595
4948
|
migrated += 1;
|
|
4596
4949
|
}
|
|
4597
4950
|
if (migrated > 0) {
|
|
@@ -4627,7 +4980,7 @@ ${reflection}
|
|
|
4627
4980
|
const results = await Promise.all(
|
|
4628
4981
|
batch.map(async (entry) => {
|
|
4629
4982
|
try {
|
|
4630
|
-
return await this.readStorageSecureFile(
|
|
4983
|
+
return await this.readStorageSecureFile(path2.join(this.entitiesDir, entry));
|
|
4631
4984
|
} catch (err) {
|
|
4632
4985
|
if (err instanceof SecureStoreLockedError) throw err;
|
|
4633
4986
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -4773,7 +5126,7 @@ ${rows.join("\n")}
|
|
|
4773
5126
|
extraSections: []
|
|
4774
5127
|
};
|
|
4775
5128
|
for (const file of files) {
|
|
4776
|
-
const filePath =
|
|
5129
|
+
const filePath = path2.join(this.entitiesDir, file);
|
|
4777
5130
|
try {
|
|
4778
5131
|
const content = await this.readStorageSecureFile(filePath);
|
|
4779
5132
|
const parsed = parseEntityFile(content, this.entitySchemas);
|
|
@@ -4904,10 +5257,10 @@ ${rows.join("\n")}
|
|
|
4904
5257
|
}
|
|
4905
5258
|
mergedEntity.created = mergedEntity.created || mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
4906
5259
|
mergedEntity.updated = mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
4907
|
-
const canonicalPath =
|
|
5260
|
+
const canonicalPath = path2.join(this.entitiesDir, `${canonical}.md`);
|
|
4908
5261
|
await this.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.entitySchemas));
|
|
4909
5262
|
for (const file of files) {
|
|
4910
|
-
const filePath =
|
|
5263
|
+
const filePath = path2.join(this.entitiesDir, file);
|
|
4911
5264
|
if (filePath !== canonicalPath) {
|
|
4912
5265
|
try {
|
|
4913
5266
|
await unlink(filePath);
|
|
@@ -5006,7 +5359,7 @@ ${memory.content}
|
|
|
5006
5359
|
const filePaths = await this.collectActiveMemoryPaths();
|
|
5007
5360
|
const foundIds = /* @__PURE__ */ new Set();
|
|
5008
5361
|
for (const filePath of filePaths) {
|
|
5009
|
-
const basename =
|
|
5362
|
+
const basename = path2.basename(filePath, ".md");
|
|
5010
5363
|
if (wantedIds.has(basename)) {
|
|
5011
5364
|
foundIds.add(basename);
|
|
5012
5365
|
if (foundIds.size === wantedIds.size) break;
|
|
@@ -5106,15 +5459,15 @@ ${sanitized.text}
|
|
|
5106
5459
|
`;
|
|
5107
5460
|
let filePath;
|
|
5108
5461
|
if (category === "correction") {
|
|
5109
|
-
filePath =
|
|
5462
|
+
filePath = path2.join(this.correctionsDir, `${id}.md`);
|
|
5110
5463
|
} else if (category === "procedure") {
|
|
5111
|
-
await mkdir(
|
|
5112
|
-
filePath =
|
|
5464
|
+
await mkdir(path2.join(this.proceduresDir, today), { recursive: true });
|
|
5465
|
+
filePath = path2.join(this.proceduresDir, today, `${id}.md`);
|
|
5113
5466
|
} else if (category === "reasoning_trace") {
|
|
5114
|
-
await mkdir(
|
|
5115
|
-
filePath =
|
|
5467
|
+
await mkdir(path2.join(this.reasoningTracesDir, today), { recursive: true });
|
|
5468
|
+
filePath = path2.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
5116
5469
|
} else {
|
|
5117
|
-
filePath =
|
|
5470
|
+
filePath = path2.join(this.factsDir, today, `${id}.md`);
|
|
5118
5471
|
}
|
|
5119
5472
|
await this.writeStorageSecureFile(filePath, fileContent);
|
|
5120
5473
|
log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
|
|
@@ -5183,14 +5536,14 @@ Reason: ${reason}`, {
|
|
|
5183
5536
|
// Memory Summarization (Phase 4A)
|
|
5184
5537
|
// ---------------------------------------------------------------------------
|
|
5185
5538
|
get summariesDir() {
|
|
5186
|
-
return
|
|
5539
|
+
return path2.join(this.baseDir, "summaries");
|
|
5187
5540
|
}
|
|
5188
5541
|
/**
|
|
5189
5542
|
* Write a memory summary.
|
|
5190
5543
|
*/
|
|
5191
5544
|
async writeSummary(summary) {
|
|
5192
5545
|
await mkdir(this.summariesDir, { recursive: true });
|
|
5193
|
-
const filePath =
|
|
5546
|
+
const filePath = path2.join(this.summariesDir, `${summary.id}.json`);
|
|
5194
5547
|
await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
|
|
5195
5548
|
log.debug(`wrote summary ${summary.id}`);
|
|
5196
5549
|
}
|
|
@@ -5203,7 +5556,7 @@ Reason: ${reason}`, {
|
|
|
5203
5556
|
const summaries = [];
|
|
5204
5557
|
for (const file of files) {
|
|
5205
5558
|
if (!file.endsWith(".json")) continue;
|
|
5206
|
-
const filePath =
|
|
5559
|
+
const filePath = path2.join(this.summariesDir, file);
|
|
5207
5560
|
const raw = await this.readStorageSecureFile(filePath);
|
|
5208
5561
|
summaries.push(JSON.parse(raw));
|
|
5209
5562
|
}
|
|
@@ -5264,7 +5617,7 @@ ${memory.content}
|
|
|
5264
5617
|
* Save topic scores to meta.json.
|
|
5265
5618
|
*/
|
|
5266
5619
|
async saveTopics(topics) {
|
|
5267
|
-
const metaPath =
|
|
5620
|
+
const metaPath = path2.join(this.stateDir, "topics.json");
|
|
5268
5621
|
await mkdir(this.stateDir, { recursive: true });
|
|
5269
5622
|
await this.writeStorageSecureFile(metaPath, JSON.stringify({ topics, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
5270
5623
|
log.debug(`saved ${topics.length} topic scores`);
|
|
@@ -5273,7 +5626,7 @@ ${memory.content}
|
|
|
5273
5626
|
* Load topic scores from meta.json.
|
|
5274
5627
|
*/
|
|
5275
5628
|
async loadTopics() {
|
|
5276
|
-
const metaPath =
|
|
5629
|
+
const metaPath = path2.join(this.stateDir, "topics.json");
|
|
5277
5630
|
try {
|
|
5278
5631
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
5279
5632
|
return JSON.parse(raw);
|
|
@@ -5351,6 +5704,21 @@ ${memory.content}
|
|
|
5351
5704
|
};
|
|
5352
5705
|
|
|
5353
5706
|
export {
|
|
5707
|
+
DEFAULT_SELF_NAME,
|
|
5708
|
+
emptySpeakerRegistry,
|
|
5709
|
+
speakersFilePath,
|
|
5710
|
+
loadSpeakerRegistry,
|
|
5711
|
+
saveSpeakerRegistry,
|
|
5712
|
+
speakerRegistryKey,
|
|
5713
|
+
resolveSpeaker,
|
|
5714
|
+
distinctSpeakerLabels,
|
|
5715
|
+
WEARABLES_DIR_NAME,
|
|
5716
|
+
isValidTranscriptDate,
|
|
5717
|
+
hashTranscriptBody,
|
|
5718
|
+
composeDayTranscriptBody,
|
|
5719
|
+
composeDayTranscriptMeta,
|
|
5720
|
+
serializeDayTranscript,
|
|
5721
|
+
parseDayTranscript,
|
|
5354
5722
|
normalizeEntityName,
|
|
5355
5723
|
ContentHashIndex,
|
|
5356
5724
|
normalizeAttributePairs,
|
|
@@ -5361,4 +5729,4 @@ export {
|
|
|
5361
5729
|
serializeEntityFile,
|
|
5362
5730
|
StorageManager
|
|
5363
5731
|
};
|
|
5364
|
-
//# sourceMappingURL=chunk-
|
|
5732
|
+
//# sourceMappingURL=chunk-UGHUNQ74.js.map
|