dotmem 0.0.4 → 0.0.7
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/AGENTS.md +3 -3
- package/LICENSE.md +10 -0
- package/README.md +1 -1
- package/SECURITY.md +2 -4
- package/cli.cjs +934 -33
- package/cli.js +958 -57
- package/global.cjs +1319 -30
- package/global.js +1344 -55
- package/index.cjs +1326 -37
- package/index.js +1350 -61
- package/llms.txt +295 -295
- package/mcp.cjs +1326 -37
- package/mcp.js +1350 -61
- package/package.json +1 -1
package/global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { store, hlc, DEV,
|
|
1
|
+
import { store as store$1, hlc, DEV, dispatch, idb, session, state, PROD, temporal } from 'memorio';
|
|
2
2
|
export { DEV, PROD, dispatch, hlc, idb, session, state, store } from 'memorio';
|
|
3
3
|
import 'memorio/global';
|
|
4
4
|
|
|
@@ -5057,13 +5057,13 @@ var init_mem_repository = __esm({
|
|
|
5057
5057
|
});
|
|
5058
5058
|
}
|
|
5059
5059
|
async loadSources(sourceIds) {
|
|
5060
|
-
const { readFile } = await nodeFs4();
|
|
5060
|
+
const { readFile: readFile4 } = await nodeFs4();
|
|
5061
5061
|
const ids = sourceIds ?? await this.discover();
|
|
5062
5062
|
const sources = [];
|
|
5063
5063
|
for (const sourceId of ids) {
|
|
5064
5064
|
const filePath = memFilePath(this.directoryPath, sourceId);
|
|
5065
5065
|
try {
|
|
5066
|
-
const decoded = await parseMemFile(await
|
|
5066
|
+
const decoded = await parseMemFile(await readFile4(filePath), sourceId);
|
|
5067
5067
|
sources.push({
|
|
5068
5068
|
id: sourceId,
|
|
5069
5069
|
filePath,
|
|
@@ -5147,10 +5147,10 @@ var init_mem_repository = __esm({
|
|
|
5147
5147
|
* valid package, so the backup is always a version this library can read.
|
|
5148
5148
|
*/
|
|
5149
5149
|
async keepLastValidVersion(filePath) {
|
|
5150
|
-
const { readFile, copyFile, rename, rm } = await nodeFs4();
|
|
5150
|
+
const { readFile: readFile4, copyFile, rename, rm } = await nodeFs4();
|
|
5151
5151
|
let current;
|
|
5152
5152
|
try {
|
|
5153
|
-
current = await
|
|
5153
|
+
current = await readFile4(filePath);
|
|
5154
5154
|
} catch {
|
|
5155
5155
|
return;
|
|
5156
5156
|
}
|
|
@@ -5183,7 +5183,7 @@ var init_mem_repository = __esm({
|
|
|
5183
5183
|
}
|
|
5184
5184
|
}
|
|
5185
5185
|
async writeSource(filePath, state3, preserved, preservedPackage) {
|
|
5186
|
-
const { mkdir, rename, rm, open, readFile } = await nodeFs4();
|
|
5186
|
+
const { mkdir, rename, rm, open, readFile: readFile4 } = await nodeFs4();
|
|
5187
5187
|
if (!Number.isInteger(state3.version) || state3.version < 0) throw new Error("Invalid writable .mem knowledge version");
|
|
5188
5188
|
for (const claim of state3.claims) validateClaim(claim);
|
|
5189
5189
|
await mkdir(parentPath(filePath), { recursive: true });
|
|
@@ -5205,7 +5205,7 @@ var init_mem_repository = __esm({
|
|
|
5205
5205
|
} finally {
|
|
5206
5206
|
await handle.close();
|
|
5207
5207
|
}
|
|
5208
|
-
await decodeMemArtifact(await
|
|
5208
|
+
await decodeMemArtifact(await readFile4(temporary));
|
|
5209
5209
|
await this.keepLastValidVersion(filePath);
|
|
5210
5210
|
for (let attempt = 0; attempt < 5; attempt++) {
|
|
5211
5211
|
try {
|
|
@@ -5233,8 +5233,8 @@ var init_mem_repository = __esm({
|
|
|
5233
5233
|
// core/knowledge/project-anchor.ts
|
|
5234
5234
|
async function projectAnchorExists(projectId) {
|
|
5235
5235
|
try {
|
|
5236
|
-
const { readFile } = await import('fs/promises');
|
|
5237
|
-
await
|
|
5236
|
+
const { readFile: readFile4 } = await import('fs/promises');
|
|
5237
|
+
await readFile4(resolveUserProjectMemoryPath(projectId));
|
|
5238
5238
|
return true;
|
|
5239
5239
|
} catch {
|
|
5240
5240
|
return false;
|
|
@@ -5270,7 +5270,7 @@ var init_project_anchor = __esm({
|
|
|
5270
5270
|
var configureUserIdentityStore;
|
|
5271
5271
|
var init_user_identity = __esm({
|
|
5272
5272
|
"core/knowledge/user-identity.ts"() {
|
|
5273
|
-
configureUserIdentityStore = /* @__PURE__ */ __name((
|
|
5273
|
+
configureUserIdentityStore = /* @__PURE__ */ __name((store7) => {
|
|
5274
5274
|
}, "configureUserIdentityStore");
|
|
5275
5275
|
}
|
|
5276
5276
|
});
|
|
@@ -5874,9 +5874,155 @@ var init_staging = __esm({
|
|
|
5874
5874
|
});
|
|
5875
5875
|
|
|
5876
5876
|
// core/knowledge/loops.ts
|
|
5877
|
+
function joinPath3(base, child) {
|
|
5878
|
+
const separator3 = process.platform === "win32" ? "\\" : "/";
|
|
5879
|
+
return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
|
|
5880
|
+
}
|
|
5881
|
+
function resolveLoopsFilePath() {
|
|
5882
|
+
return joinPath3(resolveUserDotMemPath(), LOOPS_FILE_NAME);
|
|
5883
|
+
}
|
|
5884
|
+
async function readFile(path) {
|
|
5885
|
+
try {
|
|
5886
|
+
const fs = await import('fs/promises');
|
|
5887
|
+
return await fs.readFile(path, "utf8");
|
|
5888
|
+
} catch {
|
|
5889
|
+
return null;
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
async function writeFile(path, content) {
|
|
5893
|
+
const fs = await import('fs/promises');
|
|
5894
|
+
const dir = path.replace(/[\\/][^\\/]+$/, "");
|
|
5895
|
+
await fs.mkdir(dir, { recursive: true });
|
|
5896
|
+
const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
5897
|
+
try {
|
|
5898
|
+
await fs.writeFile(temporary, content, "utf8");
|
|
5899
|
+
await fs.rename(temporary, path);
|
|
5900
|
+
} catch {
|
|
5901
|
+
await fs.rm(temporary, { force: true }).catch(() => void 0);
|
|
5902
|
+
throw new Error(`Failed to write loops file at ${path}`);
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
function emptyDocument() {
|
|
5906
|
+
return { version: LOOPS_FORMAT_VERSION, loops: {} };
|
|
5907
|
+
}
|
|
5908
|
+
function validateDocument(value) {
|
|
5909
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5910
|
+
throw new Error("Loops document must be an object");
|
|
5911
|
+
}
|
|
5912
|
+
const document = value;
|
|
5913
|
+
if (document.version !== LOOPS_FORMAT_VERSION) {
|
|
5914
|
+
throw new Error(`Unsupported loops document version: ${String(document.version)}`);
|
|
5915
|
+
}
|
|
5916
|
+
if (!document.loops || typeof document.loops !== "object" || Array.isArray(document.loops)) {
|
|
5917
|
+
throw new Error("Loops document loops must be an object");
|
|
5918
|
+
}
|
|
5919
|
+
const loops = {};
|
|
5920
|
+
for (const [id, loopValue] of Object.entries(document.loops)) {
|
|
5921
|
+
const loop = validateLoop(loopValue, id);
|
|
5922
|
+
loops[loop.id] = loop;
|
|
5923
|
+
}
|
|
5924
|
+
return { version: LOOPS_FORMAT_VERSION, loops };
|
|
5925
|
+
}
|
|
5926
|
+
function validateLoop(value, id) {
|
|
5927
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5928
|
+
throw new Error(`Loop ${id} must be an object`);
|
|
5929
|
+
}
|
|
5930
|
+
const loop = value;
|
|
5931
|
+
if (typeof loop.id !== "string" || !loop.id) {
|
|
5932
|
+
throw new Error(`Loop ${id} requires an id`);
|
|
5933
|
+
}
|
|
5934
|
+
if (typeof loop.text !== "string" || !loop.text) {
|
|
5935
|
+
throw new Error(`Loop ${id} requires non-empty text`);
|
|
5936
|
+
}
|
|
5937
|
+
if (typeof loop.waitor !== "string" || !loop.waitor) {
|
|
5938
|
+
throw new Error(`Loop ${id} requires a waitor`);
|
|
5939
|
+
}
|
|
5940
|
+
if (typeof loop.openedAt !== "string" || !loop.openedAt) {
|
|
5941
|
+
throw new Error(`Loop ${id} requires an openedAt timestamp`);
|
|
5942
|
+
}
|
|
5943
|
+
const result = {
|
|
5944
|
+
id: loop.id,
|
|
5945
|
+
text: loop.text,
|
|
5946
|
+
waitor: loop.waitor,
|
|
5947
|
+
openedAt: loop.openedAt
|
|
5948
|
+
};
|
|
5949
|
+
if (typeof loop.closedAt === "string") result.closedAt = loop.closedAt;
|
|
5950
|
+
if (typeof loop.closedBy === "string") result.closedBy = loop.closedBy;
|
|
5951
|
+
if (typeof loop.closeNote === "string") result.closeNote = loop.closeNote;
|
|
5952
|
+
return result;
|
|
5953
|
+
}
|
|
5954
|
+
async function loadLoops() {
|
|
5955
|
+
const raw = await readFile(resolveLoopsFilePath());
|
|
5956
|
+
if (!raw) return emptyDocument();
|
|
5957
|
+
try {
|
|
5958
|
+
return validateDocument(JSON.parse(raw));
|
|
5959
|
+
} catch {
|
|
5960
|
+
return emptyDocument();
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5963
|
+
async function saveLoops(document) {
|
|
5964
|
+
await writeFile(resolveLoopsFilePath(), JSON.stringify(document, null, 2) + "\n");
|
|
5965
|
+
}
|
|
5966
|
+
async function addLoop(input) {
|
|
5967
|
+
const document = await loadLoops();
|
|
5968
|
+
if (document.loops[input.id]) {
|
|
5969
|
+
throw new Error(`Loop ${input.id} already exists`);
|
|
5970
|
+
}
|
|
5971
|
+
const loop = {
|
|
5972
|
+
id: input.id,
|
|
5973
|
+
text: input.text,
|
|
5974
|
+
waitor: input.waitor,
|
|
5975
|
+
openedAt: input.openedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
5976
|
+
};
|
|
5977
|
+
document.loops[loop.id] = loop;
|
|
5978
|
+
await saveLoops(document);
|
|
5979
|
+
return loop;
|
|
5980
|
+
}
|
|
5981
|
+
async function listLoops(openOnly = true) {
|
|
5982
|
+
const document = await loadLoops();
|
|
5983
|
+
const all = Object.values(document.loops);
|
|
5984
|
+
if (openOnly) {
|
|
5985
|
+
return all.filter((loop) => loop.closedAt === void 0);
|
|
5986
|
+
}
|
|
5987
|
+
return all;
|
|
5988
|
+
}
|
|
5989
|
+
async function closeLoop(id, input) {
|
|
5990
|
+
const document = await loadLoops();
|
|
5991
|
+
const existing = document.loops[id];
|
|
5992
|
+
if (!existing) {
|
|
5993
|
+
throw new Error(`Loop ${id} not found`);
|
|
5994
|
+
}
|
|
5995
|
+
if (existing.closedAt) {
|
|
5996
|
+
throw new Error(`Loop ${id} is already closed`);
|
|
5997
|
+
}
|
|
5998
|
+
const closed = {
|
|
5999
|
+
...existing,
|
|
6000
|
+
closedAt: input.closedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
6001
|
+
closedBy: input.by,
|
|
6002
|
+
...input.note ? { closeNote: input.note } : {}
|
|
6003
|
+
};
|
|
6004
|
+
document.loops[id] = closed;
|
|
6005
|
+
await saveLoops(document);
|
|
6006
|
+
return closed;
|
|
6007
|
+
}
|
|
6008
|
+
var LOOPS_FILE_NAME, LOOPS_FORMAT_VERSION;
|
|
5877
6009
|
var init_loops = __esm({
|
|
5878
6010
|
"core/knowledge/loops.ts"() {
|
|
5879
6011
|
init_user_paths();
|
|
6012
|
+
LOOPS_FILE_NAME = "loops.json";
|
|
6013
|
+
LOOPS_FORMAT_VERSION = 1;
|
|
6014
|
+
__name(joinPath3, "joinPath");
|
|
6015
|
+
__name(resolveLoopsFilePath, "resolveLoopsFilePath");
|
|
6016
|
+
__name(readFile, "readFile");
|
|
6017
|
+
__name(writeFile, "writeFile");
|
|
6018
|
+
__name(emptyDocument, "emptyDocument");
|
|
6019
|
+
__name(validateDocument, "validateDocument");
|
|
6020
|
+
__name(validateLoop, "validateLoop");
|
|
6021
|
+
__name(loadLoops, "loadLoops");
|
|
6022
|
+
__name(saveLoops, "saveLoops");
|
|
6023
|
+
__name(addLoop, "addLoop");
|
|
6024
|
+
__name(listLoops, "listLoops");
|
|
6025
|
+
__name(closeLoop, "closeLoop");
|
|
5880
6026
|
}
|
|
5881
6027
|
});
|
|
5882
6028
|
|
|
@@ -5961,16 +6107,368 @@ var init_session = __esm({
|
|
|
5961
6107
|
});
|
|
5962
6108
|
|
|
5963
6109
|
// core/knowledge/exemplars.ts
|
|
6110
|
+
function joinPath4(base, child) {
|
|
6111
|
+
const separator3 = process.platform === "win32" ? "\\" : "/";
|
|
6112
|
+
return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
|
|
6113
|
+
}
|
|
6114
|
+
function resolveExemplarsPath() {
|
|
6115
|
+
return joinPath4(resolveUserDotMemPath(), EXEMPLARS_FILE_NAME);
|
|
6116
|
+
}
|
|
6117
|
+
async function readFile2(path) {
|
|
6118
|
+
try {
|
|
6119
|
+
const fs = await import('fs/promises');
|
|
6120
|
+
return await fs.readFile(path, "utf8");
|
|
6121
|
+
} catch {
|
|
6122
|
+
return null;
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
async function writeFile2(path, content) {
|
|
6126
|
+
const fs = await import('fs/promises');
|
|
6127
|
+
const dir = path.replace(/[\\/][^\\/]+$/, "");
|
|
6128
|
+
await fs.mkdir(dir, { recursive: true });
|
|
6129
|
+
const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
6130
|
+
try {
|
|
6131
|
+
await fs.writeFile(temporary, content, "utf8");
|
|
6132
|
+
await fs.rename(temporary, path);
|
|
6133
|
+
} catch {
|
|
6134
|
+
await fs.rm(temporary, { force: true }).catch(() => void 0);
|
|
6135
|
+
throw new Error(`Failed to write exemplars file at ${path}`);
|
|
6136
|
+
}
|
|
6137
|
+
}
|
|
6138
|
+
function emptyStore() {
|
|
6139
|
+
return { version: EXEMPLARS_FORMAT_VERSION, exemplars: {} };
|
|
6140
|
+
}
|
|
6141
|
+
function validateExemplar(value) {
|
|
6142
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6143
|
+
throw new Error("Exemplar must be an object");
|
|
6144
|
+
}
|
|
6145
|
+
const e = value;
|
|
6146
|
+
if (typeof e.id !== "string" || !e.id) throw new Error("Exemplar requires non-empty id");
|
|
6147
|
+
if (typeof e.pattern !== "string" || !e.pattern) {
|
|
6148
|
+
throw new Error(`Exemplar ${e.id} requires non-empty pattern`);
|
|
6149
|
+
}
|
|
6150
|
+
const source = e.source ?? {};
|
|
6151
|
+
if (typeof source.conversationId !== "string" || !source.conversationId) {
|
|
6152
|
+
throw new Error(`Exemplar ${e.id} requires source.conversationId`);
|
|
6153
|
+
}
|
|
6154
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
6155
|
+
return {
|
|
6156
|
+
id: e.id,
|
|
6157
|
+
type: "interaction-exemplar",
|
|
6158
|
+
source: {
|
|
6159
|
+
conversationId: source.conversationId,
|
|
6160
|
+
messageIds: Array.isArray(source.messageIds) ? source.messageIds.map(String) : [],
|
|
6161
|
+
...typeof source.timestamp === "string" ? { timestamp: source.timestamp } : {}
|
|
6162
|
+
},
|
|
6163
|
+
pattern: e.pattern,
|
|
6164
|
+
originalContent: typeof e.originalContent === "string" ? e.originalContent : null,
|
|
6165
|
+
sourceReference: typeof e.sourceReference === "string" ? e.sourceReference : null,
|
|
6166
|
+
retrievalHints: Array.isArray(e.retrievalHints) ? e.retrievalHints.map(String) : [],
|
|
6167
|
+
significance: typeof e.significance === "number" && e.significance >= 0 ? e.significance : 0,
|
|
6168
|
+
confidence: typeof e.confidence === "number" && e.confidence >= 0 && e.confidence <= 1 ? e.confidence : 0,
|
|
6169
|
+
provenance: ["human-stated", "observed", "inferred"].includes(
|
|
6170
|
+
e.provenance
|
|
6171
|
+
) ? e.provenance : "observed",
|
|
6172
|
+
createdAt: typeof e.createdAt === "string" ? e.createdAt : now2,
|
|
6173
|
+
revision: typeof e.revision === "number" && e.revision > 0 ? e.revision : 1
|
|
6174
|
+
};
|
|
6175
|
+
}
|
|
6176
|
+
function validateStore(value) {
|
|
6177
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6178
|
+
throw new Error("Exemplars document must be an object");
|
|
6179
|
+
}
|
|
6180
|
+
const doc = value;
|
|
6181
|
+
if (doc.version !== EXEMPLARS_FORMAT_VERSION) {
|
|
6182
|
+
throw new Error(`Unsupported exemplars version: ${String(doc.version)}`);
|
|
6183
|
+
}
|
|
6184
|
+
const exemplars = {};
|
|
6185
|
+
if (doc.exemplars && typeof doc.exemplars === "object" && !Array.isArray(doc.exemplars)) {
|
|
6186
|
+
for (const [_, exemplarValue] of Object.entries(doc.exemplars)) {
|
|
6187
|
+
const exemplar = validateExemplar(exemplarValue);
|
|
6188
|
+
exemplars[exemplar.id] = exemplar;
|
|
6189
|
+
}
|
|
6190
|
+
}
|
|
6191
|
+
return { version: EXEMPLARS_FORMAT_VERSION, exemplars };
|
|
6192
|
+
}
|
|
6193
|
+
async function loadExemplars() {
|
|
6194
|
+
const raw = await readFile2(resolveExemplarsPath());
|
|
6195
|
+
if (raw === null) return emptyStore();
|
|
6196
|
+
try {
|
|
6197
|
+
return validateStore(JSON.parse(raw));
|
|
6198
|
+
} catch {
|
|
6199
|
+
return emptyStore();
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
async function saveExemplars(store7) {
|
|
6203
|
+
const validated = validateStore(store7);
|
|
6204
|
+
await writeFile2(resolveExemplarsPath(), JSON.stringify(validated, null, 2));
|
|
6205
|
+
}
|
|
6206
|
+
async function addExemplar(exemplar) {
|
|
6207
|
+
const store7 = await loadExemplars();
|
|
6208
|
+
if (store7.exemplars[exemplar.id]) {
|
|
6209
|
+
throw new Error(`Exemplar ${exemplar.id} already exists`);
|
|
6210
|
+
}
|
|
6211
|
+
if (exemplar.sourceReference) {
|
|
6212
|
+
const existingRef = Object.values(store7.exemplars).find(
|
|
6213
|
+
(e) => e.sourceReference === exemplar.sourceReference
|
|
6214
|
+
);
|
|
6215
|
+
if (existingRef) {
|
|
6216
|
+
throw new Error(`Exemplar with source reference ${exemplar.sourceReference} already exists (id: ${existingRef.id})`);
|
|
6217
|
+
}
|
|
6218
|
+
}
|
|
6219
|
+
const full = {
|
|
6220
|
+
...exemplar,
|
|
6221
|
+
type: "interaction-exemplar",
|
|
6222
|
+
revision: 1
|
|
6223
|
+
};
|
|
6224
|
+
store7.exemplars[exemplar.id] = full;
|
|
6225
|
+
await saveExemplars(store7);
|
|
6226
|
+
return full;
|
|
6227
|
+
}
|
|
6228
|
+
async function updateExemplar(id, updates) {
|
|
6229
|
+
const store7 = await loadExemplars();
|
|
6230
|
+
const existing = store7.exemplars[id];
|
|
6231
|
+
if (!existing) {
|
|
6232
|
+
throw new Error(`Exemplar ${id} not found`);
|
|
6233
|
+
}
|
|
6234
|
+
const updated = {
|
|
6235
|
+
...existing,
|
|
6236
|
+
...updates,
|
|
6237
|
+
id: existing.id,
|
|
6238
|
+
type: "interaction-exemplar",
|
|
6239
|
+
createdAt: existing.createdAt,
|
|
6240
|
+
revision: (updates.revision ?? existing.revision) + 1
|
|
6241
|
+
};
|
|
6242
|
+
store7.exemplars[id] = updated;
|
|
6243
|
+
await saveExemplars(store7);
|
|
6244
|
+
return updated;
|
|
6245
|
+
}
|
|
6246
|
+
var EXEMPLARS_FILE_NAME, EXEMPLARS_FORMAT_VERSION;
|
|
5964
6247
|
var init_exemplars = __esm({
|
|
5965
6248
|
"core/knowledge/exemplars.ts"() {
|
|
5966
6249
|
init_user_paths();
|
|
6250
|
+
EXEMPLARS_FILE_NAME = "exemplars.json";
|
|
6251
|
+
EXEMPLARS_FORMAT_VERSION = 1;
|
|
6252
|
+
__name(joinPath4, "joinPath");
|
|
6253
|
+
__name(resolveExemplarsPath, "resolveExemplarsPath");
|
|
6254
|
+
__name(readFile2, "readFile");
|
|
6255
|
+
__name(writeFile2, "writeFile");
|
|
6256
|
+
__name(emptyStore, "emptyStore");
|
|
6257
|
+
__name(validateExemplar, "validateExemplar");
|
|
6258
|
+
__name(validateStore, "validateStore");
|
|
6259
|
+
__name(loadExemplars, "loadExemplars");
|
|
6260
|
+
__name(saveExemplars, "saveExemplars");
|
|
6261
|
+
__name(addExemplar, "addExemplar");
|
|
6262
|
+
__name(updateExemplar, "updateExemplar");
|
|
5967
6263
|
}
|
|
5968
6264
|
});
|
|
5969
6265
|
|
|
5970
6266
|
// core/knowledge/personality-anchor.ts
|
|
6267
|
+
function joinPath5(base, child) {
|
|
6268
|
+
const separator3 = process.platform === "win32" ? "\\" : "/";
|
|
6269
|
+
return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
|
|
6270
|
+
}
|
|
6271
|
+
function resolvePersonalityAnchorPath() {
|
|
6272
|
+
return joinPath5(resolveUserDotMemPath(), PERSONALITY_ANCHOR_FILE_NAME);
|
|
6273
|
+
}
|
|
6274
|
+
async function readFile3(path) {
|
|
6275
|
+
try {
|
|
6276
|
+
const fs = await import('fs/promises');
|
|
6277
|
+
return await fs.readFile(path, "utf8");
|
|
6278
|
+
} catch {
|
|
6279
|
+
return null;
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
async function writeFile3(path, content) {
|
|
6283
|
+
const fs = await import('fs/promises');
|
|
6284
|
+
const dir = path.replace(/[\\/][^\\/]+$/, "");
|
|
6285
|
+
await fs.mkdir(dir, { recursive: true });
|
|
6286
|
+
const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
6287
|
+
try {
|
|
6288
|
+
await fs.writeFile(temporary, content, "utf8");
|
|
6289
|
+
await fs.rename(temporary, path);
|
|
6290
|
+
} catch {
|
|
6291
|
+
await fs.rm(temporary, { force: true }).catch(() => void 0);
|
|
6292
|
+
throw new Error(`Failed to write personality anchor at ${path}`);
|
|
6293
|
+
}
|
|
6294
|
+
}
|
|
6295
|
+
function emptyAnchor() {
|
|
6296
|
+
const epoch = "1970-01-01T00:00:00.000Z";
|
|
6297
|
+
return {
|
|
6298
|
+
version: PERSONALITY_ANCHOR_FORMAT_VERSION,
|
|
6299
|
+
identity: {
|
|
6300
|
+
communicationStyle: [],
|
|
6301
|
+
durablePreferences: [],
|
|
6302
|
+
interactionBoundaries: []
|
|
6303
|
+
},
|
|
6304
|
+
metadata: {
|
|
6305
|
+
createdAt: epoch,
|
|
6306
|
+
updatedAt: epoch,
|
|
6307
|
+
revision: 1,
|
|
6308
|
+
sourceReferences: []
|
|
6309
|
+
}
|
|
6310
|
+
};
|
|
6311
|
+
}
|
|
6312
|
+
function validateCommunicationStyle(value) {
|
|
6313
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6314
|
+
throw new Error("communicationStyle entry must be an object");
|
|
6315
|
+
}
|
|
6316
|
+
const style = value;
|
|
6317
|
+
if (typeof style.description !== "string" || !style.description) {
|
|
6318
|
+
throw new Error("communicationStyle entry requires non-empty description");
|
|
6319
|
+
}
|
|
6320
|
+
const confidence = style.confidence ?? "inferred";
|
|
6321
|
+
if (!["inferred", "observed", "human-stated"].includes(confidence)) {
|
|
6322
|
+
throw new Error(`Invalid confidence value: ${String(style.confidence)}`);
|
|
6323
|
+
}
|
|
6324
|
+
const evidence = Array.isArray(style.evidence) ? style.evidence.map(String) : [];
|
|
6325
|
+
return {
|
|
6326
|
+
description: style.description,
|
|
6327
|
+
confidence,
|
|
6328
|
+
evidence,
|
|
6329
|
+
lastObserved: typeof style.lastObserved === "string" ? style.lastObserved : (/* @__PURE__ */ new Date()).toISOString()
|
|
6330
|
+
};
|
|
6331
|
+
}
|
|
6332
|
+
function validateDurablePreference(value) {
|
|
6333
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6334
|
+
throw new Error("durablePreference entry must be an object");
|
|
6335
|
+
}
|
|
6336
|
+
const pref = value;
|
|
6337
|
+
if (typeof pref.id !== "string" || !pref.id) {
|
|
6338
|
+
throw new Error("durablePreference entry requires non-empty id");
|
|
6339
|
+
}
|
|
6340
|
+
if (typeof pref.statement !== "string" || !pref.statement) {
|
|
6341
|
+
throw new Error(`durablePreference ${pref.id} requires non-empty statement`);
|
|
6342
|
+
}
|
|
6343
|
+
const confidence = pref.confidence ?? "inferred";
|
|
6344
|
+
if (!["inferred", "observed", "human-stated"].includes(confidence)) {
|
|
6345
|
+
throw new Error(`Invalid confidence value: ${String(pref.confidence)}`);
|
|
6346
|
+
}
|
|
6347
|
+
const evidence = Array.isArray(pref.evidence) ? pref.evidence.map(String) : [];
|
|
6348
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
6349
|
+
return {
|
|
6350
|
+
id: pref.id,
|
|
6351
|
+
statement: pref.statement,
|
|
6352
|
+
confidence,
|
|
6353
|
+
evidence,
|
|
6354
|
+
firstObserved: typeof pref.firstObserved === "string" ? pref.firstObserved : now2,
|
|
6355
|
+
lastConfirmed: typeof pref.lastConfirmed === "string" ? pref.lastConfirmed : now2,
|
|
6356
|
+
...typeof pref.supersededBy === "string" ? { supersededBy: pref.supersededBy } : {}
|
|
6357
|
+
};
|
|
6358
|
+
}
|
|
6359
|
+
function validateInteractionBoundary(value) {
|
|
6360
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6361
|
+
throw new Error("interactionBoundary entry must be an object");
|
|
6362
|
+
}
|
|
6363
|
+
const boundary = value;
|
|
6364
|
+
if (typeof boundary.id !== "string" || !boundary.id) {
|
|
6365
|
+
throw new Error("interactionBoundary entry requires non-empty id");
|
|
6366
|
+
}
|
|
6367
|
+
if (typeof boundary.rule !== "string" || !boundary.rule) {
|
|
6368
|
+
throw new Error(`interactionBoundary ${boundary.id} requires non-empty rule`);
|
|
6369
|
+
}
|
|
6370
|
+
const confidence = boundary.confidence ?? "inferred";
|
|
6371
|
+
if (!["inferred", "observed", "human-stated"].includes(confidence)) {
|
|
6372
|
+
throw new Error(`Invalid confidence value: ${String(boundary.confidence)}`);
|
|
6373
|
+
}
|
|
6374
|
+
const evidence = Array.isArray(boundary.evidence) ? boundary.evidence.map(String) : [];
|
|
6375
|
+
const source = boundary.source ?? "conversation";
|
|
6376
|
+
if (!["profile", "memory", "conversation"].includes(source)) {
|
|
6377
|
+
throw new Error(`Invalid boundary source: ${String(boundary.source)}`);
|
|
6378
|
+
}
|
|
6379
|
+
return {
|
|
6380
|
+
id: boundary.id,
|
|
6381
|
+
rule: boundary.rule,
|
|
6382
|
+
confidence,
|
|
6383
|
+
evidence,
|
|
6384
|
+
source,
|
|
6385
|
+
lastConfirmed: typeof boundary.lastConfirmed === "string" ? boundary.lastConfirmed : (/* @__PURE__ */ new Date()).toISOString()
|
|
6386
|
+
};
|
|
6387
|
+
}
|
|
6388
|
+
function validateAnchor(value) {
|
|
6389
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6390
|
+
throw new Error("Personality anchor document must be an object");
|
|
6391
|
+
}
|
|
6392
|
+
const doc = value;
|
|
6393
|
+
if (doc.version !== PERSONALITY_ANCHOR_FORMAT_VERSION) {
|
|
6394
|
+
throw new Error(`Unsupported personality anchor version: ${String(doc.version)}`);
|
|
6395
|
+
}
|
|
6396
|
+
const identity = doc.identity ?? {};
|
|
6397
|
+
const metadata = doc.metadata ?? {};
|
|
6398
|
+
const communicationStyle = Array.isArray(identity.communicationStyle) ? identity.communicationStyle.map(validateCommunicationStyle) : [];
|
|
6399
|
+
const durablePreferences = Array.isArray(identity.durablePreferences) ? identity.durablePreferences.map(validateDurablePreference) : [];
|
|
6400
|
+
const interactionBoundaries = Array.isArray(identity.interactionBoundaries) ? identity.interactionBoundaries.map(validateInteractionBoundary) : [];
|
|
6401
|
+
const sourceRefs = Array.isArray(metadata.sourceReferences) ? metadata.sourceReferences.map(String) : [];
|
|
6402
|
+
return {
|
|
6403
|
+
version: PERSONALITY_ANCHOR_FORMAT_VERSION,
|
|
6404
|
+
identity: {
|
|
6405
|
+
communicationStyle,
|
|
6406
|
+
durablePreferences,
|
|
6407
|
+
interactionBoundaries
|
|
6408
|
+
},
|
|
6409
|
+
metadata: {
|
|
6410
|
+
createdAt: typeof metadata.createdAt === "string" ? metadata.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
6411
|
+
updatedAt: typeof metadata.updatedAt === "string" ? metadata.updatedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
6412
|
+
revision: typeof metadata.revision === "number" && metadata.revision > 0 ? metadata.revision : 1,
|
|
6413
|
+
sourceReferences: sourceRefs
|
|
6414
|
+
}
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
6417
|
+
async function loadPersonalityAnchor() {
|
|
6418
|
+
const raw = await readFile3(resolvePersonalityAnchorPath());
|
|
6419
|
+
if (raw === null) return emptyAnchor();
|
|
6420
|
+
try {
|
|
6421
|
+
const parsed = JSON.parse(raw);
|
|
6422
|
+
return validateAnchor(parsed);
|
|
6423
|
+
} catch {
|
|
6424
|
+
return emptyAnchor();
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
async function savePersonalityAnchor(anchor) {
|
|
6428
|
+
const validated = validateAnchor(anchor);
|
|
6429
|
+
const dirPath = resolveUserDotMemPath();
|
|
6430
|
+
const fs = await import('fs/promises');
|
|
6431
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
6432
|
+
await writeFile3(resolvePersonalityAnchorPath(), JSON.stringify(validated, null, 2));
|
|
6433
|
+
}
|
|
6434
|
+
async function updatePersonalityAnchor(updates) {
|
|
6435
|
+
const existing = await loadPersonalityAnchor();
|
|
6436
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
6437
|
+
const updated = {
|
|
6438
|
+
...existing,
|
|
6439
|
+
identity: {
|
|
6440
|
+
communicationStyle: updates.communicationStyle ?? existing.identity.communicationStyle,
|
|
6441
|
+
durablePreferences: updates.durablePreferences ?? existing.identity.durablePreferences,
|
|
6442
|
+
interactionBoundaries: updates.interactionBoundaries ?? existing.identity.interactionBoundaries
|
|
6443
|
+
},
|
|
6444
|
+
metadata: {
|
|
6445
|
+
...existing.metadata,
|
|
6446
|
+
updatedAt: now2,
|
|
6447
|
+
revision: existing.metadata.revision + 1,
|
|
6448
|
+
sourceReferences: updates.sourceReferences ? [.../* @__PURE__ */ new Set([...existing.metadata.sourceReferences, ...updates.sourceReferences])] : existing.metadata.sourceReferences
|
|
6449
|
+
}
|
|
6450
|
+
};
|
|
6451
|
+
await savePersonalityAnchor(updated);
|
|
6452
|
+
return updated;
|
|
6453
|
+
}
|
|
6454
|
+
var PERSONALITY_ANCHOR_FILE_NAME, PERSONALITY_ANCHOR_FORMAT_VERSION;
|
|
5971
6455
|
var init_personality_anchor = __esm({
|
|
5972
6456
|
"core/knowledge/personality-anchor.ts"() {
|
|
5973
6457
|
init_user_paths();
|
|
6458
|
+
PERSONALITY_ANCHOR_FILE_NAME = "personality-anchor.json";
|
|
6459
|
+
PERSONALITY_ANCHOR_FORMAT_VERSION = 1;
|
|
6460
|
+
__name(joinPath5, "joinPath");
|
|
6461
|
+
__name(resolvePersonalityAnchorPath, "resolvePersonalityAnchorPath");
|
|
6462
|
+
__name(readFile3, "readFile");
|
|
6463
|
+
__name(writeFile3, "writeFile");
|
|
6464
|
+
__name(emptyAnchor, "emptyAnchor");
|
|
6465
|
+
__name(validateCommunicationStyle, "validateCommunicationStyle");
|
|
6466
|
+
__name(validateDurablePreference, "validateDurablePreference");
|
|
6467
|
+
__name(validateInteractionBoundary, "validateInteractionBoundary");
|
|
6468
|
+
__name(validateAnchor, "validateAnchor");
|
|
6469
|
+
__name(loadPersonalityAnchor, "loadPersonalityAnchor");
|
|
6470
|
+
__name(savePersonalityAnchor, "savePersonalityAnchor");
|
|
6471
|
+
__name(updatePersonalityAnchor, "updatePersonalityAnchor");
|
|
5974
6472
|
}
|
|
5975
6473
|
});
|
|
5976
6474
|
|
|
@@ -6652,19 +7150,19 @@ var journal = {
|
|
|
6652
7150
|
hlc: entry.hlc || hlc.serialize(hlc.tick())
|
|
6653
7151
|
};
|
|
6654
7152
|
const key = `${STORE_PREFIX(ns)}${row.id}`;
|
|
6655
|
-
store.set(key, row);
|
|
6656
|
-
const idx = store.get(INDEX_KEY(ns)) || [];
|
|
7153
|
+
store$1.set(key, row);
|
|
7154
|
+
const idx = store$1.get(INDEX_KEY(ns)) || [];
|
|
6657
7155
|
if (!idx.includes(row.id)) idx.push(row.id);
|
|
6658
|
-
store.set(INDEX_KEY(ns), idx);
|
|
7156
|
+
store$1.set(INDEX_KEY(ns), idx);
|
|
6659
7157
|
return row;
|
|
6660
7158
|
},
|
|
6661
7159
|
/** All pending (not-yet-synced) entries for the current namespace. */
|
|
6662
7160
|
async pending() {
|
|
6663
7161
|
const ns = namespace();
|
|
6664
7162
|
const out = [];
|
|
6665
|
-
const idx = store.get(INDEX_KEY(ns)) || [];
|
|
7163
|
+
const idx = store$1.get(INDEX_KEY(ns)) || [];
|
|
6666
7164
|
for (const id of idx) {
|
|
6667
|
-
const raw = store.get(`${STORE_PREFIX(ns)}${id}`);
|
|
7165
|
+
const raw = store$1.get(`${STORE_PREFIX(ns)}${id}`);
|
|
6668
7166
|
if (!raw) continue;
|
|
6669
7167
|
const e = parseEntry(raw);
|
|
6670
7168
|
if (e && e.sync !== "synced") out.push(e);
|
|
@@ -6687,31 +7185,31 @@ var journal = {
|
|
|
6687
7185
|
if (!ids.length) return 0;
|
|
6688
7186
|
const ns = namespace();
|
|
6689
7187
|
let count = 0;
|
|
6690
|
-
const idx = store.get(INDEX_KEY(ns)) || [];
|
|
7188
|
+
const idx = store$1.get(INDEX_KEY(ns)) || [];
|
|
6691
7189
|
for (const id of idx) {
|
|
6692
7190
|
if (!ids.includes(id)) continue;
|
|
6693
7191
|
const key = `${STORE_PREFIX(ns)}${id}`;
|
|
6694
|
-
const raw = store.get(key);
|
|
7192
|
+
const raw = store$1.get(key);
|
|
6695
7193
|
if (!raw) continue;
|
|
6696
7194
|
const e = parseEntry(raw);
|
|
6697
7195
|
if (!e || e.sync === "synced") continue;
|
|
6698
7196
|
e.sync = "synced";
|
|
6699
|
-
store.set(key, e);
|
|
7197
|
+
store$1.set(key, e);
|
|
6700
7198
|
count++;
|
|
6701
7199
|
}
|
|
6702
7200
|
return count;
|
|
6703
7201
|
},
|
|
6704
7202
|
async get(id) {
|
|
6705
7203
|
const ns = namespace();
|
|
6706
|
-
const raw = store.get(`${STORE_PREFIX(ns)}${id}`);
|
|
7204
|
+
const raw = store$1.get(`${STORE_PREFIX(ns)}${id}`);
|
|
6707
7205
|
return parseEntry(raw ?? "");
|
|
6708
7206
|
},
|
|
6709
7207
|
/** Remove all journal rows for the current namespace. */
|
|
6710
7208
|
async clear() {
|
|
6711
7209
|
const ns = namespace();
|
|
6712
|
-
const idx = store.get(INDEX_KEY(ns)) || [];
|
|
6713
|
-
for (const id of idx) store.remove(`${STORE_PREFIX(ns)}${id}`);
|
|
6714
|
-
store.remove(INDEX_KEY(ns));
|
|
7210
|
+
const idx = store$1.get(INDEX_KEY(ns)) || [];
|
|
7211
|
+
for (const id of idx) store$1.remove(`${STORE_PREFIX(ns)}${id}`);
|
|
7212
|
+
store$1.remove(INDEX_KEY(ns));
|
|
6715
7213
|
},
|
|
6716
7214
|
/**
|
|
6717
7215
|
* Reconcile the local journal against the configured provider. Pushes pending
|
|
@@ -6790,7 +7288,7 @@ var journal = {
|
|
|
6790
7288
|
*/
|
|
6791
7289
|
async status() {
|
|
6792
7290
|
try {
|
|
6793
|
-
const capabilities = store.capabilities?.();
|
|
7291
|
+
const capabilities = store$1.capabilities?.();
|
|
6794
7292
|
return capabilities?.persistent ? "store" : "memory";
|
|
6795
7293
|
} catch {
|
|
6796
7294
|
return "memory";
|
|
@@ -6851,7 +7349,7 @@ var StoreKnowledgeRepository = class {
|
|
|
6851
7349
|
__name(this, "StoreKnowledgeRepository");
|
|
6852
7350
|
}
|
|
6853
7351
|
async load() {
|
|
6854
|
-
const raw = store.get(KNOWLEDGE_STATE_KEY);
|
|
7352
|
+
const raw = store$1.get(KNOWLEDGE_STATE_KEY);
|
|
6855
7353
|
if (!raw) return { version: 0, claims: [] };
|
|
6856
7354
|
return typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
6857
7355
|
}
|
|
@@ -6861,7 +7359,7 @@ var StoreKnowledgeRepository = class {
|
|
|
6861
7359
|
if (current.version !== expectedVersion) {
|
|
6862
7360
|
throw new Error(`Stale update: expected persisted version ${expectedVersion}, received ${current.version}`);
|
|
6863
7361
|
}
|
|
6864
|
-
store.set(KNOWLEDGE_STATE_KEY, state3);
|
|
7362
|
+
store$1.set(KNOWLEDGE_STATE_KEY, state3);
|
|
6865
7363
|
}, "write");
|
|
6866
7364
|
const previous = knowledgeSaveQueue;
|
|
6867
7365
|
knowledgeSaveQueue = previous.then(write, write);
|
|
@@ -7063,27 +7561,27 @@ var auditPolicyAction = /* @__PURE__ */ __name((action, key) => {
|
|
|
7063
7561
|
}
|
|
7064
7562
|
}, "auditPolicyAction");
|
|
7065
7563
|
var resolveOverrides = /* @__PURE__ */ __name(async (namespace2, now2 = () => /* @__PURE__ */ new Date()) => {
|
|
7066
|
-
const
|
|
7564
|
+
const store7 = await getPolicyStore();
|
|
7067
7565
|
const namespaces = namespace2 ? [namespace2] : POLICY_NAMESPACES;
|
|
7068
|
-
const documents = await Promise.all(namespaces.map((entry) =>
|
|
7566
|
+
const documents = await Promise.all(namespaces.map((entry) => store7.load(entry)));
|
|
7069
7567
|
return documents.flatMap((document) => document.overrides.map(
|
|
7070
7568
|
(override) => resolveOverrideState(override, document.records.find((record) => record.id === override.targetPolicyId), now2)
|
|
7071
7569
|
)).sort((left, right) => left.override.id.localeCompare(right.override.id));
|
|
7072
7570
|
}, "resolveOverrides");
|
|
7073
7571
|
var policy = {
|
|
7074
7572
|
async assign(input, namespace2 = "operator", basedOnRevision) {
|
|
7075
|
-
const
|
|
7076
|
-
const record = await
|
|
7573
|
+
const store7 = await getPolicyStore();
|
|
7574
|
+
const record = await store7.assign(input, namespace2, basedOnRevision);
|
|
7077
7575
|
auditPolicyAction("policy.assign", record.id);
|
|
7078
7576
|
return record;
|
|
7079
7577
|
},
|
|
7080
7578
|
async list() {
|
|
7081
|
-
const
|
|
7082
|
-
return
|
|
7579
|
+
const store7 = await getPolicyStore();
|
|
7580
|
+
return store7.list();
|
|
7083
7581
|
},
|
|
7084
7582
|
async remove(id, namespace2 = "operator", basedOnRevision) {
|
|
7085
|
-
const
|
|
7086
|
-
await
|
|
7583
|
+
const store7 = await getPolicyStore();
|
|
7584
|
+
await store7.remove(id, namespace2, basedOnRevision);
|
|
7087
7585
|
auditPolicyAction("policy.remove", id);
|
|
7088
7586
|
},
|
|
7089
7587
|
/**
|
|
@@ -7097,16 +7595,16 @@ var policy = {
|
|
|
7097
7595
|
* the durable audit trail with a terminal CLEAR entry.
|
|
7098
7596
|
*/
|
|
7099
7597
|
async clear(authority) {
|
|
7100
|
-
const
|
|
7101
|
-
await
|
|
7598
|
+
const store7 = await getPolicyStore();
|
|
7599
|
+
await store7.clear(authority);
|
|
7102
7600
|
auditPolicyAction("policy.clear", "policy");
|
|
7103
7601
|
},
|
|
7104
7602
|
async evaluate(event, payload) {
|
|
7105
|
-
const
|
|
7603
|
+
const store7 = await getPolicyStore();
|
|
7106
7604
|
const [state3, policies, overrides] = await Promise.all([
|
|
7107
7605
|
loadCombinedKnowledgeState(),
|
|
7108
|
-
|
|
7109
|
-
|
|
7606
|
+
store7.list(),
|
|
7607
|
+
store7.listOverrides()
|
|
7110
7608
|
]);
|
|
7111
7609
|
const claims = activeClaims(state3);
|
|
7112
7610
|
return evaluatePolicies({ event, claims, policies, overrides, payload });
|
|
@@ -7128,14 +7626,14 @@ var policy = {
|
|
|
7128
7626
|
*/
|
|
7129
7627
|
override: {
|
|
7130
7628
|
async grant(input, namespace2 = "operator", basedOnRevision) {
|
|
7131
|
-
const
|
|
7132
|
-
const override = await
|
|
7629
|
+
const store7 = await getPolicyStore();
|
|
7630
|
+
const override = await store7.grantOverride(input, namespace2, basedOnRevision);
|
|
7133
7631
|
auditPolicyAction("policy.override", override.id);
|
|
7134
7632
|
return override;
|
|
7135
7633
|
},
|
|
7136
7634
|
async revoke(input, namespace2 = "operator", basedOnRevision) {
|
|
7137
|
-
const
|
|
7138
|
-
const override = await
|
|
7635
|
+
const store7 = await getPolicyStore();
|
|
7636
|
+
const override = await store7.revokeOverride(input, namespace2, basedOnRevision);
|
|
7139
7637
|
auditPolicyAction("policy.revoke", override.id);
|
|
7140
7638
|
return override;
|
|
7141
7639
|
},
|
|
@@ -7143,8 +7641,8 @@ var policy = {
|
|
|
7143
7641
|
return resolveOverrides(namespace2);
|
|
7144
7642
|
},
|
|
7145
7643
|
async effective(event, namespace2) {
|
|
7146
|
-
const
|
|
7147
|
-
const states = await
|
|
7644
|
+
const store7 = await getPolicyStore();
|
|
7645
|
+
const states = await store7.effectiveState(namespace2);
|
|
7148
7646
|
if (event === void 0) return states;
|
|
7149
7647
|
const canonical = event.trim();
|
|
7150
7648
|
return states.filter((state3) => state3.event === canonical);
|
|
@@ -7157,8 +7655,8 @@ var policy = {
|
|
|
7157
7655
|
* additional best-effort sink, and this is the durable record.
|
|
7158
7656
|
*/
|
|
7159
7657
|
async audit(namespace2) {
|
|
7160
|
-
const
|
|
7161
|
-
return
|
|
7658
|
+
const store7 = await getPolicyStore();
|
|
7659
|
+
return store7.auditTrail(namespace2);
|
|
7162
7660
|
},
|
|
7163
7661
|
contract() {
|
|
7164
7662
|
return MEMORY_PROJECTION_CONTRACT;
|
|
@@ -7304,7 +7802,7 @@ async function saveToScope(entry) {
|
|
|
7304
7802
|
session.set(storageKey, serialized);
|
|
7305
7803
|
break;
|
|
7306
7804
|
case "local":
|
|
7307
|
-
store.set(storageKey, serialized);
|
|
7805
|
+
store$1.set(storageKey, serialized);
|
|
7308
7806
|
break;
|
|
7309
7807
|
case "durable":
|
|
7310
7808
|
await idb.set("memories", storageKey, serialized);
|
|
@@ -7326,7 +7824,7 @@ async function loadFromScope(id, scope, isSuperseded = false) {
|
|
|
7326
7824
|
raw = session.get(storageKey);
|
|
7327
7825
|
break;
|
|
7328
7826
|
case "local":
|
|
7329
|
-
raw = store.get(storageKey);
|
|
7827
|
+
raw = store$1.get(storageKey);
|
|
7330
7828
|
break;
|
|
7331
7829
|
case "durable":
|
|
7332
7830
|
raw = await idb.get("memories", storageKey);
|
|
@@ -7370,7 +7868,7 @@ async function removeFromScope(id, scope, isSuperseded = false) {
|
|
|
7370
7868
|
session.remove(storageKey);
|
|
7371
7869
|
break;
|
|
7372
7870
|
case "local":
|
|
7373
|
-
store.remove(storageKey);
|
|
7871
|
+
store$1.remove(storageKey);
|
|
7374
7872
|
break;
|
|
7375
7873
|
case "durable":
|
|
7376
7874
|
await idb.deleteKey("memories", storageKey);
|
|
@@ -7381,7 +7879,7 @@ async function removeFromScope(id, scope, isSuperseded = false) {
|
|
|
7381
7879
|
__name(removeFromScope, "removeFromScope");
|
|
7382
7880
|
async function getAllIndexes() {
|
|
7383
7881
|
try {
|
|
7384
|
-
const raw = store.get(MEMORY_INDEX_KEY);
|
|
7882
|
+
const raw = store$1.get(MEMORY_INDEX_KEY);
|
|
7385
7883
|
if (!raw) return {};
|
|
7386
7884
|
return JSON.parse(raw);
|
|
7387
7885
|
} catch (err2) {
|
|
@@ -7393,7 +7891,7 @@ __name(getAllIndexes, "getAllIndexes");
|
|
|
7393
7891
|
async function updateIndex(id, scope, isSuperseded = false) {
|
|
7394
7892
|
const index = await getAllIndexes();
|
|
7395
7893
|
index[id] = { scope, superseded: isSuperseded };
|
|
7396
|
-
store.set(MEMORY_INDEX_KEY, JSON.stringify(index));
|
|
7894
|
+
store$1.set(MEMORY_INDEX_KEY, JSON.stringify(index));
|
|
7397
7895
|
}
|
|
7398
7896
|
__name(updateIndex, "updateIndex");
|
|
7399
7897
|
async function removeFromIndex(id, isSuperseded = false) {
|
|
@@ -7406,7 +7904,7 @@ async function removeFromIndex(id, isSuperseded = false) {
|
|
|
7406
7904
|
delete index[id];
|
|
7407
7905
|
}
|
|
7408
7906
|
}
|
|
7409
|
-
store.set(MEMORY_INDEX_KEY, JSON.stringify(index));
|
|
7907
|
+
store$1.set(MEMORY_INDEX_KEY, JSON.stringify(index));
|
|
7410
7908
|
}
|
|
7411
7909
|
__name(removeFromIndex, "removeFromIndex");
|
|
7412
7910
|
async function loadAll() {
|
|
@@ -7622,7 +8120,7 @@ var entries = {
|
|
|
7622
8120
|
for (const [id, info] of Object.entries(index)) {
|
|
7623
8121
|
await removeFromScope(id, info.scope, info.superseded);
|
|
7624
8122
|
}
|
|
7625
|
-
store.remove(MEMORY_INDEX_KEY);
|
|
8123
|
+
store$1.remove(MEMORY_INDEX_KEY);
|
|
7626
8124
|
},
|
|
7627
8125
|
async _getEntry(key) {
|
|
7628
8126
|
return getEntry(key);
|
|
@@ -8132,6 +8630,778 @@ var injectJoySeed = /* @__PURE__ */ __name(async (opts) => {
|
|
|
8132
8630
|
return { id: seedId, action: "stored" };
|
|
8133
8631
|
}, "injectJoySeed");
|
|
8134
8632
|
|
|
8633
|
+
// core/memory/capture-engine.ts
|
|
8634
|
+
init_exemplars();
|
|
8635
|
+
init_loops();
|
|
8636
|
+
init_personality_anchor();
|
|
8637
|
+
var CAPTURE_STATE_KEY = "__dotmem_capture_state__";
|
|
8638
|
+
var DEFAULT_CONFIG = {
|
|
8639
|
+
minSignificance: 0.3,
|
|
8640
|
+
maxItemsPerConversation: 50,
|
|
8641
|
+
dedupSimilarityThreshold: 0.75,
|
|
8642
|
+
preserveConflicts: true,
|
|
8643
|
+
tempContextTtlMs: 24 * 60 * 60 * 1e3,
|
|
8644
|
+
autoCreateExemplars: true,
|
|
8645
|
+
autoCreateLoops: true,
|
|
8646
|
+
autoCreateClaims: true
|
|
8647
|
+
};
|
|
8648
|
+
var CATEGORY_KEYWORDS = {
|
|
8649
|
+
fact: [
|
|
8650
|
+
"is",
|
|
8651
|
+
"are",
|
|
8652
|
+
"was",
|
|
8653
|
+
"were",
|
|
8654
|
+
"uses",
|
|
8655
|
+
"built with",
|
|
8656
|
+
"depends on",
|
|
8657
|
+
"located at",
|
|
8658
|
+
"named",
|
|
8659
|
+
"called",
|
|
8660
|
+
"version",
|
|
8661
|
+
"language",
|
|
8662
|
+
"framework",
|
|
8663
|
+
"test",
|
|
8664
|
+
"testing"
|
|
8665
|
+
],
|
|
8666
|
+
decision: [
|
|
8667
|
+
"decided",
|
|
8668
|
+
"decision",
|
|
8669
|
+
"agreed",
|
|
8670
|
+
"chose",
|
|
8671
|
+
"selected",
|
|
8672
|
+
"adopt",
|
|
8673
|
+
"going with",
|
|
8674
|
+
"will use",
|
|
8675
|
+
"commit to",
|
|
8676
|
+
"resolve",
|
|
8677
|
+
"settled"
|
|
8678
|
+
],
|
|
8679
|
+
experience: [
|
|
8680
|
+
"remember when",
|
|
8681
|
+
"we talked about",
|
|
8682
|
+
"discussed",
|
|
8683
|
+
"experienced",
|
|
8684
|
+
"encountered",
|
|
8685
|
+
"faced",
|
|
8686
|
+
"went through",
|
|
8687
|
+
"session",
|
|
8688
|
+
"conversation"
|
|
8689
|
+
],
|
|
8690
|
+
question: [
|
|
8691
|
+
"?",
|
|
8692
|
+
"how do",
|
|
8693
|
+
"what is",
|
|
8694
|
+
"why",
|
|
8695
|
+
"when",
|
|
8696
|
+
"where",
|
|
8697
|
+
"which",
|
|
8698
|
+
"can you",
|
|
8699
|
+
"should we",
|
|
8700
|
+
"is it possible"
|
|
8701
|
+
],
|
|
8702
|
+
open_loop: [
|
|
8703
|
+
"still need to",
|
|
8704
|
+
"pending",
|
|
8705
|
+
"waiting for",
|
|
8706
|
+
"todo",
|
|
8707
|
+
"to do",
|
|
8708
|
+
"open",
|
|
8709
|
+
"unresolved",
|
|
8710
|
+
"outstanding",
|
|
8711
|
+
"follow up",
|
|
8712
|
+
"blocked"
|
|
8713
|
+
],
|
|
8714
|
+
preference: [
|
|
8715
|
+
"prefer",
|
|
8716
|
+
"prefers",
|
|
8717
|
+
"like",
|
|
8718
|
+
"likes",
|
|
8719
|
+
"favorite",
|
|
8720
|
+
"always",
|
|
8721
|
+
"never",
|
|
8722
|
+
"don't like",
|
|
8723
|
+
"dislike",
|
|
8724
|
+
"style",
|
|
8725
|
+
"habit"
|
|
8726
|
+
],
|
|
8727
|
+
project_context: [
|
|
8728
|
+
"project",
|
|
8729
|
+
"repository",
|
|
8730
|
+
"codebase",
|
|
8731
|
+
"architecture",
|
|
8732
|
+
"stack",
|
|
8733
|
+
"deploy",
|
|
8734
|
+
"ci",
|
|
8735
|
+
"pipeline",
|
|
8736
|
+
"package"
|
|
8737
|
+
],
|
|
8738
|
+
temporary_context: [
|
|
8739
|
+
"for now",
|
|
8740
|
+
"just for",
|
|
8741
|
+
"temporary",
|
|
8742
|
+
"this session",
|
|
8743
|
+
"currently",
|
|
8744
|
+
"right now",
|
|
8745
|
+
"at the moment",
|
|
8746
|
+
"for this task"
|
|
8747
|
+
],
|
|
8748
|
+
inference: [
|
|
8749
|
+
"probably",
|
|
8750
|
+
"likely",
|
|
8751
|
+
"maybe",
|
|
8752
|
+
"perhaps",
|
|
8753
|
+
"seems",
|
|
8754
|
+
"appears",
|
|
8755
|
+
"suggests",
|
|
8756
|
+
"indicates",
|
|
8757
|
+
"implies",
|
|
8758
|
+
"might",
|
|
8759
|
+
"could be"
|
|
8760
|
+
]
|
|
8761
|
+
};
|
|
8762
|
+
var REMEMBER_PATTERNS = [
|
|
8763
|
+
/remember this/i,
|
|
8764
|
+
/remember that/i,
|
|
8765
|
+
/keep this in mind/i,
|
|
8766
|
+
/don't forget/i,
|
|
8767
|
+
/do not forget/i,
|
|
8768
|
+
/store this/i,
|
|
8769
|
+
/save this/i
|
|
8770
|
+
];
|
|
8771
|
+
var DO_NOT_REMEMBER_PATTERNS = [
|
|
8772
|
+
/don't remember/i,
|
|
8773
|
+
/do not remember/i,
|
|
8774
|
+
/forget this/i,
|
|
8775
|
+
/don't store/i,
|
|
8776
|
+
/do not store/i,
|
|
8777
|
+
/not relevant/i,
|
|
8778
|
+
/ignore this/i,
|
|
8779
|
+
/temporary only/i,
|
|
8780
|
+
/this session only/i
|
|
8781
|
+
];
|
|
8782
|
+
function generateId() {
|
|
8783
|
+
return `capture-${hlc.serialize(hlc.tick())}-${Math.random().toString(36).slice(2, 10)}`;
|
|
8784
|
+
}
|
|
8785
|
+
__name(generateId, "generateId");
|
|
8786
|
+
function nowIso() {
|
|
8787
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
8788
|
+
}
|
|
8789
|
+
__name(nowIso, "nowIso");
|
|
8790
|
+
function normalizeText(text) {
|
|
8791
|
+
return text.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
8792
|
+
}
|
|
8793
|
+
__name(normalizeText, "normalizeText");
|
|
8794
|
+
function tokenize(text) {
|
|
8795
|
+
return new Set(normalizeText(text).split(" ").filter((t) => t.length > 2));
|
|
8796
|
+
}
|
|
8797
|
+
__name(tokenize, "tokenize");
|
|
8798
|
+
function jaccardSimilarity(a, b) {
|
|
8799
|
+
const ta = tokenize(a);
|
|
8800
|
+
const tb = tokenize(b);
|
|
8801
|
+
if (ta.size === 0 && tb.size === 0) return 1;
|
|
8802
|
+
if (ta.size === 0 || tb.size === 0) return 0;
|
|
8803
|
+
const intersection = new Set([...ta].filter((x2) => tb.has(x2)));
|
|
8804
|
+
const union = /* @__PURE__ */ new Set([...ta, ...tb]);
|
|
8805
|
+
return intersection.size / union.size;
|
|
8806
|
+
}
|
|
8807
|
+
__name(jaccardSimilarity, "jaccardSimilarity");
|
|
8808
|
+
function containsPhrase2(text, phrase) {
|
|
8809
|
+
const t = normalizeText(text);
|
|
8810
|
+
const p = normalizeText(phrase);
|
|
8811
|
+
return t.includes(p);
|
|
8812
|
+
}
|
|
8813
|
+
__name(containsPhrase2, "containsPhrase");
|
|
8814
|
+
function detectExplicitInstructions(text, source) {
|
|
8815
|
+
const instructions = [];
|
|
8816
|
+
for (const pattern of REMEMBER_PATTERNS) {
|
|
8817
|
+
if (pattern.test(text)) {
|
|
8818
|
+
instructions.push({
|
|
8819
|
+
type: "remember",
|
|
8820
|
+
content: text,
|
|
8821
|
+
source,
|
|
8822
|
+
timestamp: nowIso()
|
|
8823
|
+
});
|
|
8824
|
+
break;
|
|
8825
|
+
}
|
|
8826
|
+
}
|
|
8827
|
+
for (const pattern of DO_NOT_REMEMBER_PATTERNS) {
|
|
8828
|
+
if (pattern.test(text)) {
|
|
8829
|
+
instructions.push({
|
|
8830
|
+
type: "do-not-remember",
|
|
8831
|
+
content: text,
|
|
8832
|
+
source,
|
|
8833
|
+
timestamp: nowIso()
|
|
8834
|
+
});
|
|
8835
|
+
break;
|
|
8836
|
+
}
|
|
8837
|
+
}
|
|
8838
|
+
return instructions;
|
|
8839
|
+
}
|
|
8840
|
+
__name(detectExplicitInstructions, "detectExplicitInstructions");
|
|
8841
|
+
function classifyCategory(text, explicitInstructions) {
|
|
8842
|
+
const lower = text.toLocaleLowerCase("en-US");
|
|
8843
|
+
if (explicitInstructions.some((i2) => i2.type === "do-not-remember")) {
|
|
8844
|
+
return "temporary_context";
|
|
8845
|
+
}
|
|
8846
|
+
if (explicitInstructions.some((i2) => i2.type === "remember")) {
|
|
8847
|
+
if (/prefer|prefers|like|likes|favorite|always|never/i.test(lower)) {
|
|
8848
|
+
return "preference";
|
|
8849
|
+
}
|
|
8850
|
+
if (/decided|decision|agreed|chose|adopt/i.test(lower)) {
|
|
8851
|
+
return "decision";
|
|
8852
|
+
}
|
|
8853
|
+
return "fact";
|
|
8854
|
+
}
|
|
8855
|
+
const scores = {};
|
|
8856
|
+
for (const cat of Object.keys(CATEGORY_KEYWORDS)) {
|
|
8857
|
+
scores[cat] = CATEGORY_KEYWORDS[cat].filter((kw) => containsPhrase2(lower, kw)).length;
|
|
8858
|
+
}
|
|
8859
|
+
if (/probably|likely|maybe|perhaps|seems|appears|might|could be/i.test(lower)) {
|
|
8860
|
+
scores.inference += 3;
|
|
8861
|
+
}
|
|
8862
|
+
if (text.includes("?")) {
|
|
8863
|
+
scores.question += 3;
|
|
8864
|
+
}
|
|
8865
|
+
if (/decided|decision|agreed|chose|adopt|will use|going with|resolve|settled/i.test(lower)) {
|
|
8866
|
+
scores.decision += 3;
|
|
8867
|
+
}
|
|
8868
|
+
if (/prefer|prefers|like|likes|favorite|always|never|don.t like|dislike/i.test(lower)) {
|
|
8869
|
+
scores.preference += 3;
|
|
8870
|
+
}
|
|
8871
|
+
if (/still need to|pending|waiting for|todo|to do|unresolved|outstanding|follow.?up|blocked/i.test(lower)) {
|
|
8872
|
+
scores.open_loop += 3;
|
|
8873
|
+
}
|
|
8874
|
+
if (/remember when|we talked about|discussed|experienced|encountered|session|conversation/i.test(lower)) {
|
|
8875
|
+
scores.experience += 2;
|
|
8876
|
+
}
|
|
8877
|
+
if (/repository|architecture|deploy|ci|pipeline/i.test(lower)) {
|
|
8878
|
+
scores.project_context += 2;
|
|
8879
|
+
}
|
|
8880
|
+
if (/just for|this session|for now|temporary/i.test(lower)) {
|
|
8881
|
+
scores.temporary_context += 3;
|
|
8882
|
+
}
|
|
8883
|
+
if (scores.fact > 0 && scores.project_context > 0 && scores.fact === scores.project_context) {
|
|
8884
|
+
scores.fact += 1;
|
|
8885
|
+
}
|
|
8886
|
+
let bestCategory = "fact";
|
|
8887
|
+
let bestScore = -1;
|
|
8888
|
+
for (const [cat, score] of Object.entries(scores)) {
|
|
8889
|
+
if (score > bestScore) {
|
|
8890
|
+
bestScore = score;
|
|
8891
|
+
bestCategory = cat;
|
|
8892
|
+
}
|
|
8893
|
+
}
|
|
8894
|
+
if (bestScore === 0) return "fact";
|
|
8895
|
+
return bestCategory;
|
|
8896
|
+
}
|
|
8897
|
+
__name(classifyCategory, "classifyCategory");
|
|
8898
|
+
function determineEpistemicType(category, text, explicitInstructions) {
|
|
8899
|
+
if (explicitInstructions.some((i2) => i2.type === "remember")) {
|
|
8900
|
+
return "human-stated";
|
|
8901
|
+
}
|
|
8902
|
+
if (category === "inference" || /probably|likely|maybe|perhaps|seems|appears/i.test(text)) {
|
|
8903
|
+
return "inferred";
|
|
8904
|
+
}
|
|
8905
|
+
if (category === "question") return "observed";
|
|
8906
|
+
return "observed";
|
|
8907
|
+
}
|
|
8908
|
+
__name(determineEpistemicType, "determineEpistemicType");
|
|
8909
|
+
function determineConfidence(category, epistemicType, _text) {
|
|
8910
|
+
if (epistemicType === "human-stated") return "high";
|
|
8911
|
+
if (epistemicType === "inferred") return "low";
|
|
8912
|
+
if (category === "decision" || category === "preference") return "medium";
|
|
8913
|
+
if (category === "question") return "medium";
|
|
8914
|
+
if (category === "fact") return "medium";
|
|
8915
|
+
return "low";
|
|
8916
|
+
}
|
|
8917
|
+
__name(determineConfidence, "determineConfidence");
|
|
8918
|
+
function extractEntities(text) {
|
|
8919
|
+
const entities = [];
|
|
8920
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8921
|
+
const capitalizedMatches = text.match(/\b[A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+)*\b/g) || [];
|
|
8922
|
+
for (const match of capitalizedMatches) {
|
|
8923
|
+
if (seen.has(match)) continue;
|
|
8924
|
+
seen.add(match);
|
|
8925
|
+
entities.push({
|
|
8926
|
+
id: `entity-${normalizeText(match)}`,
|
|
8927
|
+
type: "concept",
|
|
8928
|
+
name: match,
|
|
8929
|
+
aliases: [],
|
|
8930
|
+
relationships: []
|
|
8931
|
+
});
|
|
8932
|
+
}
|
|
8933
|
+
const quotedMatches = text.match(/["'`]([^"`']{2,})["'`]/g) || [];
|
|
8934
|
+
for (const match of quotedMatches) {
|
|
8935
|
+
const clean = match.replace(/["'`]/g, "");
|
|
8936
|
+
if (seen.has(clean)) continue;
|
|
8937
|
+
seen.add(clean);
|
|
8938
|
+
entities.push({
|
|
8939
|
+
id: `entity-${normalizeText(clean)}`,
|
|
8940
|
+
type: "concept",
|
|
8941
|
+
name: clean,
|
|
8942
|
+
aliases: [],
|
|
8943
|
+
relationships: []
|
|
8944
|
+
});
|
|
8945
|
+
}
|
|
8946
|
+
return entities;
|
|
8947
|
+
}
|
|
8948
|
+
__name(extractEntities, "extractEntities");
|
|
8949
|
+
function extractRelationships(_text, entities) {
|
|
8950
|
+
const relationships = [];
|
|
8951
|
+
if (entities.length < 2) return relationships;
|
|
8952
|
+
for (let i2 = 0; i2 < entities.length - 1; i2++) {
|
|
8953
|
+
for (let j = i2 + 1; j < entities.length; j++) {
|
|
8954
|
+
relationships.push({
|
|
8955
|
+
from: entities[i2].id,
|
|
8956
|
+
to: entities[j].id,
|
|
8957
|
+
type: "related-to",
|
|
8958
|
+
confidence: 0.5
|
|
8959
|
+
});
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8962
|
+
return relationships;
|
|
8963
|
+
}
|
|
8964
|
+
__name(extractRelationships, "extractRelationships");
|
|
8965
|
+
async function findExistingSimilarItems(statement, category, existingItems, threshold) {
|
|
8966
|
+
const matches2 = [];
|
|
8967
|
+
for (const existing of existingItems) {
|
|
8968
|
+
if (existing.category !== category) continue;
|
|
8969
|
+
const similarity = jaccardSimilarity(statement, existing.statement);
|
|
8970
|
+
if (similarity >= threshold) {
|
|
8971
|
+
matches2.push({
|
|
8972
|
+
existingId: existing.id,
|
|
8973
|
+
existingStatement: existing.statement,
|
|
8974
|
+
similarity,
|
|
8975
|
+
matchType: similarity >= 0.95 ? "exact" : "semantic",
|
|
8976
|
+
category: existing.category
|
|
8977
|
+
});
|
|
8978
|
+
}
|
|
8979
|
+
}
|
|
8980
|
+
return matches2;
|
|
8981
|
+
}
|
|
8982
|
+
__name(findExistingSimilarItems, "findExistingSimilarItems");
|
|
8983
|
+
async function findExistingMemoryEntries(statement, category) {
|
|
8984
|
+
const matches2 = [];
|
|
8985
|
+
try {
|
|
8986
|
+
const all = await entries._loadAll();
|
|
8987
|
+
for (const entry of all) {
|
|
8988
|
+
if (entry.status !== "active") continue;
|
|
8989
|
+
if (entry.type !== category && entry.type !== "fact") continue;
|
|
8990
|
+
const entryText = typeof entry.value === "string" ? entry.value : JSON.stringify(entry.value);
|
|
8991
|
+
const similarity = jaccardSimilarity(statement, entryText);
|
|
8992
|
+
if (similarity >= DEFAULT_CONFIG.dedupSimilarityThreshold) {
|
|
8993
|
+
matches2.push({
|
|
8994
|
+
existingId: entry.id,
|
|
8995
|
+
existingStatement: entryText,
|
|
8996
|
+
similarity,
|
|
8997
|
+
matchType: similarity >= 0.95 ? "exact" : "semantic",
|
|
8998
|
+
category
|
|
8999
|
+
});
|
|
9000
|
+
}
|
|
9001
|
+
}
|
|
9002
|
+
} catch {
|
|
9003
|
+
}
|
|
9004
|
+
return matches2;
|
|
9005
|
+
}
|
|
9006
|
+
__name(findExistingMemoryEntries, "findExistingMemoryEntries");
|
|
9007
|
+
function shouldStoreInCoreMemory(category, epistemicType) {
|
|
9008
|
+
return category === "preference" && epistemicType === "human-stated";
|
|
9009
|
+
}
|
|
9010
|
+
__name(shouldStoreInCoreMemory, "shouldStoreInCoreMemory");
|
|
9011
|
+
async function routeToStorage(item, adapters, config) {
|
|
9012
|
+
const { category, epistemicType, statement, entities, provenance, confidence } = item;
|
|
9013
|
+
const memKey = `capture:${item.id}`;
|
|
9014
|
+
await entries.remember(memKey, {
|
|
9015
|
+
id: item.id,
|
|
9016
|
+
category,
|
|
9017
|
+
statement,
|
|
9018
|
+
entities,
|
|
9019
|
+
relationships: item.relationships,
|
|
9020
|
+
provenance,
|
|
9021
|
+
confidence,
|
|
9022
|
+
epistemicType,
|
|
9023
|
+
capturedAt: provenance.capturedAt
|
|
9024
|
+
}, {
|
|
9025
|
+
id: item.id,
|
|
9026
|
+
type: category === "preference" ? "preference" : category === "decision" ? "decision" : category === "fact" ? "fact" : "context",
|
|
9027
|
+
confidence: confidence === "high" ? 1 : confidence === "medium" ? 0.7 : 0.4,
|
|
9028
|
+
scope: category === "temporary_context" ? "session" : "local",
|
|
9029
|
+
tags: [category, provenance.epistemicType, provenance.source.conversationId],
|
|
9030
|
+
source: `capture:${provenance.source.conversationId}`
|
|
9031
|
+
});
|
|
9032
|
+
if (shouldStoreInCoreMemory(category, epistemicType)) {
|
|
9033
|
+
try {
|
|
9034
|
+
const anchor = await loadPersonalityAnchor();
|
|
9035
|
+
const existingPref = anchor.identity.durablePreferences.find((p) => p.statement === statement);
|
|
9036
|
+
if (!existingPref) {
|
|
9037
|
+
await updatePersonalityAnchor({
|
|
9038
|
+
durablePreferences: [
|
|
9039
|
+
...anchor.identity.durablePreferences,
|
|
9040
|
+
{
|
|
9041
|
+
id: item.id,
|
|
9042
|
+
statement,
|
|
9043
|
+
confidence: epistemicType,
|
|
9044
|
+
evidence: [provenance.source.conversationId],
|
|
9045
|
+
firstObserved: provenance.capturedAt,
|
|
9046
|
+
lastConfirmed: provenance.capturedAt
|
|
9047
|
+
}
|
|
9048
|
+
]
|
|
9049
|
+
});
|
|
9050
|
+
}
|
|
9051
|
+
} catch {
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
9054
|
+
if (category === "open_loop" && config.autoCreateLoops) {
|
|
9055
|
+
try {
|
|
9056
|
+
const existingLoops = await listLoops(true);
|
|
9057
|
+
const alreadyExists = existingLoops.some((l) => l.text === statement);
|
|
9058
|
+
if (!alreadyExists) {
|
|
9059
|
+
await addLoop({
|
|
9060
|
+
id: item.id,
|
|
9061
|
+
text: statement,
|
|
9062
|
+
waitor: "joy",
|
|
9063
|
+
openedAt: provenance.capturedAt
|
|
9064
|
+
});
|
|
9065
|
+
}
|
|
9066
|
+
} catch {
|
|
9067
|
+
}
|
|
9068
|
+
}
|
|
9069
|
+
if (category === "experience" && config.autoCreateExemplars) {
|
|
9070
|
+
try {
|
|
9071
|
+
await addExemplar({
|
|
9072
|
+
id: item.id,
|
|
9073
|
+
source: {
|
|
9074
|
+
conversationId: provenance.source.conversationId,
|
|
9075
|
+
messageIds: provenance.source.messageIds
|
|
9076
|
+
},
|
|
9077
|
+
pattern: statement,
|
|
9078
|
+
originalContent: statement,
|
|
9079
|
+
sourceReference: `capture:${item.id}`,
|
|
9080
|
+
retrievalHints: [statement, ...entities.map((e) => e.name)],
|
|
9081
|
+
significance: confidence === "high" ? 0.8 : confidence === "medium" ? 0.5 : 0.3,
|
|
9082
|
+
confidence: confidence === "high" ? 1 : confidence === "medium" ? 0.7 : 0.4,
|
|
9083
|
+
provenance: epistemicType,
|
|
9084
|
+
createdAt: provenance.capturedAt
|
|
9085
|
+
});
|
|
9086
|
+
} catch {
|
|
9087
|
+
}
|
|
9088
|
+
}
|
|
9089
|
+
if (config.autoCreateClaims && (category === "fact" || category === "decision")) {
|
|
9090
|
+
try {
|
|
9091
|
+
await acquire.acquire({
|
|
9092
|
+
id: `claim-${item.id}`,
|
|
9093
|
+
knowledge: { statement, category },
|
|
9094
|
+
applicability: { area: "project" },
|
|
9095
|
+
evidence: [{
|
|
9096
|
+
id: `ev-${item.id}`,
|
|
9097
|
+
source: provenance.source.conversationId,
|
|
9098
|
+
observedAt: provenance.capturedAt,
|
|
9099
|
+
supports: statement
|
|
9100
|
+
}],
|
|
9101
|
+
epistemicType,
|
|
9102
|
+
provenance: { source: "conversation-capture", detail: `category:${category}` },
|
|
9103
|
+
acquiredAt: provenance.capturedAt,
|
|
9104
|
+
scope: "project"
|
|
9105
|
+
});
|
|
9106
|
+
} catch {
|
|
9107
|
+
}
|
|
9108
|
+
}
|
|
9109
|
+
dispatch.set("dotmem:capture:item-captured", {
|
|
9110
|
+
detail: { id: item.id, category, statement }
|
|
9111
|
+
});
|
|
9112
|
+
}
|
|
9113
|
+
__name(routeToStorage, "routeToStorage");
|
|
9114
|
+
var CaptureEngine = class {
|
|
9115
|
+
static {
|
|
9116
|
+
__name(this, "CaptureEngine");
|
|
9117
|
+
}
|
|
9118
|
+
config;
|
|
9119
|
+
adapters;
|
|
9120
|
+
sessionContexts = /* @__PURE__ */ new Map();
|
|
9121
|
+
constructor(config = {}, adapters) {
|
|
9122
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
9123
|
+
this.adapters = {
|
|
9124
|
+
remember: entries.remember.bind(entries),
|
|
9125
|
+
recall: entries.recall.bind(entries),
|
|
9126
|
+
update: entries.update.bind(entries),
|
|
9127
|
+
addExemplar: addExemplar.bind(null),
|
|
9128
|
+
updateExemplar: updateExemplar.bind(null),
|
|
9129
|
+
addLoop: addLoop.bind(null),
|
|
9130
|
+
closeLoop: closeLoop.bind(null),
|
|
9131
|
+
updatePersonalityAnchor: updatePersonalityAnchor.bind(null),
|
|
9132
|
+
...adapters
|
|
9133
|
+
};
|
|
9134
|
+
}
|
|
9135
|
+
/**
|
|
9136
|
+
* Capture information from a conversation turn.
|
|
9137
|
+
* Processes a single message or turn of conversation.
|
|
9138
|
+
*/
|
|
9139
|
+
async captureTurn(text, options) {
|
|
9140
|
+
const source = {
|
|
9141
|
+
conversationId: options.conversationId,
|
|
9142
|
+
messageIds: options.messageIds ?? [],
|
|
9143
|
+
timestamp: nowIso(),
|
|
9144
|
+
turnIndex: 0
|
|
9145
|
+
};
|
|
9146
|
+
const instructions = detectExplicitInstructions(text, source);
|
|
9147
|
+
const hasDoNotRemember = instructions.some((i2) => i2.type === "do-not-remember");
|
|
9148
|
+
const hasExplicitRemember = instructions.some((i2) => i2.type === "remember");
|
|
9149
|
+
let created = 0, linked = 0, ignored = 0;
|
|
9150
|
+
if (hasDoNotRemember && !hasExplicitRemember) {
|
|
9151
|
+
const item2 = {
|
|
9152
|
+
id: generateId(),
|
|
9153
|
+
category: "temporary_context",
|
|
9154
|
+
statement: text,
|
|
9155
|
+
content: { text },
|
|
9156
|
+
entities: [],
|
|
9157
|
+
relationships: [],
|
|
9158
|
+
provenance: {
|
|
9159
|
+
source,
|
|
9160
|
+
classification: "temporary_context",
|
|
9161
|
+
confidence: "low",
|
|
9162
|
+
epistemicType: "observed",
|
|
9163
|
+
capturedAt: nowIso(),
|
|
9164
|
+
method: "automatic"
|
|
9165
|
+
},
|
|
9166
|
+
confidence: "low",
|
|
9167
|
+
epistemicType: "observed"
|
|
9168
|
+
};
|
|
9169
|
+
await this.storeSessionContext(options.conversationId, [item2], instructions);
|
|
9170
|
+
ignored++;
|
|
9171
|
+
return { items: [item2], instructions, created: 0, linked: 0, ignored: 1, dedupMatches: [] };
|
|
9172
|
+
}
|
|
9173
|
+
const category = classifyCategory(text, instructions);
|
|
9174
|
+
const epistemicType = determineEpistemicType(category, text, instructions);
|
|
9175
|
+
const confidence = determineConfidence(category, epistemicType);
|
|
9176
|
+
const entities = extractEntities(text);
|
|
9177
|
+
const relationships = extractRelationships(text, entities);
|
|
9178
|
+
const provenance = {
|
|
9179
|
+
source,
|
|
9180
|
+
classification: category,
|
|
9181
|
+
confidence,
|
|
9182
|
+
epistemicType,
|
|
9183
|
+
capturedAt: nowIso(),
|
|
9184
|
+
method: hasExplicitRemember ? "explicit" : "automatic"
|
|
9185
|
+
};
|
|
9186
|
+
const item = {
|
|
9187
|
+
id: generateId(),
|
|
9188
|
+
category,
|
|
9189
|
+
statement: text,
|
|
9190
|
+
content: { text },
|
|
9191
|
+
entities,
|
|
9192
|
+
relationships,
|
|
9193
|
+
provenance,
|
|
9194
|
+
confidence,
|
|
9195
|
+
epistemicType
|
|
9196
|
+
};
|
|
9197
|
+
const sessionCtx = this.sessionContexts.get(options.conversationId);
|
|
9198
|
+
const existingItems = sessionCtx ? sessionCtx.items : [];
|
|
9199
|
+
const dedupMatches = await findExistingSimilarItems(
|
|
9200
|
+
text,
|
|
9201
|
+
category,
|
|
9202
|
+
existingItems,
|
|
9203
|
+
this.config.dedupSimilarityThreshold
|
|
9204
|
+
);
|
|
9205
|
+
const memoryMatches = await findExistingMemoryEntries(text, category);
|
|
9206
|
+
const allMatches = [...dedupMatches, ...memoryMatches];
|
|
9207
|
+
let decision = "create";
|
|
9208
|
+
if (allMatches.length > 0) {
|
|
9209
|
+
const exactMatch = allMatches.find((m) => m.matchType === "exact");
|
|
9210
|
+
if (exactMatch) {
|
|
9211
|
+
decision = "link";
|
|
9212
|
+
linked++;
|
|
9213
|
+
} else {
|
|
9214
|
+
decision = "create";
|
|
9215
|
+
created++;
|
|
9216
|
+
}
|
|
9217
|
+
} else {
|
|
9218
|
+
created++;
|
|
9219
|
+
}
|
|
9220
|
+
const finalItem = { ...item };
|
|
9221
|
+
const shouldStore = decision === "create" || decision === "link";
|
|
9222
|
+
if (shouldStore) {
|
|
9223
|
+
await routeToStorage(finalItem, this.adapters, this.config);
|
|
9224
|
+
}
|
|
9225
|
+
await this.storeSessionContext(options.conversationId, [finalItem], instructions);
|
|
9226
|
+
return { items: [finalItem], instructions, created, linked, ignored, dedupMatches: allMatches };
|
|
9227
|
+
}
|
|
9228
|
+
/**
|
|
9229
|
+
* Capture information from a full conversation (array of messages).
|
|
9230
|
+
* Processes each message and returns aggregated results.
|
|
9231
|
+
*/
|
|
9232
|
+
async captureConversation(messages, options) {
|
|
9233
|
+
const allItems = [];
|
|
9234
|
+
const allInstructions = [];
|
|
9235
|
+
let created = 0, updated = 0, linked = 0, ignored = 0;
|
|
9236
|
+
const allDedupMatches = [];
|
|
9237
|
+
for (const [index, msg] of messages.entries()) {
|
|
9238
|
+
const source = {
|
|
9239
|
+
conversationId: options.conversationId,
|
|
9240
|
+
messageIds: [msg.id ?? `msg-${index}`],
|
|
9241
|
+
timestamp: msg.timestamp ?? nowIso(),
|
|
9242
|
+
turnIndex: index
|
|
9243
|
+
};
|
|
9244
|
+
const instructions = detectExplicitInstructions(msg.content, source);
|
|
9245
|
+
allInstructions.push(...instructions);
|
|
9246
|
+
const hasDoNotRemember = instructions.some((i2) => i2.type === "do-not-remember");
|
|
9247
|
+
const hasExplicitRemember = instructions.some((i2) => i2.type === "remember");
|
|
9248
|
+
if (hasDoNotRemember && !hasExplicitRemember) {
|
|
9249
|
+
const item2 = {
|
|
9250
|
+
id: generateId(),
|
|
9251
|
+
category: "temporary_context",
|
|
9252
|
+
statement: msg.content,
|
|
9253
|
+
content: { text: msg.content, role: msg.role },
|
|
9254
|
+
entities: [],
|
|
9255
|
+
relationships: [],
|
|
9256
|
+
provenance: {
|
|
9257
|
+
source,
|
|
9258
|
+
classification: "temporary_context",
|
|
9259
|
+
confidence: "low",
|
|
9260
|
+
epistemicType: "observed",
|
|
9261
|
+
capturedAt: nowIso(),
|
|
9262
|
+
method: "automatic"
|
|
9263
|
+
},
|
|
9264
|
+
confidence: "low",
|
|
9265
|
+
epistemicType: "observed"
|
|
9266
|
+
};
|
|
9267
|
+
allItems.push(item2);
|
|
9268
|
+
ignored++;
|
|
9269
|
+
continue;
|
|
9270
|
+
}
|
|
9271
|
+
const category = classifyCategory(msg.content, instructions);
|
|
9272
|
+
const epistemicType = determineEpistemicType(category, msg.content, instructions);
|
|
9273
|
+
const confidence = determineConfidence(category, epistemicType, msg.content);
|
|
9274
|
+
const entities = extractEntities(msg.content);
|
|
9275
|
+
const relationships = extractRelationships(msg.content, entities);
|
|
9276
|
+
const provenance = {
|
|
9277
|
+
source,
|
|
9278
|
+
classification: category,
|
|
9279
|
+
confidence,
|
|
9280
|
+
epistemicType,
|
|
9281
|
+
capturedAt: nowIso(),
|
|
9282
|
+
method: hasExplicitRemember ? "explicit" : "automatic"
|
|
9283
|
+
};
|
|
9284
|
+
const item = {
|
|
9285
|
+
id: generateId(),
|
|
9286
|
+
category,
|
|
9287
|
+
statement: msg.content,
|
|
9288
|
+
content: { text: msg.content, role: msg.role },
|
|
9289
|
+
entities,
|
|
9290
|
+
relationships,
|
|
9291
|
+
provenance,
|
|
9292
|
+
confidence,
|
|
9293
|
+
epistemicType
|
|
9294
|
+
};
|
|
9295
|
+
const dedupMatches = await findExistingSimilarItems(
|
|
9296
|
+
msg.content,
|
|
9297
|
+
category,
|
|
9298
|
+
allItems,
|
|
9299
|
+
this.config.dedupSimilarityThreshold
|
|
9300
|
+
);
|
|
9301
|
+
const memoryMatches = await findExistingMemoryEntries(msg.content, category);
|
|
9302
|
+
const allMatches = [...dedupMatches, ...memoryMatches];
|
|
9303
|
+
allDedupMatches.push(...allMatches);
|
|
9304
|
+
let decision = "create";
|
|
9305
|
+
if (allMatches.length > 0) {
|
|
9306
|
+
const exactMatch = allMatches.find((m) => m.matchType === "exact");
|
|
9307
|
+
if (exactMatch) {
|
|
9308
|
+
decision = "link";
|
|
9309
|
+
linked++;
|
|
9310
|
+
} else {
|
|
9311
|
+
decision = "create";
|
|
9312
|
+
created++;
|
|
9313
|
+
}
|
|
9314
|
+
} else {
|
|
9315
|
+
created++;
|
|
9316
|
+
}
|
|
9317
|
+
const shouldStore = decision === "create" || decision === "link";
|
|
9318
|
+
if (shouldStore) {
|
|
9319
|
+
await routeToStorage(item, this.adapters, this.config);
|
|
9320
|
+
}
|
|
9321
|
+
if (!shouldStore) ignored++;
|
|
9322
|
+
allItems.push(item);
|
|
9323
|
+
}
|
|
9324
|
+
await this.storeSessionContext(options.conversationId, allItems, allInstructions);
|
|
9325
|
+
return {
|
|
9326
|
+
items: allItems,
|
|
9327
|
+
created,
|
|
9328
|
+
updated,
|
|
9329
|
+
linked,
|
|
9330
|
+
ignored,
|
|
9331
|
+
dedupMatches: allDedupMatches,
|
|
9332
|
+
provenance: allItems.map((i2) => i2.provenance)
|
|
9333
|
+
};
|
|
9334
|
+
}
|
|
9335
|
+
/**
|
|
9336
|
+
* Retrieve captured items for a conversation.
|
|
9337
|
+
*/
|
|
9338
|
+
async getCapturedItems(conversationId) {
|
|
9339
|
+
const ctx = this.sessionContexts.get(conversationId);
|
|
9340
|
+
return ctx ? ctx.items : [];
|
|
9341
|
+
}
|
|
9342
|
+
/**
|
|
9343
|
+
* Get all captured items across all conversations.
|
|
9344
|
+
*/
|
|
9345
|
+
async getAllCapturedItems() {
|
|
9346
|
+
const all = [];
|
|
9347
|
+
for (const ctx of this.sessionContexts.values()) {
|
|
9348
|
+
all.push(...ctx.items);
|
|
9349
|
+
}
|
|
9350
|
+
return all;
|
|
9351
|
+
}
|
|
9352
|
+
/**
|
|
9353
|
+
* Clear session context (for testing / cleanup).
|
|
9354
|
+
*/
|
|
9355
|
+
clearSession(conversationId) {
|
|
9356
|
+
this.sessionContexts.delete(conversationId);
|
|
9357
|
+
}
|
|
9358
|
+
/**
|
|
9359
|
+
* Get capture engine configuration.
|
|
9360
|
+
*/
|
|
9361
|
+
getConfig() {
|
|
9362
|
+
return { ...this.config };
|
|
9363
|
+
}
|
|
9364
|
+
// ---------------------------------------------------------------------------
|
|
9365
|
+
// Private
|
|
9366
|
+
// ---------------------------------------------------------------------------
|
|
9367
|
+
async storeSessionContext(conversationId, items, instructions) {
|
|
9368
|
+
let ctx = this.sessionContexts.get(conversationId);
|
|
9369
|
+
if (!ctx) {
|
|
9370
|
+
ctx = {
|
|
9371
|
+
conversationId,
|
|
9372
|
+
startedAt: nowIso(),
|
|
9373
|
+
items: [],
|
|
9374
|
+
explicitInstructions: []
|
|
9375
|
+
};
|
|
9376
|
+
this.sessionContexts.set(conversationId, ctx);
|
|
9377
|
+
}
|
|
9378
|
+
ctx.items.push(...items);
|
|
9379
|
+
ctx.explicitInstructions.push(...instructions);
|
|
9380
|
+
try {
|
|
9381
|
+
const stateKey = `${CAPTURE_STATE_KEY}:${conversationId}`;
|
|
9382
|
+
const existing = store.get(stateKey);
|
|
9383
|
+
let prior = [];
|
|
9384
|
+
if (existing) {
|
|
9385
|
+
try {
|
|
9386
|
+
prior = JSON.parse(existing);
|
|
9387
|
+
} catch {
|
|
9388
|
+
}
|
|
9389
|
+
}
|
|
9390
|
+
store.set(stateKey, JSON.stringify([...prior, ...items]));
|
|
9391
|
+
} catch {
|
|
9392
|
+
}
|
|
9393
|
+
}
|
|
9394
|
+
};
|
|
9395
|
+
var captureEngine = new CaptureEngine();
|
|
9396
|
+
async function captureConversation(messages, options) {
|
|
9397
|
+
return captureEngine.captureConversation(messages, options);
|
|
9398
|
+
}
|
|
9399
|
+
__name(captureConversation, "captureConversation");
|
|
9400
|
+
async function captureTurn(text, options) {
|
|
9401
|
+
return captureEngine.captureTurn(text, options);
|
|
9402
|
+
}
|
|
9403
|
+
__name(captureTurn, "captureTurn");
|
|
9404
|
+
|
|
8135
9405
|
// core/memory/index.ts
|
|
8136
9406
|
init_detection_events();
|
|
8137
9407
|
init_detection_journal();
|
|
@@ -8241,7 +9511,7 @@ var memory = {
|
|
|
8241
9511
|
*/
|
|
8242
9512
|
async clear() {
|
|
8243
9513
|
await entries.clearEntries();
|
|
8244
|
-
store.remove("__dotmem_acquired_knowledge_state__");
|
|
9514
|
+
store$1.remove("__dotmem_acquired_knowledge_state__");
|
|
8245
9515
|
await resetKnowledgeRuntimeCaches();
|
|
8246
9516
|
resetBrainPathCache();
|
|
8247
9517
|
resetPolicyStoreCache();
|
|
@@ -8319,6 +9589,25 @@ var memory = {
|
|
|
8319
9589
|
async getSeedId() {
|
|
8320
9590
|
return SEED_ID;
|
|
8321
9591
|
}
|
|
9592
|
+
},
|
|
9593
|
+
/** Automatic conversational capture engine (Phase 2 — Workstream B). */
|
|
9594
|
+
capture: {
|
|
9595
|
+
engine: captureEngine,
|
|
9596
|
+
async conversation(messages, options) {
|
|
9597
|
+
return captureConversation(messages, options);
|
|
9598
|
+
},
|
|
9599
|
+
async turn(text, options) {
|
|
9600
|
+
return captureTurn(text, options);
|
|
9601
|
+
},
|
|
9602
|
+
async getItems(conversationId) {
|
|
9603
|
+
return captureEngine.getCapturedItems(conversationId);
|
|
9604
|
+
},
|
|
9605
|
+
async getAllItems() {
|
|
9606
|
+
return captureEngine.getAllCapturedItems();
|
|
9607
|
+
},
|
|
9608
|
+
clearSession(conversationId) {
|
|
9609
|
+
captureEngine.clearSession(conversationId);
|
|
9610
|
+
}
|
|
8322
9611
|
}
|
|
8323
9612
|
};
|
|
8324
9613
|
|
|
@@ -8589,7 +9878,7 @@ var continuity = {
|
|
|
8589
9878
|
// global.ts
|
|
8590
9879
|
var global_default = {
|
|
8591
9880
|
state: state,
|
|
8592
|
-
store: store,
|
|
9881
|
+
store: store$1,
|
|
8593
9882
|
session: session,
|
|
8594
9883
|
idb: idb,
|
|
8595
9884
|
dispatch: dispatch,
|