@remnic/core 9.3.630 → 9.3.632
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +15 -13
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +4 -4
- package/dist/access-http.js +7 -6
- package/dist/access-mcp.d.ts +4 -4
- package/dist/access-mcp.js +6 -5
- package/dist/{access-service-C4v-eFjB.d.ts → access-service-C9_EpVHd.d.ts} +2 -2
- package/dist/access-service.d.ts +4 -4
- package/dist/access-service.js +5 -4
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/auto-sync-RFADEHIQ.js +75 -0
- package/dist/auto-sync-RFADEHIQ.js.map +1 -0
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -2
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -3
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-BWK5EEKS.js → chunk-242XFZ36.js} +2 -2
- package/dist/{chunk-K3BTOW7N.js → chunk-32U3N7H5.js} +3 -3
- package/dist/{chunk-5S6IREG3.js → chunk-3RDYU3JS.js} +3 -3
- package/dist/{chunk-SACS6KE6.js → chunk-4S3N6HFG.js} +2 -2
- package/dist/{chunk-VUTPRX7K.js → chunk-5PT5I6JQ.js} +14 -14
- package/dist/{chunk-2VJ7AJFX.js → chunk-7A2QKUUA.js} +2 -2
- package/dist/{chunk-EORL2IDM.js → chunk-7H5WCPBS.js} +58 -5
- package/dist/{chunk-EORL2IDM.js.map → chunk-7H5WCPBS.js.map} +1 -1
- package/dist/{chunk-NRQJBK36.js → chunk-C4KKM62E.js} +2 -2
- package/dist/{chunk-GXWFZYSR.js → chunk-CMN5AWAZ.js} +2 -2
- package/dist/{chunk-F6USGHMO.js → chunk-DOBJH4I6.js} +4 -4
- package/dist/{chunk-ADOD7PJC.js → chunk-IFVFQRZ2.js} +5 -5
- package/dist/{chunk-6LBQL5US.js → chunk-JCLECECB.js} +2 -2
- package/dist/chunk-KVDUDYEN.js +1164 -0
- package/dist/chunk-KVDUDYEN.js.map +1 -0
- package/dist/{chunk-S5W37FPX.js → chunk-LEG7XWS2.js} +2 -2
- package/dist/chunk-M7XQSUBB.js +280 -0
- package/dist/chunk-M7XQSUBB.js.map +1 -0
- package/dist/{chunk-MQ24KOOR.js → chunk-PUEAEQSN.js} +2 -2
- package/dist/{chunk-RSKUUEBA.js → chunk-QYGIQ5NM.js} +140 -417
- package/dist/chunk-QYGIQ5NM.js.map +1 -0
- package/dist/{chunk-UE57H4MA.js → chunk-UXFOGILU.js} +2 -2
- package/dist/{chunk-OQMR2SDZ.js → chunk-VTR3MNYF.js} +2 -2
- package/dist/{chunk-4QEUKASL.js → chunk-W25I7G6U.js} +2 -2
- package/dist/{chunk-YJOWWRRS.js → chunk-WLZBVYC6.js} +125 -1206
- package/dist/chunk-WLZBVYC6.js.map +1 -0
- package/dist/{chunk-OOFBE62K.js → chunk-X7EJF46S.js} +2 -2
- package/dist/{chunk-BL33LBTN.js → chunk-XG4NAWAV.js} +3 -3
- package/dist/{chunk-ZZSXUZF3.js → chunk-YROCXMCK.js} +2 -2
- package/dist/{cli-B_6EMiQc.d.ts → cli-CuVEQWKr.d.ts} +3 -3
- package/dist/cli.d.ts +5 -5
- package/dist/cli.js +18 -17
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -2
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -2
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -2
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/contradiction/index.js +4 -4
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +3 -3
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +49 -45
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +3 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
- package/dist/maintenance/rebuild-memory-projection.js +4 -3
- package/dist/mcp-memory-inspector-app.d.ts +4 -4
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +4 -3
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +3 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +7 -6
- package/dist/{orchestrator-Dlw3ae4B.d.ts → orchestrator-CoqytbK_.d.ts} +3 -2
- package/dist/orchestrator.d.ts +3 -3
- package/dist/orchestrator.js +12 -10
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-C4sefXEI.d.ts → semantic-consolidation-BPs6BURk.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -3
- package/dist/semantic-rule-promotion.js +3 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/{types-2vqxmO0j.d.ts → types-CpMPD8xl.d.ts} +20 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -2
- package/package.json +1 -1
- package/src/orchestrator.ts +58 -0
- package/src/wearables/auto-sync.test.ts +181 -0
- package/src/wearables/auto-sync.ts +129 -0
- package/src/wearables/config.test.ts +58 -8
- package/src/wearables/config.ts +75 -5
- package/src/wearables/pipeline.test.ts +87 -4
- package/src/wearables/pipeline.ts +43 -13
- package/src/wearables/types.ts +20 -1
- package/dist/chunk-RSKUUEBA.js.map +0 -1
- package/dist/chunk-YJOWWRRS.js.map +0 -1
- /package/dist/{chunk-BWK5EEKS.js.map → chunk-242XFZ36.js.map} +0 -0
- /package/dist/{chunk-K3BTOW7N.js.map → chunk-32U3N7H5.js.map} +0 -0
- /package/dist/{chunk-5S6IREG3.js.map → chunk-3RDYU3JS.js.map} +0 -0
- /package/dist/{chunk-SACS6KE6.js.map → chunk-4S3N6HFG.js.map} +0 -0
- /package/dist/{chunk-VUTPRX7K.js.map → chunk-5PT5I6JQ.js.map} +0 -0
- /package/dist/{chunk-2VJ7AJFX.js.map → chunk-7A2QKUUA.js.map} +0 -0
- /package/dist/{chunk-NRQJBK36.js.map → chunk-C4KKM62E.js.map} +0 -0
- /package/dist/{chunk-GXWFZYSR.js.map → chunk-CMN5AWAZ.js.map} +0 -0
- /package/dist/{chunk-F6USGHMO.js.map → chunk-DOBJH4I6.js.map} +0 -0
- /package/dist/{chunk-ADOD7PJC.js.map → chunk-IFVFQRZ2.js.map} +0 -0
- /package/dist/{chunk-6LBQL5US.js.map → chunk-JCLECECB.js.map} +0 -0
- /package/dist/{chunk-S5W37FPX.js.map → chunk-LEG7XWS2.js.map} +0 -0
- /package/dist/{chunk-MQ24KOOR.js.map → chunk-PUEAEQSN.js.map} +0 -0
- /package/dist/{chunk-UE57H4MA.js.map → chunk-UXFOGILU.js.map} +0 -0
- /package/dist/{chunk-OQMR2SDZ.js.map → chunk-VTR3MNYF.js.map} +0 -0
- /package/dist/{chunk-4QEUKASL.js.map → chunk-W25I7G6U.js.map} +0 -0
- /package/dist/{chunk-OOFBE62K.js.map → chunk-X7EJF46S.js.map} +0 -0
- /package/dist/{chunk-BL33LBTN.js.map → chunk-XG4NAWAV.js.map} +0 -0
- /package/dist/{chunk-ZZSXUZF3.js.map → chunk-YROCXMCK.js.map} +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WEARABLES_DIR_NAME,
|
|
3
|
+
isValidTranscriptDate
|
|
4
|
+
} from "./chunk-M7XQSUBB.js";
|
|
1
5
|
import {
|
|
2
6
|
isErrnoCode
|
|
3
7
|
} from "./chunk-5UZXUTVO.js";
|
|
@@ -77,274 +81,8 @@ import {
|
|
|
77
81
|
// src/storage.ts
|
|
78
82
|
import { access, readdir, readFile, stat, writeFile, mkdir, unlink, appendFile, open } from "fs/promises";
|
|
79
83
|
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
|
|
84
84
|
import { createHash } from "crypto";
|
|
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
|
|
85
|
+
import path from "path";
|
|
348
86
|
var ARTIFACT_SEARCH_STOPWORDS = /* @__PURE__ */ new Set([
|
|
349
87
|
"a",
|
|
350
88
|
"an",
|
|
@@ -928,17 +666,17 @@ var KNOWN_ENTITY_FILENAME_PREFIXES = /* @__PURE__ */ new Set([
|
|
|
928
666
|
"topic"
|
|
929
667
|
]);
|
|
930
668
|
function inferEntityTypeFromFilename(pathRel) {
|
|
931
|
-
const basename =
|
|
669
|
+
const basename = path.basename(pathRel, ".md").toLowerCase();
|
|
932
670
|
const separator = basename.indexOf("-");
|
|
933
671
|
if (separator <= 0) return void 0;
|
|
934
672
|
const candidate = basename.slice(0, separator);
|
|
935
673
|
return KNOWN_ENTITY_FILENAME_PREFIXES.has(candidate) ? candidate : void 0;
|
|
936
674
|
}
|
|
937
675
|
function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
|
|
938
|
-
const normalizedPath = pathRel.split(
|
|
676
|
+
const normalizedPath = pathRel.split(path.sep).join("/");
|
|
939
677
|
let normalizedFrontmatter = frontmatter;
|
|
940
678
|
if (normalizedPath === "entities" || normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/")) {
|
|
941
|
-
const basename =
|
|
679
|
+
const basename = path.basename(pathRel, ".md");
|
|
942
680
|
const inferredType = inferEntityTypeFromContent(content) || inferEntityTypeFromFilename(pathRel) || "entity";
|
|
943
681
|
const existingTags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
|
|
944
682
|
normalizedFrontmatter = {
|
|
@@ -1005,8 +743,8 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
1005
743
|
secureStoreKeyProvider;
|
|
1006
744
|
secureStoreWriteKeyProvider;
|
|
1007
745
|
memoryDir;
|
|
1008
|
-
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir =
|
|
1009
|
-
this.filePath =
|
|
746
|
+
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path.dirname(stateDir)) {
|
|
747
|
+
this.filePath = path.join(stateDir, "fact-hashes.txt");
|
|
1010
748
|
this.secureStoreKeyProvider = secureStoreKeyProvider;
|
|
1011
749
|
this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
|
|
1012
750
|
this.memoryDir = memoryDir;
|
|
@@ -1053,7 +791,7 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
1053
791
|
/** Persist index to disk if changed. */
|
|
1054
792
|
async save() {
|
|
1055
793
|
if (!this.dirty) return;
|
|
1056
|
-
await mkdir(
|
|
794
|
+
await mkdir(path.dirname(this.filePath), { recursive: true });
|
|
1057
795
|
await writeMaybeEncryptedFile(
|
|
1058
796
|
this.filePath,
|
|
1059
797
|
[...this.hashes].join("\n") + "\n",
|
|
@@ -1105,7 +843,7 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
1105
843
|
/** Normalize content and compute SHA-256 hash. */
|
|
1106
844
|
static computeHash(content) {
|
|
1107
845
|
const normalized = _ContentHashIndex.normalizeContent(content);
|
|
1108
|
-
return
|
|
846
|
+
return createHash("sha256").update(normalized).digest("hex");
|
|
1109
847
|
}
|
|
1110
848
|
};
|
|
1111
849
|
function stripAttributesSuffix(content) {
|
|
@@ -1606,7 +1344,7 @@ function fingerprintEntityStructuredFacts(entity) {
|
|
|
1606
1344
|
facts: normalizeStructuredSectionFacts(section.facts).slice().sort((left, right) => left.localeCompare(right))
|
|
1607
1345
|
})).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")));
|
|
1608
1346
|
if (normalizedSections.length === 0) return void 0;
|
|
1609
|
-
return
|
|
1347
|
+
return createHash("sha256").update(JSON.stringify(normalizedSections)).digest("hex");
|
|
1610
1348
|
}
|
|
1611
1349
|
function isEntitySynthesisStale(entity) {
|
|
1612
1350
|
const structuredFactCount = countEntityStructuredFacts(entity);
|
|
@@ -2120,7 +1858,7 @@ var StorageManager = class _StorageManager {
|
|
|
2120
1858
|
void 0,
|
|
2121
1859
|
this.baseDir
|
|
2122
1860
|
);
|
|
2123
|
-
const rel =
|
|
1861
|
+
const rel = path.relative(this.baseDir, filePath).split(path.sep).join("/");
|
|
2124
1862
|
return `${rel}:${version.versionId}`;
|
|
2125
1863
|
} catch (err) {
|
|
2126
1864
|
log.warn(
|
|
@@ -2135,13 +1873,13 @@ var StorageManager = class _StorageManager {
|
|
|
2135
1873
|
}
|
|
2136
1874
|
identityFilePath(workspaceDir, namespace) {
|
|
2137
1875
|
const rawNamespace = typeof namespace === "string" ? namespace.trim() : "";
|
|
2138
|
-
if (!rawNamespace) return
|
|
1876
|
+
if (!rawNamespace) return path.join(workspaceDir, "IDENTITY.md");
|
|
2139
1877
|
const safeNamespace = rawNamespace.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
2140
|
-
return
|
|
1878
|
+
return path.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
|
|
2141
1879
|
}
|
|
2142
1880
|
versionFilePath(kind) {
|
|
2143
1881
|
const fileName = kind === "memory-status" ? ".memory-status-version.log" : kind === "artifact-write" ? ".artifact-write-version.log" : ".cold-write-version.log";
|
|
2144
|
-
return
|
|
1882
|
+
return path.join(this.stateDir, fileName);
|
|
2145
1883
|
}
|
|
2146
1884
|
bumpSharedVersion(kind, fallbackMap) {
|
|
2147
1885
|
const filePath = this.versionFilePath(kind);
|
|
@@ -2187,7 +1925,7 @@ var StorageManager = class _StorageManager {
|
|
|
2187
1925
|
// memories.
|
|
2188
1926
|
// -------------------------------------------------------------------------
|
|
2189
1927
|
get wearablesDir() {
|
|
2190
|
-
return
|
|
1928
|
+
return path.join(this.baseDir, WEARABLES_DIR_NAME);
|
|
2191
1929
|
}
|
|
2192
1930
|
/**
|
|
2193
1931
|
* Resolve the on-disk path for a source/day transcript. Throws on
|
|
@@ -2205,7 +1943,7 @@ var StorageManager = class _StorageManager {
|
|
|
2205
1943
|
`invalid wearable transcript date '${String(date)}' \u2014 expected YYYY-MM-DD`
|
|
2206
1944
|
);
|
|
2207
1945
|
}
|
|
2208
|
-
return
|
|
1946
|
+
return path.join(this.wearablesDir, sourceId, `${date}.md`);
|
|
2209
1947
|
}
|
|
2210
1948
|
async writeWearableDayTranscript(sourceId, date, serialized) {
|
|
2211
1949
|
const targetPath = this.wearableTranscriptPath(sourceId, date);
|
|
@@ -2243,7 +1981,7 @@ var StorageManager = class _StorageManager {
|
|
|
2243
1981
|
if (!/^[a-z][a-z0-9-]{0,63}$/.test(source)) continue;
|
|
2244
1982
|
let entries;
|
|
2245
1983
|
try {
|
|
2246
|
-
entries = await readdir(
|
|
1984
|
+
entries = await readdir(path.join(this.wearablesDir, source));
|
|
2247
1985
|
} catch (err) {
|
|
2248
1986
|
if (err.code === "ENOENT") continue;
|
|
2249
1987
|
throw err;
|
|
@@ -2326,25 +2064,25 @@ var StorageManager = class _StorageManager {
|
|
|
2326
2064
|
});
|
|
2327
2065
|
}
|
|
2328
2066
|
get factsDir() {
|
|
2329
|
-
return
|
|
2067
|
+
return path.join(this.baseDir, "facts");
|
|
2330
2068
|
}
|
|
2331
2069
|
get correctionsDir() {
|
|
2332
|
-
return
|
|
2070
|
+
return path.join(this.baseDir, "corrections");
|
|
2333
2071
|
}
|
|
2334
2072
|
get proceduresDir() {
|
|
2335
|
-
return
|
|
2073
|
+
return path.join(this.baseDir, "procedures");
|
|
2336
2074
|
}
|
|
2337
2075
|
get reasoningTracesDir() {
|
|
2338
|
-
return
|
|
2076
|
+
return path.join(this.baseDir, "reasoning-traces");
|
|
2339
2077
|
}
|
|
2340
2078
|
get entitiesDir() {
|
|
2341
|
-
return
|
|
2079
|
+
return path.join(this.baseDir, "entities");
|
|
2342
2080
|
}
|
|
2343
2081
|
resolveEntityFilePath(name) {
|
|
2344
2082
|
if (typeof name !== "string") return null;
|
|
2345
|
-
const filePath =
|
|
2346
|
-
const relative =
|
|
2347
|
-
if (relative === "" || relative.startsWith("..") ||
|
|
2083
|
+
const filePath = path.resolve(this.entitiesDir, `${name}.md`);
|
|
2084
|
+
const relative = path.relative(this.entitiesDir, filePath);
|
|
2085
|
+
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
2348
2086
|
return null;
|
|
2349
2087
|
}
|
|
2350
2088
|
return filePath;
|
|
@@ -2356,10 +2094,10 @@ var StorageManager = class _StorageManager {
|
|
|
2356
2094
|
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir);
|
|
2357
2095
|
}
|
|
2358
2096
|
assertManagedStoragePath(filePath, method) {
|
|
2359
|
-
const resolved =
|
|
2360
|
-
const base =
|
|
2361
|
-
const rel =
|
|
2362
|
-
if (rel === "" || rel === ".." || rel.startsWith(`..${
|
|
2097
|
+
const resolved = path.resolve(filePath);
|
|
2098
|
+
const base = path.resolve(this.baseDir);
|
|
2099
|
+
const rel = path.relative(base, resolved);
|
|
2100
|
+
if (rel === "" || rel === ".." || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel)) {
|
|
2363
2101
|
throw new Error(`${method}: file path escapes memory dir`);
|
|
2364
2102
|
}
|
|
2365
2103
|
return resolved;
|
|
@@ -2371,7 +2109,7 @@ var StorageManager = class _StorageManager {
|
|
|
2371
2109
|
async digestOfflineSyncFile(filePath) {
|
|
2372
2110
|
const target = this.assertManagedStoragePath(filePath, "storage.digestOfflineSyncFile");
|
|
2373
2111
|
const st = await stat(target);
|
|
2374
|
-
const relPath =
|
|
2112
|
+
const relPath = path.relative(this.baseDir, target).split(path.sep).join("/");
|
|
2375
2113
|
const cache = await this.loadOfflineSyncDigestCache();
|
|
2376
2114
|
const cached = cache.get(relPath);
|
|
2377
2115
|
if (cached && cached.statBytes === st.size && cached.mtimeMs === st.mtimeMs && cached.ctimeMs === st.ctimeMs && !cached.encrypted) {
|
|
@@ -2385,11 +2123,11 @@ var StorageManager = class _StorageManager {
|
|
|
2385
2123
|
if (encrypted) {
|
|
2386
2124
|
const content = await readMaybeEncryptedFileBuffer(target, this._secureStoreKey, this.baseDir);
|
|
2387
2125
|
digest = {
|
|
2388
|
-
sha256:
|
|
2126
|
+
sha256: createHash("sha256").update(content).digest("hex"),
|
|
2389
2127
|
bytes: content.byteLength
|
|
2390
2128
|
};
|
|
2391
2129
|
} else {
|
|
2392
|
-
const hash =
|
|
2130
|
+
const hash = createHash("sha256");
|
|
2393
2131
|
let bytes = 0;
|
|
2394
2132
|
for await (const rawChunk of createReadStream(target)) {
|
|
2395
2133
|
const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk);
|
|
@@ -2432,7 +2170,7 @@ var StorageManager = class _StorageManager {
|
|
|
2432
2170
|
const bytes = typeof record.bytes === "number" ? record.bytes : NaN;
|
|
2433
2171
|
const sha256 = typeof record.sha256 === "string" ? record.sha256 : "";
|
|
2434
2172
|
const encrypted = record.encrypted === true;
|
|
2435
|
-
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") ||
|
|
2173
|
+
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") || path.isAbsolute(cachePath) || !Number.isFinite(statBytes) || !Number.isFinite(mtimeMs) || !Number.isFinite(ctimeMs) || !Number.isFinite(bytes) || !/^[a-f0-9]{64}$/i.test(sha256)) {
|
|
2436
2174
|
continue;
|
|
2437
2175
|
}
|
|
2438
2176
|
cache.set(cachePath, { statBytes, mtimeMs, ctimeMs, encrypted, sha256, bytes });
|
|
@@ -2474,7 +2212,7 @@ var StorageManager = class _StorageManager {
|
|
|
2474
2212
|
const cache = this.offlineSyncDigestCache;
|
|
2475
2213
|
if (!cache) return;
|
|
2476
2214
|
const entries = [...cache.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([entryPath, entry]) => ({ path: entryPath, ...entry }));
|
|
2477
|
-
await mkdir(
|
|
2215
|
+
await mkdir(path.dirname(this.offlineSyncDigestCachePath), { recursive: true });
|
|
2478
2216
|
await writeFile(
|
|
2479
2217
|
this.offlineSyncDigestCachePath,
|
|
2480
2218
|
`${JSON.stringify({ version: 1, entries })}
|
|
@@ -2528,10 +2266,10 @@ var StorageManager = class _StorageManager {
|
|
|
2528
2266
|
if (isErrnoCode(error, "ENOENT")) return;
|
|
2529
2267
|
throw error;
|
|
2530
2268
|
});
|
|
2531
|
-
if (filePath.includes(`${
|
|
2269
|
+
if (filePath.includes(`${path.sep}cold${path.sep}`)) {
|
|
2532
2270
|
this.invalidateColdMemoriesCache();
|
|
2533
2271
|
}
|
|
2534
|
-
if (filePath.includes(`${
|
|
2272
|
+
if (filePath.includes(`${path.sep}artifacts${path.sep}`)) {
|
|
2535
2273
|
this.bumpArtifactWriteVersion();
|
|
2536
2274
|
}
|
|
2537
2275
|
this.bumpMemoryStatusVersion();
|
|
@@ -2559,7 +2297,7 @@ var StorageManager = class _StorageManager {
|
|
|
2559
2297
|
}
|
|
2560
2298
|
async appendStorageSecureFileUnlocked(filePath, content) {
|
|
2561
2299
|
const writeKey = this.resolveWriteKey();
|
|
2562
|
-
await mkdir(
|
|
2300
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
2563
2301
|
if (writeKey === null) {
|
|
2564
2302
|
try {
|
|
2565
2303
|
if (isEncryptedFile(await readFile(filePath))) {
|
|
@@ -2582,16 +2320,16 @@ var StorageManager = class _StorageManager {
|
|
|
2582
2320
|
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, writeKey, {}, this.baseDir);
|
|
2583
2321
|
}
|
|
2584
2322
|
get stateDir() {
|
|
2585
|
-
return
|
|
2323
|
+
return path.join(this.baseDir, "state");
|
|
2586
2324
|
}
|
|
2587
2325
|
get offlineSyncDigestCachePath() {
|
|
2588
|
-
return
|
|
2326
|
+
return path.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
|
|
2589
2327
|
}
|
|
2590
2328
|
get entitySynthesisQueuePath() {
|
|
2591
|
-
return
|
|
2329
|
+
return path.join(this.stateDir, "entity-synthesis-queue.json");
|
|
2592
2330
|
}
|
|
2593
2331
|
get factHashIndexReadyPath() {
|
|
2594
|
-
return
|
|
2332
|
+
return path.join(this.stateDir, "fact-hashes.ready");
|
|
2595
2333
|
}
|
|
2596
2334
|
async getFactHashIndex() {
|
|
2597
2335
|
if (this.factHashIndex) {
|
|
@@ -2658,7 +2396,7 @@ var StorageManager = class _StorageManager {
|
|
|
2658
2396
|
);
|
|
2659
2397
|
}
|
|
2660
2398
|
await factHashIndex.save();
|
|
2661
|
-
await mkdir(
|
|
2399
|
+
await mkdir(path.dirname(this.factHashIndexReadyPath), { recursive: true });
|
|
2662
2400
|
await writeFile(this.factHashIndexReadyPath, "v1\n", "utf-8");
|
|
2663
2401
|
this.factHashIndexAuthoritative = true;
|
|
2664
2402
|
})().finally(() => {
|
|
@@ -2667,55 +2405,55 @@ var StorageManager = class _StorageManager {
|
|
|
2667
2405
|
await this.factHashIndexAuthoritativePromise;
|
|
2668
2406
|
}
|
|
2669
2407
|
get questionsDir() {
|
|
2670
|
-
return
|
|
2408
|
+
return path.join(this.baseDir, "questions");
|
|
2671
2409
|
}
|
|
2672
2410
|
get artifactsDir() {
|
|
2673
|
-
return
|
|
2411
|
+
return path.join(this.baseDir, "artifacts");
|
|
2674
2412
|
}
|
|
2675
2413
|
get identityDir() {
|
|
2676
|
-
return
|
|
2414
|
+
return path.join(this.baseDir, "identity");
|
|
2677
2415
|
}
|
|
2678
2416
|
get identityAnchorPath() {
|
|
2679
|
-
return
|
|
2417
|
+
return path.join(this.identityDir, "identity-anchor.md");
|
|
2680
2418
|
}
|
|
2681
2419
|
get identityIncidentsDir() {
|
|
2682
|
-
return
|
|
2420
|
+
return path.join(this.identityDir, "incidents");
|
|
2683
2421
|
}
|
|
2684
2422
|
get identityAuditsWeeklyDir() {
|
|
2685
|
-
return
|
|
2423
|
+
return path.join(this.identityDir, "audits", "weekly");
|
|
2686
2424
|
}
|
|
2687
2425
|
get identityAuditsMonthlyDir() {
|
|
2688
|
-
return
|
|
2426
|
+
return path.join(this.identityDir, "audits", "monthly");
|
|
2689
2427
|
}
|
|
2690
2428
|
get identityImprovementLoopsPath() {
|
|
2691
|
-
return
|
|
2429
|
+
return path.join(this.identityDir, "improvement-loops.md");
|
|
2692
2430
|
}
|
|
2693
2431
|
get identityReflectionsPath() {
|
|
2694
|
-
return
|
|
2432
|
+
return path.join(this.identityDir, "reflections.md");
|
|
2695
2433
|
}
|
|
2696
2434
|
get profilePath() {
|
|
2697
|
-
return
|
|
2435
|
+
return path.join(this.baseDir, "profile.md");
|
|
2698
2436
|
}
|
|
2699
2437
|
get memoryActionsPath() {
|
|
2700
|
-
return
|
|
2438
|
+
return path.join(this.stateDir, "memory-actions.jsonl");
|
|
2701
2439
|
}
|
|
2702
2440
|
get memoryLifecycleLedgerPath() {
|
|
2703
|
-
return
|
|
2441
|
+
return path.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
|
|
2704
2442
|
}
|
|
2705
2443
|
get compressionGuidelinesPath() {
|
|
2706
|
-
return
|
|
2444
|
+
return path.join(this.stateDir, "compression-guidelines.md");
|
|
2707
2445
|
}
|
|
2708
2446
|
get compressionGuidelineDraftPath() {
|
|
2709
|
-
return
|
|
2447
|
+
return path.join(this.stateDir, "compression-guidelines.draft.md");
|
|
2710
2448
|
}
|
|
2711
2449
|
get compressionGuidelineStatePath() {
|
|
2712
|
-
return
|
|
2450
|
+
return path.join(this.stateDir, "compression-guideline-state.json");
|
|
2713
2451
|
}
|
|
2714
2452
|
get compressionGuidelineDraftStatePath() {
|
|
2715
|
-
return
|
|
2453
|
+
return path.join(this.stateDir, "compression-guideline-draft-state.json");
|
|
2716
2454
|
}
|
|
2717
2455
|
get behaviorSignalsPath() {
|
|
2718
|
-
return
|
|
2456
|
+
return path.join(this.stateDir, "behavior-signals.jsonl");
|
|
2719
2457
|
}
|
|
2720
2458
|
/**
|
|
2721
2459
|
* Buffer surprise telemetry ledger (issue #563 PR 3).
|
|
@@ -2728,7 +2466,7 @@ var StorageManager = class _StorageManager {
|
|
|
2728
2466
|
* governance sweeps can treat it uniformly.
|
|
2729
2467
|
*/
|
|
2730
2468
|
get bufferSurpriseLedgerPath() {
|
|
2731
|
-
return
|
|
2469
|
+
return path.join(this.stateDir, "buffer-surprise-ledger.jsonl");
|
|
2732
2470
|
}
|
|
2733
2471
|
/**
|
|
2734
2472
|
* Load user-defined entity aliases from config/aliases.json in the memory store.
|
|
@@ -2736,7 +2474,7 @@ var StorageManager = class _StorageManager {
|
|
|
2736
2474
|
* Call this once at startup (e.g. from orchestrator.initialize()).
|
|
2737
2475
|
*/
|
|
2738
2476
|
async loadAliases() {
|
|
2739
|
-
const aliasPath =
|
|
2477
|
+
const aliasPath = path.join(this.baseDir, "config", "aliases.json");
|
|
2740
2478
|
try {
|
|
2741
2479
|
const raw = await readFile(aliasPath, "utf-8");
|
|
2742
2480
|
const parsed = JSON.parse(raw);
|
|
@@ -2750,9 +2488,9 @@ var StorageManager = class _StorageManager {
|
|
|
2750
2488
|
}
|
|
2751
2489
|
async ensureDirectories() {
|
|
2752
2490
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2753
|
-
await mkdir(
|
|
2754
|
-
await mkdir(
|
|
2755
|
-
await mkdir(
|
|
2491
|
+
await mkdir(path.join(this.factsDir, today), { recursive: true });
|
|
2492
|
+
await mkdir(path.join(this.proceduresDir, today), { recursive: true });
|
|
2493
|
+
await mkdir(path.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2756
2494
|
await mkdir(this.correctionsDir, { recursive: true });
|
|
2757
2495
|
await mkdir(this.entitiesDir, { recursive: true });
|
|
2758
2496
|
await mkdir(this.stateDir, { recursive: true });
|
|
@@ -2762,7 +2500,7 @@ var StorageManager = class _StorageManager {
|
|
|
2762
2500
|
await mkdir(this.identityIncidentsDir, { recursive: true });
|
|
2763
2501
|
await mkdir(this.identityAuditsWeeklyDir, { recursive: true });
|
|
2764
2502
|
await mkdir(this.identityAuditsMonthlyDir, { recursive: true });
|
|
2765
|
-
await mkdir(
|
|
2503
|
+
await mkdir(path.join(this.baseDir, "config"), { recursive: true });
|
|
2766
2504
|
}
|
|
2767
2505
|
async writeMemory(category, content, options = {}) {
|
|
2768
2506
|
await this.ensureDirectories();
|
|
@@ -2832,15 +2570,15 @@ ${sanitized.text}
|
|
|
2832
2570
|
`;
|
|
2833
2571
|
let filePath;
|
|
2834
2572
|
if (category === "correction") {
|
|
2835
|
-
filePath =
|
|
2573
|
+
filePath = path.join(this.correctionsDir, `${id}.md`);
|
|
2836
2574
|
} else if (category === "procedure") {
|
|
2837
|
-
await mkdir(
|
|
2838
|
-
filePath =
|
|
2575
|
+
await mkdir(path.join(this.proceduresDir, today), { recursive: true });
|
|
2576
|
+
filePath = path.join(this.proceduresDir, today, `${id}.md`);
|
|
2839
2577
|
} else if (category === "reasoning_trace") {
|
|
2840
|
-
await mkdir(
|
|
2841
|
-
filePath =
|
|
2578
|
+
await mkdir(path.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2579
|
+
filePath = path.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
2842
2580
|
} else {
|
|
2843
|
-
filePath =
|
|
2581
|
+
filePath = path.join(this.factsDir, today, `${id}.md`);
|
|
2844
2582
|
}
|
|
2845
2583
|
await this.snapshotBeforeWrite(filePath, "write");
|
|
2846
2584
|
await writeMaybeEncryptedFile(filePath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
@@ -2955,7 +2693,7 @@ ${sanitized.text}
|
|
|
2955
2693
|
await this.ensureDirectories();
|
|
2956
2694
|
const now = /* @__PURE__ */ new Date();
|
|
2957
2695
|
const day = now.toISOString().slice(0, 10);
|
|
2958
|
-
const dir =
|
|
2696
|
+
const dir = path.join(this.artifactsDir, day);
|
|
2959
2697
|
await mkdir(dir, { recursive: true });
|
|
2960
2698
|
const id = `artifact-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
2961
2699
|
const fm = {
|
|
@@ -2979,7 +2717,7 @@ ${sanitized.text}
|
|
|
2979
2717
|
log.warn(`artifact content rejected for ${id}; violations=${sanitized.violations.join(", ")}`);
|
|
2980
2718
|
return "";
|
|
2981
2719
|
}
|
|
2982
|
-
const filePath =
|
|
2720
|
+
const filePath = path.join(dir, `${id}.md`);
|
|
2983
2721
|
await writeMaybeEncryptedFile(filePath, `${serializeFrontmatter(fm)}
|
|
2984
2722
|
|
|
2985
2723
|
${sanitized.text}
|
|
@@ -3007,7 +2745,7 @@ ${sanitized.text}
|
|
|
3007
2745
|
try {
|
|
3008
2746
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3009
2747
|
for (const entry of entries) {
|
|
3010
|
-
const fullPath =
|
|
2748
|
+
const fullPath = path.join(dir, entry.name);
|
|
3011
2749
|
if (entry.isDirectory()) {
|
|
3012
2750
|
await readDir(fullPath);
|
|
3013
2751
|
continue;
|
|
@@ -3073,7 +2811,7 @@ ${sanitized.text}
|
|
|
3073
2811
|
log.debug(`fuzzy match: "${normalized}" \u2192 existing "${match}"`);
|
|
3074
2812
|
normalized = match;
|
|
3075
2813
|
}
|
|
3076
|
-
const filePath =
|
|
2814
|
+
const filePath = path.join(this.entitiesDir, `${normalized}.md`);
|
|
3077
2815
|
let entity = {
|
|
3078
2816
|
name,
|
|
3079
2817
|
type,
|
|
@@ -3308,7 +3046,7 @@ ${sanitized.text}
|
|
|
3308
3046
|
* per-process in-memory cache safe across process boundaries.
|
|
3309
3047
|
*/
|
|
3310
3048
|
invalidateColdMemoriesCache() {
|
|
3311
|
-
const coldRoot =
|
|
3049
|
+
const coldRoot = path.join(this.baseDir, "cold");
|
|
3312
3050
|
_StorageManager.coldMemoriesCache.delete(coldRoot);
|
|
3313
3051
|
this.bumpColdWriteVersion();
|
|
3314
3052
|
}
|
|
@@ -3336,7 +3074,7 @@ ${sanitized.text}
|
|
|
3336
3074
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3337
3075
|
const subdirs = [];
|
|
3338
3076
|
for (const entry of entries) {
|
|
3339
|
-
const fullPath =
|
|
3077
|
+
const fullPath = path.join(dir, entry.name);
|
|
3340
3078
|
if (entry.isDirectory()) {
|
|
3341
3079
|
subdirs.push(fullPath);
|
|
3342
3080
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3420,7 +3158,7 @@ ${sanitized.text}
|
|
|
3420
3158
|
const correctionPaths = [];
|
|
3421
3159
|
const factPaths = [];
|
|
3422
3160
|
for (const filePath of filePaths) {
|
|
3423
|
-
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${
|
|
3161
|
+
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path.sep}`)) {
|
|
3424
3162
|
correctionPaths.push(filePath);
|
|
3425
3163
|
} else {
|
|
3426
3164
|
factPaths.push(filePath);
|
|
@@ -3540,7 +3278,7 @@ ${sanitized.text}
|
|
|
3540
3278
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3541
3279
|
const subdirs = [];
|
|
3542
3280
|
for (const entry of entries) {
|
|
3543
|
-
const fullPath =
|
|
3281
|
+
const fullPath = path.join(dir, entry.name);
|
|
3544
3282
|
if (entry.isDirectory()) {
|
|
3545
3283
|
subdirs.push(fullPath);
|
|
3546
3284
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3569,7 +3307,7 @@ ${sanitized.text}
|
|
|
3569
3307
|
try {
|
|
3570
3308
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3571
3309
|
for (const entry of entries) {
|
|
3572
|
-
const fullPath =
|
|
3310
|
+
const fullPath = path.join(dir, entry.name);
|
|
3573
3311
|
if (entry.isDirectory()) {
|
|
3574
3312
|
await readDir(fullPath);
|
|
3575
3313
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3614,11 +3352,11 @@ ${sanitized.text}
|
|
|
3614
3352
|
content: parsed.content
|
|
3615
3353
|
};
|
|
3616
3354
|
}
|
|
3617
|
-
const normalizedPath = filePath.split(
|
|
3355
|
+
const normalizedPath = filePath.split(path.sep).join("/");
|
|
3618
3356
|
if (normalizedPath.includes("/entities/") && filePath.endsWith(".md")) {
|
|
3619
3357
|
const entity = parseEntityFile(raw, this.entitySchemas);
|
|
3620
3358
|
if (!entity.name) return null;
|
|
3621
|
-
const nameWithoutExt =
|
|
3359
|
+
const nameWithoutExt = path.basename(filePath, ".md");
|
|
3622
3360
|
const fileMtime = entity.updated || await stat(filePath).then((s) => s.mtime.toISOString()).catch(() => (/* @__PURE__ */ new Date(0)).toISOString());
|
|
3623
3361
|
return {
|
|
3624
3362
|
path: filePath,
|
|
@@ -3642,7 +3380,7 @@ ${sanitized.text}
|
|
|
3642
3380
|
}
|
|
3643
3381
|
}
|
|
3644
3382
|
resolveTierRootDir(tier) {
|
|
3645
|
-
return tier === "cold" ?
|
|
3383
|
+
return tier === "cold" ? path.join(this.baseDir, "cold") : this.baseDir;
|
|
3646
3384
|
}
|
|
3647
3385
|
resolveMemoryDateDir(memory) {
|
|
3648
3386
|
const preferred = memory.frontmatter.created || memory.frontmatter.updated;
|
|
@@ -3657,18 +3395,18 @@ ${sanitized.text}
|
|
|
3657
3395
|
buildTierMemoryPath(memory, tier) {
|
|
3658
3396
|
const root = this.resolveTierRootDir(tier);
|
|
3659
3397
|
if (this.isArtifactMemory(memory)) {
|
|
3660
|
-
return
|
|
3398
|
+
return path.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3661
3399
|
}
|
|
3662
3400
|
if (memory.frontmatter.category === "correction") {
|
|
3663
|
-
return
|
|
3401
|
+
return path.join(root, "corrections", `${memory.frontmatter.id}.md`);
|
|
3664
3402
|
}
|
|
3665
3403
|
if (memory.frontmatter.category === "procedure") {
|
|
3666
|
-
return
|
|
3404
|
+
return path.join(root, "procedures", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3667
3405
|
}
|
|
3668
3406
|
if (memory.frontmatter.category === "reasoning_trace") {
|
|
3669
|
-
return
|
|
3407
|
+
return path.join(root, "reasoning-traces", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3670
3408
|
}
|
|
3671
|
-
return
|
|
3409
|
+
return path.join(root, "facts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3672
3410
|
}
|
|
3673
3411
|
async writeMemoryFileAtomic(targetPath, memory) {
|
|
3674
3412
|
const fileContent = `${serializeFrontmatter(memory.frontmatter)}
|
|
@@ -3680,8 +3418,8 @@ ${memory.content}
|
|
|
3680
3418
|
}
|
|
3681
3419
|
async moveMemoryToPath(memory, targetPath) {
|
|
3682
3420
|
await this.writeMemoryFileAtomic(targetPath, memory);
|
|
3683
|
-
const sourcePath =
|
|
3684
|
-
const destPath =
|
|
3421
|
+
const sourcePath = path.resolve(memory.path);
|
|
3422
|
+
const destPath = path.resolve(targetPath);
|
|
3685
3423
|
if (sourcePath !== destPath) {
|
|
3686
3424
|
try {
|
|
3687
3425
|
await unlink(memory.path);
|
|
@@ -3696,8 +3434,8 @@ ${memory.content}
|
|
|
3696
3434
|
}
|
|
3697
3435
|
async migrateMemoryToTier(memory, targetTier) {
|
|
3698
3436
|
const targetPath = this.buildTierMemoryPath(memory, targetTier);
|
|
3699
|
-
const sourcePath =
|
|
3700
|
-
const destPath =
|
|
3437
|
+
const sourcePath = path.resolve(memory.path);
|
|
3438
|
+
const destPath = path.resolve(targetPath);
|
|
3701
3439
|
if (sourcePath === destPath) {
|
|
3702
3440
|
return { changed: false, targetPath };
|
|
3703
3441
|
}
|
|
@@ -3723,7 +3461,7 @@ ${memory.content}
|
|
|
3723
3461
|
return { changed: true, targetPath };
|
|
3724
3462
|
}
|
|
3725
3463
|
get archiveDir() {
|
|
3726
|
-
return
|
|
3464
|
+
return path.join(this.baseDir, "archive");
|
|
3727
3465
|
}
|
|
3728
3466
|
/**
|
|
3729
3467
|
* Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
|
|
@@ -3734,7 +3472,7 @@ ${memory.content}
|
|
|
3734
3472
|
try {
|
|
3735
3473
|
const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
|
|
3736
3474
|
const today = now.toISOString().slice(0, 10);
|
|
3737
|
-
const destDir =
|
|
3475
|
+
const destDir = path.join(this.archiveDir, today);
|
|
3738
3476
|
await mkdir(destDir, { recursive: true });
|
|
3739
3477
|
const updatedFm = {
|
|
3740
3478
|
...memory.frontmatter,
|
|
@@ -3746,7 +3484,7 @@ ${memory.content}
|
|
|
3746
3484
|
|
|
3747
3485
|
${memory.content}
|
|
3748
3486
|
`;
|
|
3749
|
-
const destPath =
|
|
3487
|
+
const destPath = path.join(destDir, path.basename(memory.path));
|
|
3750
3488
|
await writeMaybeEncryptedFile(destPath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3751
3489
|
await unlink(memory.path);
|
|
3752
3490
|
this.invalidateAllMemoriesCache();
|
|
@@ -3908,7 +3646,7 @@ ${memory.content}
|
|
|
3908
3646
|
`;
|
|
3909
3647
|
await writeMaybeEncryptedFile(memory.path, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3910
3648
|
this.invalidateAllMemoriesCache();
|
|
3911
|
-
if (memory.path.includes(`${
|
|
3649
|
+
if (memory.path.includes(`${path.sep}cold${path.sep}`)) {
|
|
3912
3650
|
this.invalidateColdMemoriesCache();
|
|
3913
3651
|
}
|
|
3914
3652
|
try {
|
|
@@ -3980,7 +3718,7 @@ ${memory.content}
|
|
|
3980
3718
|
return deleted;
|
|
3981
3719
|
}
|
|
3982
3720
|
async loadBuffer() {
|
|
3983
|
-
const bufferPath =
|
|
3721
|
+
const bufferPath = path.join(this.stateDir, "buffer.json");
|
|
3984
3722
|
try {
|
|
3985
3723
|
const raw = await this.readStorageSecureFile(bufferPath);
|
|
3986
3724
|
return JSON.parse(raw);
|
|
@@ -3992,11 +3730,11 @@ ${memory.content}
|
|
|
3992
3730
|
}
|
|
3993
3731
|
async saveBuffer(state) {
|
|
3994
3732
|
await this.ensureDirectories();
|
|
3995
|
-
const bufferPath =
|
|
3733
|
+
const bufferPath = path.join(this.stateDir, "buffer.json");
|
|
3996
3734
|
await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
|
|
3997
3735
|
}
|
|
3998
3736
|
async loadMeta() {
|
|
3999
|
-
const metaPath =
|
|
3737
|
+
const metaPath = path.join(this.stateDir, "meta.json");
|
|
4000
3738
|
try {
|
|
4001
3739
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
4002
3740
|
const parsed = JSON.parse(raw);
|
|
@@ -4030,7 +3768,7 @@ ${memory.content}
|
|
|
4030
3768
|
}
|
|
4031
3769
|
async saveMeta(state) {
|
|
4032
3770
|
await this.ensureDirectories();
|
|
4033
|
-
const metaPath =
|
|
3771
|
+
const metaPath = path.join(this.stateDir, "meta.json");
|
|
4034
3772
|
await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
|
|
4035
3773
|
}
|
|
4036
3774
|
async appendMemoryActionEvents(events) {
|
|
@@ -4200,7 +3938,7 @@ ${memory.content}
|
|
|
4200
3938
|
async appendReextractJobs(events) {
|
|
4201
3939
|
if (events.length === 0) return 0;
|
|
4202
3940
|
await this.ensureDirectories();
|
|
4203
|
-
const filePath =
|
|
3941
|
+
const filePath = path.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4204
3942
|
const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
|
|
4205
3943
|
try {
|
|
4206
3944
|
await this.appendStorageSecureFile(filePath, lines);
|
|
@@ -4213,7 +3951,7 @@ ${memory.content}
|
|
|
4213
3951
|
}
|
|
4214
3952
|
async readReextractJobs(limit = 200) {
|
|
4215
3953
|
const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
|
|
4216
|
-
const filePath =
|
|
3954
|
+
const filePath = path.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4217
3955
|
try {
|
|
4218
3956
|
const raw = await this.readStorageSecureFile(filePath);
|
|
4219
3957
|
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
@@ -4385,7 +4123,7 @@ ${memory.content}
|
|
|
4385
4123
|
return false;
|
|
4386
4124
|
}
|
|
4387
4125
|
if (draftState.contentHash) {
|
|
4388
|
-
const contentHash =
|
|
4126
|
+
const contentHash = createHash("sha256").update(draftContent).digest("hex");
|
|
4389
4127
|
if (contentHash !== draftState.contentHash) return false;
|
|
4390
4128
|
}
|
|
4391
4129
|
await this.writeCompressionGuidelines(draftContent);
|
|
@@ -4467,7 +4205,7 @@ ${memory.content}
|
|
|
4467
4205
|
const date = nowIso.slice(0, 10);
|
|
4468
4206
|
const id = this.generateId("incident");
|
|
4469
4207
|
const incident = createContinuityIncidentRecord(id, input, nowIso);
|
|
4470
|
-
const filePath =
|
|
4208
|
+
const filePath = path.join(this.identityIncidentsDir, `${date}-${id}.md`);
|
|
4471
4209
|
await this.writeStorageSecureFile(filePath, serializeContinuityIncident(incident));
|
|
4472
4210
|
return { ...incident, filePath };
|
|
4473
4211
|
}
|
|
@@ -4480,7 +4218,7 @@ ${memory.content}
|
|
|
4480
4218
|
const incidents = [];
|
|
4481
4219
|
for (const file of candidates) {
|
|
4482
4220
|
if (incidents.length >= cappedLimit) break;
|
|
4483
|
-
const filePath =
|
|
4221
|
+
const filePath = path.join(this.identityIncidentsDir, file);
|
|
4484
4222
|
try {
|
|
4485
4223
|
const raw = await this.readStorageSecureFile(filePath);
|
|
4486
4224
|
const parsed = parseContinuityIncident(raw);
|
|
@@ -4511,7 +4249,7 @@ ${memory.content}
|
|
|
4511
4249
|
await this.ensureDirectories();
|
|
4512
4250
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4513
4251
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4514
|
-
const filePath =
|
|
4252
|
+
const filePath = path.join(dir, `${safeKey}.md`);
|
|
4515
4253
|
await this.writeStorageSecureFile(filePath, content);
|
|
4516
4254
|
return filePath;
|
|
4517
4255
|
}
|
|
@@ -4519,7 +4257,7 @@ ${memory.content}
|
|
|
4519
4257
|
try {
|
|
4520
4258
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4521
4259
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4522
|
-
return await this.readStorageSecureFile(
|
|
4260
|
+
return await this.readStorageSecureFile(path.join(dir, `${safeKey}.md`));
|
|
4523
4261
|
} catch (err) {
|
|
4524
4262
|
if (err instanceof Error && err.message === "Invalid identity audit key") return null;
|
|
4525
4263
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -4583,12 +4321,12 @@ ${memory.content}
|
|
|
4583
4321
|
const fileNames = await this.readContinuityIncidentFileNames();
|
|
4584
4322
|
const directMatch = fileNames.find((name) => name.endsWith(`-${id}.md`));
|
|
4585
4323
|
if (directMatch) {
|
|
4586
|
-
const directPath =
|
|
4324
|
+
const directPath = path.join(this.identityIncidentsDir, directMatch);
|
|
4587
4325
|
const parsed = await this.readContinuityIncidentFile(directPath);
|
|
4588
4326
|
if (parsed?.id === id) return directPath;
|
|
4589
4327
|
}
|
|
4590
4328
|
for (const fileName of fileNames) {
|
|
4591
|
-
const filePath =
|
|
4329
|
+
const filePath = path.join(this.identityIncidentsDir, fileName);
|
|
4592
4330
|
const parsed = await this.readContinuityIncidentFile(filePath);
|
|
4593
4331
|
if (parsed?.id === id) return filePath;
|
|
4594
4332
|
}
|
|
@@ -4618,7 +4356,7 @@ ${question}
|
|
|
4618
4356
|
|
|
4619
4357
|
**Context:** ${context}
|
|
4620
4358
|
`;
|
|
4621
|
-
const filePath =
|
|
4359
|
+
const filePath = path.join(this.questionsDir, `${id}.md`);
|
|
4622
4360
|
await writeFile(filePath, content, "utf-8");
|
|
4623
4361
|
log.debug(`wrote question ${id} to ${filePath}`);
|
|
4624
4362
|
this.invalidateQuestionsCache();
|
|
@@ -4642,7 +4380,7 @@ ${question}
|
|
|
4642
4380
|
const questions = [];
|
|
4643
4381
|
for (const file of files) {
|
|
4644
4382
|
if (!file.endsWith(".md")) continue;
|
|
4645
|
-
const filePath =
|
|
4383
|
+
const filePath = path.join(this.questionsDir, file);
|
|
4646
4384
|
const raw = await readMaybeEncryptedFile(filePath, this._secureStoreKey, this.baseDir);
|
|
4647
4385
|
const parsed = this.parseQuestionFile(raw, filePath);
|
|
4648
4386
|
if (parsed) {
|
|
@@ -4665,7 +4403,7 @@ ${question}
|
|
|
4665
4403
|
if (!match) return null;
|
|
4666
4404
|
const frontmatterStr = match[1];
|
|
4667
4405
|
const body = match[2].trim();
|
|
4668
|
-
const id = this.extractFrontmatterValue(frontmatterStr, "id") ??
|
|
4406
|
+
const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path.basename(filePath, ".md");
|
|
4669
4407
|
const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
|
|
4670
4408
|
const priority = parseFloat(
|
|
4671
4409
|
this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5"
|
|
@@ -4727,11 +4465,11 @@ ${question}
|
|
|
4727
4465
|
} catch {
|
|
4728
4466
|
}
|
|
4729
4467
|
const hygiene = opts?.hygiene;
|
|
4730
|
-
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(
|
|
4468
|
+
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path.basename(identityPath));
|
|
4731
4469
|
if (rotateEnabled) {
|
|
4732
4470
|
const maxBytes = hygiene.rotateMaxBytes;
|
|
4733
4471
|
if (existing.length > maxBytes) {
|
|
4734
|
-
const archiveDir =
|
|
4472
|
+
const archiveDir = path.join(workspaceDir, hygiene.archiveDir);
|
|
4735
4473
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
4736
4474
|
filePath: identityPath,
|
|
4737
4475
|
archiveDir,
|
|
@@ -4825,7 +4563,7 @@ ${reflection}
|
|
|
4825
4563
|
* Deduplicates by target+label.
|
|
4826
4564
|
*/
|
|
4827
4565
|
async addEntityRelationship(name, rel) {
|
|
4828
|
-
const filePath =
|
|
4566
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4829
4567
|
let entity;
|
|
4830
4568
|
try {
|
|
4831
4569
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4850,7 +4588,7 @@ ${reflection}
|
|
|
4850
4588
|
* Prepends to the beginning, prunes oldest entries beyond maxEntries.
|
|
4851
4589
|
*/
|
|
4852
4590
|
async addEntityActivity(name, entry, maxEntries) {
|
|
4853
|
-
const filePath =
|
|
4591
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4854
4592
|
let entity;
|
|
4855
4593
|
try {
|
|
4856
4594
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4873,7 +4611,7 @@ ${reflection}
|
|
|
4873
4611
|
* Add an alias to an entity file. Deduplicates.
|
|
4874
4612
|
*/
|
|
4875
4613
|
async addEntityAlias(name, alias) {
|
|
4876
|
-
const filePath =
|
|
4614
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4877
4615
|
let entity;
|
|
4878
4616
|
try {
|
|
4879
4617
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4894,7 +4632,7 @@ ${reflection}
|
|
|
4894
4632
|
* Set or rewrite the synthesis layer of an entity file.
|
|
4895
4633
|
*/
|
|
4896
4634
|
async updateEntitySynthesis(name, synthesis, options = {}) {
|
|
4897
|
-
const filePath =
|
|
4635
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4898
4636
|
let entity;
|
|
4899
4637
|
try {
|
|
4900
4638
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4932,7 +4670,7 @@ ${reflection}
|
|
|
4932
4670
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4933
4671
|
let synthesisTimelineCount;
|
|
4934
4672
|
try {
|
|
4935
|
-
const filePath =
|
|
4673
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4936
4674
|
const content = await this.readStorageSecureFile(filePath);
|
|
4937
4675
|
synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
|
|
4938
4676
|
} catch (err) {
|
|
@@ -5015,7 +4753,7 @@ ${reflection}
|
|
|
5015
4753
|
if (!raw) continue;
|
|
5016
4754
|
const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
|
|
5017
4755
|
if (raw.trimEnd() === serialized.trimEnd()) continue;
|
|
5018
|
-
await this.writeStorageSecureFile(
|
|
4756
|
+
await this.writeStorageSecureFile(path.join(this.entitiesDir, `${entityName}.md`), serialized);
|
|
5019
4757
|
migrated += 1;
|
|
5020
4758
|
}
|
|
5021
4759
|
if (migrated > 0) {
|
|
@@ -5051,7 +4789,7 @@ ${reflection}
|
|
|
5051
4789
|
const results = await Promise.all(
|
|
5052
4790
|
batch.map(async (entry) => {
|
|
5053
4791
|
try {
|
|
5054
|
-
return await this.readStorageSecureFile(
|
|
4792
|
+
return await this.readStorageSecureFile(path.join(this.entitiesDir, entry));
|
|
5055
4793
|
} catch (err) {
|
|
5056
4794
|
if (err instanceof SecureStoreLockedError) throw err;
|
|
5057
4795
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -5197,7 +4935,7 @@ ${rows.join("\n")}
|
|
|
5197
4935
|
extraSections: []
|
|
5198
4936
|
};
|
|
5199
4937
|
for (const file of files) {
|
|
5200
|
-
const filePath =
|
|
4938
|
+
const filePath = path.join(this.entitiesDir, file);
|
|
5201
4939
|
try {
|
|
5202
4940
|
const content = await this.readStorageSecureFile(filePath);
|
|
5203
4941
|
const parsed = parseEntityFile(content, this.entitySchemas);
|
|
@@ -5328,10 +5066,10 @@ ${rows.join("\n")}
|
|
|
5328
5066
|
}
|
|
5329
5067
|
mergedEntity.created = mergedEntity.created || mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
5330
5068
|
mergedEntity.updated = mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
5331
|
-
const canonicalPath =
|
|
5069
|
+
const canonicalPath = path.join(this.entitiesDir, `${canonical}.md`);
|
|
5332
5070
|
await this.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.entitySchemas));
|
|
5333
5071
|
for (const file of files) {
|
|
5334
|
-
const filePath =
|
|
5072
|
+
const filePath = path.join(this.entitiesDir, file);
|
|
5335
5073
|
if (filePath !== canonicalPath) {
|
|
5336
5074
|
try {
|
|
5337
5075
|
await unlink(filePath);
|
|
@@ -5430,7 +5168,7 @@ ${memory.content}
|
|
|
5430
5168
|
const filePaths = await this.collectActiveMemoryPaths();
|
|
5431
5169
|
const foundIds = /* @__PURE__ */ new Set();
|
|
5432
5170
|
for (const filePath of filePaths) {
|
|
5433
|
-
const basename =
|
|
5171
|
+
const basename = path.basename(filePath, ".md");
|
|
5434
5172
|
if (wantedIds.has(basename)) {
|
|
5435
5173
|
foundIds.add(basename);
|
|
5436
5174
|
if (foundIds.size === wantedIds.size) break;
|
|
@@ -5530,15 +5268,15 @@ ${sanitized.text}
|
|
|
5530
5268
|
`;
|
|
5531
5269
|
let filePath;
|
|
5532
5270
|
if (category === "correction") {
|
|
5533
|
-
filePath =
|
|
5271
|
+
filePath = path.join(this.correctionsDir, `${id}.md`);
|
|
5534
5272
|
} else if (category === "procedure") {
|
|
5535
|
-
await mkdir(
|
|
5536
|
-
filePath =
|
|
5273
|
+
await mkdir(path.join(this.proceduresDir, today), { recursive: true });
|
|
5274
|
+
filePath = path.join(this.proceduresDir, today, `${id}.md`);
|
|
5537
5275
|
} else if (category === "reasoning_trace") {
|
|
5538
|
-
await mkdir(
|
|
5539
|
-
filePath =
|
|
5276
|
+
await mkdir(path.join(this.reasoningTracesDir, today), { recursive: true });
|
|
5277
|
+
filePath = path.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
5540
5278
|
} else {
|
|
5541
|
-
filePath =
|
|
5279
|
+
filePath = path.join(this.factsDir, today, `${id}.md`);
|
|
5542
5280
|
}
|
|
5543
5281
|
await this.writeStorageSecureFile(filePath, fileContent);
|
|
5544
5282
|
log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
|
|
@@ -5607,14 +5345,14 @@ Reason: ${reason}`, {
|
|
|
5607
5345
|
// Memory Summarization (Phase 4A)
|
|
5608
5346
|
// ---------------------------------------------------------------------------
|
|
5609
5347
|
get summariesDir() {
|
|
5610
|
-
return
|
|
5348
|
+
return path.join(this.baseDir, "summaries");
|
|
5611
5349
|
}
|
|
5612
5350
|
/**
|
|
5613
5351
|
* Write a memory summary.
|
|
5614
5352
|
*/
|
|
5615
5353
|
async writeSummary(summary) {
|
|
5616
5354
|
await mkdir(this.summariesDir, { recursive: true });
|
|
5617
|
-
const filePath =
|
|
5355
|
+
const filePath = path.join(this.summariesDir, `${summary.id}.json`);
|
|
5618
5356
|
await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
|
|
5619
5357
|
log.debug(`wrote summary ${summary.id}`);
|
|
5620
5358
|
}
|
|
@@ -5627,7 +5365,7 @@ Reason: ${reason}`, {
|
|
|
5627
5365
|
const summaries = [];
|
|
5628
5366
|
for (const file of files) {
|
|
5629
5367
|
if (!file.endsWith(".json")) continue;
|
|
5630
|
-
const filePath =
|
|
5368
|
+
const filePath = path.join(this.summariesDir, file);
|
|
5631
5369
|
const raw = await this.readStorageSecureFile(filePath);
|
|
5632
5370
|
summaries.push(JSON.parse(raw));
|
|
5633
5371
|
}
|
|
@@ -5688,7 +5426,7 @@ ${memory.content}
|
|
|
5688
5426
|
* Save topic scores to meta.json.
|
|
5689
5427
|
*/
|
|
5690
5428
|
async saveTopics(topics) {
|
|
5691
|
-
const metaPath =
|
|
5429
|
+
const metaPath = path.join(this.stateDir, "topics.json");
|
|
5692
5430
|
await mkdir(this.stateDir, { recursive: true });
|
|
5693
5431
|
await this.writeStorageSecureFile(metaPath, JSON.stringify({ topics, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
5694
5432
|
log.debug(`saved ${topics.length} topic scores`);
|
|
@@ -5697,7 +5435,7 @@ ${memory.content}
|
|
|
5697
5435
|
* Load topic scores from meta.json.
|
|
5698
5436
|
*/
|
|
5699
5437
|
async loadTopics() {
|
|
5700
|
-
const metaPath =
|
|
5438
|
+
const metaPath = path.join(this.stateDir, "topics.json");
|
|
5701
5439
|
try {
|
|
5702
5440
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
5703
5441
|
return JSON.parse(raw);
|
|
@@ -5775,21 +5513,6 @@ ${memory.content}
|
|
|
5775
5513
|
};
|
|
5776
5514
|
|
|
5777
5515
|
export {
|
|
5778
|
-
DEFAULT_SELF_NAME,
|
|
5779
|
-
emptySpeakerRegistry,
|
|
5780
|
-
speakersFilePath,
|
|
5781
|
-
loadSpeakerRegistry,
|
|
5782
|
-
saveSpeakerRegistry,
|
|
5783
|
-
speakerRegistryKey,
|
|
5784
|
-
resolveSpeaker,
|
|
5785
|
-
distinctSpeakerLabels,
|
|
5786
|
-
WEARABLES_DIR_NAME,
|
|
5787
|
-
isValidTranscriptDate,
|
|
5788
|
-
hashTranscriptBody,
|
|
5789
|
-
composeDayTranscriptBody,
|
|
5790
|
-
composeDayTranscriptMeta,
|
|
5791
|
-
serializeDayTranscript,
|
|
5792
|
-
parseDayTranscript,
|
|
5793
5516
|
normalizeEntityName,
|
|
5794
5517
|
ContentHashIndex,
|
|
5795
5518
|
stripAttributesSuffix,
|
|
@@ -5801,4 +5524,4 @@ export {
|
|
|
5801
5524
|
serializeEntityFile,
|
|
5802
5525
|
StorageManager
|
|
5803
5526
|
};
|
|
5804
|
-
//# sourceMappingURL=chunk-
|
|
5527
|
+
//# sourceMappingURL=chunk-QYGIQ5NM.js.map
|